/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /** s2sh: the s2 shell Intended uses of this code: 1) A copy/paste bootstrap for creating new s2-using clients. To that end, this file "should" be commented relatively well. 2) An extensible shell for use in running client-defined functionality. Extensibility comes in these forms: 2.1) Via editing this and/or shell_common.c file (discourged, as i copy it amongst several trees ;). Note that shell_common.c is used by both this file and shell2.c (its successor). 2.2) Editing shell_extend.c and defining S2_SHELL_EXTEND when building this file. Preferred, as this allows clients to statically link in their features to the shell. 2.3) A platform for loading new s2 features via DLLs. 2.4) provide an auto-load feature which clients can hook into to extend the script-side environment during shell startup. 3) Running s2 script files in batch mode or via an interactive session (requires 3rd-party libs described later in these sources). The non-API s2 docs include much more detail on the above points: https://fossil.wanderinghorse.net/r/cwal/doc/trunk/s2/ (Or, if you're reading this from the canonical s2 source tree, see index.md in this file's directory.) Concepts needed to make any sense of this file: - cwal is a separate lib (bundled with s2) which provides the core-most features: Value system, memory management/lifetime, and garbage collector. - s2 is a script language built on that engine. Thus clients will see many mixes of the two in this code. In practice, most client code uses only the cwal-level APIs, but this app's level of code uses the s2 API relatively often as well. */ #define S2SH_VERSION 1 #include "shell_common.c" /** gcc bug: if this function is marked static here, it does not recognize that shell_common.c uses it and declares that it's unused. */ CliAppSwitch const * s2sh_cliapp_switches(){ static const CliAppSwitch cliAppSwitches[] = { #define F6(IDFLAGS,DASHES,KEY,VAL,BRIEF,PFLAGS) \ {IDFLAGS, DASHES, KEY, VAL, BRIEF, 0, 0, PFLAGS} #define F5(IDFLAGS,DASHES,KEY,VAL,BRIEF) \ F6(IDFLAGS,DASHES,KEY,VAL,BRIEF,0) /** Continues the help text for the previous entry. */ #define FCONTINUE(LABEL) {SW_CONTINUE, 0, 0, 0, LABEL, 0, 0, 0} /** Adds an "additional info" line, not indented. */ #define FINFOLINE(LABEL) {SW_INFOLINE, 0, 0, 0, LABEL, 0, 0, 0} /** -short | --long[=VALUE]*/ #define FX(IDFLAGS,SHORT,LONG,VALUE,BRIEF,PFLAGS) \ F6(IDFLAGS,2,LONG,VALUE,BRIEF,PFLAGS), \ F6(IDFLAGS,1,SHORT,VALUE,0,PFLAGS) /** -short, --long on/off switches ...*/ #define F01(IDFLAGS,KEY,BRIEF) \ {IDFLAGS, 2, KEY, 0, "Disable " BRIEF, 0, 0, 0}, \ {IDFLAGS+1, 1, KEY, 0, "Enable " BRIEF, 0, 0, 0} /** Start the next group (for --help grouping). */ #define GROUP(GID,DESC) {GID, 0, 0, 0, DESC, 0, 0, 0} /***********************************************************************/ GROUP(SW_GROUP_0,0), F5(SW_HELP, 2, "help", 0, "Send help text to stdout and exit with code 0."), F5(SW_HELP, 1, "?", 0, 0), F5(SW_HELP | SW_UNDOCUMENTED, 1, "help", 0, 0), FCONTINUE("The -v flag can be used to get more info."), F5(SW_VERBOSE, 1, "v", 0, "Increase verbosity level by one."), FCONTINUE("Use with -?/--help to increase help info level."), F5(SW_VERSION,2,"version",0, "Show version info and exit with code 0. "), FCONTINUE("Use with -v for more details."), F6(SW_OUTFILE,1,"o","outfile", "Sets the engine's default output channel. Default=stdout.", CLIAPP_F_SPACE_VALUE | CLIAPP_F_ONCE), F6(SW_INFILE,1, "f", "infile", "Runs the given script file in a new scope.", CLIAPP_F_SPACE_VALUE | CLIAPP_F_ONCE), FCONTINUE("Defaults to the first non-flag argument."), FX(SW_ESCRIPT,"e","eval","SCRIPT", "Evaluates the given script code in the global scope. " "May be used multiple times.", CLIAPP_F_SPACE_VALUE), /***********************************************************************/ GROUP(SW_GROUP_1,"Less-common options:"), F01(SW_ASSERT_0,"A","assert tracing."), FCONTINUE("Enable twice to also trace affirm calls."), F5(SW_INTERACTIVE,1,"i",0, "Enter interactive mode even if -e/-f disable it."), F01(SW_AUTOLOAD_0,"a","autoloading of init script."), FCONTINUE("Init script name = same as this binary plus \".s2\" "), FCONTINUE("or set via the S2SH_INIT_SCRIPT environment variable."), /***********************************************************************/ GROUP(SW_GROUP_2,"Esoteric options:"), F5(SW_METRICS, 1, "m", 0, "Dump cwal/s2 metrics before shutdown."), FCONTINUE("Use -v 1-3 times for more information."), F01(SW_MOD_INIT_0,"M","initialization of built-in static modules."), F01(SW_SHELL_API_0,"s2.shell","installation of s2.shell API."), FCONTINUE("By default s2.shell is only installed in interactive mode."), F01(SW_SCOPE_H0,"H","hashes for scope storage (else objects)."), F6(SW_HIST_FILE_1,1,"h","filename", "Set editing history file.", CLIAPP_F_SPACE_VALUE | CLIAPP_F_ONCE), F5(SW_HIST_FILE_0,2,"h",0, "Disable editing history file."), F5(SW_CLEANROOM, 1, "cleanroom", 0, "Do not install any global/prototype-level functionality."), FCONTINUE("Disables the s2 global object and auto-loading of the " "init script."), F5(SW_SHOW_SIZEOFS,1,"z",0,"Dump various sizeof() values."), F5(SW_INTERNAL_FU,1,"fu",0, "May or may not enable some internal testing. Only for use in developing this app."), F5(SW_CLAMPDOWN,-1,"clampdown",0,"No longer available: use --s2-disable instead."), F6(SW_DISABLE, 2, "s2-disable", "comma,list", "Disables certain s2 API features by name.",0), FCONTINUE("Use a comma-and/or-space-separated list with any of " "the following entries:"), FCONTINUE("fs-stat, fs-read, fs-write, fs-io, fs-all"), F5(SW_SWEEP_INTERVAL,1,"w",0,"Increase sweep interval by 1."), F5(SW_VAC_INTERVAL,-1,"w",0, "Increase vacuum interval by 1."), F01(SW_TRACE_STACKS_0,"T","stack machine tracing."), F01(SW_TRACE_SWEEP_0,"W","sweep tracking."), FCONTINUE("Enable multiple times for (possibly) more detail."), FINFOLINE("Recycling-related options:"), F01(SW_RE_V0,"R","value recycling."), F01(SW_RE_S0,"S","string interning."), F01(SW_RE_C0,"C","the chunk recyler."), FINFOLINE("Memory-tracking/capping options:"), F6(SW_MCAP_TOTAL_ALLOCS, 1, "cap-ta", "N", "* Limit the (T)otal number of (A)llocations to N.", CLIAPP_F_SPACE_VALUE), F6(SW_MCAP_TOTAL_ALLOCS, 1, "cap-tb", "N", "* Limit the (T)otal number of allocated (B)ytes to N.", CLIAPP_F_SPACE_VALUE), F6(SW_MCAP_TOTAL_ALLOCS, 1, "cap-ca", "N", "Limit the (C)oncurrent number of (A)llocations to N.", CLIAPP_F_SPACE_VALUE), F6(SW_MCAP_TOTAL_ALLOCS, 1, "cap-cb", "N", "Limit the (C)oncurrent number of allocated (B)ytes to N.", CLIAPP_F_SPACE_VALUE), F6(SW_MCAP_TOTAL_ALLOCS, 1, "cap-sb", "N", "Limit the size of any (S)ingle allocation to N (B)ytes.", CLIAPP_F_SPACE_VALUE), FINFOLINE("The allocator starts failing (returning NULL) when a capping constraint is violated."), FCONTINUE("The 'tb' and 'ta' constraint violations are permanent (recovery requires resetting the engine)."), FCONTINUE("The 'ca' and 'cb' constraints are recoverable once some cwal-managed memory gets freed."), FCONTINUE("Capping only applies to memory allocated by/via the scripting\n" "engine, not 3rd-party APIs."), F01(SW_MEM_FAST0, "fst", "(F)orced alloc (S)ize (T)racking."), FCONTINUE("Enabled implicitly by some -cap flags."), #undef GROUP #undef F01 #undef F5 #undef F6 #undef FX #undef FPLUS #undef FPLUSX #undef FINFOLINE CliAppSwitch_sentinel /* MUST be the last entry in the list */ }; return cliAppSwitches; }