home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / rolodex / part3 / toolsdir / args.c next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  8.4 KB  |  334 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include "basics.h"
  4. #include "args.h"        
  5. #include "sys5.h"
  6.  
  7. /***************************************************************************/
  8. /***************************************************************************/
  9.  
  10.            /*****     COMMAND LINE ARGUMENT PARSER    *****/
  11.  
  12. /***************************************************************************/
  13. /***************************************************************************/
  14.  
  15. /* Author: JP Massar */
  16.  
  17. /* parses command line arguments in argv under the following rules: */
  18. /* any argument not beginning with '-' is treated as a unit. */
  19. /* any argument beginning with a '-' must have the remaining characters */
  20. /* be in the set {a-zA-Z}.  Each character is considered a separate option. */
  21. /* (Thus -abc is equivalent to -a -b -c).  Non-dashed arguments are */
  22. /* associated with the option that precedes them, e.g, 'cat -a foo -b bar' */
  23. /* has foo associated with 'a' and bar associated with 'b'.  A non-dashed */
  24. /* argument preceding any option is not associated with any option. */
  25. /* users can specify whether duplicate options are errors. */
  26.  
  27. /* Non-dashed arguments are henceforth referred to as arguments, and */
  28. /* dashed arguments are henceforth referred to as options. */
  29. /* Arguments are ordered from left to right. */
  30.  
  31. /* The following routines are available to users: */
  32.  
  33. /* get_args()           called to parse argv.  Detects syntactic errors */
  34. /* any_option_present() are any options present in the command line? */
  35. /* option_present()     is an option present? */
  36. /* option_arg()         returns an argument associated with an option */
  37. /* non_option_arg()     returns an argument not associated with any option */
  38. /* non_dash_arg()       returns an argument */
  39. /* n_option_args()      returns number of args associated with an option */
  40. /* n_non_option_args()  rtns number of args not associated with any option */
  41. /* n_non_dash_args()    returns number of arguments. */
  42. /* check_option_args()  checks bounds on number of args assoc with an option */
  43. /* legal_options()      checks that options provided are a subset of a-zA-Z */
  44. /* set_option()         turns on option */
  45. /* error_message()      prints out an illegal syntax error message to stderr */
  46.  
  47.  
  48. int option_to_index (achar) char achar;
  49. {
  50.   if (isupper(achar)) return(achar - 'A');
  51.   if (islower(achar)) return(achar - 'a' + 26);
  52.   return(NO_OPTION);
  53. }
  54.  
  55. char index_to_option (index) int index;
  56. {        
  57.   if (index < 26) return('A' + index);
  58.   return('a' + index - 26);
  59. }  
  60.  
  61.  
  62. /* the command line arguments are parsed into Cmd when get_args returns */
  63. /* successfully */
  64.  
  65. static Ptr_Cmd_Line Cmd = NIL;
  66.  
  67. int get_args (argc, argv, dup_error, print_msg)
  68.         
  69.   /* Returns one of NO_ARGS, ARG_ERROR, or ARGS_PRESENT */
  70.  
  71.   int argc;
  72.   char **argv;
  73.   Bool print_msg, dup_error;
  74.  
  75. {
  76.   int i,j,dash_index;
  77.   Ptr_Cmd_Arg arg,last = NIL;
  78.   char echar, *optr;
  79.  
  80.   Cmd = (Ptr_Cmd_Line) malloc(sizeof(Cmd_Line));
  81.   Cmd -> non_dash_arg_list = NIL;
  82.   for (j = 0; j < MAX_OPTIONS; j++) (Cmd -> dash_options)[j] = F;
  83.  
  84.   if (argc == 1) return(NO_ARGS);
  85.  
  86.   i = 0;
  87.   dash_index = NO_OPTION;
  88.   
  89.   while (++i < argc) {
  90.         
  91.         /* parse arguments (i.e., anything not beginning with '-' */
  92.         
  93.         if (argv[i][0] != '-') {
  94.                 arg = (Ptr_Cmd_Arg) malloc(sizeof(Cmd_Arg));
  95.                 arg -> option = argv[i];
  96.                 arg -> option_index = dash_index;
  97.                 arg -> next = NIL;
  98.                 if (last == NIL) {
  99.                         Cmd -> non_dash_arg_list = arg;
  100.                         last = arg;
  101.                 }                
  102.                 else {
  103.                         last -> next = arg;
  104.                         last = arg;
  105.                 }
  106.                 continue;
  107.         }
  108.  
  109.         /* parse options. '-' by itself is illegal syntax */
  110.         
  111.         if (strlen(argv[i]) < 2) {
  112.                 echar = '-';
  113.                 goto parse_error;
  114.         }        
  115.         optr = argv[i];
  116.         optr++;
  117.         while (*optr != '\0') {
  118.                 if (NO_OPTION == (dash_index = option_to_index(*optr))) {
  119.                         echar = *optr;
  120.                         goto parse_error;
  121.                 };
  122.                 if ((Cmd -> dash_options)[dash_index] && dup_error) {
  123.                         echar = *optr;
  124.                         goto duplicate_error;
  125.                 }
  126.                 (Cmd -> dash_options)[dash_index] = T;
  127.                 optr++;
  128.         }
  129.  
  130.   }
  131.  
  132.   return(ARGS_PRESENT);
  133.  
  134.   parse_error :
  135.  
  136.   if (print_msg) fprintf(stderr,"illegal option: %c\n",echar);
  137.   return(ARG_ERROR);
  138.  
  139.   duplicate_error:
  140.  
  141.   if (print_msg) fprintf(stderr,"duplicate option: %c\n",echar);
  142.   return(ARG_ERROR);
  143.  
  144. }  
  145.  
  146.  
  147. Bool option_present (achar) char achar;
  148. {        
  149.   return((Cmd -> dash_options)[option_to_index(achar)]);
  150. }
  151.  
  152.  
  153. Bool any_option_present ()
  154. {
  155.   int j;
  156.   for (j = 0; j < MAX_OPTIONS; j++) {
  157.       if ((Cmd -> dash_options)[j]) return(T);
  158.   }      
  159.   return(F);
  160. }  
  161.  
  162.   
  163. char * get_option_arg (i,n) int i; int n;
  164.  
  165.   /* get the nth option associated with the option whose index is 'i' */
  166.         
  167. {
  168.   int count;
  169.   Ptr_Cmd_Arg args;        
  170.   args = Cmd -> non_dash_arg_list;  
  171.   count = 0;
  172.   while (args != NIL) {
  173.         if (i == args -> option_index && ++count == n) {
  174.                 return(args -> option);
  175.         }
  176.         args = args -> next;
  177.   }
  178.   return(NIL);
  179. }  
  180.  
  181.  
  182. char * option_arg (achar,n) char achar; int n;
  183. {
  184.   return(get_option_arg(option_to_index(achar),n));
  185. }
  186.  
  187.  
  188. char * non_option_arg (n) int n;
  189. {
  190.   return(get_option_arg(NO_OPTION,n));
  191. }  
  192.  
  193.  
  194. char * non_dash_arg (n) int n;
  195.  
  196. {
  197.   int count = 0;
  198.   Ptr_Cmd_Arg arg;
  199.   arg = Cmd -> non_dash_arg_list;
  200.   while (arg != NIL) {
  201.         if (++count == n) return(arg -> option);
  202.         arg = arg -> next;
  203.   }
  204.   return(NIL);
  205. }
  206.  
  207. print_args ()
  208.  
  209.   /* debugging routine which prints out the Cmd structure in readable form */
  210.  
  211. {
  212.   int j,i,n;
  213.   char *option,ochar;
  214.  
  215.   if (Cmd == NIL) {
  216.         printf("\n\nNo arguments\n\n");
  217.         return;
  218.   }        
  219.   
  220.   printf("\n\narguments not associated with options: ");
  221.   n = 1;
  222.   while (T) {
  223.         if (NIL == (option = non_option_arg(n++))) break;
  224.         printf("%s ",option);
  225.   }
  226.   printf("\n");
  227.  
  228.   printf("\n\noptions and their arguments:\n\n");
  229.   for (j = 0; j < MAX_OPTIONS; j++) {
  230.       ochar = index_to_option(j);
  231.       if (option_present(ochar)) {
  232.          printf("%c : \t",ochar);
  233.          i = 1;
  234.          while (T) {
  235.            if (NIL == (option = option_arg(ochar,i++))) break;
  236.            printf("%s ",option);
  237.          }
  238.          printf("     \t(# is %d)",n_option_args(ochar));
  239.          printf("\n");
  240.       }
  241.   }
  242.  
  243.   printf("\nnumber of non-dashed args is: %d\n",n_non_dash_args());
  244.   printf("number of non-option args is  : %d\n",n_non_option_args());
  245.   
  246. }
  247.  
  248.  
  249. #define ALL -1
  250. #define NON_OPTION -2
  251.  
  252. int arg_counter (type) int type;
  253.  
  254.   /* general routine which counts arguments */
  255.   /* if type isn't ALL or NON_OPTION then type is an index of an option */
  256.  
  257. {
  258.   int index,count;
  259.   Ptr_Cmd_Arg arg;
  260.   arg = Cmd -> non_dash_arg_list;        
  261.   count = 0;
  262.   index = (type == NON_OPTION) ? NO_OPTION : type;
  263.   while (arg != NIL) {
  264.         if (type == ALL) {
  265.                 count++;
  266.         }
  267.         else if (arg -> option_index == index) count++;
  268.         arg = arg -> next;
  269.   }
  270.   return(count);
  271. }
  272.  
  273. int n_option_args (achar) char achar;
  274. {        
  275.   return(arg_counter(option_to_index(achar)));
  276. }
  277.  
  278. int n_non_option_args ()
  279. {
  280.   return(arg_counter(NON_OPTION));
  281. }
  282.  
  283. int n_non_dash_args ()
  284. {
  285.   return(arg_counter(ALL));
  286. }
  287.  
  288.  
  289. set_option (achar) char achar;
  290. {
  291.   (Cmd -> dash_options)[option_to_index(achar)] = T;
  292. }
  293.  
  294.  
  295. error_message (progname, argv, i, usage)
  296.         char *progname; char ** argv; int i; char *usage;
  297. {
  298.   fprintf(stderr,"\nillegal argument to %s : %s\n",progname,argv[i]);
  299.   if (usage) fprintf(stderr,"%s\n",usage);
  300. }
  301.  
  302.  
  303. Bool
  304. check_option_args (achar,themin,themax) char achar; int themin,themax;
  305. {
  306.   int n;
  307.   if (themin > themax) return(T);
  308.   n = n_option_args(achar);
  309.   return ((Bool) (n >= themin && n <= themax));
  310. }
  311.  
  312.  
  313. char legal_options (legalstring) char *legalstring;
  314.  
  315.   /* are all the options the user specified characters in legalstring? */
  316.   /* returns ALL_LEGAL if so, otherwise the first option not in the string */
  317.  
  318. {
  319.   int j;
  320.   char option, *s;
  321.   for (j = 0; j < MAX_OPTIONS; j++) {
  322.       if ((Cmd -> dash_options)[j]) {
  323.          option = index_to_option(j);
  324.          s = legalstring;
  325.          while (T) {
  326.                if (*s == '\0') return(option);
  327.                if (*s == option) break;
  328.                s++;
  329.          }
  330.       }
  331.   }
  332.   return(ALL_LEGAL);
  333. }
  334.