aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c330
1 files changed, 251 insertions, 79 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 81845dc60..36ddda1bc 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -66,6 +66,22 @@
66//config: default y 66//config: default y
67//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH 67//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH
68//config: 68//config:
69//config:config ASH_BASH_SOURCE_CURDIR
70//config: bool "'source' and '.' builtins search current directory after $PATH"
71//config: default n # do not encourage non-standard behavior
72//config: depends on ASH_BASH_COMPAT
73//config: help
74//config: This is not compliant with standards. Avoid if possible.
75//config:
76//config:config ASH_BASH_NOT_FOUND_HOOK
77//config: bool "command_not_found_handle hook support"
78//config: default y
79//config: depends on ASH_BASH_COMPAT
80//config: help
81//config: Enable support for the 'command_not_found_handle' hook function,
82//config: from GNU bash, which allows for alternative command not found
83//config: handling.
84//config:
69//config:config ASH_JOB_CONTROL 85//config:config ASH_JOB_CONTROL
70//config: bool "Job control" 86//config: bool "Job control"
71//config: default y 87//config: default y
@@ -278,6 +294,19 @@ typedef long arith_t;
278# error "Do not even bother, ash will not run on NOMMU machine" 294# error "Do not even bother, ash will not run on NOMMU machine"
279#endif 295#endif
280 296
297/* We use a trick to have more optimized code (fewer pointer reloads):
298 * ash.c: extern struct globals *const ash_ptr_to_globals;
299 * ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
300 * This way, compiler in ash.c knows the pointer can not change.
301 *
302 * However, this may break on weird arches or toolchains. In this case,
303 * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
304 * this optimization.
305 */
306#ifndef BB_GLOBAL_CONST
307# define BB_GLOBAL_CONST const
308#endif
309
281#if ENABLE_PLATFORM_MINGW32 310#if ENABLE_PLATFORM_MINGW32
282union node; 311union node;
283struct strlist; 312struct strlist;
@@ -393,6 +422,8 @@ struct globals_misc {
393 /* shell level: 0 for the main shell, 1 for its children, and so on */ 422 /* shell level: 0 for the main shell, 1 for its children, and so on */
394 int shlvl; 423 int shlvl;
395#define rootshell (!shlvl) 424#define rootshell (!shlvl)
425 int errlinno;
426
396 char *minusc; /* argument to -c option */ 427 char *minusc; /* argument to -c option */
397 428
398 char *curdir; // = nullstr; /* current working directory */ 429 char *curdir; // = nullstr; /* current working directory */
@@ -469,13 +500,14 @@ struct globals_misc {
469#endif 500#endif
470 pid_t backgndpid; /* pid of last background process */ 501 pid_t backgndpid; /* pid of last background process */
471}; 502};
472extern struct globals_misc *const ash_ptr_to_globals_misc; 503extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
473#define G_misc (*ash_ptr_to_globals_misc) 504#define G_misc (*ash_ptr_to_globals_misc)
474#define exitstatus (G_misc.exitstatus ) 505#define exitstatus (G_misc.exitstatus )
475#define back_exitstatus (G_misc.back_exitstatus ) 506#define back_exitstatus (G_misc.back_exitstatus )
476#define job_warning (G_misc.job_warning) 507#define job_warning (G_misc.job_warning)
477#define rootpid (G_misc.rootpid ) 508#define rootpid (G_misc.rootpid )
478#define shlvl (G_misc.shlvl ) 509#define shlvl (G_misc.shlvl )
510#define errlinno (G_misc.errlinno )
479#define minusc (G_misc.minusc ) 511#define minusc (G_misc.minusc )
480#define curdir (G_misc.curdir ) 512#define curdir (G_misc.curdir )
481#define physdir (G_misc.physdir ) 513#define physdir (G_misc.physdir )
@@ -810,6 +842,7 @@ union node;
810 842
811struct ncmd { 843struct ncmd {
812 smallint type; /* Nxxxx */ 844 smallint type; /* Nxxxx */
845 int linno;
813 union node *assign; 846 union node *assign;
814 union node *args; 847 union node *args;
815 union node *redirect; 848 union node *redirect;
@@ -823,6 +856,7 @@ struct npipe {
823 856
824struct nredir { 857struct nredir {
825 smallint type; 858 smallint type;
859 int linno;
826 union node *n; 860 union node *n;
827 union node *redirect; 861 union node *redirect;
828}; 862};
@@ -842,6 +876,7 @@ struct nif {
842 876
843struct nfor { 877struct nfor {
844 smallint type; 878 smallint type;
879 int linno;
845 union node *args; 880 union node *args;
846 union node *body; 881 union node *body;
847 char *var; 882 char *var;
@@ -849,6 +884,7 @@ struct nfor {
849 884
850struct ncase { 885struct ncase {
851 smallint type; 886 smallint type;
887 int linno;
852 union node *expr; 888 union node *expr;
853 union node *cases; 889 union node *cases;
854}; 890};
@@ -860,6 +896,13 @@ struct nclist {
860 union node *body; 896 union node *body;
861}; 897};
862 898
899struct ndefun {
900 smallint type;
901 int linno;
902 char *text;
903 union node *body;
904};
905
863struct narg { 906struct narg {
864 smallint type; 907 smallint type;
865 union node *next; 908 union node *next;
@@ -911,6 +954,7 @@ union node {
911 struct nfor nfor; 954 struct nfor nfor;
912 struct ncase ncase; 955 struct ncase ncase;
913 struct nclist nclist; 956 struct nclist nclist;
957 struct ndefun ndefun;
914 struct narg narg; 958 struct narg narg;
915 struct nfile nfile; 959 struct nfile nfile;
916 struct ndup ndup; 960 struct ndup ndup;
@@ -1340,7 +1384,6 @@ struct parsefile {
1340 1384
1341static struct parsefile basepf; /* top level input file */ 1385static struct parsefile basepf; /* top level input file */
1342static struct parsefile *g_parsefile = &basepf; /* current input file */ 1386static struct parsefile *g_parsefile = &basepf; /* current input file */
1343static int startlinno; /* line # where last token started */
1344static char *commandname; /* currently executing command */ 1387static char *commandname; /* currently executing command */
1345 1388
1346 1389
@@ -1354,7 +1397,7 @@ ash_vmsg(const char *msg, va_list ap)
1354 if (strcmp(arg0, commandname)) 1397 if (strcmp(arg0, commandname))
1355 fprintf(stderr, "%s: ", commandname); 1398 fprintf(stderr, "%s: ", commandname);
1356 if (!iflag || g_parsefile->pf_fd > 0) 1399 if (!iflag || g_parsefile->pf_fd > 0)
1357 fprintf(stderr, "line %d: ", startlinno); 1400 fprintf(stderr, "line %d: ", errlinno);
1358 } 1401 }
1359 vfprintf(stderr, msg, ap); 1402 vfprintf(stderr, msg, ap);
1360 newline_and_flush(stderr); 1403 newline_and_flush(stderr);
@@ -1407,6 +1450,7 @@ static void raise_error_syntax(const char *) NORETURN;
1407static void 1450static void
1408raise_error_syntax(const char *msg) 1451raise_error_syntax(const char *msg)
1409{ 1452{
1453 errlinno = g_parsefile->linno;
1410 ash_msg_and_raise_error("syntax error: %s", msg); 1454 ash_msg_and_raise_error("syntax error: %s", msg);
1411 /* NOTREACHED */ 1455 /* NOTREACHED */
1412} 1456}
@@ -1529,7 +1573,7 @@ struct globals_memstack {
1529 size_t g_stacknleft; // = MINSIZE; 1573 size_t g_stacknleft; // = MINSIZE;
1530 struct stack_block stackbase; 1574 struct stack_block stackbase;
1531}; 1575};
1532extern struct globals_memstack *const ash_ptr_to_globals_memstack; 1576extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1533#define G_memstack (*ash_ptr_to_globals_memstack) 1577#define G_memstack (*ash_ptr_to_globals_memstack)
1534#define g_stackp (G_memstack.g_stackp ) 1578#define g_stackp (G_memstack.g_stackp )
1535#define g_stacknxt (G_memstack.g_stacknxt ) 1579#define g_stacknxt (G_memstack.g_stacknxt )
@@ -1619,7 +1663,7 @@ sstrdup(const char *p)
1619 return memcpy(stalloc(len), p, len); 1663 return memcpy(stalloc(len), p, len);
1620} 1664}
1621 1665
1622static inline void 1666static ALWAYS_INLINE void
1623grabstackblock(size_t len) 1667grabstackblock(size_t len)
1624{ 1668{
1625 stalloc(len); 1669 stalloc(len);
@@ -2094,6 +2138,7 @@ static const struct {
2094#if ENABLE_ASH_GETOPTS 2138#if ENABLE_ASH_GETOPTS
2095 { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset }, 2139 { VSTRFIXED|VTEXTFIXED , defoptindvar, getoptsreset },
2096#endif 2140#endif
2141 { VSTRFIXED|VTEXTFIXED , NULL /* inited to linenovar */, NULL },
2097#if ENABLE_ASH_RANDOM_SUPPORT 2142#if ENABLE_ASH_RANDOM_SUPPORT
2098 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random }, 2143 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2099#endif 2144#endif
@@ -2114,25 +2159,18 @@ struct globals_var {
2114 int preverrout_fd; /* stderr fd: usually 2, unless redirect moved it */ 2159 int preverrout_fd; /* stderr fd: usually 2, unless redirect moved it */
2115 struct var *vartab[VTABSIZE]; 2160 struct var *vartab[VTABSIZE];
2116 struct var varinit[ARRAY_SIZE(varinit_data)]; 2161 struct var varinit[ARRAY_SIZE(varinit_data)];
2162 int lineno;
2163 char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2117}; 2164};
2118extern struct globals_var *const ash_ptr_to_globals_var; 2165extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2119#define G_var (*ash_ptr_to_globals_var) 2166#define G_var (*ash_ptr_to_globals_var)
2120#define shellparam (G_var.shellparam ) 2167#define shellparam (G_var.shellparam )
2121//#define redirlist (G_var.redirlist ) 2168//#define redirlist (G_var.redirlist )
2122#define preverrout_fd (G_var.preverrout_fd) 2169#define preverrout_fd (G_var.preverrout_fd)
2123#define vartab (G_var.vartab ) 2170#define vartab (G_var.vartab )
2124#define varinit (G_var.varinit ) 2171#define varinit (G_var.varinit )
2125#define INIT_G_var() do { \ 2172#define lineno (G_var.lineno )
2126 unsigned i; \ 2173#define linenovar (G_var.linenovar )
2127 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2128 barrier(); \
2129 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2130 varinit[i].flags = varinit_data[i].flags; \
2131 varinit[i].var_text = varinit_data[i].var_text; \
2132 varinit[i].var_func = varinit_data[i].var_func; \
2133 } \
2134} while (0)
2135
2136#define vifs varinit[0] 2174#define vifs varinit[0]
2137#if ENABLE_ASH_MAIL 2175#if ENABLE_ASH_MAIL
2138# define vmail (&vifs)[1] 2176# define vmail (&vifs)[1]
@@ -2146,14 +2184,28 @@ extern struct globals_var *const ash_ptr_to_globals_var;
2146#define vps4 (&vps2)[1] 2184#define vps4 (&vps2)[1]
2147#if ENABLE_ASH_GETOPTS 2185#if ENABLE_ASH_GETOPTS
2148# define voptind (&vps4)[1] 2186# define voptind (&vps4)[1]
2187# define vlineno (&voptind)[1]
2149# if ENABLE_ASH_RANDOM_SUPPORT 2188# if ENABLE_ASH_RANDOM_SUPPORT
2150# define vrandom (&voptind)[1] 2189# define vrandom (&vlineno)[1]
2151# endif 2190# endif
2152#else 2191#else
2192# define vlineno (&vps4)[1]
2153# if ENABLE_ASH_RANDOM_SUPPORT 2193# if ENABLE_ASH_RANDOM_SUPPORT
2154# define vrandom (&vps4)[1] 2194# define vrandom (&vlineno)[1]
2155# endif 2195# endif
2156#endif 2196#endif
2197#define INIT_G_var() do { \
2198 unsigned i; \
2199 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2200 barrier(); \
2201 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2202 varinit[i].flags = varinit_data[i].flags; \
2203 varinit[i].var_text = varinit_data[i].var_text; \
2204 varinit[i].var_func = varinit_data[i].var_func; \
2205 } \
2206 strcpy(linenovar, "LINENO="); \
2207 vlineno.var_text = linenovar; \
2208} while (0)
2157 2209
2158/* 2210/*
2159 * The following macros access the values of the above variables. 2211 * The following macros access the values of the above variables.
@@ -2289,8 +2341,12 @@ lookupvar(const char *name)
2289 if (v->flags & VDYNAMIC) 2341 if (v->flags & VDYNAMIC)
2290 v->var_func(NULL); 2342 v->var_func(NULL);
2291#endif 2343#endif
2292 if (!(v->flags & VUNSET)) 2344 if (!(v->flags & VUNSET)) {
2345 if (v == &vlineno && v->var_text == linenovar) {
2346 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2347 }
2293 return var_end(v->var_text); 2348 return var_end(v->var_text);
2349 }
2294 } 2350 }
2295 return NULL; 2351 return NULL;
2296} 2352}
@@ -5125,7 +5181,7 @@ cmdtxt(union node *n)
5125 p = "; done"; 5181 p = "; done";
5126 goto dodo; 5182 goto dodo;
5127 case NDEFUN: 5183 case NDEFUN:
5128 cmdputs(n->narg.text); 5184 cmdputs(n->ndefun.text);
5129 p = "() { ... }"; 5185 p = "() { ... }";
5130 goto dotail2; 5186 goto dotail2;
5131 case NCMD: 5187 case NCMD:
@@ -6151,6 +6207,26 @@ ash_arith(const char *s)
6151 return result; 6207 return result;
6152} 6208}
6153#endif 6209#endif
6210#if BASH_SUBSTR
6211# if ENABLE_FEATURE_SH_MATH
6212static int substr_atoi(const char *s)
6213{
6214 arith_t t = ash_arith(s);
6215 if (sizeof(t) > sizeof(int)) {
6216 /* clamp very large or very large negative nums for ${v:N:M}:
6217 * else "${v:0:0x100000001}" would work as "${v:0:1}"
6218 */
6219 if (t > INT_MAX)
6220 t = INT_MAX;
6221 if (t < INT_MIN)
6222 t = INT_MIN;
6223 }
6224 return t;
6225}
6226# else
6227# define substr_atoi(s) number(s)
6228# endif
6229#endif
6154 6230
6155/* 6231/*
6156 * expandarg flags 6232 * expandarg flags
@@ -6182,7 +6258,6 @@ ash_arith(const char *s)
6182#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ 6258#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
6183#define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ 6259#define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
6184#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ 6260#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
6185#define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */
6186 6261
6187/* Add CTLESC when necessary. */ 6262/* Add CTLESC when necessary. */
6188#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT) 6263#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT)
@@ -6363,8 +6438,12 @@ esclen(const char *start, const char *p)
6363/* 6438/*
6364 * Remove any CTLESC characters from a string. 6439 * Remove any CTLESC characters from a string.
6365 */ 6440 */
6441#if !BASH_PATTERN_SUBST
6442#define rmescapes(str, flag, slash_position) \
6443 rmescapes(str, flag)
6444#endif
6366static char * 6445static char *
6367rmescapes(char *str, int flag) 6446rmescapes(char *str, int flag, int *slash_position)
6368{ 6447{
6369 static const char qchars[] ALIGN1 = { 6448 static const char qchars[] ALIGN1 = {
6370 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' }; 6449 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
@@ -6373,9 +6452,8 @@ rmescapes(char *str, int flag)
6373 unsigned inquotes; 6452 unsigned inquotes;
6374 unsigned protect_against_glob; 6453 unsigned protect_against_glob;
6375 unsigned globbing; 6454 unsigned globbing;
6376 IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
6377 6455
6378 p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash)); 6456 p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6379 if (!p) 6457 if (!p)
6380 return str; 6458 return str;
6381 6459
@@ -6455,10 +6533,11 @@ rmescapes(char *str, int flag)
6455 goto copy; 6533 goto copy;
6456 } 6534 }
6457#if BASH_PATTERN_SUBST 6535#if BASH_PATTERN_SUBST
6458 else if (*p == '/' && slash) { 6536 else if (slash_position && p == str + *slash_position) {
6459 /* stop handling globbing and mark location of slash */ 6537 /* stop handling globbing */
6460 globbing = slash = 0; 6538 globbing = 0;
6461 *p = CTLESC; 6539 *slash_position = q - r;
6540 slash_position = NULL;
6462 } 6541 }
6463#endif 6542#endif
6464 protect_against_glob = globbing; 6543 protect_against_glob = globbing;
@@ -6482,7 +6561,7 @@ rmescapes(char *str, int flag)
6482static char * 6561static char *
6483preglob(const char *pattern, int flag) 6562preglob(const char *pattern, int flag)
6484{ 6563{
6485 return rmescapes((char *)pattern, flag | RMESCAPE_GLOB); 6564 return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6486} 6565}
6487 6566
6488/* 6567/*
@@ -6837,7 +6916,7 @@ expari(int flag)
6837 expdest = p; 6916 expdest = p;
6838 6917
6839 if (flag & QUOTES_ESC) 6918 if (flag & QUOTES_ESC)
6840 rmescapes(p + 1, 0); 6919 rmescapes(p + 1, 0, NULL);
6841 6920
6842 len = cvtnum(ash_arith(p + 1)); 6921 len = cvtnum(ash_arith(p + 1));
6843 6922
@@ -7125,20 +7204,58 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7125 char *rmesc, *rmescend; 7204 char *rmesc, *rmescend;
7126 char *str; 7205 char *str;
7127 int amount, resetloc; 7206 int amount, resetloc;
7207 int argstr_flags;
7128 IF_BASH_PATTERN_SUBST(int workloc;) 7208 IF_BASH_PATTERN_SUBST(int workloc;)
7129 IF_BASH_PATTERN_SUBST(char *repl = NULL;) 7209 IF_BASH_PATTERN_SUBST(int slash_pos;)
7210 IF_BASH_PATTERN_SUBST(char *repl;)
7130 int zero; 7211 int zero;
7131 char *(*scan)(char*, char*, char*, char*, int, int); 7212 char *(*scan)(char*, char*, char*, char*, int, int);
7132 7213
7133 //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)", 7214 //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
7134 // p, varname, strloc, subtype, startloc, varflags, quotes); 7215 // p, varname, strloc, subtype, startloc, varflags, quotes);
7135 7216
7136 argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? 7217#if BASH_PATTERN_SUBST
7137 (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0) 7218 /* For "${v/pattern/repl}", we must find the delimiter _before_
7138 ); 7219 * argstr() call expands possible variable references in pattern:
7220 * think about "v=a; a=a/; echo ${v/$a/r}" case.
7221 */
7222 repl = NULL;
7223 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7224 /* Find '/' and replace with NUL */
7225 repl = p;
7226 for (;;) {
7227 /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
7228 if (*repl == '\0') {
7229 repl = NULL;
7230 break;
7231 }
7232 if (*repl == '/') {
7233 *repl = '\0';
7234 break;
7235 }
7236 if ((unsigned char)*repl == CTLESC && repl[1])
7237 repl++;
7238 repl++;
7239 }
7240 }
7241#endif
7242 argstr_flags = EXP_TILDE;
7243 if (subtype != VSASSIGN && subtype != VSQUESTION)
7244 argstr_flags |= (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE);
7245 argstr(p, argstr_flags);
7246#if BASH_PATTERN_SUBST
7247 slash_pos = -1;
7248 if (repl) {
7249 slash_pos = expdest - ((char *)stackblock() + strloc);
7250 STPUTC('/', expdest);
7251 argstr(repl + 1, argstr_flags);
7252 *repl = '/';
7253 }
7254#endif
7139 STPUTC('\0', expdest); 7255 STPUTC('\0', expdest);
7140 argbackq = saveargbackq; 7256 argbackq = saveargbackq;
7141 startp = (char *)stackblock() + startloc; 7257 startp = (char *)stackblock() + startloc;
7258 //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
7142 7259
7143 switch (subtype) { 7260 switch (subtype) {
7144 case VSASSIGN: 7261 case VSASSIGN:
@@ -7158,13 +7275,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7158 7275
7159 loc = str = stackblock() + strloc; 7276 loc = str = stackblock() + strloc;
7160 7277
7161# if !ENABLE_FEATURE_SH_MATH
7162# define ash_arith number
7163# endif
7164 /* Read POS in ${var:POS:LEN} */ 7278 /* Read POS in ${var:POS:LEN} */
7165 colon = strchr(loc, ':'); 7279 colon = strchr(loc, ':');
7166 if (colon) *colon = '\0'; 7280 if (colon) *colon = '\0';
7167 pos = ash_arith(loc); 7281 pos = substr_atoi(loc);
7168 if (colon) *colon = ':'; 7282 if (colon) *colon = ':';
7169 7283
7170 /* Read LEN in ${var:POS:LEN} */ 7284 /* Read LEN in ${var:POS:LEN} */
@@ -7172,7 +7286,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7172 /* *loc != '\0', guaranteed by parser */ 7286 /* *loc != '\0', guaranteed by parser */
7173 if (quotes) { 7287 if (quotes) {
7174 char *ptr; 7288 char *ptr;
7175
7176 /* Adjust the length by the number of escapes */ 7289 /* Adjust the length by the number of escapes */
7177 for (ptr = startp; ptr < (str - 1); ptr++) { 7290 for (ptr = startp; ptr < (str - 1); ptr++) {
7178 if ((unsigned char)*ptr == CTLESC) { 7291 if ((unsigned char)*ptr == CTLESC) {
@@ -7184,19 +7297,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7184 orig_len = len; 7297 orig_len = len;
7185 if (*loc++ == ':') { 7298 if (*loc++ == ':') {
7186 /* ${var::LEN} */ 7299 /* ${var::LEN} */
7187 len = ash_arith(loc); 7300 len = substr_atoi(loc);
7188 } else { 7301 } else {
7189 /* Skip POS in ${var:POS:LEN} */ 7302 /* Skip POS in ${var:POS:LEN} */
7190 len = orig_len; 7303 len = orig_len;
7191 while (*loc && *loc != ':') { 7304 while (*loc && *loc != ':')
7192 loc++; 7305 loc++;
7193 } 7306 if (*loc++ == ':')
7194 if (*loc++ == ':') { 7307 len = substr_atoi(loc);
7195 len = ash_arith(loc);
7196 }
7197 } 7308 }
7198# undef ash_arith
7199
7200 if (pos < 0) { 7309 if (pos < 0) {
7201 /* ${VAR:$((-n)):l} starts n chars from the end */ 7310 /* ${VAR:$((-n)):l} starts n chars from the end */
7202 pos = orig_len + pos; 7311 pos = orig_len + pos;
@@ -7236,6 +7345,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7236 resetloc = expdest - (char *)stackblock(); 7345 resetloc = expdest - (char *)stackblock();
7237 7346
7238#if BASH_PATTERN_SUBST 7347#if BASH_PATTERN_SUBST
7348 repl = NULL;
7349
7239 /* We'll comeback here if we grow the stack while handling 7350 /* We'll comeback here if we grow the stack while handling
7240 * a VSREPLACE or VSREPLACEALL, since our pointers into the 7351 * a VSREPLACE or VSREPLACEALL, since our pointers into the
7241 * stack will need rebasing, and we'll need to remove our work 7352 * stack will need rebasing, and we'll need to remove our work
@@ -7250,8 +7361,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7250 7361
7251 rmesc = startp; 7362 rmesc = startp;
7252 rmescend = (char *)stackblock() + strloc; 7363 rmescend = (char *)stackblock() + strloc;
7364 //bb_error_msg("str7:'%s'", rmescend);
7253 if (quotes) { 7365 if (quotes) {
7254 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW); 7366//TODO: how to handle slash_pos here if string changes (shortens?)
7367 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7255 if (rmesc != startp) { 7368 if (rmesc != startp) {
7256 rmescend = expdest; 7369 rmescend = expdest;
7257 startp = (char *)stackblock() + startloc; 7370 startp = (char *)stackblock() + startloc;
@@ -7264,12 +7377,13 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7264 * The result is a_\_z_c (not a\_\_z_c)! 7377 * The result is a_\_z_c (not a\_\_z_c)!
7265 * 7378 *
7266 * The search pattern and replace string treat backslashes differently! 7379 * The search pattern and replace string treat backslashes differently!
7267 * RMESCAPE_SLASH causes preglob to work differently on the pattern 7380 * "&slash_pos" causes rmescapes() to work differently on the pattern
7268 * and string. It's only used on the first call. 7381 * and string. It's only used on the first call.
7269 */ 7382 */
7270 preglob(str, IF_BASH_PATTERN_SUBST( 7383 //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7271 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? 7384 rmescapes(str, RMESCAPE_GLOB,
7272 RMESCAPE_SLASH : ) 0); 7385 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7386 );
7273 7387
7274#if BASH_PATTERN_SUBST 7388#if BASH_PATTERN_SUBST
7275 workloc = expdest - (char *)stackblock(); 7389 workloc = expdest - (char *)stackblock();
@@ -7278,11 +7392,12 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
7278 char *idx, *end; 7392 char *idx, *end;
7279 7393
7280 if (!repl) { 7394 if (!repl) {
7281 repl = strchr(str, CTLESC); 7395 //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7282 if (repl) 7396 repl = nullstr;
7397 if (slash_pos >= 0) {
7398 repl = str + slash_pos;
7283 *repl++ = '\0'; 7399 *repl++ = '\0';
7284 else 7400 }
7285 repl = nullstr;
7286 } 7401 }
7287 //bb_error_msg("str:'%s' repl:'%s'", str, repl); 7402 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7288 7403
@@ -7802,7 +7917,7 @@ expandmeta(struct strlist *str /*, int flag*/)
7802 INT_ON; 7917 INT_ON;
7803 nometa: 7918 nometa:
7804 *exparg.lastp = str; 7919 *exparg.lastp = str;
7805 rmescapes(str->text, 0); 7920 rmescapes(str->text, 0, NULL);
7806 exparg.lastp = &str->next; 7921 exparg.lastp = &str->next;
7807 break; 7922 break;
7808 default: /* GLOB_NOSPACE */ 7923 default: /* GLOB_NOSPACE */
@@ -8031,7 +8146,7 @@ expandmeta(struct strlist *str /*, int flag*/)
8031 */ 8146 */
8032 nometa: 8147 nometa:
8033 *exparg.lastp = str; 8148 *exparg.lastp = str;
8034 rmescapes(str->text, 0); 8149 rmescapes(str->text, 0, NULL);
8035 exparg.lastp = &str->next; 8150 exparg.lastp = &str->next;
8036 } else { 8151 } else {
8037 *exparg.lastp = NULL; 8152 *exparg.lastp = NULL;
@@ -8970,6 +9085,10 @@ calcsize(union node *n)
8970 IF_PLATFORM_MINGW32(nodeptrsize += 3); 9085 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8971 break; 9086 break;
8972 case NDEFUN: 9087 case NDEFUN:
9088 calcsize(n->ndefun.body);
9089 funcstringsize += strlen(n->ndefun.text) + 1;
9090 IF_PLATFORM_MINGW32(nodeptrsize += 2);
9091 break;
8973 case NARG: 9092 case NARG:
8974 sizenodelist(n->narg.backquote); 9093 sizenodelist(n->narg.backquote);
8975 funcstringsize += strlen(n->narg.text) + 1; 9094 funcstringsize += strlen(n->narg.text) + 1;
@@ -9067,6 +9186,7 @@ copynode(union node *n)
9067 new->ncmd.redirect = copynode(n->ncmd.redirect); 9186 new->ncmd.redirect = copynode(n->ncmd.redirect);
9068 new->ncmd.args = copynode(n->ncmd.args); 9187 new->ncmd.args = copynode(n->ncmd.args);
9069 new->ncmd.assign = copynode(n->ncmd.assign); 9188 new->ncmd.assign = copynode(n->ncmd.assign);
9189 new->ncmd.linno = n->ncmd.linno;
9070 SAVE_PTR3(new->ncmd.redirect,new->ncmd.args, new->ncmd.assign); 9190 SAVE_PTR3(new->ncmd.redirect,new->ncmd.args, new->ncmd.assign);
9071 break; 9191 break;
9072 case NPIPE: 9192 case NPIPE:
@@ -9079,6 +9199,7 @@ copynode(union node *n)
9079 case NSUBSHELL: 9199 case NSUBSHELL:
9080 new->nredir.redirect = copynode(n->nredir.redirect); 9200 new->nredir.redirect = copynode(n->nredir.redirect);
9081 new->nredir.n = copynode(n->nredir.n); 9201 new->nredir.n = copynode(n->nredir.n);
9202 new->nredir.linno = n->nredir.linno;
9082 SAVE_PTR2(new->nredir.redirect,new->nredir.n); 9203 SAVE_PTR2(new->nredir.redirect,new->nredir.n);
9083 break; 9204 break;
9084 case NAND: 9205 case NAND:
@@ -9100,11 +9221,13 @@ copynode(union node *n)
9100 new->nfor.var = nodeckstrdup(n->nfor.var); 9221 new->nfor.var = nodeckstrdup(n->nfor.var);
9101 new->nfor.body = copynode(n->nfor.body); 9222 new->nfor.body = copynode(n->nfor.body);
9102 new->nfor.args = copynode(n->nfor.args); 9223 new->nfor.args = copynode(n->nfor.args);
9224 new->nfor.linno = n->nfor.linno;
9103 SAVE_PTR3(new->nfor.var,new->nfor.body,new->nfor.args); 9225 SAVE_PTR3(new->nfor.var,new->nfor.body,new->nfor.args);
9104 break; 9226 break;
9105 case NCASE: 9227 case NCASE:
9106 new->ncase.cases = copynode(n->ncase.cases); 9228 new->ncase.cases = copynode(n->ncase.cases);
9107 new->ncase.expr = copynode(n->ncase.expr); 9229 new->ncase.expr = copynode(n->ncase.expr);
9230 new->ncase.linno = n->ncase.linno;
9108 SAVE_PTR2(new->ncase.cases,new->ncase.expr); 9231 SAVE_PTR2(new->ncase.cases,new->ncase.expr);
9109 break; 9232 break;
9110 case NCLIST: 9233 case NCLIST:
@@ -9114,6 +9237,11 @@ copynode(union node *n)
9114 SAVE_PTR3(new->nclist.body,new->nclist.pattern,new->nclist.next); 9237 SAVE_PTR3(new->nclist.body,new->nclist.pattern,new->nclist.next);
9115 break; 9238 break;
9116 case NDEFUN: 9239 case NDEFUN:
9240 new->ndefun.body = copynode(n->ndefun.body);
9241 new->ndefun.text = nodeckstrdup(n->ndefun.text);
9242 new->ndefun.linno = n->ndefun.linno;
9243 SAVE_PTR2(new->ndefun.body,new->ndefun.text);
9244 break;
9117 case NARG: 9245 case NARG:
9118 new->narg.backquote = copynodelist(n->narg.backquote); 9246 new->narg.backquote = copynodelist(n->narg.backquote);
9119 new->narg.text = nodeckstrdup(n->narg.text); 9247 new->narg.text = nodeckstrdup(n->narg.text);
@@ -9190,7 +9318,7 @@ defun(union node *func)
9190 INT_OFF; 9318 INT_OFF;
9191 entry.cmdtype = CMDFUNCTION; 9319 entry.cmdtype = CMDFUNCTION;
9192 entry.u.func = copyfunc(func); 9320 entry.u.func = copyfunc(func);
9193 addcmdentry(func->narg.text, &entry); 9321 addcmdentry(func->ndefun.text, &entry);
9194 INT_ON; 9322 INT_ON;
9195} 9323}
9196 9324
@@ -9200,8 +9328,8 @@ defun(union node *func)
9200#define SKIPFUNC (1 << 2) 9328#define SKIPFUNC (1 << 2)
9201static smallint evalskip; /* set to SKIPxxx if we are skipping commands */ 9329static smallint evalskip; /* set to SKIPxxx if we are skipping commands */
9202static int skipcount; /* number of levels to skip */ 9330static int skipcount; /* number of levels to skip */
9203static int funcnest; /* depth of function calls */
9204static int loopnest; /* current loop nesting level */ 9331static int loopnest; /* current loop nesting level */
9332static int funcline; /* starting line number of current function, or 0 if not in a function */
9205 9333
9206/* Forward decl way out to parsing code - dotrap needs it */ 9334/* Forward decl way out to parsing code - dotrap needs it */
9207static int evalstring(char *s, int flags); 9335static int evalstring(char *s, int flags);
@@ -9296,6 +9424,9 @@ evaltree(union node *n, int flags)
9296 status = !evaltree(n->nnot.com, EV_TESTED); 9424 status = !evaltree(n->nnot.com, EV_TESTED);
9297 goto setstatus; 9425 goto setstatus;
9298 case NREDIR: 9426 case NREDIR:
9427 errlinno = lineno = n->nredir.linno;
9428 if (funcline)
9429 lineno -= funcline - 1;
9299 expredir(n->nredir.redirect); 9430 expredir(n->nredir.redirect);
9300 pushredir(n->nredir.redirect); 9431 pushredir(n->nredir.redirect);
9301 status = redirectsafe(n->nredir.redirect, REDIR_PUSH); 9432 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
@@ -9450,6 +9581,10 @@ evalfor(union node *n, int flags)
9450 struct stackmark smark; 9581 struct stackmark smark;
9451 int status = 0; 9582 int status = 0;
9452 9583
9584 errlinno = lineno = n->ncase.linno;
9585 if (funcline)
9586 lineno -= funcline - 1;
9587
9453 setstackmark(&smark); 9588 setstackmark(&smark);
9454 arglist.list = NULL; 9589 arglist.list = NULL;
9455 arglist.lastp = &arglist.list; 9590 arglist.lastp = &arglist.list;
@@ -9481,6 +9616,10 @@ evalcase(union node *n, int flags)
9481 struct stackmark smark; 9616 struct stackmark smark;
9482 int status = 0; 9617 int status = 0;
9483 9618
9619 errlinno = lineno = n->ncase.linno;
9620 if (funcline)
9621 lineno -= funcline - 1;
9622
9484 setstackmark(&smark); 9623 setstackmark(&smark);
9485 arglist.list = NULL; 9624 arglist.list = NULL;
9486 arglist.lastp = &arglist.list; 9625 arglist.lastp = &arglist.list;
@@ -9516,6 +9655,10 @@ evalsubshell(union node *n, int flags)
9516 int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */ 9655 int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9517 int status; 9656 int status;
9518 9657
9658 errlinno = lineno = n->nredir.linno;
9659 if (funcline)
9660 lineno -= funcline - 1;
9661
9519 expredir(n->nredir.redirect); 9662 expredir(n->nredir.redirect);
9520 if (!backgnd && (flags & EV_EXIT) && !may_have_traps) 9663 if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9521 goto nofork; 9664 goto nofork;
@@ -9846,8 +9989,10 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
9846 struct jmploc *volatile savehandler; 9989 struct jmploc *volatile savehandler;
9847 struct jmploc jmploc; 9990 struct jmploc jmploc;
9848 int e; 9991 int e;
9992 int savefuncline;
9849 9993
9850 saveparam = shellparam; 9994 saveparam = shellparam;
9995 savefuncline = funcline;
9851 savehandler = exception_handler; 9996 savehandler = exception_handler;
9852 e = setjmp(jmploc.loc); 9997 e = setjmp(jmploc.loc);
9853 if (e) { 9998 if (e) {
@@ -9857,7 +10002,7 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
9857 exception_handler = &jmploc; 10002 exception_handler = &jmploc;
9858 shellparam.malloced = 0; 10003 shellparam.malloced = 0;
9859 func->count++; 10004 func->count++;
9860 funcnest++; 10005 funcline = func->n.ndefun.linno;
9861 INT_ON; 10006 INT_ON;
9862 shellparam.nparam = argc - 1; 10007 shellparam.nparam = argc - 1;
9863 shellparam.p = argv + 1; 10008 shellparam.p = argv + 1;
@@ -9866,11 +10011,11 @@ evalfun(struct funcnode *func, int argc, char **argv, int flags)
9866 shellparam.optoff = -1; 10011 shellparam.optoff = -1;
9867#endif 10012#endif
9868 pushlocalvars(); 10013 pushlocalvars();
9869 evaltree(func->n.narg.next, flags & EV_TESTED); 10014 evaltree(func->n.ndefun.body, flags & EV_TESTED);
9870 poplocalvars(0); 10015 poplocalvars(0);
9871 funcdone: 10016 funcdone:
9872 INT_OFF; 10017 INT_OFF;
9873 funcnest--; 10018 funcline = savefuncline;
9874 freefunc(func); 10019 freefunc(func);
9875 freeparam(&shellparam); 10020 freeparam(&shellparam);
9876 shellparam = saveparam; 10021 shellparam = saveparam;
@@ -10235,6 +10380,10 @@ evalcommand(union node *cmd, int flags)
10235 char **nargv; 10380 char **nargv;
10236 smallint cmd_is_exec; 10381 smallint cmd_is_exec;
10237 10382
10383 errlinno = lineno = cmd->ncmd.linno;
10384 if (funcline)
10385 lineno -= funcline - 1;
10386
10238 /* First expand the arguments. */ 10387 /* First expand the arguments. */
10239 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); 10388 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10240 setstackmark(&smark); 10389 setstackmark(&smark);
@@ -10280,7 +10429,7 @@ evalcommand(union node *cmd, int flags)
10280 *nargv = NULL; 10429 *nargv = NULL;
10281 10430
10282 lastarg = NULL; 10431 lastarg = NULL;
10283 if (iflag && funcnest == 0 && argc > 0) 10432 if (iflag && funcline == 0 && argc > 0)
10284 lastarg = nargv[-1]; 10433 lastarg = nargv[-1];
10285 10434
10286 expredir(cmd->ncmd.redirect); 10435 expredir(cmd->ncmd.redirect);
@@ -10410,7 +10559,9 @@ evalcommand(union node *cmd, int flags)
10410 switch (cmdentry.cmdtype) { 10559 switch (cmdentry.cmdtype) {
10411 default: { 10560 default: {
10412 10561
10413#if ENABLE_FEATURE_SH_NOFORK 10562#if ENABLE_FEATURE_SH_STANDALONE \
10563 && ENABLE_FEATURE_SH_NOFORK \
10564 && NUM_APPLETS > 1
10414/* (1) BUG: if variables are set, we need to fork, or save/restore them 10565/* (1) BUG: if variables are set, we need to fork, or save/restore them
10415 * around run_nofork_applet() call. 10566 * around run_nofork_applet() call.
10416 * (2) Should this check also be done in forkshell()? 10567 * (2) Should this check also be done in forkshell()?
@@ -11341,7 +11492,7 @@ shiftcmd(int argc UNUSED_PARAM, char **argv)
11341 if (argv[1]) 11492 if (argv[1])
11342 n = number(argv[1]); 11493 n = number(argv[1]);
11343 if (n > shellparam.nparam) 11494 if (n > shellparam.nparam)
11344 n = 0; /* bash compat, was = shellparam.nparam; */ 11495 return 1;
11345 INT_OFF; 11496 INT_OFF;
11346 shellparam.nparam -= n; 11497 shellparam.nparam -= n;
11347 for (ap1 = shellparam.p; --n >= 0; ap1++) { 11498 for (ap1 = shellparam.p; --n >= 0; ap1++) {
@@ -11811,7 +11962,7 @@ parsefname(void)
11811 if (quoteflag == 0) 11962 if (quoteflag == 0)
11812 n->type = NXHERE; 11963 n->type = NXHERE;
11813 TRACE(("Here document %d\n", n->type)); 11964 TRACE(("Here document %d\n", n->type));
11814 rmescapes(wordtext, 0); 11965 rmescapes(wordtext, 0, NULL);
11815 here->eofmark = wordtext; 11966 here->eofmark = wordtext;
11816 here->next = NULL; 11967 here->next = NULL;
11817 if (heredoclist == NULL) 11968 if (heredoclist == NULL)
@@ -11836,6 +11987,7 @@ simplecmd(void)
11836 union node *vars, **vpp; 11987 union node *vars, **vpp;
11837 union node **rpp, *redir; 11988 union node **rpp, *redir;
11838 int savecheckkwd; 11989 int savecheckkwd;
11990 int savelinno;
11839#if BASH_TEST2 11991#if BASH_TEST2
11840 smallint double_brackets_flag = 0; 11992 smallint double_brackets_flag = 0;
11841#endif 11993#endif
@@ -11849,6 +12001,7 @@ simplecmd(void)
11849 rpp = &redir; 12001 rpp = &redir;
11850 12002
11851 savecheckkwd = CHKALIAS; 12003 savecheckkwd = CHKALIAS;
12004 savelinno = g_parsefile->linno;
11852 for (;;) { 12005 for (;;) {
11853 int t; 12006 int t;
11854 checkkwd = savecheckkwd; 12007 checkkwd = savecheckkwd;
@@ -11938,7 +12091,9 @@ simplecmd(void)
11938 } 12091 }
11939 n->type = NDEFUN; 12092 n->type = NDEFUN;
11940 checkkwd = CHKNL | CHKKWD | CHKALIAS; 12093 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11941 n->narg.next = parse_command(); 12094 n->ndefun.text = n->narg.text;
12095 n->ndefun.linno = g_parsefile->linno;
12096 n->ndefun.body = parse_command();
11942 return n; 12097 return n;
11943 } 12098 }
11944 IF_BASH_FUNCTION(function_flag = 0;) 12099 IF_BASH_FUNCTION(function_flag = 0;)
@@ -11954,6 +12109,7 @@ simplecmd(void)
11954 *rpp = NULL; 12109 *rpp = NULL;
11955 n = stzalloc(sizeof(struct ncmd)); 12110 n = stzalloc(sizeof(struct ncmd));
11956 n->type = NCMD; 12111 n->type = NCMD;
12112 n->ncmd.linno = savelinno;
11957 n->ncmd.args = args; 12113 n->ncmd.args = args;
11958 n->ncmd.assign = vars; 12114 n->ncmd.assign = vars;
11959 n->ncmd.redirect = redir; 12115 n->ncmd.redirect = redir;
@@ -11969,10 +12125,13 @@ parse_command(void)
11969 union node *redir, **rpp; 12125 union node *redir, **rpp;
11970 union node **rpp2; 12126 union node **rpp2;
11971 int t; 12127 int t;
12128 int savelinno;
11972 12129
11973 redir = NULL; 12130 redir = NULL;
11974 rpp2 = &redir; 12131 rpp2 = &redir;
11975 12132
12133 savelinno = g_parsefile->linno;
12134
11976 switch (readtoken()) { 12135 switch (readtoken()) {
11977 default: 12136 default:
11978 raise_error_unexpected_syntax(-1); 12137 raise_error_unexpected_syntax(-1);
@@ -12023,6 +12182,7 @@ parse_command(void)
12023 raise_error_syntax("bad for loop variable"); 12182 raise_error_syntax("bad for loop variable");
12024 n1 = stzalloc(sizeof(struct nfor)); 12183 n1 = stzalloc(sizeof(struct nfor));
12025 n1->type = NFOR; 12184 n1->type = NFOR;
12185 n1->nfor.linno = savelinno;
12026 n1->nfor.var = wordtext; 12186 n1->nfor.var = wordtext;
12027 checkkwd = CHKNL | CHKKWD | CHKALIAS; 12187 checkkwd = CHKNL | CHKKWD | CHKALIAS;
12028 if (readtoken() == TIN) { 12188 if (readtoken() == TIN) {
@@ -12063,6 +12223,7 @@ parse_command(void)
12063 case TCASE: 12223 case TCASE:
12064 n1 = stzalloc(sizeof(struct ncase)); 12224 n1 = stzalloc(sizeof(struct ncase));
12065 n1->type = NCASE; 12225 n1->type = NCASE;
12226 n1->ncase.linno = savelinno;
12066 if (readtoken() != TWORD) 12227 if (readtoken() != TWORD)
12067 raise_error_unexpected_syntax(TWORD); 12228 raise_error_unexpected_syntax(TWORD);
12068 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg)); 12229 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
@@ -12114,6 +12275,7 @@ parse_command(void)
12114 case TLP: 12275 case TLP:
12115 n1 = stzalloc(sizeof(struct nredir)); 12276 n1 = stzalloc(sizeof(struct nredir));
12116 n1->type = NSUBSHELL; 12277 n1->type = NSUBSHELL;
12278 n1->nredir.linno = savelinno;
12117 n1->nredir.n = list(0); 12279 n1->nredir.n = list(0);
12118 /*n1->nredir.redirect = NULL; - stzalloc did it */ 12280 /*n1->nredir.redirect = NULL; - stzalloc did it */
12119 t = TRP; 12281 t = TRP;
@@ -12147,6 +12309,7 @@ parse_command(void)
12147 if (n1->type != NSUBSHELL) { 12309 if (n1->type != NSUBSHELL) {
12148 n2 = stzalloc(sizeof(struct nredir)); 12310 n2 = stzalloc(sizeof(struct nredir));
12149 n2->type = NREDIR; 12311 n2->type = NREDIR;
12312 n2->nredir.linno = savelinno;
12150 n2->nredir.n = n1; 12313 n2->nredir.n = n1;
12151 n1 = n2; 12314 n1 = n2;
12152 } 12315 }
@@ -12245,10 +12408,8 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12245 IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */ 12408 IF_FEATURE_SH_MATH(int arinest;) /* levels of arithmetic expansion */
12246 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ 12409 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
12247 int dqvarnest; /* levels of variables expansion within double quotes */ 12410 int dqvarnest; /* levels of variables expansion within double quotes */
12248
12249 IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;) 12411 IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12250 12412
12251 startlinno = g_parsefile->linno;
12252 bqlist = NULL; 12413 bqlist = NULL;
12253 quotef = 0; 12414 quotef = 0;
12254 IF_FEATURE_SH_MATH(prevsyntax = 0;) 12415 IF_FEATURE_SH_MATH(prevsyntax = 0;)
@@ -12425,7 +12586,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12425 if (syntax != BASESYNTAX && eofmark == NULL) 12586 if (syntax != BASESYNTAX && eofmark == NULL)
12426 raise_error_syntax("unterminated quoted string"); 12587 raise_error_syntax("unterminated quoted string");
12427 if (varnest != 0) { 12588 if (varnest != 0) {
12428 startlinno = g_parsefile->linno;
12429 /* { */ 12589 /* { */
12430 raise_error_syntax("missing '}'"); 12590 raise_error_syntax("missing '}'");
12431 } 12591 }
@@ -12817,7 +12977,6 @@ parsebackq: {
12817 12977
12818 case PEOF: 12978 case PEOF:
12819 IF_ASH_ALIAS(case PEOA:) 12979 IF_ASH_ALIAS(case PEOA:)
12820 startlinno = g_parsefile->linno;
12821 raise_error_syntax("EOF in backquote substitution"); 12980 raise_error_syntax("EOF in backquote substitution");
12822 12981
12823 case '\n': 12982 case '\n':
@@ -12899,8 +13058,6 @@ parsearith: {
12899 * quoted. 13058 * quoted.
12900 * If the token is TREDIR, then we set redirnode to a structure containing 13059 * If the token is TREDIR, then we set redirnode to a structure containing
12901 * the redirection. 13060 * the redirection.
12902 * In all cases, the variable startlinno is set to the number of the line
12903 * on which the token starts.
12904 * 13061 *
12905 * [Change comment: here documents and internal procedures] 13062 * [Change comment: here documents and internal procedures]
12906 * [Readtoken shouldn't have any arguments. Perhaps we should make the 13063 * [Readtoken shouldn't have any arguments. Perhaps we should make the
@@ -12938,7 +13095,6 @@ xxreadtoken(void)
12938 return lasttoken; 13095 return lasttoken;
12939 } 13096 }
12940 setprompt_if(needprompt, 2); 13097 setprompt_if(needprompt, 2);
12941 startlinno = g_parsefile->linno;
12942 for (;;) { /* until token or start of word found */ 13098 for (;;) { /* until token or start of word found */
12943 c = pgetc(); 13099 c = pgetc();
12944 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) 13100 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
@@ -12999,7 +13155,6 @@ xxreadtoken(void)
12999 return lasttoken; 13155 return lasttoken;
13000 } 13156 }
13001 setprompt_if(needprompt, 2); 13157 setprompt_if(needprompt, 2);
13002 startlinno = g_parsefile->linno;
13003 for (;;) { /* until token or start of word found */ 13158 for (;;) { /* until token or start of word found */
13004 c = pgetc(); 13159 c = pgetc();
13005 switch (c) { 13160 switch (c) {
@@ -13391,10 +13546,14 @@ find_dot_file(char *name)
13391 if (fullname != name) 13546 if (fullname != name)
13392 stunalloc(fullname); 13547 stunalloc(fullname);
13393 } 13548 }
13549 /* not found in PATH */
13394 13550
13395 /* not found in the PATH */ 13551#if ENABLE_ASH_BASH_SOURCE_CURDIR
13552 return name;
13553#else
13396 ash_msg_and_raise_error("%s: not found", name); 13554 ash_msg_and_raise_error("%s: not found", name);
13397 /* NOTREACHED */ 13555 /* NOTREACHED */
13556#endif
13398} 13557}
13399 13558
13400static int FAST_FUNC 13559static int FAST_FUNC
@@ -13689,8 +13848,21 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
13689 /* We failed. If there was an entry for this command, delete it */ 13848 /* We failed. If there was an entry for this command, delete it */
13690 if (cmdp && updatetbl) 13849 if (cmdp && updatetbl)
13691 delete_cmd_entry(); 13850 delete_cmd_entry();
13692 if (act & DO_ERR) 13851 if (act & DO_ERR) {
13852#if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13853 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13854 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13855 char *argv[3];
13856 argv[0] = (char*) "command_not_found_handle";
13857 argv[1] = name;
13858 argv[2] = NULL;
13859 evalfun(hookp->param.func, 2, argv, 0);
13860 entry->cmdtype = CMDUNKNOWN;
13861 return;
13862 }
13863#endif
13693 ash_msg("%s: %s", name, errmsg(e, "not found")); 13864 ash_msg("%s: %s", name, errmsg(e, "not found"));
13865 }
13694 entry->cmdtype = CMDUNKNOWN; 13866 entry->cmdtype = CMDUNKNOWN;
13695 return; 13867 return;
13696 13868