home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume10 / parsergs.p1 < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  15.2 KB

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