Module Name: src Committed By: kre Date: Wed Jun 7 04:44:17 UTC 2017
Modified Files: src/bin/sh: eval.c input.c input.h nodetypes parser.c var.c var.h Log Message: An initial attempt at implementing LINENO to meet the specs. Aside from one problem (not too hard to fix if it was ever needed) this version does about as well as most other shell implementations when expanding $((LINENO)) and better for ${LINENO} as it retains the "LINENO hack" for the latter, and that is very accurate. Unfortunately that means that ${LINENO} and $((LINENO)) do not always produce the same value when used on the same line (a defect that other shells do not share - aside from the FreeBSD sh as it is today, where only the LINENO hack exists and so (like for us before this commit) $((LINENO)) is always either 0, or at least whatever value was last set, perhaps by LINENO=${LINENO} which does actually work ... for that one line...) This could be corrected by simply removing the LINENO hack (look for the string LINENO in parser.c) in which case ${LINENO} and $((LINENO)) would give the same (not perfectly accurate) values, as do most other shells. POSIX requires that LINENO be set before each command, and this implementation does that fairly literally - except that we only bother before the commands which actually expand words (for, case and simple commands). Unfortunately this forgot that expansions also occur in redirects, and the other compound commands can also have redirects, so if a redirect on one of the other compound commands wants to use the value of $((LINENO)) as a part of a generated file name, then it will get an incorrect value. This is the "one problem" above. (Because the LINENO hack is still enabled, using ${LINENO} works.) This could be fixed, but as this version of the LINENO implementation is just for reference purposes (it will be superseded within minutes by a better one) I won't bother. However should anyone else decide that this is a better choice (it is probably a smaller implementation, in terms of code & data space then the replacement, but also I would expect, slower, and definitely less accurate) this defect is something to bear in mind, and fix. This version retains the *BSD historical practice that line numbers in functions (all functions) count from 1 from the start of the function, and elsewhere, start from 1 from where the shell started reading the input file/stream in question. In an "eval" expression the line number starts at the line of the "eval" (and then increases if the input is a multi-line string). Note: this version is not documented (beyond as much as LINENO was before) hence this slightly longer than usual commit message. To generate a diff of this commit: cvs rdiff -u -r1.141 -r1.142 src/bin/sh/eval.c cvs rdiff -u -r1.56 -r1.57 src/bin/sh/input.c cvs rdiff -u -r1.18 -r1.19 src/bin/sh/input.h cvs rdiff -u -r1.15 -r1.16 src/bin/sh/nodetypes cvs rdiff -u -r1.132 -r1.133 src/bin/sh/parser.c cvs rdiff -u -r1.55 -r1.56 src/bin/sh/var.c cvs rdiff -u -r1.28 -r1.29 src/bin/sh/var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/bin/sh/eval.c diff -u src/bin/sh/eval.c:1.141 src/bin/sh/eval.c:1.142 --- src/bin/sh/eval.c:1.141 Sun Jun 4 20:27:14 2017 +++ src/bin/sh/eval.c Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: eval.c,v 1.141 2017/06/04 20:27:14 kre Exp $ */ +/* $NetBSD: eval.c,v 1.142 2017/06/07 04:44:17 kre Exp $ */ /*- * Copyright (c) 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #else -__RCSID("$NetBSD: eval.c,v 1.141 2017/06/04 20:27:14 kre Exp $"); +__RCSID("$NetBSD: eval.c,v 1.142 2017/06/07 04:44:17 kre Exp $"); #endif #endif /* not lint */ @@ -117,6 +117,7 @@ STATIC void expredir(union node *); STATIC void evalpipe(union node *); STATIC void evalcommand(union node *, int, struct backcmd *); STATIC void prehash(union node *); +STATIC void set_lineno(int); STATIC char *find_dot_file(char *); @@ -216,7 +217,7 @@ evalstring(char *s, int flag) struct stackmark smark; setstackmark(&smark); - setinputstring(s, 1); + setinputstring(s, 1, atoi(line_num.text + line_num.name_len + 1)); while ((n = parsecmd(0)) != NEOF) { TRACE(("evalstring: "); showtree(n)); @@ -308,9 +309,11 @@ evaltree(union node *n, int flags) evalloop(n, sflags); break; case NFOR: + set_lineno(n->nfor.lineno); evalfor(n, sflags); break; case NCASE: + set_lineno(n->ncase.lineno); evalcase(n, sflags); break; case NDEFUN: @@ -770,6 +773,9 @@ evalcommand(union node *cmd, int flgs, s setstackmark(&smark); back_exitstatus = 0; + if (cmd != NULL) + set_lineno(cmd->ncmd.lineno); + arglist.lastp = &arglist.list; varflag = 1; /* Expand arguments, ignoring the initial 'name=value' ones */ @@ -1456,3 +1462,12 @@ timescmd(int argc, char **argv) return 0; } + +STATIC void +set_lineno(int lno) +{ + char lineno[24]; + + (void)snprintf(lineno, sizeof lineno, "%u", lno); + (void)setvarsafe("LINENO", lineno, 0); +} Index: src/bin/sh/input.c diff -u src/bin/sh/input.c:1.56 src/bin/sh/input.c:1.57 --- src/bin/sh/input.c:1.56 Wed May 3 06:20:12 2017 +++ src/bin/sh/input.c Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: input.c,v 1.56 2017/05/03 06:20:12 kre Exp $ */ +/* $NetBSD: input.c,v 1.57 2017/06/07 04:44:17 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; #else -__RCSID("$NetBSD: input.c,v 1.56 2017/05/03 06:20:12 kre Exp $"); +__RCSID("$NetBSD: input.c,v 1.57 2017/06/07 04:44:17 kre Exp $"); #endif #endif /* not lint */ @@ -478,7 +478,7 @@ setinputfd(int fd, int push) */ void -setinputstring(char *string, int push) +setinputstring(char *string, int push, int line1) { INTOFF; @@ -487,7 +487,7 @@ setinputstring(char *string, int push) parsenextc = string; parselleft = parsenleft = strlen(string); parsefile->buf = NULL; - plinno = 1; + plinno = line1; INTON; } Index: src/bin/sh/input.h diff -u src/bin/sh/input.h:1.18 src/bin/sh/input.h:1.19 --- src/bin/sh/input.h:1.18 Wed May 3 04:51:04 2017 +++ src/bin/sh/input.h Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: input.h,v 1.18 2017/05/03 04:51:04 kre Exp $ */ +/* $NetBSD: input.h,v 1.19 2017/06/07 04:44:17 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -56,7 +56,7 @@ void pushstring(const char *, int, struc void popstring(void); void setinputfile(const char *, int); void setinputfd(int, int); -void setinputstring(char *, int); +void setinputstring(char *, int, int); void popfile(void); void popallfiles(void); void closescript(int); Index: src/bin/sh/nodetypes diff -u src/bin/sh/nodetypes:1.15 src/bin/sh/nodetypes:1.16 --- src/bin/sh/nodetypes:1.15 Tue May 9 05:14:03 2017 +++ src/bin/sh/nodetypes Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -# $NetBSD: nodetypes,v 1.15 2017/05/09 05:14:03 kre Exp $ +# $NetBSD: nodetypes,v 1.16 2017/06/07 04:44:17 kre Exp $ # Copyright (c) 1991, 1993 # The Regents of the University of California. All rights reserved. # @@ -58,6 +58,7 @@ NCMD ncmd # a simple command backgnd int # set to run command in background args nodeptr # the arguments redirect nodeptr # list of file redirections + lineno int NPIPE npipe # a pipeline type int @@ -89,11 +90,13 @@ NFOR nfor # the for statement args nodeptr # for var in args body nodeptr # do body; done var string # the for variable + lineno int NCASE ncase # a case statement type int expr nodeptr # the word to switch on cases nodeptr # the list of cases (NCLIST nodes) + lineno int NCLISTCONT nclist # a case terminated by ';&' (fall through) NCLIST nclist # a case Index: src/bin/sh/parser.c diff -u src/bin/sh/parser.c:1.132 src/bin/sh/parser.c:1.133 --- src/bin/sh/parser.c:1.132 Sat Jun 3 18:31:35 2017 +++ src/bin/sh/parser.c Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: parser.c,v 1.132 2017/06/03 18:31:35 kre Exp $ */ +/* $NetBSD: parser.c,v 1.133 2017/06/07 04:44:17 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; #else -__RCSID("$NetBSD: parser.c,v 1.132 2017/06/03 18:31:35 kre Exp $"); +__RCSID("$NetBSD: parser.c,v 1.133 2017/06/07 04:44:17 kre Exp $"); #endif #endif /* not lint */ @@ -389,6 +389,7 @@ command(void) n1 = stalloc(sizeof(struct nfor)); n1->type = NFOR; n1->nfor.var = wordtext; + n1->nfor.lineno = startlinno; if (readtoken()==TWORD && !quoteflag && equal(wordtext,"in")) { app = ≈ while (readtoken() == TWORD) { @@ -436,6 +437,7 @@ command(void) case TCASE: n1 = stalloc(sizeof(struct ncase)); n1->type = NCASE; + n1->ncase.lineno = startlinno; if (readtoken() != TWORD) synexpect(TWORD, 0); n1->ncase.expr = n2 = stalloc(sizeof(struct narg)); @@ -663,6 +665,7 @@ simplecmd(union node **rpp, union node * n->ncmd.backgnd = 0; n->ncmd.args = args; n->ncmd.redirect = redir; + n->ncmd.lineno = startlinno; checkneg: #ifdef BOGUS_NOT_COMMAND @@ -921,7 +924,7 @@ readheredocs(void) /* * Now "parse" here docs that have unquoted eofmarkers. */ - setinputstring(wordtext, 1); + setinputstring(wordtext, 1, startlinno); readtoken1(pgetc(), DQSYNTAX, 1); n->narg.text = wordtext; n->narg.backquote = backquotelist; @@ -1374,7 +1377,7 @@ parsebackq(VSS *const stack, char * cons psavelen = out - stackblock(); if (psavelen > 0) { pstr = grabstackstr(out); - setinputstring(pstr, 1); + setinputstring(pstr, 1, startlinno); } } nlpp = pbqlist; Index: src/bin/sh/var.c diff -u src/bin/sh/var.c:1.55 src/bin/sh/var.c:1.56 --- src/bin/sh/var.c:1.55 Sat May 27 11:19:57 2017 +++ src/bin/sh/var.c Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.55 2017/05/27 11:19:57 kre Exp $ */ +/* $NetBSD: var.c,v 1.56 2017/06/07 04:44:17 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; #else -__RCSID("$NetBSD: var.c,v 1.55 2017/05/27 11:19:57 kre Exp $"); +__RCSID("$NetBSD: var.c,v 1.56 2017/06/07 04:44:17 kre Exp $"); #endif #endif /* not lint */ @@ -100,6 +100,7 @@ struct var vps2; struct var vps4; struct var vvers; struct var voptind; +struct var line_num; char ifs_default[] = " \t\n"; @@ -131,6 +132,8 @@ const struct varinit varinit[] = { #endif { &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", getoptsreset }, + { &line_num, VSTRFIXED|VTEXTFIXED, "LINENO=1", + NULL }, { NULL, 0, NULL, NULL } }; @@ -204,6 +207,8 @@ INIT { " BOGUS_NOT" #endif , VTEXTFIXED|VREADONLY|VNOEXPORT); + + setvar("LINENO", "1", VTEXTFIXED); } #endif Index: src/bin/sh/var.h diff -u src/bin/sh/var.h:1.28 src/bin/sh/var.h:1.29 --- src/bin/sh/var.h:1.28 Thu Mar 31 16:16:35 2016 +++ src/bin/sh/var.h Wed Jun 7 04:44:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: var.h,v 1.28 2016/03/31 16:16:35 christos Exp $ */ +/* $NetBSD: var.h,v 1.29 2017/06/07 04:44:17 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -79,6 +79,7 @@ extern struct var vpath; extern struct var vps1; extern struct var vps2; extern struct var vps4; +extern struct var line_num; #ifndef SMALL extern struct var vterm; extern struct var vtermcap;