#include "parseargs.hfa" // #include // #include #include extern "C" { #include struct FILE; extern FILE * stderr; extern FILE * stdout; extern int fprintf ( FILE * stream, const char * format, ... ); extern long long int strtoll (const char* str, char** endptr, int base); } void parse_args( int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, char ** & left ) { struct option optarr[opt_count + 2]; int width = 0; { int idx = 0; for(i; opt_count) { if(options[i].long_name) { optarr[idx].name = options[i].long_name; optarr[idx].flag = 0p; optarr[idx].val = options[i].short_name; if( ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue) || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) { optarr[idx].has_arg = no_argument; } else { optarr[idx].has_arg = required_argument; } idx++; int w = strlen(options[i].long_name); if(w > width) width = w; } } optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0p, 'h']; optarr[idx+1].[name, has_arg, flag, val] = [0p, no_argument, 0p, 0]; } char optstring[opt_count * 3] = { '\0' }; { int idx = 0; for(i; opt_count) { optstring[idx] = options[i].short_name; idx++; if( ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue) && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) { optstring[idx] = ':'; idx++; } } optstring[idx+0] = 'h'; optstring[idx+1] = '\0'; } FILE * out = stderr; NEXT_ARG: for() { int idx = 0; int opt = getopt_long(argc, argv, optstring, optarr, &idx); switch(opt) { case -1: if(&left != 0p) left = argv + optind; return; case 'h': out = stdout; case '?': goto USAGE; default: for(i; opt_count) { if(opt == options[i].short_name) { const char * arg = optarg ? optarg : ""; bool success = options[i].parse( arg, options[i].variable ); if(success) continue NEXT_ARG; fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt); goto USAGE; } } abort("Internal parse arg error\n"); } } USAGE: fprintf(out, "%s\n", usage); for(i; opt_count) { fprintf(out, " -%c, --%-*s %s\n", options[i].short_name, width, options[i].long_name, options[i].help); } fprintf(out, " -%c, --%-*s %s\n", 'h', width, "help", "print this help message"); exit(out == stdout ? 0 : 1); } bool parse_yesno(const char * arg, bool & value ) { if(strcmp(arg, "yes") == 0) { value = true; return true; } if(strcmp(arg, "no") == 0) { value = false; return true; } return false; } bool parse_settrue (const char *, bool & value ) { value = true; return true; } bool parse_setfalse(const char *, bool & value ) { value = false; return true; } bool parse(const char * arg, const char * & value ) { value = arg; return true; } bool parse(const char * arg, int & value) { char * end; int r = strtoll(arg, &end, 10); if(*end != '\0') return false; value = r; return true; }