%struct-type %language=ANSI-C %7bit %readonly-tables %define initializer-suffix ,0 %{ #include #include #include #include #include #include #include "../src/parse.h" const char PARSE_YES[] = "yes"; const char PARSE_NO[] = "no"; const char PARSE_CLOBBER[] = ":-("; // for painful lang/locale priority situation struct cfg { const char *name; void (*val)(void); }; #define MULTIVAL 0x00000000 #define POS 0x00000001 #define NEG 0x00000002 #define BOOLMASK (POS|NEG) #define BITS 2 // if this grows past 2, must shift the offset #define FLAGMASK ((1< <%s>\n",str,arg); if(isdigit(*str)) { if(opt && !strcmp(opt,"no")) str = "640x480"; opt = str; str = "windowsize"; } noflag = 2*(str[0]=='n' && str[1]=='o' && str[2]); cfg = in_word_set(str+noflag, strlen(str+noflag)); uintptr = cfg ? (uintptr_t)cfg->val : 0; flags = (uintptr= CFGINFO_MAXOFFSET)) { if(src) { // immediate options are only for the command line printf("Unknown option '%s' in config file '%s'\n",str,src); exit(49); } if(opt) { printf("Command line option '--%s' doesn't take a value.\n",str); exit(50); } cfg->val(); exit(0); } if(flags & BOOLMASK) { int flip = !!noflag ^ !!(flags & NEG); if(!opt) opt = flip ? PARSE_NO : PARSE_YES; else if(!strcmp("yes",opt)) opt = flip ? PARSE_NO : PARSE_YES; else if(!strcmp("no",opt)) opt = flip ? PARSE_YES : PARSE_NO; else { if(src) printf("Option '%s' in config file '%s' is yes/no only, but got '%s'\n",str,src,opt); else printf("Command line option '--%s' is yes/no only, but got '%s'\n",str,opt); exit(51); } } else if(!opt || !*opt) { if(src) printf("Option '%s' in config file '%s' needs a value\n",str,src); else printf("Command line option '--%s' needs a value\n",str); exit(52); } offset = uintptr &~ FLAGMASK; memcpy(&dupecheck, offset+(char*)tmpcfg, sizeof(char*)); if(dupecheck) { if(src) printf("Option '%s' in config file '%s' sets '%s' again.\n",str,src,cfg->name); else printf("Command line option '--%s' sets '%s' again.\n",str,cfg->name); exit(53); } memcpy(offset+(char*)tmpcfg, &opt, sizeof(char*)); }