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;

Reply via email to