"Fossies" - the Fresh Open Source Software Archive

Member "mlr-5.6.2/c/cli/argparse.c" (25 Aug 2019, 6641 Bytes) of package /linux/misc/mlr-5.6.2.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 "argparse.c" see the Fossies "Dox" file reference documentation.

    1 #include <stdio.h>
    2 #include "lib/mlrutil.h"
    3 #include "cli/argparse.h"
    4 
    5 // ================================================================
    6 typedef enum _ap_flag_t {
    7     AP_INT_VALUE_FLAG,
    8     AP_INT_FLAG,
    9     AP_LONG_LONG_FLAG,
   10     AP_DOUBLE_FLAG,
   11     AP_STRING_FLAG,
   12     AP_STRING_BUILD_LIST_FLAG,
   13     AP_STRING_LIST_FLAG,
   14     AP_STRING_ARRAY_FLAG
   15 } ap_flag_t;
   16 
   17 typedef struct _ap_flag_def_t {
   18     char*     flag_name;
   19     ap_flag_t type;
   20     int       intval;
   21     void*     pval;
   22     int       count; // 1 for bool flags; 2 for the rest
   23 } ap_flag_def_t;
   24 
   25 static ap_flag_def_t* ap_find(ap_state_t* pstate, char* flag_name) {
   26     for (sllve_t* pe = pstate->pflag_defs->phead; pe != NULL; pe = pe->pnext) {
   27         ap_flag_def_t* pdef = pe->pvvalue;
   28         if (streq(pdef->flag_name, flag_name))
   29             return pdef;
   30     }
   31     return NULL;
   32 }
   33 
   34 static ap_flag_def_t* ap_flag_def_alloc(char* flag_name, ap_flag_t ap_type, int intval, void* pval, int count) {
   35     ap_flag_def_t* pdef = mlr_malloc_or_die(sizeof(ap_flag_def_t));
   36     pdef->flag_name = flag_name;
   37     pdef->type      = ap_type;
   38     pdef->intval    = intval;
   39     pdef->pval      = pval;
   40     pdef->count     = count;
   41     return pdef;
   42 }
   43 
   44 // ================================================================
   45 ap_state_t* ap_alloc() {
   46     ap_state_t* pstate = mlr_malloc_or_die(sizeof(ap_state_t));
   47     pstate->pflag_defs = sllv_alloc();
   48 
   49     return pstate;
   50 }
   51 
   52 void ap_free(ap_state_t* pstate) {
   53     if (pstate == NULL)
   54         return;
   55 
   56     for (sllve_t* pe = pstate->pflag_defs->phead; pe != NULL; pe = pe->pnext) {
   57         ap_flag_def_t* pdef = pe->pvvalue;
   58 
   59         // Linked-lists are pointed to by mappers and freed by their free
   60         // methods.  If any mappers miss on that contract, we can find out by
   61         // using valgrind --leak-check=full (e.g. reg_test/run --valgrind).
   62         //
   63         //if (pdef->type == AP_STRING_LIST_FLAG && pdef->pval != NULL) {
   64         //  slls_t** pplist = pdef->pval;
   65         //  slls_free(*pplist);
   66         //}
   67 
   68         free(pdef);
   69     }
   70     sllv_free(pstate->pflag_defs);
   71 
   72     free(pstate);
   73 }
   74 
   75 // ----------------------------------------------------------------
   76 void ap_define_true_flag(ap_state_t* pstate, char* flag_name, int* pintval) {
   77     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_VALUE_FLAG, TRUE, pintval, 1));
   78 }
   79 
   80 void ap_define_false_flag(ap_state_t* pstate, char* flag_name, int* pintval) {
   81     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_VALUE_FLAG, FALSE, pintval, 1));
   82 }
   83 
   84 void ap_define_int_value_flag(ap_state_t* pstate, char* flag_name, int intval, int* pintval) {
   85     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_VALUE_FLAG, intval, pintval, 1));
   86 }
   87 
   88 void ap_define_int_flag(ap_state_t* pstate, char* flag_name, int* pintval) {
   89     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_INT_FLAG, 0, pintval, 2));
   90 }
   91 void ap_define_long_long_flag(ap_state_t* pstate, char* flag_name, long long* pintval) {
   92     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_LONG_LONG_FLAG, 0, pintval, 2));
   93 }
   94 
   95 void ap_define_float_flag(ap_state_t* pstate, char* flag_name, double* pdoubleval) {
   96     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_DOUBLE_FLAG, 0, pdoubleval, 2));
   97 }
   98 
   99 void ap_define_string_flag(ap_state_t* pstate, char* flag_name, char** pstring) {
  100     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_FLAG, 0, pstring, 2));
  101 }
  102 
  103 void ap_define_string_build_list_flag(ap_state_t* pstate, char* flag_name, slls_t** pplist) {
  104     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_BUILD_LIST_FLAG, 0, pplist, 2));
  105 }
  106 
  107 void ap_define_string_list_flag(ap_state_t* pstate, char* flag_name, slls_t** pplist) {
  108     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_LIST_FLAG, 0, pplist, 2));
  109 }
  110 
  111 void ap_define_string_array_flag(ap_state_t* pstate, char* flag_name, string_array_t** pparray) {
  112     sllv_append(pstate->pflag_defs, ap_flag_def_alloc(flag_name, AP_STRING_ARRAY_FLAG, 0, pparray, 2));
  113 }
  114 
  115 // ----------------------------------------------------------------
  116 int ap_parse(ap_state_t* pstate, char* verb, int* pargi, int argc, char** argv) {
  117     return ap_parse_aux(pstate, verb, pargi, argc, argv, TRUE);
  118 }
  119 
  120 int ap_parse_aux(ap_state_t* pstate, char* verb, int* pargi, int argc, char** argv,
  121     int error_on_unrecognized)
  122 {
  123     int argi = *pargi;
  124     int ok = TRUE;
  125 
  126     while (argi < argc) {
  127         if (argv[argi][0] != '-') {
  128             break;
  129         }
  130         if (streq(argv[argi], "-h") || streq(argv[argi], "--help")) {
  131             ok = FALSE;
  132             break;
  133         }
  134 
  135         ap_flag_def_t* pdef = ap_find(pstate, argv[argi]);
  136         if (pdef == NULL) {
  137             if (error_on_unrecognized)
  138                 ok = FALSE;
  139             break;
  140         }
  141 
  142         if ((argc-argi) < pdef->count) {
  143             fprintf(stderr, "%s %s: option %s requires an argument.\n",
  144                 argv[0], verb, argv[argi]);
  145             fprintf(stderr, "\n");
  146             ok = FALSE;
  147             break;
  148         }
  149 
  150         if (pdef->type == AP_INT_VALUE_FLAG) {
  151             *(int *)pdef->pval = pdef->intval;
  152 
  153         } else if (pdef->type == AP_INT_FLAG) {
  154             if (sscanf(argv[argi+1], "%d", (int *)pdef->pval) != 1) {
  155                 fprintf(stderr, "%s %s: couldn't parse \"%s\" after \"%s\" as integer.\n",
  156                     argv[0], verb, argv[argi+1], argv[argi]);
  157                 fprintf(stderr, "\n");
  158             }
  159 
  160         } else if (pdef->type == AP_LONG_LONG_FLAG) {
  161             if (sscanf(argv[argi+1], "%lld", (long long *)pdef->pval) != 1) {
  162                 fprintf(stderr, "%s %s: couldn't parse \"%s\" after \"%s\" as integer.\n",
  163                     argv[0], verb, argv[argi+1], argv[argi]);
  164                 fprintf(stderr, "\n");
  165             }
  166 
  167         } else if (pdef->type == AP_DOUBLE_FLAG) {
  168             if (!mlr_try_float_from_string(argv[argi+1], (double *)pdef->pval)) {
  169                 fprintf(stderr, "%s %s: couldn't parse \"%s\" after \"%s\" as double.\n",
  170                     argv[0], verb, argv[argi+1], argv[argi]);
  171                 fprintf(stderr, "\n");
  172             }
  173 
  174         } else if (pdef->type == AP_STRING_FLAG) {
  175             char** pstring = pdef->pval;
  176             *pstring = argv[argi+1];
  177             pdef->pval = pstring;
  178 
  179         } else if (pdef->type == AP_STRING_BUILD_LIST_FLAG) {
  180             slls_t** pplist = pdef->pval;
  181             if (*pplist == NULL) {
  182                 *pplist = slls_alloc();
  183             }
  184             slls_append_no_free(*pplist, argv[argi+1]);
  185             pdef->pval = pplist;
  186 
  187         } else if (pdef->type == AP_STRING_LIST_FLAG) {
  188             slls_t** pplist = pdef->pval;
  189             if (*pplist != NULL)
  190                 slls_free(*pplist);
  191             *pplist = slls_from_line(argv[argi+1], ',', FALSE);
  192             pdef->pval = pplist;
  193 
  194         } else if (pdef->type == AP_STRING_ARRAY_FLAG) {
  195             string_array_t** pparray = pdef->pval;
  196             if (*pparray != NULL)
  197                 string_array_free(*pparray);
  198             *pparray = string_array_from_line(argv[argi+1], ',');
  199             pdef->pval = pparray;
  200 
  201         } else {
  202             ok = FALSE;
  203             fprintf(stderr, "argparse.c: internal coding error: flag-def type %x not recognized.\n", pdef->type);
  204             fprintf(stderr, "\n");
  205             break;
  206         }
  207 
  208         argi += pdef->count;
  209     }
  210 
  211     *pargi = argi;
  212     return ok;
  213 }