#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *mystrtok(char *s1, const char *s2, char ** lasts);
static int test(char *s, char *delim, char **lasts, char *new,
                char *result, char **p);


int main(void) {
   char *lasts1;
   char *lasts2;
   char *lasts3;
   char *delim = ":;";
   char s1[] = "abc:;def::ghi;jkl";
   char s2[] = ":;:abc:;def::ghi;jkl:;:";
   char s3[] = ":;:";
   char *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10, *p11;

   fprintf(stderr,"First call of simple test\n");
   if (test(s1,delim,&lasts1,s1,"abc",&p1))
      return 0;
   
   fprintf(stderr,"Second call of simple test\n");
   if (test(NULL,delim,&lasts1,s1+5,"def",&p2))
      return 0;

   fprintf(stderr,"First call of second test\n");
   if (test(s2,delim,&lasts2,s2+3,"abc",&p6))
      return 0;
 
   fprintf(stderr,"Second call of second test\n");
   if (test(NULL,delim,&lasts2,s2+8,"def",&p7))
      return 0;
 
   fprintf(stderr,"Third call of simple test\n");
   if (test(NULL,delim,&lasts1,s1+10,"ghi",&p3))
      return 0;

   fprintf(stderr,"fourth call of simple test\n");
   if (test(NULL,delim,&lasts1,s1+14,"jkl",&p4))
      return 0;

   fprintf(stderr,"fifth call of simple test\n");
   if (test(NULL,delim,&lasts1,NULL,NULL,&p5))
      return 0;

   if ( (p1 == NULL) || strcmp(p1,"abc")) {
      fprintf(stderr,"modified first token in simple test\n");
      return 0;
   }
   if ( (p2 == NULL) || strcmp(p2,"def")) {
      fprintf(stderr,"modified second token in simple test\n");
      return 0;
   }
   if ( (p3 == NULL) || strcmp(p3,"ghi")) {
      fprintf(stderr,"modified third token in simple test\n");
      return 0;
   }
   if ( (p4 == NULL) || strcmp(p4,"jkl")) {
      fprintf(stderr,"modified fourth token in simple test\n");
      return 0;
   }


   fprintf(stderr,"third call of second test\n");
   if (test(NULL,delim,&lasts2,s2+13,"ghi",&p8)) {
      fprintf(stderr,"failed test 8\n");
      return 0;
   }

   fprintf(stderr,"fourth call of second test\n");
   if (test(NULL,delim,&lasts2,s2+17,"jkl",&p9)) {
      fprintf(stderr,"failed test 9\n");
      return 0;
   }

   fprintf(stderr,"fifth call of second test\n");
   if (test(NULL,delim,&lasts2,NULL,NULL,&p10)) {
      fprintf(stderr,"failed test 10\n");
      return 0;
   }

   if ( (p6 == NULL) || strcmp(p6,"abc")) {
      fprintf(stderr,"modified first token in second test\n");
      return 0;
   }
   if ( (p7 == NULL) || strcmp(p7,"def")) {
      fprintf(stderr,"modified second token in second test\n");
      return 0;
   }
   if ( (p8 == NULL) || strcmp(p8,"ghi")) {
      fprintf(stderr,"modified third token in second test\n");
      return 0;
   }
   if ( (p9 == NULL) || strcmp(p9,"jkl")) {
      fprintf(stderr,"modified fourth token in second test\n");
      return 0;
   }

   fprintf(stderr,"last test with no tokens\n");
   if (test(s3,delim,&lasts3,NULL,NULL,&p11)) {
      fprintf(stderr,"failed test with no tokens");
      return 0;
   }

   else
      fprintf(stderr,"All tests passed successfully\n");
   return 0;

}

/* returns 1 on failure, 0 on success */
/* the first three parameters are passed to mystrtok */
/* The return value of mystrtok is put in *p */
/* new is the correct pointer that should be returned */
/* result points to a copy of the string that should be returned */
static int test(char *s, char *delim, char **lasts, char *new,
                char *result, char **p) {
   fprintf(stderr,"Calling mystrtok with s=%p and lasts = %p\n",
           (void *)s,(void *)lasts);
   if (*lasts != NULL)
      fprintf(stderr,"  *lasts is %p\n",*lasts);
   else
      fprintf(stderr,"  *lasts is NULL\n");
   fprintf(stderr,"About to call mystrtok\n");
   *p = mystrtok(s,delim,lasts);
   fprintf(stderr,"   returned %p and should be %p\n",(void *)*p,(void *)new);
   if (*p != new) {
      if (new == NULL)
         fprintf(stderr,"  should have returned NULL pointer\n");
      else
         fprintf(stderr, "  incorrect pointer returned, difference is %d\n",
             *p - new);
      return 1;
   }
   if ( (new != NULL) && (strcmp(*p,result) != 0)) {
      fprintf(stderr, "  incorrect string generated\n");
      return 1;
   }
   return 0;
}


