#define ARGTABLE_COMPATIBILITY_10
#include "argtable.h"
#include "argtable.c"   /*-- want access to the static fns for testing too --*/


void exitfail(const char* msg)
  {
  printf(msg);
  exit(1);
  }



/*-- test arg_typestr[] --*/
void test20(void)
  {
  printf("test20()\n");
  if (strcmp(arg_typestr[arg_int], "<int>")!=0)
     exitfail("arg_int name failed\n");
  if (strcmp(arg_typestr[arg_dbl], "<double>")!=0)
     exitfail("arg_dbl name failed\n");
  if (strcmp(arg_typestr[arg_str], "<string>")!=0)
     exitfail("arg_str name failed\n");
  if (strcmp(arg_typestr[arg_bool], "<bool>")!=0)
     exitfail("arg_bool name failed\n");
  if (strcmp(arg_typestr[arg_lit], "")!=0)
     exitfail("arg_lit name failed\n");
  }


/*-- test arg_convertbool() --*/
void test30(void)
  {
  const char* truestrings[] = 
    { "y", "Y", "ye", "yE", " Ye", "YE", "yes", "  yeS", "yEs", "Yes", "   YES",
      "t", "T", "tr", "tR", "Tr", "   TR", "tRu", "Tru", " true", "TRUE", " TrUE",
      "on", "On", "oN", "  ON" };
  const char* falsestrings[] = 
    { "n", "N", "no", "nO", "No", "NO",
      "f", "F", "fa", "fA", "Fa", "FA", "false", "faLsE", "FAlse", "FaLSe", "FALSE",
      "of", "Of", "oF", "OF", "ofF", "Off", "OFf", "OFF" };
  const char* badstrings[] =
    { NULL, "", " ", "   ", "o", "O", "y ", "n ", "yes ", "yes\t", " no\n", "0", "1", "t ", " f " };
  const int ntrue  = sizeof(truestrings)/sizeof(const char*);
  const int nfalse = sizeof(falsestrings)/sizeof(const char*);
  const int nbad   = sizeof(badstrings)/sizeof(const char*);
  int i;
 
  printf("test30()\n");
 
  /*-- test the 'true' strings all convert to 1 --*/
  for (i=0; i<ntrue; i++)
     if (arg_convertbool(truestrings[i])!=1)
        {
        static char errmsg[100];
        sprintf(errmsg,"true string \"%s\" failed\n", truestrings[i]);
        exitfail(errmsg);
        }
  
  /*-- test the 'false' strings all convert to 0 --*/
  for (i=0; i<nfalse; i++)
     if (arg_convertbool(falsestrings[i])!=0)
        {
        static char errmsg[100];
        sprintf(errmsg,"false string \"%s\" failed\n", falsestrings[i]);
        exitfail(errmsg);
        }
  
  /*-- test the 'bad' strings all convert to -1 --*/
  for (i=0; i<nbad; i++)
     if (arg_convertbool(badstrings[i])!=-1)
        {
        static char errmsg[100];
        sprintf(errmsg,"bad string \"%s\" failed\n", badstrings[i]);
        exitfail(errmsg);
        }
  
  }



