home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume10 / parseargs.p1 < prev    next >
Encoding:
Text File  |  1990-02-20  |  14.9 KB  |  617 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Xenix Support, FICC
  3. subject: v10i075: Patches to parseargs posting
  4. from: peter@ficc.uu.net (Peter da Silva)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 10, Issue 75
  8. Submitted-by: peter@ficc.uu.net (Peter da Silva)
  9. Archive-name: parseargs.p1
  10.  
  11. [A short pause while a large submission accretes... not this one.  ++bsa]
  12.  
  13. This set of patches covers the two complaints with the parseargs version
  14. I sent out a few days ago. First, lists are reversed before returning: I
  15. thought this would be easier on users than going to a doubly-linked list
  16. or circular list. Second, ARGLIST is now a *flag* instead of a type, so
  17. new list arguments can be implemented. I also fixed a potential bug in
  18. unix_args.c.
  19.  
  20. *** post/Makefile
  21. --- Makefile
  22. ***************
  23. *** 15,20 ****
  24. --- 15,21 ----
  25.   
  26.   OFILES=        ckalloc.o \
  27.           argtype.o \
  28. +         arglist.o \
  29.           fp_argtype.o \
  30.           funclist.o \
  31.           openpath.o \
  32. ***************
  33. *** 29,34 ****
  34. --- 30,36 ----
  35.   
  36.   CFILES=        ckalloc.c \
  37.           argtype.c \
  38. +         arglist.c \
  39.           fp_argtype.c \
  40.           funclist.c \
  41.           openpath.c \
  42. *** post/README.PDS
  43. --- README.PDS
  44. ***************
  45. *** 20,54 ****
  46.   The second change was to allow for a trailing list of arguments. I
  47.   originally implemented this by changing the calling sequence to parseargs.
  48.   On reflection this would just produce incompatibilities, so I added a
  49. ! new "type", argList. This handles a pointer to a list of names:
  50.   
  51. ! struct namelist {
  52. !     struct namelist *nl_next;
  53. !     char *nl_name;
  54. ! };
  55.   
  56. ! This is implemented with some "magic" in parseargs, and perhaps it would
  57. ! do better as an additional flag, ARGLIST, and a set of listType routines
  58. ! to handle them. Also, it currently keeps the list in LIFO order. It would
  59. ! be more convenient in FIFO order, though this would take a little more
  60. ! work to implement (basically just stepping through the list in argList to
  61. ! find the tail, instead of inserting at the head), and can be fixed in a
  62. ! single pass after parseargs returns with (say) !argv = reverselist(argv)!:
  63.   
  64. ! struct namelist *reverselist(from)
  65. ! struct namelist *from;
  66. ! {
  67. !     struct namelist *to, *tmp;
  68. !     to = NULL;
  69. !     while(from) {
  70. !         tmp = from->nl_next; /* remove top from old list */
  71. !         from = from->nl_next;
  72. !         tmp->nl_next = to; /* insert top in new list */
  73. !         to = tmp;
  74. !     }
  75. !     return to;
  76. ! }
  77.   
  78.   The final change is the addition of a 'argChar' type. This parses character
  79.   arguments (such as the '-T' option to 'awk'), accepting single characters,
  80. --- 20,36 ----
  81.   The second change was to allow for a trailing list of arguments. I
  82.   originally implemented this by changing the calling sequence to parseargs.
  83.   On reflection this would just produce incompatibilities, so I added a
  84. ! new flag, ARGLIST, and a new type, listStr. Later, other kinds of lists
  85. ! can presumably be added. A list handles a pointer to a list of objects:
  86.   
  87. !     struct arglist *fred;
  88.   
  89. ! Operations are defined on arglists, L_NEXT(fred) produces the next element
  90. ! in fred. L_STRING(fred) produces the value of fred cast to "char *".
  91.   
  92. ! During evaluation the list is kept in LIFO order, and it's reversed just
  93. ! before returning to parseargs. This simplifies the coding of the list
  94. ! routines, but still lets you step through the list in a reasonable order.
  95.   
  96.   The final change is the addition of a 'argChar' type. This parses character
  97.   arguments (such as the '-T' option to 'awk'), accepting single characters,
  98. *** post/amiga_args.c
  99. --- amiga_args.c
  100. ***************
  101. *** 35,42 ****
  102.   #define ALL_AD        ad = argd; ad->ad_name != '\0'; ad++
  103.   #define ALL_DEFS    ad = _DefaultArgs; ad->ad_name != '\0'; ad++
  104.   
  105. ! char    *ProgName;
  106.   
  107.   #ifdef TRACESTUFF
  108.   extern BOOL    argTrace ARGS((ARGDESC *, char *, BOOL));
  109.   #endif
  110. --- 35,44 ----
  111.   #define ALL_AD        ad = argd; ad->ad_name != '\0'; ad++
  112.   #define ALL_DEFS    ad = _DefaultArgs; ad->ad_name != '\0'; ad++
  113.   
  114. ! #define HANDLE(a,n,f) ((*(a)->ad_type)(a,n,f))
  115.   
  116. + char    *ProgName;
  117.   #ifdef TRACESTUFF
  118.   extern BOOL    argTrace ARGS((ARGDESC *, char *, BOOL));
  119.   #endif
  120. ***************
  121. *** 100,106 ****
  122.           if(ad)
  123.           {
  124.               /* try to convert the type */
  125. !             if (!(*ad->ad_type)(ad, *av, FALSE))
  126.                   error = TRUE;
  127.               else
  128.                   ad->ad_flags |= ARGGIVEN;
  129. --- 102,108 ----
  130.           if(ad)
  131.           {
  132.               /* try to convert the type */
  133. !             if (!HANDLE(ad, *av, FALSE))
  134.                   error = TRUE;
  135.               else
  136.                   ad->ad_flags |= ARGGIVEN;
  137. ***************
  138. *** 130,136 ****
  139.               {
  140.                   p++;
  141.                   /* try to convert the type */
  142. !                 if (!(*ad->ad_type)(ad, p, FALSE))
  143.                       error = TRUE;
  144.                   else
  145.                       ad->ad_flags |= ARGGIVEN;
  146. --- 132,138 ----
  147.               {
  148.                   p++;
  149.                   /* try to convert the type */
  150. !                 if (!HANDLE(ad, p, FALSE))
  151.                       error = TRUE;
  152.                   else
  153.                       ad->ad_flags |= ARGGIVEN;
  154. ***************
  155. *** 150,156 ****
  156.                       ad->ad_flags |= ARGGIVEN;
  157.                       ad = NULL;
  158.                   }
  159. !                 else if (ad->ad_type == argList)
  160.                   {
  161.                       list = ad;
  162.                       ad = NULL;
  163. --- 152,158 ----
  164.                       ad->ad_flags |= ARGGIVEN;
  165.                       ad = NULL;
  166.                   }
  167. !                 else if (ad->ad_flags & ARGLIST)
  168.                   {
  169.                       list = ad;
  170.                       ad = NULL;
  171. ***************
  172. *** 160,166 ****
  173.           else /* it's a positional argument */
  174.           {
  175.               if(list) {
  176. !                 if (!argList(list, *av, FALSE))
  177.                       error = TRUE;
  178.                   list->ad_flags |= ARGGIVEN;
  179.                   continue;
  180. --- 162,168 ----
  181.           else /* it's a positional argument */
  182.           {
  183.               if(list) {
  184. !                 if (!HANDLE(list, *av, FALSE))
  185.                       error = TRUE;
  186.                   list->ad_flags |= ARGGIVEN;
  187.                   continue;
  188. ***************
  189. *** 170,176 ****
  190.                   for (ALL_AD)
  191.                   {
  192.                       if (ad->ad_name == ' ' &&
  193. !                         (ad->ad_type == argList ||
  194.                            !BITSET(ARGGIVEN, ad->ad_flags))
  195.                          )
  196.                           break;
  197. --- 172,178 ----
  198.                   for (ALL_AD)
  199.                   {
  200.                       if (ad->ad_name == ' ' &&
  201. !                         ( (ad->ad_flags & ARGLIST) ||
  202.                            !BITSET(ARGGIVEN, ad->ad_flags))
  203.                          )
  204.                           break;
  205. ***************
  206. *** 184,190 ****
  207.                   else
  208.                   {
  209.                       /* try to convert */
  210. !                     if (!(*ad->ad_type)(ad, *av, FALSE))
  211.                           error = TRUE;
  212.                       else
  213.                           ad->ad_flags |= ARGGIVEN;
  214. --- 186,192 ----
  215.                   else
  216.                   {
  217.                       /* try to convert */
  218. !                     if (!HANDLE(ad, *av, FALSE))
  219.                           error = TRUE;
  220.                       else
  221.                           ad->ad_flags |= ARGGIVEN;
  222. ***************
  223. *** 231,236 ****
  224. --- 233,239 ----
  225.           usage(argd);
  226.           exit(20);
  227.       }
  228. +     cleanup_lists(argd);
  229.   }
  230.    /*
  231.   **  USAGE -- print a usage message
  232. ***************
  233. *** 302,308 ****
  234.           }
  235.           if (!BITSET(ARGREQ, ad->ad_flags))
  236.               pl += 2;                /* [ ] */
  237. !         if (ad->ad_type == argList)
  238.               pl += 3;            /* ... */
  239.           pl += 1;                    /* leading sp */
  240.   
  241. --- 305,311 ----
  242.           }
  243.           if (!BITSET(ARGREQ, ad->ad_flags))
  244.               pl += 2;                /* [ ] */
  245. !         if (ad->ad_flags & ARGLIST)
  246.               pl += 3;            /* ... */
  247.           pl += 1;                    /* leading sp */
  248.   
  249. ***************
  250. *** 333,339 ****
  251.               fprintf(stderr, "<%s>", name);
  252.           if (!BITSET(ARGREQ, ad->ad_flags))
  253.               fprintf(stderr, "]");
  254. !         if (ad->ad_type == argList)
  255.               fprintf(stderr, "...");
  256.       }
  257.       fprintf(stderr, "\n");
  258. --- 336,342 ----
  259.               fprintf(stderr, "<%s>", name);
  260.           if (!BITSET(ARGREQ, ad->ad_flags))
  261.               fprintf(stderr, "]");
  262. !         if (ad->ad_flags & ARGLIST)
  263.               fprintf(stderr, "...");
  264.       }
  265.       fprintf(stderr, "\n");
  266. *** post/argtype.c
  267. --- argtype.c
  268. ***************
  269. *** 252,293 ****
  270.   {
  271.       return (FALSE);
  272.   }
  273. - BOOL
  274. - argList(ad, vp, copyf)
  275. -     register ARGDESC *ad;
  276. -     register char *vp;
  277. -     BOOL copyf;
  278. - {
  279. -     char *cp;
  280. -     struct namelist *nl;
  281. -     if (copyf)
  282. -     {
  283. -         register int i;
  284. -         i = strlen(vp) + 1;
  285. -         cp = (char *) malloc(i);
  286. -         if(!cp) {
  287. -             usrerr("out of memory saving string %s", ad->ad_prompt);
  288. -             return FALSE;
  289. -         }
  290. -         bcopy(vp, cp, i);
  291. -     }
  292. -     else
  293. -     {
  294. -         cp = vp;
  295. -     }
  296. -     nl = (struct namelist *) malloc(sizeof *nl);
  297. -     if(!nl) {
  298. -         usrerr("out of memory saving arg %s", ad->ad_prompt);
  299. -         if(copyf) free(cp);
  300. -         return FALSE;
  301. -     }
  302. -     nl->nl_next = *(struct namelist **) ad->ad_valp;
  303. -     nl->nl_name = cp;
  304. -     *(struct namelist **) ad->ad_valp = nl;
  305. -     return (TRUE);
  306. - }
  307. --- 252,254 ----
  308. *** post/parseargs.h
  309. --- parseargs.h
  310. ***************
  311. *** 31,36 ****
  312. --- 31,37 ----
  313.   #define ARGOPT        0x00    /* optional argument pseudo-flag */
  314.   #define ARGHIDDEN    0x02    /* don't display in usage message */
  315.   #define ARGGIVEN    0x08    /* (internal) argument has been specified */
  316. + #define ARGLIST        0x10    /* Argument is a list handler */
  317.   
  318.   /* types available for ad_type */
  319.   extern BOOL    argBool ARGS((ARGDESC *, char *, BOOL));
  320. ***************
  321. *** 41,52 ****
  322.   extern BOOL    argLong ARGS((ARGDESC *, char *, BOOL));
  323.   extern BOOL    argFloat ARGS((ARGDESC *, char *, BOOL));
  324.   extern BOOL    argDouble ARGS((ARGDESC *, char *, BOOL));
  325. ! extern BOOL    argList ARGS((ARGDESC *, char *, BOOL));
  326.   
  327. ! struct namelist {
  328. !     struct namelist *nl_next;
  329. !     char *nl_name;
  330.   };
  331.   
  332.   #define ENDOFARGS    { '\0' }
  333.   
  334. --- 42,56 ----
  335.   extern BOOL    argLong ARGS((ARGDESC *, char *, BOOL));
  336.   extern BOOL    argFloat ARGS((ARGDESC *, char *, BOOL));
  337.   extern BOOL    argDouble ARGS((ARGDESC *, char *, BOOL));
  338. ! extern BOOL    listStr ARGS((ARGDESC *, char *, BOOL));
  339.   
  340. ! struct arglist {
  341. !     struct arglist *nl_next;
  342. !     ARBPTR nl_val;
  343.   };
  344. + #define L_NEXT(l) ((l)->nl_next)        /* Next elt of list */
  345. + #define L_STRING(e) ((char *)((e)->nl_val))    /* Elt as a string */
  346.   
  347.   #define ENDOFARGS    { '\0' }
  348.   
  349. *** post/stest.c
  350. --- stest.c
  351. ***************
  352. *** 18,30 ****
  353.   BOOL    YFlag =        FALSE;
  354.   BOOL    ZFlag =        FALSE;
  355.   char    TabChar =    ':';
  356. ! struct namelist *Argv =    NULL;
  357. ! struct namelist *Groups = NULL;
  358.   
  359.   ARGDESC    Args[] =
  360.   {
  361.       ' ',    ARGREQ,        argStr,        __ &Name,    "Name",
  362. !     'n',    ARGOPT,        argList,    __ &Groups,    "newsGROUP",
  363.       'c',    ARGOPT,        argInt,        __ &RepCount,    "REPcount",
  364.       'd',    ARGOPT,        argStr,        __ &DirName,    "DIRname",
  365.       'x',    ARGOPT,        argBool,    __ &XFlag,    "Xflag",
  366. --- 18,30 ----
  367.   BOOL    YFlag =        FALSE;
  368.   BOOL    ZFlag =        FALSE;
  369.   char    TabChar =    ':';
  370. ! struct arglist *Argv =    NULL;
  371. ! struct arglist *Groups = NULL;
  372.   
  373.   ARGDESC    Args[] =
  374.   {
  375.       ' ',    ARGREQ,        argStr,        __ &Name,    "Name",
  376. !     'n',    ARGOPT|ARGLIST,    listStr,    __ &Groups,    "newsGROUP",
  377.       'c',    ARGOPT,        argInt,        __ &RepCount,    "REPcount",
  378.       'd',    ARGOPT,        argStr,        __ &DirName,    "DIRname",
  379.       'x',    ARGOPT,        argBool,    __ &XFlag,    "Xflag",
  380. ***************
  381. *** 31,37 ****
  382.       'y',    ARGOPT,        argBool,    __ &YFlag,    "Yflag",
  383.       'z',    ARGOPT,        argBool,    __ &ZFlag,    "Zflag",
  384.       't',    ARGOPT,        argChar,    __ &TabChar,    "TABchar",
  385. !     ' ',    ARGOPT,        argList,    __ &Argv,    "File",
  386.       ENDOFARGS
  387.   };
  388.   
  389. --- 31,37 ----
  390.       'y',    ARGOPT,        argBool,    __ &YFlag,    "Yflag",
  391.       'z',    ARGOPT,        argBool,    __ &ZFlag,    "Zflag",
  392.       't',    ARGOPT,        argChar,    __ &TabChar,    "TABchar",
  393. !     ' ',    ARGOPT|ARGLIST,    listStr,    __ &Argv,    "File",
  394.       ENDOFARGS
  395.   };
  396.   
  397. ***************
  398. *** 49,56 ****
  399.       if(Groups) {
  400.           printf("Newsgroups: ");
  401.           while(Groups) {
  402. !             printf("%s", Groups->nl_name);
  403. !             Groups = Groups->nl_next;
  404.               if(Groups)
  405.                   putchar(' ');
  406.               else
  407. --- 49,56 ----
  408.       if(Groups) {
  409.           printf("Newsgroups: ");
  410.           while(Groups) {
  411. !             printf("%s", L_STRING(Groups));
  412. !             Groups = L_NEXT(Groups);
  413.               if(Groups)
  414.                   putchar(' ');
  415.               else
  416. ***************
  417. *** 61,68 ****
  418.       if(Argv) {
  419.           printf("Remaining args: ");
  420.           while(Argv) {
  421. !             printf("%s", Argv->nl_name);
  422. !             Argv = Argv->nl_next;
  423.               if(Argv)
  424.                   putchar(' ');
  425.               else
  426. --- 61,68 ----
  427.       if(Argv) {
  428.           printf("Remaining args: ");
  429.           while(Argv) {
  430. !             printf("%s", L_STRING(Argv));
  431. !             Argv = L_NEXT(Argv);
  432.               if(Argv)
  433.                   putchar(' ');
  434.               else
  435. *** post/unix_args.c
  436. --- unix_args.c
  437. ***************
  438. *** 35,42 ****
  439.   #define ALL_AD        ad = argd; ad->ad_name != '\0'; ad++
  440.   #define ALL_DEFS    ad = _DefaultArgs; ad->ad_name != '\0'; ad++
  441.   
  442. ! char    *ProgName;
  443.   
  444.   #ifdef TRACESTUFF
  445.   extern BOOL    argTrace ARGS((ARGDESC *, char *, BOOL));
  446.   #endif
  447. --- 35,44 ----
  448.   #define ALL_AD        ad = argd; ad->ad_name != '\0'; ad++
  449.   #define ALL_DEFS    ad = _DefaultArgs; ad->ad_name != '\0'; ad++
  450.   
  451. ! #define HANDLE(a,n,f) ((*(a)->ad_type)(a,n,f))
  452.   
  453. + char    *ProgName;
  454.   #ifdef TRACESTUFF
  455.   extern BOOL    argTrace ARGS((ARGDESC *, char *, BOOL));
  456.   #endif
  457. ***************
  458. *** 176,186 ****
  459.                   }
  460.   
  461.                   /* try to convert the type */
  462. !                 if (!(*ad->ad_type)(ad, p, FALSE))
  463.                       error = TRUE;
  464.                   else
  465.                       ad->ad_flags |= ARGGIVEN;
  466. !                 if(ad->ad_type == argList)
  467.                       list = ad;
  468.                   else
  469.                       list = NULL;
  470. --- 178,188 ----
  471.                   }
  472.   
  473.                   /* try to convert the type */
  474. !                 if (!HANDLE(ad, p, FALSE))
  475.                       error = TRUE;
  476.                   else
  477.                       ad->ad_flags |= ARGGIVEN;
  478. !                 if(ad->ad_flags & ARGLIST)
  479.                       list = ad;
  480.                   else
  481.                       list = NULL;
  482. ***************
  483. *** 191,197 ****
  484.           {
  485.               /* parsing a list of arguments */
  486.               if(list) {
  487. !                 if (!argList(list, p, FALSE))
  488.                       error = TRUE;
  489.                   continue;
  490.               }
  491. --- 193,199 ----
  492.           {
  493.               /* parsing a list of arguments */
  494.               if(list) {
  495. !                 if (!HANDLE(list, p, FALSE))
  496.                       error = TRUE;
  497.                   continue;
  498.               }
  499. ***************
  500. *** 199,205 ****
  501.               for (ALL_AD)
  502.               {
  503.                   if (ad->ad_name == ' ' &&
  504. !                     (ad->ad_type == argList ||
  505.                        !BITSET(ARGGIVEN, ad->ad_flags))
  506.                       )
  507.                       break;
  508. --- 201,207 ----
  509.               for (ALL_AD)
  510.               {
  511.                   if (ad->ad_name == ' ' &&
  512. !                     ( (ad->ad_flags & ARGLIST) ||
  513.                        !BITSET(ARGGIVEN, ad->ad_flags))
  514.                       )
  515.                       break;
  516. ***************
  517. *** 212,218 ****
  518.               }
  519.   
  520.               /* try to convert */
  521. !             if (!(*ad->ad_type)(ad, p, FALSE))
  522.                   error = TRUE;
  523.               else
  524.                   ad->ad_flags |= ARGGIVEN;
  525. --- 214,220 ----
  526.               }
  527.   
  528.               /* try to convert */
  529. !             if (!HANDLE(ad, p, FALSE))
  530.                   error = TRUE;
  531.               else
  532.                   ad->ad_flags |= ARGGIVEN;
  533. ***************
  534. *** 242,248 ****
  535.                       usrerr("value required");
  536.                       continue;
  537.                   }
  538. !                 if ((*ad->ad_type)(ad, buf, TRUE))
  539.                   {
  540.                       ad->ad_flags |= ARGGIVEN;
  541.                       break;
  542. --- 244,250 ----
  543.                       usrerr("value required");
  544.                       continue;
  545.                   }
  546. !                 if (HANDLE(ad, buf, TRUE))
  547.                   {
  548.                       ad->ad_flags |= ARGGIVEN;
  549.                       break;
  550. ***************
  551. *** 274,280 ****
  552.           exit(2);
  553.       }
  554.   
  555. !     return argc;
  556.   }
  557.    /*
  558.   **  USAGE -- print a usage message
  559. --- 276,282 ----
  560.           exit(2);
  561.       }
  562.   
  563. !     cleanup_lists(argd);
  564.   }
  565.    /*
  566.   **  USAGE -- print a usage message
  567. ***************
  568. *** 327,333 ****
  569.           }
  570.           if (!BITSET(ARGREQ, ad->ad_flags))
  571.               pl += 2;                /* [ ] */
  572. !         if (ad->ad_type == argList)            /* ... */
  573.               pl += 3;
  574.           pl += 1;                    /* leading sp */
  575.   
  576. --- 329,335 ----
  577.           }
  578.           if (!BITSET(ARGREQ, ad->ad_flags))
  579.               pl += 2;                /* [ ] */
  580. !         if (ad->ad_flags & ARGLIST)            /* ... */
  581.               pl += 3;
  582.           pl += 1;                    /* leading sp */
  583.   
  584. ***************
  585. *** 358,364 ****
  586.               fprintf(stderr, "<%s>", ad->ad_prompt);
  587.           if (!BITSET(ARGREQ, ad->ad_flags))
  588.               fprintf(stderr, "]");
  589. !         if (ad->ad_type == argList)
  590.               fprintf(stderr, "...");
  591.       }
  592.       fprintf(stderr, "\n");
  593. --- 360,366 ----
  594.               fprintf(stderr, "<%s>", ad->ad_prompt);
  595.           if (!BITSET(ARGREQ, ad->ad_flags))
  596.               fprintf(stderr, "]");
  597. !         if (ad->ad_flags & ARGLIST)
  598.               fprintf(stderr, "...");
  599.       }
  600.       fprintf(stderr, "\n");
  601. -- 
  602.  _--_|\  Peter da Silva. +1 713 274 5180. <peter@ficc.uu.net>.
  603. /      \
  604. \_.--._/ Xenix Support -- it's not just a job, it's an adventure!
  605.       v  "Have you hugged your wolf today?" `-_-'
  606.  
  607.  
  608.