Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/parseargs.cfa

    rd1abc63c rf82f07e  
    5050extern char ** cfa_args_envp __attribute__((weak));
    5151
    52 forall([N])
    53 static void usage(char * cmd, const array( cfa_option, N ) & options, const char * usage, FILE * out)  __attribute__ ((noreturn));
     52static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out)  __attribute__ ((noreturn));
    5453//-----------------------------------------------------------------------------
    5554// checking
    56 forall([N])
    57 static void check_args( const array( cfa_option, N ) & options ) {
    58         for(i; N) {
    59                 for(j; N) {
     55static void check_args(cfa_option options[], size_t opt_count) {
     56        for(i; opt_count) {
     57                for(j; opt_count) {
    6058                        if(i == j) continue;
    6159
     
    7270//-----------------------------------------------------------------------------
    7371// Parsing args
    74 forall([opt_count]) {
    75         void parse_args( const array( cfa_option, opt_count ) & options, const char * usage, char ** & left ) {
    76                 if( 0p != &cfa_args_argc ) {
    77                         parse_args(cfa_args_argc, cfa_args_argv, options, usage, left );
    78                 }
    79                 else {
    80                         char * temp = "";
    81                         parse_args(0, &temp, options, usage, left );
    82                 }
    83         }
    84 
    85         void parse_args(
    86                 int argc,
    87                 char * argv[],
    88                 const array( cfa_option, opt_count ) & options,
    89                 const char * usage,
    90                 char ** & left
    91         ) {
    92                 check_args(options);
    93 
    94                 int maxv = 'h';
    95                 char optstring[(opt_count * 3) + 2] = { '\0' };
    96                 {
    97                         int idx = 0;
    98                         for(i; opt_count) {
    99                                 if (options[i].short_name) {
    100                                         maxv = max(options[i].short_name, maxv);
    101                                         optstring[idx] = options[i].short_name;
    102                                         idx++;
    103                                         if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
    104                                         && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
    105                                                 optstring[idx] = ':';
    106                                                 idx++;
    107                                         }
    108                                 }
    109                         }
    110                         optstring[idx+0] = 'h';
    111                         optstring[idx+1] = '\0';
    112                 }
    113 
    114                 struct option optarr[opt_count + 2];
    115                 {
    116                         int idx = 0;
    117                         for(i; opt_count) {
    118                                 if(options[i].long_name) {
    119                                         // we don't have the mutable keyword here, which is really what we would want
    120                                         int & val_ref = (int &)(const int &)options[i].val;
    121                                         val_ref = (options[i].short_name != '\0') ? ((int)options[i].short_name) : ++maxv;
    122 
    123                                         optarr[idx].name = options[i].long_name;
    124                                         optarr[idx].flag = 0p;
    125                                         optarr[idx].val  = options[i].val;
    126                                         if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
    127                                         || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
    128                                                 optarr[idx].has_arg = no_argument;
    129                                         } else {
    130                                                 optarr[idx].has_arg = required_argument;
    131                                         }
     72void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
     73        if( 0p != &cfa_args_argc ) {
     74                parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
     75        }
     76        else {
     77                char * temp = "";
     78                parse_args(0, &temp, options, opt_count, usage, left );
     79        }
     80}
     81
     82void parse_args(
     83        int argc,
     84        char * argv[],
     85        cfa_option options[],
     86        size_t opt_count,
     87        const char * usage,
     88        char ** & left
     89) {
     90        check_args(options, opt_count);
     91
     92        int maxv = 'h';
     93        char optstring[(opt_count * 3) + 2] = { '\0' };
     94        {
     95                int idx = 0;
     96                for(i; opt_count) {
     97                        if (options[i].short_name) {
     98                                maxv = max(options[i].short_name, maxv);
     99                                optstring[idx] = options[i].short_name;
     100                                idx++;
     101                                if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
     102                                && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
     103                                        optstring[idx] = ':';
    132104                                        idx++;
    133105                                }
    134106                        }
    135                         optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
    136                         optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
    137                 }
    138 
    139                 FILE * out = stderr;
    140                 NEXT_ARG:
    141                 for() {
    142                         int idx = 0;
    143                         int opt = getopt_long(argc, argv, optstring, optarr, &idx);
    144                         switch(opt) {
    145                                 case -1:
    146                                         if(&left != 0p) left = argv + optind;
    147                                         return;
    148                                 case 'h':
    149                                         out = stdout;
    150                                 case '?':
    151                                         usage(argv[0], options, usage, out);
    152                                 default:
    153                                         for(i; opt_count) {
    154                                                 if(opt == options[i].val) {
    155                                                         const char * arg = optarg ? optarg : "";
    156                                                         if( arg[0] == '=' ) { arg++; }
    157                                                         // work around for some weird bug
    158                                                         void * variable = options[i].variable;
    159                                                         bool (*parse_func)(const char *, void * ) = options[i].parse;
    160                                                         bool success = parse_func( arg, variable );
    161                                                         if(success) continue NEXT_ARG;
    162 
    163                                                         fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
    164                                                         usage(argv[0], options, usage, out);
    165                                                 }
     107                }
     108                optstring[idx+0] = 'h';
     109                optstring[idx+1] = '\0';
     110        }
     111
     112        struct option optarr[opt_count + 2];
     113        {
     114                int idx = 0;
     115                for(i; opt_count) {
     116                        if(options[i].long_name) {
     117                                options[i].val = (options[i].short_name != '\0') ? ((int)options[i].short_name) : ++maxv;
     118                                optarr[idx].name = options[i].long_name;
     119                                optarr[idx].flag = 0p;
     120                                optarr[idx].val  = options[i].val;
     121                                if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
     122                                    || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
     123                                        optarr[idx].has_arg = no_argument;
     124                                } else {
     125                                        optarr[idx].has_arg = required_argument;
     126                                }
     127                                idx++;
     128                        }
     129                }
     130                optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
     131                optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
     132        }
     133
     134        FILE * out = stderr;
     135        NEXT_ARG:
     136        for() {
     137                int idx = 0;
     138                int opt = getopt_long(argc, argv, optstring, optarr, &idx);
     139                switch(opt) {
     140                        case -1:
     141                                if(&left != 0p) left = argv + optind;
     142                                return;
     143                        case 'h':
     144                                out = stdout;
     145                        case '?':
     146                                usage(argv[0], options, opt_count, usage, out);
     147                        default:
     148                                for(i; opt_count) {
     149                                        if(opt == options[i].val) {
     150                                                const char * arg = optarg ? optarg : "";
     151                                                if( arg[0] == '=' ) { arg++; }
     152                                                bool success = options[i].parse( arg, options[i].variable );
     153                                                if(success) continue NEXT_ARG;
     154
     155                                                fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
     156                                                usage(argv[0], options, opt_count, usage, out);
    166157                                        }
    167                                         abort("Internal parse arg error\n");
    168                         }
    169 
    170                 }
     158                                }
     159                                abort("Internal parse arg error\n");
     160                }
     161
    171162        }
    172163}
     
    231222
    232223void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    233         const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
    234         usage(cfa_args_argv[0], arr, usage, error ? stderr : stdout);
     224        usage(cfa_args_argv[0], options, opt_count, usage, error ? stderr : stdout);
    235225}
    236226
    237227void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error)  __attribute__ ((noreturn)) {
    238         const array( cfa_option, opt_count ) & arr = (const array( cfa_option, opt_count ) &) *options;
    239         usage(argv[0], arr, usage, error ? stderr : stdout);
    240 }
    241 
    242 forall( [N] ) {
    243         void print_args_usage( const array(cfa_option, N ) & options, const char * usage, bool error) {
    244                 usage(cfa_args_argv[0], options, usage, error ? stderr : stdout);
    245         }
    246 
    247         void print_args_usage(int argc, char * argv[], const array( cfa_option, N ) & options, const char * usage, bool error) {
    248                 usage(argv[0], options, usage, error ? stderr : stdout);
    249         }
    250 }
    251 
    252 forall([N])
    253 static void usage(char * cmd, const array( cfa_option, N ) & options, const char * help, FILE * out) __attribute__((noreturn)) {
     228        usage(argv[0], options, opt_count, usage, error ? stderr : stdout);
     229}
     230
     231static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * help, FILE * out) __attribute__((noreturn)) {
    254232        int width = 0;
    255233        {
    256                 for(i; N) {
     234                for(i; opt_count) {
    257235                        if(options[i].long_name) {
    258236                                int w = strlen(options[i].long_name);
     
    273251        fprintf(out, "Usage:\n  %s %s\n", cmd, help);
    274252
    275         for(i; N) {
     253        for(i; opt_count) {
    276254                printopt(out, width, max_width, options[i].short_name, options[i].long_name, options[i].help);
    277255        }
Note: See TracChangeset for help on using the changeset viewer.