/*-- test arg_set_defaults() --*/
void test40(void)
  {
  static int     i1,i2,i3,i4,i5;
  static double  f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14;
  static char    s1[100], s2[100], s3[100], s4[100], s5[100], s6[100];     
  static int     b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15;
  static int     bf1,bf2,bf3,bf4,bf5;

  arg_rec good_table[] =
     {
       { NULL, NULL, arg_int, NULL, NULL,                  NULL },
       { NULL, NULL, arg_int, &i1,  "1",                   NULL },
       { NULL, NULL, arg_int, &i2,  "-2",                  NULL },
       { NULL, NULL, arg_int, &i3,  "+3",                  NULL },
       { NULL, NULL, arg_int, &i4,  " +4",                 NULL },
       { NULL, NULL, arg_int, &i5,  "   5",                NULL },
       { NULL, NULL, arg_dbl, NULL, NULL,                  NULL },
       { NULL, NULL, arg_dbl, &f1,  "12",                  NULL },
       { NULL, NULL, arg_dbl, &f2,  "0.3",                 NULL },
       { NULL, NULL, arg_dbl, &f3,  "-0.4",                NULL },
       { NULL, NULL, arg_dbl, &f4,  "+0.5",                NULL },
       { NULL, NULL, arg_dbl, &f5,  "0.3e4",               NULL },
       { NULL, NULL, arg_dbl, &f6,  "-0.5e-7",             NULL },
       { NULL, NULL, arg_dbl, &f7,  ".234",                NULL },
       { NULL, NULL, arg_dbl, &f8,  ".235e+6",             NULL },
       { NULL, NULL, arg_dbl, &f9,  " 12",                 NULL },
       { NULL, NULL, arg_dbl, &f10, " 0.3",                NULL },
       { NULL, NULL, arg_dbl, &f11, " -0.4",               NULL },
       { NULL, NULL, arg_dbl, &f12, " -0.5e-7",            NULL },
       { NULL, NULL, arg_dbl, &f13, "  .234",              NULL },
       { NULL, NULL, arg_dbl, &f14, ".235e+6",             NULL },
       { NULL, NULL, arg_str, NULL, NULL,                  NULL },
       { NULL, NULL, arg_str, s1,   "",                    NULL },
       { NULL, NULL, arg_str, s2,   " ",                   NULL },
       { NULL, NULL, arg_str, s3,   "hello",               NULL },
       { NULL, NULL, arg_str, s4,   " hello ",             NULL },
       { NULL, NULL, arg_str, s5,   "hello world",         NULL },
       { NULL, NULL, arg_str, s6,   " Hello   World ",     NULL },
       { NULL, NULL, arg_bool, NULL,  NULL,                 NULL },
       { NULL, NULL, arg_bool, &b1,   "y",                  NULL },
       { NULL, NULL, arg_bool, &b2,   "yes",                NULL },
       { NULL, NULL, arg_bool, &b3,   "YES",                NULL },
       { NULL, NULL, arg_bool, &b4,   "t",                  NULL },
       { NULL, NULL, arg_bool, &b5,   "true",               NULL },
       { NULL, NULL, arg_bool, &b6,   "TRUE",               NULL },
       { NULL, NULL, arg_bool, &b7,   " On",                NULL },
       { NULL, NULL, arg_bool, &b8,   "n",                  NULL },
       { NULL, NULL, arg_bool, &b9,   "no",                 NULL },
       { NULL, NULL, arg_bool, &b10,  "NO",                 NULL },
       { NULL, NULL, arg_bool, &b11,  " f",                 NULL },
       { NULL, NULL, arg_bool, &b12,  "F",                  NULL },
       { NULL, NULL, arg_bool, &b13,  "FALSE",              NULL },
       { NULL, NULL, arg_bool, &b14,  "of",                 NULL },
       { NULL, NULL, arg_bool, &b15,  "OFF",                NULL },
       { NULL, NULL, arg_lit,  NULL,  NULL,                 NULL },
       { NULL, NULL, arg_lit,  &bf1,  "0",                  NULL },
       { NULL, NULL, arg_lit,  &bf2,  "  0",                NULL },
       { NULL, NULL, arg_lit,  &bf3,  " -2",                NULL },
       { NULL, NULL, arg_lit,  &bf4,  "+3",                 NULL },
       { NULL, NULL, arg_lit,  &bf5,  " 5",                 NULL },
     };
  const int ngood = sizeof(good_table)/sizeof(arg_rec);
  char ErrMsg[100]="blah blah blah";

  printf("test40()\n");

  /*-- test the good default values --*/
  if (!arg_set_defaults(good_table,ngood,ErrMsg))
     {
     static char buff[100];
     sprintf(buff,"good defaults failed with \"%s\"\n",ErrMsg);
     exitfail(buff);
     }
  if (strcmp(ErrMsg,"")!=0)
     exitfail("good_table returned unexpected error message\n");
  /*arg_dump(stderr,good_table,ngood);*/
  if (i1 !=  1 ||
      i2 != -2 ||
      i3 != +3 ||
      i4 != +4 ||
      i5 !=  5 ||
      f1  != 12.0 ||
      f2  !=  0.3 ||
      f3  != -0.4 ||
      f4 != +0.5 ||
      f5 != 0.3e4 ||
      f6 != -0.5e-7 ||
      f7 != 0.234 ||
      f8 != 0.235e+6 ||
      f9 != 12.0 ||
      f10 !=  0.3 ||
      f11 != -0.4 ||
      f12 != -0.5e-7 ||
      f13 != 0.234 ||
      f14 != 0.235e+6 ||
      strcmp(s1, "")!=0 ||
      strcmp(s2, " ")!=0 ||
      strcmp(s3, "hello")!=0 ||
      strcmp(s4, " hello ")!=0 ||
      strcmp(s5, "hello world")!=0 ||
      strcmp(s6, " Hello   World ")!=0 ||
      b1 != 1 ||
      b2 != 1 ||
      b3 != 1 ||
      b4 != 1 ||
      b5 != 1 ||
      b6 != 1 ||
      b7 != 1 ||
      b8 != 0 ||
      b9 != 0 ||
      b10 != 0 ||
      b11 != 0 ||
      b12 != 0 ||
      b13 != 0 ||
      b14 != 0 ||
      b15 != 0 ||
      bf1 != 0  ||
      bf2 != 0  ||
      bf3 != -2 ||
      bf4 != 3  ||
      bf5 != 5
      )
     exitfail("failure to convert good default value\n");
  }


/*-- test arg_set_defaults() --*/
void test41(void)
  {
  static int a,b,f;
  static double d;
  arg_rec bad_table[] =
     {
       { NULL, NULL, arg_int,  &a,  "",                   NULL },
       { NULL, NULL, arg_int,  &a,  " ",                  NULL },
       { NULL, NULL, arg_int,  &a,  "1 ",                 NULL },
       { NULL, NULL, arg_int,  &a,  "+ 1",                NULL },
       { NULL, NULL, arg_int,  &a,  "1+1",                NULL },
       { NULL, NULL, arg_dbl,  &d,  "",                   NULL },
       { NULL, NULL, arg_dbl,  &d,  " ",                  NULL },
       { NULL, NULL, arg_dbl,  &d,  "- 0.4",              NULL },
       { NULL, NULL, arg_dbl,  &d,  "+0.5 ",              NULL },
       { NULL, NULL, arg_dbl,  &d,  "0.1+0.2",            NULL },
       { NULL, NULL, arg_bool, &b,  "",                   NULL },
       { NULL, NULL, arg_bool, &b,  " ",                  NULL },
       { NULL, NULL, arg_bool, &b,  "yo",                 NULL },
       { NULL, NULL, arg_bool, &b,  "truu",               NULL },
       { NULL, NULL, arg_bool, &b,  "true ",              NULL },
       { NULL, NULL, arg_bool, &b,  "TRUET",              NULL },
       { NULL, NULL, arg_bool, &b,  "o",                  NULL },
       { NULL, NULL, arg_lit,  &f,  "",                   NULL },
       { NULL, NULL, arg_lit,  &f,  " ",                  NULL },
       { NULL, NULL, arg_lit,  &f,  "YO",                 NULL },
       { NULL, NULL, arg_lit,  &f,  "tf",                 NULL },
       { NULL, NULL, arg_lit,  &f,  "true ",              NULL },
     };
  const int nbad = sizeof(bad_table)/sizeof(arg_rec);
  char ErrMsg[100]="blah blah blah";
  int i;

  printf("test41()\n");

  /*-- test the bad default values one by one --*/
  for (i=0; i<nbad; i++)
     {
     /*-- test with non-NULL ErrMsg --*/
     if (arg_set_defaults(bad_table+i,1,ErrMsg)==1)
        {
        static char buff[100];
        sprintf(buff,"bad default [%d]=\"%s\" failed to fail\n",i,bad_table[i].defaultstr);
        exitfail(buff);
        }

     /*-- repeat test with NULL ErrMsg --*/
     if (arg_set_defaults(bad_table+i,1,NULL))
        {
        static char buff[100];
        sprintf(buff,"bad default [%s] failed to fail\n",bad_table[i].defaultstr);
        exitfail(buff);
        }
     }
  }



