Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh An initial attempt at implementing LINENO to meet the...



details:   https://anonhg.NetBSD.org/src/rev/5aa968c95a0d
branches:  trunk
changeset: 824497:5aa968c95a0d
user:      kre <kre%NetBSD.org@localhost>
date:      Wed Jun 07 04:44:17 2017 +0000

description:
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.

diffstat:

 bin/sh/eval.c    |  21 ++++++++++++++++++---
 bin/sh/input.c   |   8 ++++----
 bin/sh/input.h   |   4 ++--
 bin/sh/nodetypes |   5 ++++-
 bin/sh/parser.c  |  11 +++++++----
 bin/sh/var.c     |   9 +++++++--
 bin/sh/var.h     |   3 ++-
 7 files changed, 44 insertions(+), 17 deletions(-)

diffs (276 lines):

diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/eval.c
--- a/bin/sh/eval.c     Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/eval.c     Wed Jun 07 04:44:17 2017 +0000
@@ -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 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 @@
        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 @@
                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 @@
        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 @@
 
        return 0;
 }
+
+STATIC void
+set_lineno(int lno)
+{
+       char lineno[24];
+
+       (void)snprintf(lineno, sizeof lineno, "%u", lno);
+       (void)setvarsafe("LINENO", lineno, 0);
+}
diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/input.c
--- a/bin/sh/input.c    Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/input.c    Wed Jun 07 04:44:17 2017 +0000
@@ -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 @@
  */
 
 void
-setinputstring(char *string, int push)
+setinputstring(char *string, int push, int line1)
 {
 
        INTOFF;
@@ -487,7 +487,7 @@
        parsenextc = string;
        parselleft = parsenleft = strlen(string);
        parsefile->buf = NULL;
-       plinno = 1;
+       plinno = line1;
        INTON;
 }
 
diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/input.h
--- a/bin/sh/input.h    Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/input.h    Wed Jun 07 04:44:17 2017 +0000
@@ -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 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);
diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/nodetypes
--- a/bin/sh/nodetypes  Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/nodetypes  Wed Jun 07 04:44:17 2017 +0000
@@ -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 @@
        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 @@
        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
diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/parser.c
--- a/bin/sh/parser.c   Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/parser.c   Wed Jun 07 04:44:17 2017 +0000
@@ -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 @@
                n1 = stalloc(sizeof(struct nfor));
                n1->type = NFOR;
                n1->nfor.var = wordtext;
+               n1->nfor.lineno = startlinno;
                if (readtoken()==TWORD && !quoteflag && equal(wordtext,"in")) {
                        app = &ap;
                        while (readtoken() == TWORD) {
@@ -436,6 +437,7 @@
        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 @@
        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 @@
                /*
                 * 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 @@
                psavelen = out - stackblock();
                if (psavelen > 0) {
                        pstr = grabstackstr(out);
-                       setinputstring(pstr, 1);
+                       setinputstring(pstr, 1, startlinno);
                }
        }
        nlpp = pbqlist;
diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/var.c
--- a/bin/sh/var.c      Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/var.c      Wed Jun 07 04:44:17 2017 +0000
@@ -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 vps4;
 struct var vvers;
 struct var voptind;
+struct var line_num;
 
 char ifs_default[] = " \t\n";
 
@@ -131,6 +132,8 @@
 #endif
        { &voptind,     VSTRFIXED|VTEXTFIXED|VNOFUNC,   "OPTIND=1",
          getoptsreset },
+       { &line_num,    VSTRFIXED|VTEXTFIXED,           "LINENO=1",
+         NULL },
        { NULL, 0,                              NULL,
          NULL }
 };
@@ -204,6 +207,8 @@
                " BOGUS_NOT"
 #endif
                    , VTEXTFIXED|VREADONLY|VNOEXPORT);
+
+       setvar("LINENO", "1", VTEXTFIXED);
 }
 #endif
 
diff -r 1243c8c39fcf -r 5aa968c95a0d bin/sh/var.h
--- a/bin/sh/var.h      Wed Jun 07 03:53:11 2017 +0000
+++ b/bin/sh/var.h      Wed Jun 07 04:44:17 2017 +0000
@@ -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 vps1;
 extern struct var vps2;
 extern struct var vps4;
+extern struct var line_num;
 #ifndef SMALL
 extern struct var vterm;
 extern struct var vtermcap;



Home | Main Index | Thread Index | Old Index