From 704c596563a5b4da4349b272d0c9c71aacea34a7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 15 Sep 2021 19:31:44 +0200 Subject: [PATCH] ash: introduce bash-like $FUNCNAME Patch adapted from Roberto A. Foglietta work. function old new delta lookupvar 106 150 +44 evalfun 369 408 +39 ash_main 1218 1242 +24 varinit_data 156 168 +12 .rodata 104162 104172 +10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/0 up/down: 129/0) Total: 129 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index b12b859d5..4bc4f55d0 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2158,6 +2158,7 @@ static const struct { { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset }, #endif { VSTRFIXED|VTEXTFIXED , NULL /* inited to linenovar */, NULL }, + { VSTRFIXED|VTEXTFIXED , NULL /* inited to funcnamevar */, NULL }, #if ENABLE_ASH_RANDOM_SUPPORT { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random }, #endif @@ -2184,6 +2185,8 @@ struct globals_var { struct var varinit[ARRAY_SIZE(varinit_data)]; int lineno; char linenovar[sizeof("LINENO=") + sizeof(int)*3]; + char funcnamevar[sizeof("FUNCNAME=") + 64]; + char *funcname; unsigned trap_depth; bool in_trap_ERR; /* ERR cannot recurse, no need to be a counter */ }; @@ -2196,6 +2199,8 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #define varinit (G_var.varinit ) #define lineno (G_var.lineno ) #define linenovar (G_var.linenovar ) +#define funcnamevar (G_var.funcnamevar ) +#define funcname (G_var.funcname ) #define trap_depth (G_var.trap_depth ) #define in_trap_ERR (G_var.in_trap_ERR ) #define vifs varinit[0] @@ -2213,13 +2218,14 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; #endif #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS) #define vlineno varinit[VAR_OFFSET2 + 5] +#define vfuncname varinit[VAR_OFFSET2 + 6] #if ENABLE_ASH_RANDOM_SUPPORT -# define vrandom varinit[VAR_OFFSET2 + 6] +# define vrandom varinit[VAR_OFFSET2 + 7] #endif #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT) #if BASH_EPOCH_VARS -# define vepochs varinit[VAR_OFFSET3 + 6] -# define vepochr varinit[VAR_OFFSET3 + 7] +# define vepochs varinit[VAR_OFFSET3 + 7] +# define vepochr varinit[VAR_OFFSET3 + 8] #endif #define INIT_G_var() do { \ unsigned i; \ @@ -2232,6 +2238,8 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var; } \ strcpy(linenovar, "LINENO="); \ vlineno.var_text = linenovar; \ + strcpy(funcnamevar, "FUNCNAME="); \ + vfuncname.var_text = funcnamevar; \ } while (0) /* @@ -2371,6 +2379,9 @@ lookupvar(const char *name) if (!(v->flags & VUNSET)) { if (v->var_text == linenovar) { fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno); + } else + if (v->var_text == funcnamevar) { + safe_strncpy(funcnamevar+9, funcname ? funcname : "", sizeof(funcnamevar)-9); } return var_end(v->var_text); } @@ -9875,6 +9886,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) int e; int savelineno; int savefuncline; + char *savefuncname; char *savetrap = NULL; if (!Eflag) { @@ -9884,6 +9896,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) savelineno = lineno; saveparam = shellparam; savefuncline = funcline; + savefuncname = funcname; savehandler = exception_handler; e = setjmp(jmploc.loc); if (e) { @@ -9893,6 +9906,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) exception_handler = &jmploc; shellparam.malloced = 0; func->count++; + funcname = func->n.ndefun.text; funcline = func->n.ndefun.linno; INT_ON; shellparam.nparam = argc - 1; @@ -9904,6 +9918,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags) evaltree(func->n.ndefun.body, flags & EV_TESTED); funcdone: INT_OFF; + funcname = savefuncname; if (savetrap) { if (!trap[NTRAP_ERR]) trap[NTRAP_ERR] = savetrap; @@ -13639,6 +13654,12 @@ exitcmd(int argc UNUSED_PARAM, char **argv) if (argv[1]) savestatus = number(argv[1]); +//TODO: this script +// trap 'echo trap:$FUNCNAME' EXIT +// f() { exit; } +// f +//prints "trap:f" in bash. We can call exitshell() here to achieve this. +//For now, keeping dash code: raise_exception(EXEXIT); /* NOTREACHED */ }