/*-- test arg_catargs() --*/
void test50(void)
  {
  char* argv1[] = {"myprog"};
  int   argc1   = sizeof(argv1)/sizeof(char*);
  char  ans1[]  = "myprog ";

  char* argv2[] = {"myprog", "one", "two", "three", "four"};
  int   argc2   = sizeof(argv2)/sizeof(char*);
  char  ans2[]  = "myprog one two three four ";

  char* argv3[] = {"myprog", "one", "two and  two  ", " three", "four"};
  int   argc3   = sizeof(argv2)/sizeof(char*);
  char  ans3[]  = "myprog one 'two and  two  ' ' three' four ";

  char* argv4[] = {"myprog", "one", " \"two and  two \" ", "three", "four  "};
  int   argc4   = sizeof(argv2)/sizeof(char*);
  char  ans4[]  = "myprog one ' \"two and  two \" ' three 'four  ' ";

  char buff[100];

  printf("test50()\n");

  arg_catargs(argc1,argv1,buff);
  if (strcmp(buff,ans1)!=0)
      exitfail("argv1 failed\n");

  arg_catargs(argc2,argv2,buff);
  if (strcmp(buff,ans2)!=0)
      exitfail("argv2 failed\n");

  arg_catargs(argc3,argv3,buff);
  if (strcmp(buff,ans3)!=0)
      exitfail("argv3 failed\n");

  arg_catargs(argc4,argv4,buff);
  if (strcmp(buff,ans4)!=0)
      exitfail("argv4 failed\n");
  }



/*-- test arg_checktable() --*/
void test60(void)
  {
  static int a,b,f;
  static double d;
  static char s[100];
  arg_rec bad_table[] =
     {
       { "",      NULL, arg_int,   NULL, NULL,  NULL },
       { " ",     NULL, arg_int,   NULL, NULL,  NULL },
       { NULL,    NULL, arg_int,   NULL, "blah", NULL},
       { NULL,    NULL, arg_int,   &a,   "blah",NULL },
       { NULL,    NULL, arg_dbl,   NULL, "abc",  NULL },
       { NULL,    NULL, arg_dbl,   &d,   "abc", NULL },
       { NULL,    NULL, arg_bool,  &b,   "def", NULL },
       { "",      NULL, arg_lit,   NULL, NULL,  NULL },
       { " ",     NULL, arg_lit,   NULL, NULL,  NULL },
       { "mytag", NULL, arg_lit,   NULL, "",    NULL },
     };
  arg_rec good_table[] =
     {
       { NULL,        NULL, arg_int,  NULL,  NULL,  NULL},
       { NULL,        NULL, arg_int,  NULL, " 2",   NULL},
       { "mytag",     NULL, arg_int,  NULL,  NULL,  NULL},
       { "mytag ",    NULL, arg_int,  NULL,  NULL,  NULL},
       { NULL,        "x ", arg_int,  NULL,  NULL,  NULL},
       { NULL,        " x", arg_int,  &a,    NULL,  NULL},
       { NULL,        NULL, arg_int,  &a,    "0",   NULL},
       { NULL,        NULL, arg_int,  &a,    " 0",  NULL},
       { NULL,        NULL, arg_int,  &a,    " +2", NULL },
       { NULL,        NULL, arg_dbl,  NULL,  NULL,  NULL },
       { NULL,        NULL, arg_dbl,  NULL, "0.123",NULL },
       { "mytag",     NULL, arg_dbl,  NULL,  NULL,  NULL },
       { "mytag ",    NULL, arg_dbl,  NULL,  NULL,  NULL },
       { NULL,        "x ", arg_dbl,  NULL,  NULL,  NULL },
       { NULL,        " x", arg_dbl,  &d,    NULL,  NULL },
       { NULL,        NULL, arg_dbl,  &d,    "0.0", NULL },
       { NULL,        NULL, arg_dbl,  &d,    " 0.0",NULL },
       { NULL,        NULL, arg_dbl,  &d,    "+2.0",NULL },
       { NULL,        NULL, arg_str,  NULL,  NULL,  NULL },
       { "mytag",     NULL, arg_str,  NULL,  NULL,  NULL },
       { "mytag ",    NULL, arg_str,  NULL,  NULL,  NULL },
       { NULL,        "x ", arg_str,  NULL,  NULL,  NULL },
       { NULL,        " x", arg_str,  s,     NULL,  NULL },
       { NULL,        NULL, arg_str,  s,     " ",   NULL },
       { NULL,        NULL, arg_str,  s,     " a",  NULL },
       { NULL,        NULL, arg_str,  s,     "ab ", NULL },
       { NULL,        NULL, arg_str,  s,     "ab 'cdef' ", NULL },
       { NULL,        NULL, arg_bool,  NULL, NULL,  NULL },
       { NULL,        NULL, arg_bool,  NULL, "true",NULL },
       { "mytag",     NULL, arg_bool,  NULL, NULL,  NULL },
       { "mytag ",    NULL, arg_bool,  NULL, NULL,  NULL },
       { NULL,        "x ", arg_bool,  NULL, NULL,  NULL },
       { NULL,        " x", arg_bool,  &b,   NULL,  NULL },
       { NULL,        NULL, arg_bool,  &b,   " t",  NULL },
       { NULL,        NULL, arg_bool,  &b,   "of",  NULL },
       { NULL,        NULL, arg_bool,  &b,   "f",   NULL },
       { "mytag",     NULL, arg_lit,   &f,   NULL,  NULL },
       { "mytag",     NULL, arg_lit,   &f,   "0",   NULL },
       { "mytag",     NULL, arg_lit,   NULL, "0",   NULL },
       { "mytag ",    NULL, arg_lit,   &f,   " 1",  NULL },
       { "mytag ",    NULL, arg_lit,   NULL, " 1",  NULL },
       { NULL,        "x ", arg_lit,   &f,   NULL,  NULL },
       { NULL,        " x", arg_lit,   &f,   "0",   NULL },
       { NULL,        "X",  arg_lit,   NULL, "0",   NULL },
     };
  const int nbad  = sizeof(bad_table)/sizeof(arg_rec);
  const int ngood = sizeof(good_table)/sizeof(arg_rec);
  char ErrMsg[100]="blah blah blah";
  int i;

  printf("test60()\n");

  /*-- test the bad argument table entries one by one --*/
  for (i=0; i<nbad; i++)
     {
     /*-- test with non-NULL ErrMsg --*/
     if (arg_checktable(bad_table+i,1,ErrMsg))
        {
        static char buff[100];
        sprintf(buff,"invalid entry [%d] failed to fail\n%s\n",i,ErrMsg);
        exitfail(buff);
        }

     /*-- repeat test with NULL ErrMsg --*/
     if (arg_checktable(bad_table+i,1,NULL))
        {
        static char buff[100];
        sprintf(buff,"invalid entry [%d] failed to fail\n",i);
        exitfail(buff);
        }
     }

  /*-- test the good argument table as a whole --*/
  if (!arg_checktable(good_table,ngood,ErrMsg))
        {
        static char buff[100];
        sprintf(buff,"valid entry [%d] failed unexpectedly\n%s\n",i,ErrMsg);
        exitfail(buff);
        }

  /*-- repeat test, this time  with NULL ErrMsg ptr --*/
  if (!arg_checktable(good_table,ngood,NULL))
      exitfail("good argument table unexpectedly failed\n");
  }




