#ifndef __COMMAND_H__ #define __COMMAND_H__ #include "OSLib.h" #include "centry.h" enum { caa_READ, caa_WRITE }; /* tasks for action */ struct command_arg; typedef int (*command_arg_action)(struct command_arg *self, int task); #define DECL_ARG_ACTION(name) int name(struct command_arg *arg, int task) // Flags for commands: bitmask typedef enum { c_NONE = 0, c_STATIC = 0, // static value for saving c_DYNAMIC = 1, // dynamically determines config, // pass csa_READ multiple times with increasing iter c_DONT_SAVE = 2, // don't save value back to config c_SESSION_ONLY = 4, // if set, item should be saved for sessions but // not in general config c_CONFIG_ONLY = 8 // if set, item should only be saved in basic // config file, not in session } command_symbol_flags; // Types of command arguments typedef enum { ca_VOID, ca_SYM, ca_NUM, ca_STRING, ca_SPEC, ca_PATHSPEC, ca_NAMESPEC, ca_TOGGLE } command_arg_type; extern char *ca_types[]; #define ca_ISSPEC(x) ((x)==ca_SPEC || (x)==ca_PATHSPEC || (x)==ca_NAMESPEC) typedef struct command_arg { char *name; /* name of argument */ char *help; /* usage info */ command_arg_action action; /* action associated with argument */ command_arg_type type; /* ca_NUM, ca_STRING */ union { struct { int sz; /* 1,2,4 = size of pointed var */ void *mem; } num; /* ca_NUM */ struct { int sz; /* 1,2,4 = size of pointed var */ void *mem; int flag; } toggle; /* ca_TOGGLE */ struct { int maxlen; /* max len of string [memory] */ union { char *mem; /* if maxlen >= 0 */ char **ptr; /* if maxlen < 0, we store ptr to buffer */ } m; } string; /* ca_STRING */ struct { OSSpec *mem; } spec; /* ca_SPEC */ struct { OSPathSpec *mem; } pathspec; /* ca_PATHSPEC */ struct { OSNameSpec *mem; } namespec; /* ca_NAMESPEC */ } u; struct command_arg *next; } command_arg; enum { csa_READ, csa_WRITE }; /* tasks for action */ struct command_symbol; typedef int (*command_symbol_action)(struct command_symbol *self, int task, int iter); // task is caa_XXX, iter=0..x for caa_READ_CONFIG #define DECL_SYMBOL_ACTION(name) int name(struct command_symbol *sym, int task, int iter) #define SYM_ARG_1st (sym->args) #define SYM_ARG_2nd (SYM_ARG_1st ? sym->args->next : 0L) #define SYM_ARG_3rd (SYM_ARG_2nd ? sym->args->next->next : 0L) #define SYM_ARG_4th (SYM_ARG_3rd ? sym->args->next->next->next : 0L) #define SYM_ARG_5th (SYM_ARG_4th ? sym->args->next->next->next->next : 0L) #define SYM_ARG_6th (SYM_ARG_5th ? sym->args->next->next->next->next->next : 0L) #define SYMBOL_ACTION_BIT_TOGGLE(var, bit) \ do { \ int flag; \ if (task == caa_WRITE) { \ command_arg_get_num(sym->args, &flag); \ if (flag) \ var |= bit; \ else \ var &= ~bit; \ } else { \ flag = (var & bit) != 0; \ command_arg_set_num(sym->args, flag); \ } \ } while (0) typedef struct command_symbol { char *name; /* name (case-insensitive) */ char *help; /* description of use */ command_symbol_flags flags; /* flags for symbol */ command_symbol_action action; /* action associated with command */ struct command_arg *ret; /* value if used on RHS */ struct command_arg *args; /* arguments we take */ struct command_symbol *next; } command_symbol; typedef struct command_symbol_table { char *name; /* name of table */ char *help; /* more info */ struct command_symbol_table *sub; /* table of subcommands */ struct command_symbol *list; /* list of symbols */ struct command_symbol_table *next; /* next table */ } command_symbol_table; extern command_symbol_table *universe; command_symbol_table * command_symbol_table_new(char *name, char *help, command_symbol *list, command_symbol_table *sub, command_symbol_table *next); command_symbol_table * command_symbol_table_add_subtable(command_symbol_table *parent, command_symbol_table *table); command_symbol_table * command_symbol_table_add(command_symbol_table *parent, command_symbol *list); /* Any symbol may define ret==RET_FIRST_ARG to mean return value of first argument. */ #define RET_FIRST_ARG (command_arg *)(-1) command_symbol * command_symbol_new(char *name, char *help, command_symbol_flags flags, command_symbol_action action, command_arg *ret, command_arg *args, command_symbol *next); #define ARG_NUM(x) sizeof(x), &x #define NEW_ARG_NUM(t) sizeof(t), xmalloc(sizeof(t)) #define NEW_ARG_CONST_NUM(x) sizeof(int), xintdup(x) command_arg * command_arg_new_num(char *name, char *help, command_arg_action action, int sz, void *mem, command_arg *next); /* You may specify an unbounded string array by passing maxlen < 0 and treating 'str' as a pointer to a pointer to the string. */ #define ARG_STR(x) sizeof(x), x #define NEW_ARG_STR(l) l, xmalloc(l) #define NEW_ARG_STRBUF(p) -1, p #define NEW_ARG_NEW_STRBUF -1, xcalloc(sizeof(void *)) command_arg * command_arg_new_string(char *name, char *help, command_arg_action action, int maxlen, void *str, command_arg *next); command_arg * command_arg_new_spec(char *name, char *help, command_arg_action action, OSSpec *spec, command_arg *next); command_arg * command_arg_new_pathspec(char *name, char *help, command_arg_action action, OSPathSpec *pathspec, command_arg *next); command_arg * command_arg_new_namespec(char *name, char *help, command_arg_action action, OSNameSpec *namespec, command_arg *next); command_arg * command_arg_new_toggle(char *name, char *help, command_arg_action action, int sz, void *mem, int val, command_arg *next); /*****************/ void command_arg_read_num(command_arg *arg, int *val); int command_arg_get_num(command_arg *arg, int *val); int command_arg_set_num(command_arg *arg, int val); void command_arg_read_string(command_arg *arg, char **str); int command_arg_get_string(command_arg *arg, char **str); int command_arg_set_string(command_arg *arg, const char *str); void command_arg_read_spec(command_arg *arg, char **str); int command_arg_get_spec(command_arg *arg, char **str); int command_arg_set_spec(command_arg *arg, const char *str); void command_arg_read_toggle(command_arg *arg, int *val); int command_arg_get_toggle(command_arg *arg, int *val); int command_arg_set_toggle(command_arg *arg, int val); int command_match_symbol(const command_symbol_table *table, const char *name, command_symbol **sym); void command_match_symbols(const command_symbol_table *table, const char *name, command_symbol ***matches, int *nmatches); struct command_exprval; int command_set_args(struct command_exprval *ret, command_symbol *sym, ... /* command_exprval */); int command_get_val(command_symbol *sym, struct command_exprval *val); /* Interface to lexer */ int command_lexer_setup_text(char *name, char *text, int len); int command_lexer_setup_file(char *filename); /* Interface to parser */ int command_parse(command_symbol_table *universe); /* Interface to emulator */ void command_init(void); int command_parse_file(char *name); int command_parse_text(char *str); /* Filter execution of session-only commands */ bool command_get_session_filter(void); void command_set_session_filter(bool allow_session_only); /* Interface to help */ void command_help(void); #include "cexit.h" #endif