From b71085aacf405e824dfbbb10dddb092b3bd9d332 Mon Sep 17 00:00:00 2001 From: Stefan Farfeleder Date: Thu, 15 May 2008 19:55:27 +0000 Subject: [PATCH] Expand $LINENO to the current line number. This is required by SUSv3's "User Portability Utilities" option. Often configure scripts generated by the autotools test if $LINENO works and refuse to use /bin/sh if not. Package test run by: pav --- bin/sh/expand.c | 9 ++++++++- bin/sh/parser.c | 25 ++++++++++++++++++++++--- bin/sh/parser.h | 8 +++++--- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 1bd707936a32..2f0b9fda54fa 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -638,7 +638,13 @@ evalvar(char *p, int flag) special = 1; p = strchr(p, '=') + 1; again: /* jump here after setting a variable with ${var=text} */ - if (special) { + if (varflags & VSLINENO) { + set = 1; + special = 0; + val = var; + p[-1] = '\0'; /* temporarily overwrite '=' to have \0 + terminated string */ + } else if (special) { set = varisset(var, varflags & VSNUL); val = NULL; } else { @@ -768,6 +774,7 @@ record: default: abort(); } + p[-1] = '='; /* recover overwritten '=' */ if (subtype != VSNORMAL) { /* skip to end of alternative */ int nesting = 1; diff --git a/bin/sh/parser.c b/bin/sh/parser.c index fb9abc9ff4c7..75b4cac74ba4 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -94,6 +94,7 @@ STATIC union node *redirnode; STATIC struct heredoc *heredoc; STATIC int quoteflag; /* set if (part of) last token was quoted */ STATIC int startlinno; /* line # where last token started */ +STATIC int funclinno; /* line # where the current function started */ /* XXX When 'noaliases' is set to one, no alias expansion takes place. */ static int noaliases = 0; @@ -567,12 +568,14 @@ simplecmd(union node **rpp, union node *redir) /* We have a function */ if (readtoken() != TRP) synexpect(TRP); + funclinno = plinno; #ifdef notdef if (! goodname(n->narg.text)) synerror("Bad function name"); #endif n->type = NDEFUN; n->narg.next = command(); + funclinno = 0; goto checkneg; } else { tokpushback++; @@ -1176,12 +1179,15 @@ parseredir: { */ parsesub: { + char buf[10]; int subtype; int typeloc; int flags; char *p; static const char types[] = "}-+?="; - int bracketed_name = 0; /* used to handle ${[0-9]*} variables */ + int bracketed_name = 0; /* used to handle ${[0-9]*} variables */ + int i; + int linno; c = pgetc(); if (c != '(' && c != '{' && (is_eof(c) || !is_name(c)) && @@ -1200,6 +1206,7 @@ parsesub: { typeloc = out - stackblock(); USTPUTC(VSNORMAL, out); subtype = VSNORMAL; + flags = 0; if (c == '{') { bracketed_name = 1; c = pgetc(); @@ -1213,10 +1220,23 @@ parsesub: { subtype = 0; } if (!is_eof(c) && is_name(c)) { + p = out; do { STPUTC(c, out); c = pgetc(); } while (!is_eof(c) && is_in_name(c)); + if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) { + /* Replace the variable name with the + * current line number. */ + linno = plinno; + if (funclinno != 0) + linno -= funclinno - 1; + snprintf(buf, sizeof(buf), "%d", linno); + STADJUST(-6, out); + for (i = 0; buf[i] != '\0'; i++) + STPUTC(buf[i], out); + flags |= VSLINENO; + } } else if (is_digit(c)) { if (bracketed_name) { do { @@ -1239,11 +1259,10 @@ parsesub: { c = pgetc(); } } - flags = 0; if (subtype == 0) { switch (c) { case ':': - flags = VSNUL; + flags |= VSNUL; c = pgetc(); /*FALLTHROUGH*/ default: diff --git a/bin/sh/parser.h b/bin/sh/parser.h index 6b5687d9d71c..40dd8bda2405 100644 --- a/bin/sh/parser.h +++ b/bin/sh/parser.h @@ -45,9 +45,11 @@ #define CTLQUOTEMARK '\210' /* variable substitution byte (follows CTLVAR) */ -#define VSTYPE 0x0f /* type of variable substitution */ -#define VSNUL 0x10 /* colon--treat the empty string as unset */ -#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ +#define VSTYPE 0x0f /* type of variable substitution */ +#define VSNUL 0x10 /* colon--treat the empty string as unset */ +#define VSLINENO 0x20 /* expansion of $LINENO, the line number \ + follows immediately */ +#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ /* values of VSTYPE field */ #define VSNORMAL 0x1 /* normal variable: $var or ${var} */