/*-- test arg_scanf() with integers--*/
void test70a(const char* str, int retval, int ans)
  {
  int r;
  static int ival;
  arg_rec rec = { NULL, NULL, arg_int,  &ival,  NULL, NULL };

  printf("test70a(\"%s\",%d,%d)\n",str,retval,ans);

  r = arg_scanf(str, &rec);
  if (r!=retval)
     {
     printf("return is %d, value is %d\n", r, ival);
     exitfail("unexpected return value\n");
     }
  if (retval!=-1)
     {
     if ( ival != ans )
        exitfail("integer failed to scan correctly\n");
     }
  }


/*-- test arg_scanf() with doubles--*/
void test70b(const char* str, int retval, double ans)
  {
  int r;
  static double dval;
  arg_rec rec = { NULL, NULL, arg_dbl, &dval,  NULL, NULL};

  printf("test70b(\"%s\",%d,%f)\n",str,retval,ans);

  r = arg_scanf(str, &rec);
  if (r!=retval)
     {
     printf("return is %d, value is %f\n", r, dval);
     exitfail("unexpected return value\n");
     }
  if (retval!=-1)
     {
     if ( dval != ans )
        exitfail("double failed to scan correctly\n");
     }
  }

/*-- test arg_scanf() with strings--*/
void test70c(const char* str, int retval, const char* ans)
  {
  int r;
  static char s[100];
  arg_rec rec = { NULL, NULL, arg_str, s,  NULL, NULL};

  printf("test70c(\"%s\",%d,\"%s\")\n",str,retval,ans);

  r = arg_scanf(str, &rec);
  if (r!=retval)
     {
     printf("return is %d, value is %s\n", r, s);
     exitfail("unexpected return value\n");
     }
  if (retval!=-1)
     {
     if ( strcmp(s,ans) != 0 )
        exitfail("string failed to scan correctly\n");
     }
  }

/*-- test arg_scanf() with bools --*/
void test70d(const char* str, int retval, int ans)
  {
  int r;
  static int boolval;
  arg_rec rec = { NULL, NULL, arg_bool, &boolval,  NULL, NULL };

  printf("test70d(\"%s\",%d,%d)\n",str,retval,ans);

  r = arg_scanf(str, &rec);
  if (r!=retval)
     {
     printf("return is %d, value is %d\n", r, boolval);
     exitfail("unexpected return value\n");
     }
  if (retval!=-1)
     {
     if ( boolval != ans )
        exitfail("bool failed to scan correctly\n");
     }
  }


