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>
diff --git a/shell/ash.c b/shell/ash.c
index b12b859..4bc4f55 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2158,6 +2158,7 @@
{ 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 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 @@
#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 @@
#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 @@
} \
strcpy(linenovar, "LINENO="); \
vlineno.var_text = linenovar; \
+ strcpy(funcnamevar, "FUNCNAME="); \
+ vfuncname.var_text = funcnamevar; \
} while (0)
/*
@@ -2371,6 +2379,9 @@
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 @@
int e;
int savelineno;
int savefuncline;
+ char *savefuncname;
char *savetrap = NULL;
if (!Eflag) {
@@ -9884,6 +9896,7 @@
savelineno = lineno;
saveparam = shellparam;
savefuncline = funcline;
+ savefuncname = funcname;
savehandler = exception_handler;
e = setjmp(jmploc.loc);
if (e) {
@@ -9893,6 +9906,7 @@
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 @@
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 @@
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 */
}