diff --git a/src/parse.gperf b/src/parse.gperf new file mode 100644 index 000000000..e558289d6 --- /dev/null +++ b/src/parse.gperf @@ -0,0 +1,201 @@ +%struct-type +%language=ANSI-C +%7bit +%readonly-tables +%define initializer-suffix ,0 + +%{ + +#include "parse.h" +#include +#include +#include +#include +#include +#include + +const char PARSE_YES[] = "yes"; +const char PARSE_NO[] = "no"; + +struct cfg +{ + const char *name; + void (*val)(void); +}; + +#define MULTIVAL 0x00000000 +#define POS 0x00000001 +#define NEG 0x00000002 +#define BOOL (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"; + } + + int noflag = 2*(str[0]=='n' && str[1]=='o' && str[2]); + const struct cfg *cfg = in_word_set(str+noflag, strlen(str+noflag)); + + uintptr_t uintptr = cfg ? (uintptr_t)cfg->val : 0; + unsigned 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 & BOOL) + { + 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) + { + 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); + } + + unsigned offset = uintptr &~ FLAGMASK; + memcpy(offset+(char*)tmpcfg, &opt, sizeof(char*)); +} diff --git a/src/parse.h b/src/parse.h new file mode 100644 index 000000000..ceb57ee0f --- /dev/null +++ b/src/parse.h @@ -0,0 +1,57 @@ +#pragma once +#include "compiler.h" + +extern const char PARSE_YES[]; +extern const char PARSE_NO[]; + +struct cfginfo +{ + const char *all_locale_fonts; + const char *alt_print_command_default; + const char *altprintcommand; + const char *autosave_on_quit; + const char *colorfile; + const char *datadir; + const char *disable_label; + const char *disable_magic_controls; + const char *disable_print; + const char *disable_quit; + const char *disable_save; + const char *disable_screensaver; + const char *disable_stamp_controls; + const char *dont_do_xor; + const char *dont_load_stamps; + const char *fullscreen; + const char *grab_input; + const char *hide_cursor; + const char *keymouse; + const char *mirrorstamps; + const char *native_screensize; + const char *no_button_distinction; + const char *no_fancy_cursors; + const char *no_system_fonts; + const char *noshortcuts; + const char *ok_to_use_lockfile; + const char *only_uppercase; + const char *papersize; + const char *parsertmp_fullscreen_native; + const char *parsertmp_lang; + const char *parsertmp_locale; + const char *parsertmp_sysconfig; + const char *parsertmp_windowsize; + const char *print_delay; + const char *printcommand; + const char *promptless_save; + const char *rotate_orientation; + const char *savedir; + const char *simple_shapes; + const char *stamp_size_override; + const char *start_blank; + const char *use_print_config; + const char *use_sound; + const char *wheely; +}; + +#define CFGINFO_MAXOFFSET (sizeof(struct cfginfo)) + +extern void parse_one_option(struct cfginfo *restrict tmpcfg, const char *str, const char *opt, const char *restrict src);