void test70(void)
  {
  /*-- test valid int scans --*/
  test70a("1234",4,1234);
  test70a(" 1234",5,1234);
  test70a("\t1234",5,1234);
  test70a(" +1",3,1);
  test70a("-3",2,-3);
  test70a("0000",4,0);

  /*-- test invalid int scans --*/
  test70a("x",-1,0);
  /*test70a("9.1234",-1,0);*/
  test70a("+-1234",-1,0);

  /*-- test valid  double scans --*/
  test70b("0.1234", 6, 0.1234);
  test70b(" .1234", 6, 0.1234);
  test70b("-0.1234", 7, -0.1234);
  test70b("+1.234e-6", 9, +1.234e-6);
  test70b("1234", 4, 1234.0);

  /*-- test invalid double scans --*/
  test70b("x",-1,0);
  /*test70b("0.1.1",-1,0);*/
  test70b("+-3.9",-1,0);

  /*-- test valid string scans --*/
  test70c("abcdefg",      7,  "abcdefg");
  test70c("  abcdefg",    9,  "abcdefg");
  test70c("  abcdefg  ",  9,  "abcdefg");
  test70c("abc defg",     3,  "abc");
  test70c(" ' abc defg'", 12, " abc defg");

  /*-- test valid bool scans --*/
  test70d("true",   4, 1);
  test70d(" true",  5, 1);
  test70d(" t",     2, 1);
  test70d(" f",     2, 0);
  test70d("FA  ",   2, 0);
  test70d("  off",  5, 0);

  /*-- test invalid bool scans --*/
  test70d("tue",    -1,0);
  test70d("  abc",  -1,0);
  test70d("truely", -1,0);
  }


/*-- test arg_extract_tag() --*/
void test80(char* str, char* tag, char* retval, char* newstr)
  {
  const char nullstr[]="NULL";
  char *out;

  printf("test80(\"%s\",\"%s\",\"%s\",\"%s\")\n",
         str ? str : nullstr,
         tag ? tag : nullstr,
         retval ? retval : nullstr,
         newstr ? newstr : nullstr);

  out = arg_extract_tag(str,tag);
  if (out==NULL && retval==NULL)
      return;
  if (out==NULL && retval!=NULL)
      exitfail("tag was not correctly located\n");
  if (strcmp(out,retval)!=0)
      exitfail("incorrect return value\n");
  if (strcmp(str,newstr)!=0)
      exitfail("tag was not correctly extracted\n");
  }


void test80a(void)
  {
  char str[100];

  sprintf(str,"this is my string");
  test80(str,"his",&str[4],"t    is my string");

  sprintf(str,"this is my string");
  test80(str,"is",&str[4],"th   is my string");

  sprintf(str,"this is my string");
  test80(str,"nope",NULL,"this is my string");

  sprintf(str,"this is my string");
  test80(str,"my ",&str[11],"this is    string");
  }



/*-- test arg_sprint_marker() --*/
void test90(int i, int n, const char* ans)
  {
  char buff[100];
  printf("test90(%d,%d,\"%s\")\n",i,n,ans);

  arg_sprint_marker(i,n,buff);
  if (strcmp(buff,ans)!=0)
      exitfail("arg_sprint_marker() failed\n");
  }


