"Fossies" - the Fresh Open Source Software Archive

Member "parsearg.c" (9 May 1995, 14271 Bytes) of package /linux/misc/old/cpost.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "parsearg.c" see the Fossies "Dox" file reference documentation.

    1 /*------------------------------------------------------------------*/
    2 /* parsearg : parse parameters and options in an argv list          */
    3 /*            see parsearg.h for a description                      */
    4 /*------------------------------------------------------------------*/
    5 /* 03-13-90 originally by Patrick J. Mueller                        */
    6 /* 01-09-91 version 2.0 by Patrick J. Mueller                       */
    7 /* 04-29-91 version 3.0 by Patrick J. Mueller                       */
    8 /*------------------------------------------------------------------*/
    9 
   10 #include <stdio.h>
   11 #include <stdlib.h>
   12 #include <stdarg.h>
   13 #include <string.h>
   14 #include <ctype.h>
   15 
   16 /*------------------------------------------------------------------*/
   17 /* typedefs                                                         */
   18 /*------------------------------------------------------------------*/
   19 typedef enum
   20    {
   21    Boolean_Switch,
   22    Variable_Switch
   23    } Item_Type;
   24 
   25 typedef struct Cmdline_Item
   26    {
   27    Item_Type             type;
   28    int                   position;
   29    char                  sw_char;
   30    void                 *variable;
   31    struct Cmdline_Item  *next;
   32    } Cmdline_Item;
   33 
   34 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
   35 /*------------------------------------------------------------------*/
   36 /*               L O C A L   F U N C T I O N S                      */
   37 /*------------------------------------------------------------------*/
   38 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
   39 
   40 /*------------------------------------------------------------------*/
   41 /* Search the Cmdline_Item list for a particular switch.  Look for  */
   42 /* the option with a particular switch character (Boolean and       */
   43 /* Variable are treated as the same)                                */
   44 /*------------------------------------------------------------------*/
   45 
   46 static Cmdline_Item *get_item(
   47    Cmdline_Item *head,
   48    char          sw_char,
   49    int           case_sense
   50    )
   51 
   52    {
   53    Cmdline_Item *next;
   54 
   55    /*---------------------------------------------------------------*/
   56    /* traverse the linked list ...                                  */
   57    /*---------------------------------------------------------------*/
   58    next = head;
   59    while (next != NULL)
   60       {
   61       /*------------------------------------------------------------*/
   62       /* for case sensitive switches, just compare chars            */
   63       /*------------------------------------------------------------*/
   64       if (case_sense)
   65          {
   66          if (next->sw_char == sw_char)
   67             return(next);
   68          }
   69 
   70       /*------------------------------------------------------------*/
   71       /* otherwise, toupper the chars and compare                   */
   72       /*------------------------------------------------------------*/
   73       else
   74          {
   75          if (toupper(sw_char) == toupper(next->sw_char))
   76             return(next);
   77          }
   78 
   79       /*------------------------------------------------------------*/
   80       /* no matches so traverse to next item                        */
   81       /*------------------------------------------------------------*/
   82       next = next->next;
   83       }
   84 
   85    /*---------------------------------------------------------------*/
   86    /* no matches at all!                                            */
   87    /*---------------------------------------------------------------*/
   88    return(NULL);
   89    }
   90 
   91 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
   92 /*------------------------------------------------------------------*/
   93 /*               M A I N     F U N C T I O N                        */
   94 /*------------------------------------------------------------------*/
   95 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
   96 
   97 /*------------------------------------------------------------------*/
   98 /* the main function                                                */
   99 /*------------------------------------------------------------------*/
  100 void parsearg(
  101    int    *argc,
  102    char  **argv,
  103    int     case_sense,
  104    char   *env_var,
  105    char   *delimiters,
  106    char   *format_string,
  107    ...
  108    )
  109 
  110    {
  111    char         *tok;
  112    Cmdline_Item *item_head;
  113    Cmdline_Item *item_tail;
  114    Cmdline_Item *item;
  115    va_list       arg_marker;
  116    int           i;
  117    int           parms;
  118    int          *ptr_int;
  119    char        **ptr_ptr_char;
  120    char          sw_char;
  121    char         *env_value;
  122    int           envc;
  123    char         *envv;
  124    char         *temp;
  125 
  126    /*---------------------------------------------------------------*/
  127    /* sanity checks                                                 */
  128    /*---------------------------------------------------------------*/
  129    if ((NULL == format_string)  ||
  130        (NULL == argv)           ||
  131        (0    == *argc))
  132       return;
  133 
  134    /*---------------------------------------------------------------*/
  135    /* make a copy of the format string since we will be strtok()ing */
  136    /* through it                                                    */
  137    /*---------------------------------------------------------------*/
  138    temp = malloc(1+strlen(format_string));
  139    if (NULL == temp)
  140       {
  141       puts("Error allocating memory in parsearg()");
  142       return;
  143       }
  144 
  145    strcpy(temp,format_string);
  146    format_string = temp;
  147 
  148    /*---------------------------------------------------------------*/
  149    /* get environment variable value                                */
  150    /*---------------------------------------------------------------*/
  151    env_value = NULL;
  152 
  153    if (NULL != env_var)
  154       if ('\0' != *env_var)
  155          {
  156 
  157          /*---------------------------------------------------------*/
  158          /* get value and copy if we found something                */
  159          /*---------------------------------------------------------*/
  160          env_value = getenv(env_var);
  161 
  162          if (NULL != env_value)
  163             {
  164             temp = malloc(1+strlen(env_value));
  165             if (NULL == temp)
  166                {
  167                puts("Error allocating memory in parsearg()");
  168                return;
  169                }
  170 
  171             strcpy(temp,env_value);
  172             env_value = temp;
  173             }
  174          }
  175 
  176    /*---------------------------------------------------------------*/
  177    /* build option list                                             */
  178    /*---------------------------------------------------------------*/
  179    item_head = item_tail = NULL;
  180    va_start(arg_marker,format_string);
  181 
  182    /*---------------------------------------------------------------*/
  183    /* parse the format_string with strtok                           */
  184    /*---------------------------------------------------------------*/
  185    tok = strtok(format_string," ");
  186 
  187    while (NULL != tok)
  188       {
  189       /*------------------------------------------------------------*/
  190       /* allocate area for a new Item                               */
  191       /*------------------------------------------------------------*/
  192       item = (Cmdline_Item *) malloc(sizeof(Cmdline_Item));
  193       if (NULL == item)
  194          {
  195          puts("Error allocating memory in parsearg()");
  196          return;
  197          }
  198 
  199       /*------------------------------------------------------------*/
  200       /* start assigning values to it                               */
  201       /*------------------------------------------------------------*/
  202       item->next    = NULL;
  203       item->sw_char = *tok++;
  204 
  205       /*---------------------------------------------------------*/
  206       /* is it a boolean switch?                                 */
  207       /*---------------------------------------------------------*/
  208       if ('\0' == *tok)
  209          item->type = Boolean_Switch;
  210 
  211       /*---------------------------------------------------------*/
  212       /* must be a variable switch                               */
  213       /*---------------------------------------------------------*/
  214       else
  215          item->type = Variable_Switch;
  216 
  217       /*------------------------------------------------------------*/
  218       /* now get the variable pointer                               */
  219       /*------------------------------------------------------------*/
  220       item->variable = va_arg(arg_marker,void *);
  221 
  222       /*------------------------------------------------------------*/
  223       /* initialize boolean switches to 0                           */
  224       /*------------------------------------------------------------*/
  225       if (Boolean_Switch == item->type)
  226          {
  227          ptr_int  = item->variable;
  228          *ptr_int = 0;
  229          }
  230 
  231       /*------------------------------------------------------------*/
  232       /* and variable switches to NULL                              */
  233       /*------------------------------------------------------------*/
  234       else
  235          {
  236          ptr_ptr_char  = item->variable;
  237          *ptr_ptr_char = NULL;
  238          }
  239 
  240       /*------------------------------------------------------------*/
  241       /* now insert into list (at end)                              */
  242       /*------------------------------------------------------------*/
  243       if (NULL == item_head)
  244          item_head = item_tail = item;
  245 
  246       else
  247          {
  248          item_tail->next = item;
  249          item_tail       = item;
  250          }
  251 
  252       /*------------------------------------------------------------*/
  253       /* get next item in format_string                             */
  254       /*------------------------------------------------------------*/
  255       tok = strtok(NULL," ");
  256       }
  257 
  258    /*---------------------------------------------------------------*/
  259    /* now we've set up the format_string.  time to step through the */
  260    /* args to set the switches on and off and to scanf through      */
  261    /* variable switches and parameters                              */
  262    /*---------------------------------------------------------------*/
  263 
  264    /*---------------------------------------------------------------*/
  265    /* assign argc to parms and initialize argc to 0                 */
  266    /*---------------------------------------------------------------*/
  267    parms = *argc;
  268    *argc = 0;
  269 
  270    /*---------------------------------------------------------------*/
  271    /* We want to check the environment variables first.  Try to get */
  272    /* the first item with strtok (if we had anything to begin with. */
  273    /* If we have anything, set envv to the value and set env to 1.  */
  274    /*---------------------------------------------------------------*/
  275    envc = 0;
  276    envv = NULL;
  277 
  278    if (NULL != env_value)
  279       {
  280       envv = strtok(env_value," ");
  281       if (NULL != envv)
  282          envc = 1;
  283       }
  284 
  285    /*---------------------------------------------------------------*/
  286    /* now loop through the environment variables and arguments      */
  287    /* setting the appropriate value in the CmdLine_Item list.       */
  288    /*---------------------------------------------------------------*/
  289    for (i = 0; i < envc + parms; i++)
  290       {
  291       if (NULL != envv)
  292          tok = envv;
  293 
  294       else
  295          tok = argv[i-envc];
  296 
  297       /*------------------------------------------------------------*/
  298       /* if it's a parameter, assign it to next argv pointer        */
  299       /*------------------------------------------------------------*/
  300       if (('\0' == *tok) || (NULL == strchr(delimiters,*tok)))
  301          {
  302 
  303          /*---------------------------------------------------------*/
  304          /* we don't want to handle environment values though       */
  305          /*---------------------------------------------------------*/
  306          if (NULL == envv)
  307             {
  308             argv[*argc] = tok;
  309             (*argc)++;
  310             }
  311          }
  312 
  313       /*------------------------------------------------------------*/
  314       /* otherwise it's a switch                                    */
  315       /*------------------------------------------------------------*/
  316       else
  317          {
  318          tok++;
  319 
  320 parse_switches:
  321          sw_char = *tok++;
  322 
  323          /*---------------------------------------------------------*/
  324          /* is it a switch?                                         */
  325          /*---------------------------------------------------------*/
  326          item = get_item(item_head,sw_char,case_sense);
  327 
  328          if (NULL != item)
  329             {
  330             /*------------------------------------------------------*/
  331             /* it's a switch, but is it variable or boolean?        */
  332             /*------------------------------------------------------*/
  333             if (Variable_Switch == item->type)
  334                {
  335                ptr_ptr_char  = item->variable;
  336                *ptr_ptr_char = tok;
  337                }
  338 
  339             else
  340                {
  341                ptr_int  = item->variable;
  342                *ptr_int = 1;
  343 
  344                /*---------------------------------------------------*/
  345                /* handle multiple switches concatenated             */
  346                /*---------------------------------------------------*/
  347                if ('\0' != *tok)
  348                   goto parse_switches;
  349                }
  350             }
  351 
  352          }
  353 
  354       /*------------------------------------------------------------*/
  355       /* now get the next environment value if we need to           */
  356       /*------------------------------------------------------------*/
  357       if (NULL != envv)
  358          {
  359          envv = strtok(NULL," ");
  360          if (NULL != envv)
  361             envc++;
  362          }
  363 
  364       }
  365 
  366    /*---------------------------------------------------------------*/
  367    /* now release all the memory we used                            */
  368    /*---------------------------------------------------------------*/
  369    item = item_head;
  370    while (NULL != item)
  371       {
  372       item_head = item->next;
  373       free(item);
  374       item = item_head;
  375       }
  376 
  377    free(format_string);
  378 
  379    /*---------------------------------------------------------------*/
  380    /* don't release this memory as we may have set pointers into it */
  381    /* I guess if we wanted to be >real< tricky we could somehow     */
  382    /* return pointers into the original string ... nah!!!           */
  383    /*---------------------------------------------------------------*/
  384 #if defined(SHOOT_YOURSELF_IN_THE_FOOT)
  385    if (NULL != env_value)
  386       free(env_value);
  387 #endif
  388 
  389    return;
  390    }
  391