This documents the major structures of LIL. Signed-off-by: Sean Anderson <sean...@gmail.com> ---
common/cli_lil.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ include/cli_lil.h | 57 ++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/common/cli_lil.c b/common/cli_lil.c index 66ee62bf33..7fbae1964a 100644 --- a/common/cli_lil.c +++ b/common/cli_lil.c @@ -29,20 +29,44 @@ #define HASHMAP_CELLS 256 #define HASHMAP_CELLMASK 0xFF +/** + * struct hashentry - An entry in a cell + * @k: The key + * @v: The value + */ struct hashentry { char *k; void *v; }; +/** + * struct hashcell - A list of entries with the same hash + * @e: An array of entries + * @c: The capacity of this cell + */ struct hashcell { struct hashentry *e; size_t c; }; +/** + * struct hashmap - An array-based hash map + * @cell: An array of cells + * + * This hash map uses separate chaining with an array for each cell. We cannot + * use the existing hash map functions (hsearch_r et al.) because they assume + * that the value is a string. + */ struct hashmap { struct hashcell cell[HASHMAP_CELLS]; }; +/** + * struct lil_value - A string and its length + * @l: The length of the value. + * @c: The capacity of this value (maximum of @l before requiring reallocation). + * @d: The contents of the value, as a nul-terminated string. + */ struct lil_value { size_t l; #ifdef LIL_ENABLE_POOLS @@ -51,12 +75,34 @@ struct lil_value { char *d; }; +/** + * struct lil_var - A variable + * @n: The name of this variable + * @env: The environment containing this variable + * @v: The value of this variable + */ struct lil_var { char *n; struct lil_env *env; struct lil_value *v; }; +/** + * struct lil_env - A function call's execution environment + * @parent: The parent of this environment. This is %NULL for the root + * environment. + * @func: The currently-executing function + * @proc: The name of the currently-executing built-in procedure + * @var: A list of the variables in this environment + * @vars: The number of variables in @var + * @varmap: A hash map mapping variable names to pointers to variables in @var + * @retval: The value set by "return" or "result" + * @retval_set: Whether @retval has been set + * @breakrun: Whether to immediately break out the current run of execution. + * This is set by "return" + * + * Variables are inherited from @parent. + */ struct lil_env { struct lil_env *parent; struct lil_func *func; @@ -69,12 +115,28 @@ struct lil_env { int breakrun; }; +/** + * struct list - A list of values + * @v: A list of pointers to &struct lil_value + * @c: The number of values in this list + * @cap: The space allocated for @v + */ struct lil_list { struct lil_value **v; size_t c; size_t cap; }; +/** + * struct lil_func - A function which may be evaluated with a list of arguments + * @name: The name of the function + * @code: A value containing LIL code to be evaluated + * @argnames: The names of variables to assign to the passed-in arguments + * @proc: A C function to use to evaluate this function + * + * @code and @argnames are only used to evaluate the function if @proc is %NULL. + * If @argnames is empty, then the arguments are assigned to a variable "args". + */ struct lil_func { char *name; struct lil_value *code; @@ -82,6 +144,31 @@ struct lil_func { lil_func_proc_t proc; }; +/** + * struct lil - The current state of the interpreter + * @code: The code which is being interpreted + * @rootcode: The top-level code (e.g. the code for the initial call to + * lil_parse()) + * @clen: The length of @code + * @head: The first uninterpreted part of this code, as an index of @code + * @ignoreeol: Whether to treat newlines as whitespace or command terminators + * @cmd: A list of the current commands + * @cmds: The number of commands in @cmd + * @cmdmap: A hash map mapping command names to pointers to commands in @cmd + * @env: The current environment to evaluate commands in + * @rootenv: The top-level "root" environment + * @downenv: The original environment after a call to "topeval" or "upeval" + * @empty: An empty value, allocated once + * @ERROR_NOERROR: There is no error. + * @ERROR_DEFAULT: There was an error. + * @ERROR_FIXHEAD: There was an error, but @err_head needs to be fixed. + * @ERROR_UNBALANCED: An opening quote or bracket lacks a balancing closing + * quote or bracket. + * @error: The current error status + * @err_head: The offset in @code which caused the @error + * @err_msg: An optional string describing the current @error + * @parse_depth: The depth of recursive function calls + */ struct lil { const char *code; /* need save on parse */ const char *rootcode; @@ -101,6 +188,19 @@ struct lil { size_t parse_depth; }; +/** + * struct expreval - A (mathematical) expression being evaluated + * @code: The complete code for this expression + * @len: The length of @code + * @head: The first unevaluated part of this expression, as an index of @code + * @ival: The integer value of this expression + * @EERR_NO_ERROR: There is no error + * @EERR_SYNTAX_ERROR: Syntax error. For now this is just mismatched + * parentheses. + * @EERR_DIVISION_BY_ZERO: Attempted division by zero + * @EERR_INVALID_EXPRESSION: A non-number was present + * @error: The error of this expression (if any) + */ struct expreval { const char *code; size_t len, head; diff --git a/include/cli_lil.h b/include/cli_lil.h index cdaa79fd15..91e79c12f4 100644 --- a/include/cli_lil.h +++ b/include/cli_lil.h @@ -13,10 +13,35 @@ #define LIL_VERSION_STRING "0.1" +/** + * enum lil_setvar - The strategy to use when creating new variables + */ enum lil_setvar { + /** + * @LIL_SETVAR_GLOBAL: Set in the root environment + */ LIL_SETVAR_GLOBAL = 0, + /** + * @LIL_SETVAR_LOCAL: Set, starting with the local environment + * + * Search for a variable. If one is found, overwrite it. Otherwise, + * create a new variable in the local environment. + */ LIL_SETVAR_LOCAL, + /** + * @LIL_SETVAR_LOCAL_NEW: Create in the local environment + * + * Create a new variable in the local environment. This never overrides + * existing variables (even if one exists in the local environment). + */ LIL_SETVAR_LOCAL_NEW, + /** + * @LIL_SETVAR_LOCAL_ONLY: Set in a local environment only + * + * Search for a variable in the local environment. If one is found, + * overwrite it. Otherwise, create a new variable in the local + * environment. + */ LIL_SETVAR_LOCAL_ONLY, }; @@ -32,9 +57,41 @@ struct lil; typedef struct lil_value *(*lil_func_proc_t)(struct lil *lil, size_t argc, struct lil_value **argv); +/** + * struct lil_callbacks - Functions called by LIL to allow overriding behavior + */ struct lil_callbacks { + /** + * @setvar: Called when a non-existent global variable is assigned + * + * @lil: The LIL interpreter + * + * @name: The name of the variable + * + * @value: A pointer to the value which would be assigned. This may be + * modified to assign a different value. + * + * This can be used to override or cancel the assignment of a variable + * + * @Return: A negative value to prevent the assignment, %0 to assign the + * original value, or a positive value to assign @value. + */ int (*setvar)(struct lil *lil, const char *name, struct lil_value **value); + /** + * @getvar: Called when a global variable is read + * + * @lil: The LIL interpreter + * + * @name The name of the variable + * + * @value: The pointer to the value which would be read. This may be + * modified to read a different value. + * + * @Return: A non-zero value to read the value pointed to by @value + * instead of the original value, or anything else to use the + * original value + */ int (*getvar)(struct lil *lil, const char *name, struct lil_value **value); }; -- 2.32.0