/*-- test arg_extract_tagged_args() --*/
void test100(void)
  {
  static char cmd1[]="abc3 def:1.234 ghi: hello -jkltrue -mno ";
  static char cmd2[]="  abc  3   def:   1.234    ghi:    hello  -jkl    true   -mno   ";
  static char cmd3[]="-mno -jkl tr  def: 1.234 abc 3  ghi: 'hello'";
  char* cmd[] = {cmd1,cmd2,cmd3};
  int ncmd = sizeof(cmd)/sizeof(char*);
  static int     abc, jkl, mno;
  static double  def;
  static char    ghi[100];
  arg_rec argtable[] =
    {
      /*-tag--------name---type-----ptr---default--descr-*/
      { "abc",      NULL, arg_int,  &abc, NULL,     NULL },
      { "def:",     NULL, arg_dbl,  &def, NULL,     NULL },
      { "ghi: ",    NULL, arg_str,  ghi,  NULL,     NULL },
      { "-jkl",     NULL, arg_bool, &jkl, NULL,     NULL },
      { "-mno ",    NULL, arg_lit,  &mno, "0",      NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  int i;

  printf("test100()\n");
  for (i=0; i<ncmd; i++)
    {
    char errmsg[100], errmark[100];
  
    /*printf("%s\n",cmd[i]);*/
    if (!arg_extract_tagged_args(cmd[i],argtable,narg,errmsg,errmark))
       {
       printf("%s %s\n",errmark,errmsg);
       exitfail("cmd failed unexpectedly\n");
       }
    /*arg_dump(stdout,argtable,narg);*/
    if (abc!=3     ||
        def!=1.234 ||
        strcmp(ghi,"hello")!=0 ||
        jkl!=1    ||
        mno!=1 )
       exitfail("cmd1 arg values failed\n");
    }
  }



/*-- test arg_extract_tagged_args() with default arg values--*/
void test110(void)
  {
  static char cmd1[]="  abc  3   def:   1.234    ghi:    hello  -jkl    true   ";
  static char cmd2[]=" -jkl tr  def: 1.234 abc 3  ghi: 'hello'";
  static char cmd3[]="def: 1.234 abc 3  ghi: 'hello'";
  static char cmd4[]="abc 3  ghi: 'hello'";
  static char cmd5[]="ghi: 'hello'";
  static char cmd6[]="";
  char* cmd[] = {cmd1,cmd2,cmd3,cmd4,cmd5,cmd6};
  int ncmd = sizeof(cmd)/sizeof(char*);
  static int     abc, jkl, mno;
  static double  def;
  static char    ghi[100];
  arg_rec argtable[] =
    {
      /*-tag--------name---type-----ptr---default--descr--*/
      { "abc",      NULL, arg_int,  &abc, "3",      NULL },
      { "def:",     NULL, arg_dbl,  &def, "1.234",  NULL },
      { "ghi: ",    NULL, arg_str,  ghi,  "hello",  NULL },
      { "-jkl",     NULL, arg_bool, &jkl, "true",   NULL },
      { "-mno ",    NULL, arg_lit,  &mno, "0",      NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  int i;

  printf("test110()\n");
  for (i=0; i<ncmd; i++)
    {
    char errmsg[100], errmark[100];
  
    /*printf("%s\n",cmd[i]);*/
    arg_set_defaults(argtable,narg,NULL);
    if (!arg_extract_tagged_args(cmd[i],argtable,narg,errmsg,errmark))
       {
       printf("%s %s\n",errmark,errmsg);
       exitfail("cmd failed unexpectedly\n");
       }
    /*arg_dump(stdout,argtable,narg);*/
    if (abc!=3     ||
        def!=1.234 ||
        strcmp(ghi,"hello")!=0 ||
        jkl!=1    ||
        mno!=0 )
       exitfail("cmd1 arg values failed\n");
    }
  }



/*-- test arg_extract_tagged_args() with bad cmdline values--*/
void test120(void)
  {
  static char cmd1[] ="abc x  def: 1.234  ghi: hello  -jkl true -mno";
  static char cmd2[] ="abc 3  def: x      ghi: hello  -jkl true -mno";
  static char cmd3[] ="abc 3  def: 1.234  ghi: hello  -jkl tralse -mno";
  static char cmd4[] ="       def: 1.234  ghi: hello  -jkl tr -mno";
  static char cmd5[] ="abc 3              ghi: hello  -jkl tr -mno";
  static char cmd6[] ="abc 3  def: 1.234              -jkl tr -mno";
  static char cmd7[] ="abc 3  def: 1.234  ghi: hello          -mno";
  static char cmd8[] ="abc 3  def: 1.234  ghi: hello  -jkl    -mno";
  static char cmd9[] ="abc 3  def: 1.234  ghi: hello  -jkl tr -mno abc 3";
  static char cmd10[]="abc 3  def: 1.234  ghi: hello  -jkl tr -mno def: 1.234";
  static char cmd11[]="abc 3  def: 1.234  ghi: hello  -jkl tr -mno ghi: hello";
  static char cmd12[]="abc 3  def: 1.234  ghi: hello  -jkl tr -mno -jkl true";
  static char cmd13[]="abc 3  def: 1.234  ghi: hello  -jkl tr -mno -mno ";
  char* cmd[] = {cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10,cmd11,cmd12,cmd13};
  int ncmd = sizeof(cmd)/sizeof(char*);
  arg_rec argtable[] =
    {
      /*-tag--------name---type-----ptr---default--descr--*/
      { "abc",      NULL, arg_int,  NULL, NULL,    NULL },
      { "def:",     NULL, arg_dbl,  NULL, NULL,    NULL },
      { "ghi: ",    NULL, arg_str,  NULL, NULL,    NULL },
      { "-jkl",     NULL, arg_bool, NULL, NULL,    NULL },
      { "-mno ",    NULL, arg_lit,  NULL, "0",     NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  int i;

  printf("test120()\n");
  for (i=0; i<ncmd; i++)
    {
    char errmsg[100], errmark[100];
  
    /*printf("%s\n",cmd[i]);*/
    arg_set_defaults(argtable,narg,NULL);
    if (arg_extract_tagged_args(cmd[i],argtable,narg,errmsg,errmark))
       exitfail("cmd failed to fail\n");
    /*printf("%s %s\n",errmark,errmsg);*/
    }
  }



/*-- test arg_extract_untagged_args() --*/
void test130(void)
  {
  static char cmd1[] ="3 1.234 hello tr";
  static char cmd2[] ="3       hello tr";
  static char cmd3[] ="        hello tr";
  static char cmd4[] ="3 1.234 hello";
  static char cmd5[] ="3 1.234";
  static char cmd6[] ="3";
  static char cmd7[] ="";
  static char cmd8[] ="3 1.234 hello true extra extraneous too many";
  char* cmd[] = {cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8};
  int ncmd = sizeof(cmd)/sizeof(char*);
  static int     i1, b1;
  static double  d1;
  static char    s1[100];
  arg_rec argtable[] =
    {
      /*-tag--name---type-----ptr---default--descr--*/
      { NULL, NULL, arg_int,  &i1,  "3",     NULL },
      { NULL, NULL, arg_dbl,  &d1,  "1.234", NULL },
      { NULL, NULL, arg_str,  s1,   "hello", NULL },
      { NULL, NULL, arg_bool, &b1,  "true",  NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  int i;

  printf("test130()\n");
  for (i=0; i<ncmd; i++)
     {
     char errmsg[100], errmark[100];
  
     /*printf("%s\n",cmd[i]);*/

     arg_set_defaults(argtable,narg,NULL);
     if (!arg_extract_untagged_args(cmd[i],argtable,narg,errmsg,errmark))
        {
        printf("%s %s\n",errmark,errmsg);       
        exitfail("cmd failed unexpectedly\n");
        }
     /*printf("remaining args[%s]\n",cmd[i]);*/

     /*arg_dump(stdout,argtable,narg);*/
     if (i1!=3     ||
         d1!=1.234 ||
         strcmp(s1,"hello")!=0 ||
         b1!=1 )
        exitfail("cmd arg values failed\n");
     }
  }



/*-- test arg_extract_untagged_args() with bad cmdline values--*/
void test140(void)
  {
  static char cmd1[]  = "3 1.234 hello truest";
  static char cmd2[]  = "3 1.234       truest";
  static char cmd3[]  = "3       hello truest";
  static char cmd4[]  = "3 1.234 hello";
  static char cmd5[]  = "3 1.234";
  static char cmd6[]  = "3";
  static char cmd7[]  = "";
  static char cmd8[]  = "1.234";
  static char cmd9[]  = "hello";
  static char cmd10[] = "3 hello";
  static char cmd11[] = "3 1.234 hello r";
  char* cmd[] = {cmd1,cmd2,cmd3,cmd4,cmd5,cmd6,cmd7,cmd8,cmd9,cmd10,cmd11};
  int ncmd = sizeof(cmd)/sizeof(char*);
  arg_rec argtable[] =
    {
      /*-tag---name---type-----ptr--default--descr--*/
      { NULL,  NULL, arg_int,  NULL, NULL,    NULL },
      { NULL,  NULL, arg_dbl,  NULL, NULL,    NULL },
      { NULL,  NULL, arg_str,  NULL, NULL,    NULL },
      { NULL,  NULL, arg_bool, NULL, NULL,    NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  int i;

  printf("test140()\n");
  for (i=0; i<ncmd; i++)
    {
    char errmsg[100], errmark[100];
  
    /*printf("%s\n",cmd[i]);*/
    if (arg_extract_untagged_args(cmd[i],argtable,narg,errmsg,errmark))
       exitfail("cmd failed to fail\n");
    /*printf("%s %s\n",errmark,errmsg);*/
    }
  }


/*-- test arg_scanstr() on valid arguments --*/
void test150(void)
  {
  static char cmd1[]="";
  static char rem1[]="";
  static char cmd2[]="  ";
  static char rem2[]="  ";
  static char cmd3[]="abc3 def:1.234 ghi: hello -jkltrue ";
  static char rem3[]="                                   ";
  static char cmd4[]="-jkl true 6 abc 3  ghi: hello  ";
  static char rem4[]="                               ";
  static char cmd5[]=" 6 ghi: hello 9.345 abc 3 bye false extraneous -jkl true excess";
  static char rem5[]="                                    extraneous           excess";
  char* cmd[] = {cmd1,cmd2,cmd3,cmd4,cmd5};
  char* rem[] = {rem1,rem2,rem3,rem4,rem5};
  int ncmd = sizeof(cmd)/sizeof(char*);
  static int     i1,i2,b1,b2,f1;
  static double  d1,d2;
  static char    s1[100],s2[100];
  arg_rec argtable[] =
    {
      /*-tag--------name---type-----ptr---default--descr--*/
      { "abc",      NULL, arg_int,  &i1, "3",      NULL },
      { "def:",     NULL, arg_dbl,  &d1, "1.234",  NULL },
      { "ghi: ",    NULL, arg_str,  s1,  "hello",  NULL },
      { "-jkl",     NULL, arg_bool, &b1, "true",   NULL },
      { "-mno ",    NULL, arg_lit,  &f1, "0",      NULL },
      { NULL,       NULL, arg_int,  &i2,  "6",     NULL },
      { NULL,       NULL, arg_dbl,  &d2,  "9.345", NULL },
      { NULL,       NULL, arg_str,  s2,   "bye",   NULL },
      { NULL,       NULL, arg_bool, &b2,  "false", NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  int i;

  printf("test150()\n");
  for (i=0; i<ncmd; i++)
    {
    char errmsg[100], errmark[100];
  
    /*printf("cmd[%d]='%s'\n",i,cmd[i]);*/
    if (!arg_scanstr(cmd[i],argtable,narg,errmsg,errmark))
       {
       printf("        %s\n%s\n",errmark,errmsg);
       exitfail("cmd failed unexpectedly\n");
       }
    /*arg_dump(stdout,argtable,narg);*/
    if (i1!=3     ||
        d1!=1.234 ||
        strcmp(s1,"hello")!=0 ||
        b1!=1    ||
        f1!=0    ||
        i2!=6     ||
        d2!=9.345 ||
        strcmp(s2,"bye")!=0   ||
        b2!=0 )
       exitfail("cmd arg values failed\n");
    if (strcmp(cmd[i],rem[i])!=0)
       exitfail("remaining args not as expected\n");
    }

  /*-- test an empty argtable --*/
  {
  char cmdline[] = "yeah nah whatever", errmsg[100], errmark[100];
  if (!arg_scanstr(cmdline,argtable,0,errmsg,errmark))
       {
       printf("        %s\n%s\n",errmark,errmsg);
       exitfail("cmd failed unexpectedly\n");
       }
  }
     
  }


/* test arg_scanargv() */
void test160(void)
  {
  static int i1,i2;
  static double d1,d2;
  static int b1,b2;
  static int l1,l2;
  static char s1[100], s2[100];

  arg_rec argtable[] =
    {
      /*-tag--------name---type-----ptr---default--descr--*/
      { "abc",      NULL, arg_int,  &i1,  "3",     NULL },
      { "def:",     NULL, arg_dbl,  &d1,  "1.234", NULL },
      { "ghi: ",    NULL, arg_str,  s1,   "hello", NULL },
      { "-jkl",     NULL, arg_bool, &b1,  "true",  NULL },
      { "-mno ",    NULL, arg_lit,  &l1,  "1",     NULL },
      { NULL,       NULL, arg_int,  &i2,  "6",     NULL },
      { NULL,       NULL, arg_dbl,  &d2,  "9.345", NULL },
      { NULL,       NULL, arg_str,  s2,   "bye",   NULL },
      { NULL,      "xyz", arg_lit,  &l2,  "1",     NULL },
      { NULL,       NULL, arg_bool, &b2,  "false", NULL },
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);

  /*-- legal usages --*/
  static char* argv1[]={"abc","3","def:","1.234","ghi:","hello","-jkl","true","6","9.345","bye","xyz","false"};
  static char* argv2[]={"6","def:","1.234","abc","3","9.345","bye","-jkl","true","xyz","false"};
  static char* argv3[]={"ghi:","hello","-jkl","true","6","9.345","bye","false"};
  static char* argv4[]={"abc","3","def:","1.234","6"};
  static char* argv5[]={"6"};
  char** argvv[]={argv1,argv2,argv3,argv4,argv5};
  int argcc[]=
        {
	sizeof(argv1)/sizeof(char*),
        sizeof(argv2)/sizeof(char*),
        sizeof(argv3)/sizeof(char*),
        sizeof(argv4)/sizeof(char*),
        sizeof(argv5)/sizeof(char*),
	};
  int n = sizeof(argvv)/sizeof(char**);
  int i;

  printf("test160()\n");
  for (i=0; i<n; i++)
    {
    char cmdline[100], errmsg[100], errmark[100];
  
    if (!arg_scanargv(argcc[i],argvv[i],argtable,narg,cmdline,errmsg,errmark))
       {
       printf("%s\n%s\n%s\n",cmdline,errmark,errmsg);
       exitfail("cmd failed unexpectedly\n");
       }
    /*arg_dump(stdout,argtable,narg);*/
    if (i1!=3     ||
        d1!=1.234 ||
        strcmp(s1,"hello")!=0 ||
        b1!=1     ||
        l1!=1     ||
        i2!=6     ||
        d2!=9.345 ||
        strcmp(s2,"bye")!=0   ||
        b2!=0     ||
        l2!=1)
       exitfail("cmd arg values failed\n");
    }

  }


/* test arg_syntax() */
void test180(void)
  {
  arg_rec argtable[] =
    {
      /*-tag--------name------type------ptr----default--descrip --*/
      { NULL,      "x",       arg_int,  NULL,  NULL,    NULL },
      { "-ny ",    "y",       arg_int,  NULL,  NULL,    NULL },
      { "-nz",     NULL,      arg_int,  NULL,  "1",     NULL },
      { "-rad ",   NULL,      arg_dbl,  NULL,  "3.141", NULL },
      { NULL,      NULL,      arg_dbl,  NULL,  "6.282", NULL },
      { "-quiet ", "on/off",  arg_bool, NULL,  "on",    NULL },
      { "-verb ",  NULL,      arg_lit,  NULL,  "0",     NULL },
      { "-title ", NULL,      arg_str,  NULL,  "noname",NULL },
      { "",        "",        arg_str,  NULL,  "nill",  NULL },
      { "-file " , "myfile",  arg_str,  NULL,  NULL,    NULL }
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);

  char usage[]="x -ny y [-nz<int>] [-rad <double>] [<double>] [-quiet on/off] [-verb ] [-title <string>] -file myfile";

  printf("test180()\n");
  /*printf("\"%s\"\n",arg_syntax(argtable,narg)); */
  if (strcmp(arg_syntax(argtable,narg),usage)!=0)
    exitfail("arg_syntax() failed\n");
  }



/* test arg_glossary()*/
void test190(void)
  {
  arg_rec argtable[] =
    {
      /*-tag--------name------type------ptr---default--descrip ---------*/
      { NULL,      "x",       arg_int,  NULL,  NULL,    NULL },
      { "-ny ",    "y",       arg_int,  NULL,  NULL,    " the y stuff" },
      { "-nz",     NULL,      arg_int,  NULL,  "1",     " the z stuff" },
      { "-rad ",   NULL,      arg_dbl,  NULL,  "3.141", "" },
      { NULL,      "a long long long long name",
                              arg_dbl,  NULL,  "6.282", " dunno" },
      { "-quiet ", "on/off",  arg_bool, NULL,  "on",    " quiteness" },
      { "-verb ",  NULL,      arg_lit,  NULL,  "0",     " loudness" },
      { "-title ", NULL,      arg_str,  NULL,  "noname"," guess what" },
      { "",        "",        arg_str,  NULL,  "nill",  NULL },
      { "-file " , "myfile",  arg_str,  NULL,  NULL,    " the X file" }
    };
  int narg = sizeof(argtable)/sizeof(arg_rec);
  
  char glossary[]=
    "   -ny y the y stuff\n"
    "   -nz<int> the z stuff\n"
    "   -rad <double>\n"
    "   a long long long long name dunno\n"
    "   -quiet on/off quiteness\n"
    "   -verb  loudness\n"
    "   -title <string> guess what\n"
    "   -file myfile the X file\n";
  
  printf("test190()\n");
  /*printf(arg_glossary(argtable,narg,"   "));*/
  if (strcmp(arg_glossary(argtable,narg,"   "),glossary)!=0)
    exitfail("arg_glossary() failed\n");
  }





int main(void)
  {
  /*-- arg_typestr[] --*/
  test20();

  /*-- arg_convert_bool() --*/
  test30();

  /*-- arg_set_defaults() --*/
  test40();
  test41();

  /*-- arg_catargs() --*/
  test50();

  /*-- arg_checktable() --*/
  test60();
  
  /*-- arg_scanf() --*/
  test70();

  /*-- arg_extract_tag() --*/
  test80a();  

  /*-- arg_sprint_marker() --*/
  test90(0,0,"");
  test90(0,1,"^");
  test90(0,2,"^^");
  test90(1,0," ");
  test90(1,1," ^");
  test90(5,3,"     ^^^");

  /*-- arg_extract_tagged_args() --*/
  test100();
  test110();
  test120();

  /*-- arg_extract_untagged_args() --*/
  test130();
  test140();

  /*-- arg_scanstr() --*/
  test150();

  /*-- arg_scanargv() --*/
  test160();

  /*-- arg_syntax() --*/
  test180();

  /*-- arg_glossary --*/
  test190();

  printf("tests passed ok\n");
  return 0;
  }
