a parser for config files and the command line
This commit is contained in:
parent
e43ae6f497
commit
667bc062f9
2 changed files with 258 additions and 0 deletions
201
src/parse.gperf
Normal file
201
src/parse.gperf
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
%struct-type
|
||||
%language=ANSI-C
|
||||
%7bit
|
||||
%readonly-tables
|
||||
%define initializer-suffix ,0
|
||||
|
||||
%{
|
||||
|
||||
#include "parse.h"
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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<<BITS)-1)
|
||||
|
||||
#define MULTI(x) (void*)(offsetof(struct cfginfo,x)|MULTIVAL)
|
||||
#define POSBOOL(x) (void*)(offsetof(struct cfginfo,x)|POS|BOOL)
|
||||
#define NEGBOOL(x) (void*)(offsetof(struct cfginfo,x)|NEG|BOOL)
|
||||
#define IMM(x) imm_##x
|
||||
|
||||
static void imm_version(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void imm_verbose_version(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void imm_usage(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void imm_help(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void imm_copying(void)
|
||||
{
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
struct cfg
|
||||
|
||||
%%
|
||||
alllocalefonts, POSBOOL(all_locale_fonts)
|
||||
allowscreensaver, NEGBOOL(disable_screensaver)
|
||||
altprint, MULTI(alt_print_command_default)
|
||||
altprintalways, MULTI(alt_print_command_default)
|
||||
altprintcommand, MULTI(altprintcommand)
|
||||
altprintmod, MULTI(alt_print_command_default)
|
||||
altprintnever, MULTI(alt_print_command_default)
|
||||
autosave, POSBOOL(autosave_on_quit)
|
||||
buttondistinction, NEGBOOL(no_button_distinction)
|
||||
colorfile, MULTI(colorfile)
|
||||
complexshapes, NEGBOOL(simple_shapes)
|
||||
copying, IMM(copying)
|
||||
currentlocalefont, NEGBOOL(all_locale_fonts)
|
||||
datadir, MULTI(datadir)
|
||||
disablescreensaver, POSBOOL(disable_screensaver)
|
||||
dontgrab, NEGBOOL(grab_input)
|
||||
dontmirrorstamps, NEGBOOL(mirrorstamps)
|
||||
fancycursors, NEGBOOL(no_fancy_cursors)
|
||||
fullscreen, MULTI(parsertmp_fullscreen_native)
|
||||
grab, POSBOOL(grab_input)
|
||||
help, IMM(help)
|
||||
hidecursor, POSBOOL(hide_cursor)
|
||||
keyboard, POSBOOL(keymouse)
|
||||
label, NEGBOOL(disable_label)
|
||||
lang, MULTI(parsertmp_lang)
|
||||
locale, MULTI(parsertmp_locale)
|
||||
lockfile, POSBOOL(ok_to_use_lockfile)
|
||||
magiccontrols, NEGBOOL(disable_magic_controls)
|
||||
mirrorstamps, POSBOOL(mirrorstamps)
|
||||
mixedcase, NEGBOOL(only_uppercase)
|
||||
mouse, NEGBOOL(keymouse)
|
||||
native, POSBOOL(native_screensize)
|
||||
orient, MULTI(rotate_orientation)
|
||||
outlines, NEGBOOL(dont_do_xor)
|
||||
papersize, MULTI(papersize)
|
||||
print, NEGBOOL(disable_print)
|
||||
printcfg, POSBOOL(use_print_config)
|
||||
printcommand, MULTI(printcommand)
|
||||
printdelay, MULTI(print_delay)
|
||||
quit, NEGBOOL(disable_quit)
|
||||
save, NEGBOOL(disable_save)
|
||||
savedir, MULTI(savedir)
|
||||
saveover, MULTI(promptless_save)
|
||||
saveoverask, MULTI(promptless_save)
|
||||
saveovernew, MULTI(promptless_save)
|
||||
shortcuts, NEGBOOL(noshortcuts)
|
||||
showcursor, NEGBOOL(hide_cursor)
|
||||
simpleshapes, POSBOOL(simple_shapes)
|
||||
sound, POSBOOL(use_sound)
|
||||
stampcontrols, NEGBOOL(disable_stamp_controls)
|
||||
stamps, NEGBOOL(dont_load_stamps)
|
||||
stampsize, MULTI(stamp_size_override)
|
||||
startblank, POSBOOL(start_blank)
|
||||
startlast, NEGBOOL(start_blank)
|
||||
sysconfig, POSBOOL(parsertmp_sysconfig)
|
||||
sysfonts, NEGBOOL(no_system_fonts)
|
||||
uppercase, POSBOOL(only_uppercase)
|
||||
usage, IMM(usage)
|
||||
verbose-version, IMM(verbose_version)
|
||||
version, IMM(version)
|
||||
wheelmouse, POSBOOL(wheely)
|
||||
windowed, NEGBOOL(fullscreen)
|
||||
windowsize, MULTI(parsertmp_windowsize)
|
||||
%%
|
||||
|
||||
void parse_one_option(struct cfginfo *restrict tmpcfg, const char *str, const char *opt, const char *restrict src)
|
||||
{
|
||||
//printf("parsing: <%s> <%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) ? (uintptr & FLAGMASK) : 0;
|
||||
|
||||
if(!cfg || (!(flags & BOOL) && noflag) )
|
||||
{
|
||||
if(src)
|
||||
printf("Unknown option '%s' in config file '%s'\n",str,src);
|
||||
else
|
||||
printf("Unknown command line option '--%s'\n",str);
|
||||
exit(47);
|
||||
}
|
||||
|
||||
if(unlikely(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*));
|
||||
}
|
||||
57
src/parse.h
Normal file
57
src/parse.h
Normal file
|
|
@ -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);
|
||||
Loading…
Add table
Add a link
Reference in a new issue