home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 19 Printer / 19-Printer.zip / cpostsrc.zip / PARSEARG.C < prev    next >
C/C++ Source or Header  |  1992-12-04  |  15KB  |  392 lines

  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.  
  392.