ash: introduce bash-like $FUNCNAME

Patch adapted from Roberto A. Foglietta <roberto.foglietta@gmail.com>
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 <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2021-09-15 19:31:44 +02:00
parent 3512ef8018
commit 704c596563

View File

@ -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 */
}