aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--awkgram.c49
-rw-r--r--awkgram.y49
-rw-r--r--eval.c8
-rw-r--r--test/ChangeLog11
-rw-r--r--test/Makefile.am10
-rw-r--r--test/Makefile.in20
-rw-r--r--test/Maketests10
-rw-r--r--test/inpref.awk9
-rw-r--r--test/inpref.in2
-rw-r--r--test/inpref.ok2
-rw-r--r--test/regexpbrack2.awk2
-rw-r--r--test/regexpbrack2.in2
-rw-r--r--test/regexpbrack2.ok2
14 files changed, 146 insertions, 47 deletions
diff --git a/ChangeLog b/ChangeLog
index 327af606..171fc155 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2015-04-28 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awkgram.y (yylex): Rework the bracket handling from zero.
+ Thanks to Michal Jaegermann for yet another test case.
+
+ Unrelated:
+
+ * eval.c (setup_frame): Restore call-by-value for $0. This was
+ necessitated by the changes on 2014-11-11 for conserving
+ memory use. Thanks to Andrew Schorr for the report and isolating
+ the cause of the problem.
+
+2015-04-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awkgram.y (yylex): Make change of Jan 7 for parsing regexps
+ work better. Thanks to Nelson Beebe.
+
2015-04-26 Arnold D. Robbins <arnold@skeeve.com>
* dfa.c: Sync with grep.
diff --git a/awkgram.c b/awkgram.c
index 6fb66123..ea8c48d8 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -5548,21 +5548,24 @@ yylex(void)
thisline = NULL;
if (want_regexp) {
int in_brack = 0; /* count brackets, [[:alnum:]] allowed */
+ int b_index = -1;
+ int cur_index = 0;
+
/*
- * Counting brackets is non-trivial. [[] is ok,
- * and so is [\]], with a point being that /[/]/ as a regexp
- * constant has to work.
+ * Here is what's ok with brackets:
+ *
+ * [[] [^[] []] [^]] [.../...]
+ * [...\[...] [...\]...] [...\/...]
+ *
+ * (Remember that all of the above are inside /.../)
+ *
+ * The code for \ handles \[, \] and \/.
*
- * Do not count [ or ] if either one is preceded by a \.
- * A `[' should be counted if
- * a) it is the first one so far (in_brack == 0)
- * b) it is the `[' in `[:'
- * A ']' should be counted if not preceded by a \, since
- * it is either closing `:]' or just a plain list.
- * According to POSIX, []] is how you put a ] into a set.
- * Try to handle that too.
+ * Otherwise, track the first open [ position, and if
+ * an embedded [ or ] occurs, allow it to pass through
+ * if it's right after the first [ or after [^.
*
- * The code for \ handles \[ and \].
+ * Whew!
*/
want_regexp = false;
@@ -5572,17 +5575,21 @@ yylex(void)
if (gawk_mb_cur_max == 1 || nextc_is_1stbyte) switch (c) {
case '[':
- /* one day check for `.' and `=' too */
- if (nextc(false) == ':' || in_brack == 0)
- in_brack++;
- pushback();
- break;
case ']':
- if (tok[-1] == '['
- || (tok[-2] == '[' && tok[-1] == '^'))
- /* do nothing */;
- else
+ cur_index = tok - tokstart;
+ if (in_brack > 0
+ && (cur_index == b_index + 1
+ || (cur_index == b_index + 2 && tok[-1] == '^')))
+ ; /* do nothing */
+ else if (c == '[') {
+ in_brack++;
+ if (in_brack == 1)
+ b_index = tok - tokstart;
+ } else {
in_brack--;
+ if (in_brack == 0)
+ b_index = -1;
+ }
break;
case '\\':
if ((c = nextc(false)) == END_FILE) {
diff --git a/awkgram.y b/awkgram.y
index d14cf68e..3b555a6e 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -3216,21 +3216,24 @@ yylex(void)
thisline = NULL;
if (want_regexp) {
int in_brack = 0; /* count brackets, [[:alnum:]] allowed */
+ int b_index = -1;
+ int cur_index = 0;
+
/*
- * Counting brackets is non-trivial. [[] is ok,
- * and so is [\]], with a point being that /[/]/ as a regexp
- * constant has to work.
+ * Here is what's ok with brackets:
+ *
+ * [[] [^[] []] [^]] [.../...]
+ * [...\[...] [...\]...] [...\/...]
+ *
+ * (Remember that all of the above are inside /.../)
+ *
+ * The code for \ handles \[, \] and \/.
*
- * Do not count [ or ] if either one is preceded by a \.
- * A `[' should be counted if
- * a) it is the first one so far (in_brack == 0)
- * b) it is the `[' in `[:'
- * A ']' should be counted if not preceded by a \, since
- * it is either closing `:]' or just a plain list.
- * According to POSIX, []] is how you put a ] into a set.
- * Try to handle that too.
+ * Otherwise, track the first open [ position, and if
+ * an embedded [ or ] occurs, allow it to pass through
+ * if it's right after the first [ or after [^.
*
- * The code for \ handles \[ and \].
+ * Whew!
*/
want_regexp = false;
@@ -3240,17 +3243,21 @@ yylex(void)
if (gawk_mb_cur_max == 1 || nextc_is_1stbyte) switch (c) {
case '[':
- /* one day check for `.' and `=' too */
- if (nextc(false) == ':' || in_brack == 0)
- in_brack++;
- pushback();
- break;
case ']':
- if (tok[-1] == '['
- || (tok[-2] == '[' && tok[-1] == '^'))
- /* do nothing */;
- else
+ cur_index = tok - tokstart;
+ if (in_brack > 0
+ && (cur_index == b_index + 1
+ || (cur_index == b_index + 2 && tok[-1] == '^')))
+ ; /* do nothing */
+ else if (c == '[') {
+ in_brack++;
+ if (in_brack == 1)
+ b_index = tok - tokstart;
+ } else {
in_brack--;
+ if (in_brack == 0)
+ b_index = -1;
+ }
break;
case '\\':
if ((c = nextc(false)) == END_FILE) {
diff --git a/eval.c b/eval.c
index 2d820580..b50bcea8 100644
--- a/eval.c
+++ b/eval.c
@@ -1328,7 +1328,13 @@ setup_frame(INSTRUCTION *pc)
if (m->type == Node_param_list)
m = GET_PARAM(m->param_cnt);
-
+
+ /* $0 needs to be passed by value to a function */
+ if (m == fields_arr[0]) {
+ DEREF(m);
+ m = dupnode(m);
+ }
+
switch (m->type) {
case Node_var_new:
case Node_var_array:
diff --git a/test/ChangeLog b/test/ChangeLog
index b84345f9..fda382c1 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,14 @@
+2015-04-27 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (inpref): New test.
+ * inpref.awk, inpref.in, inpref.ok: New files.
+
+2015-04-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (regexpbrack2): New test.
+ * regexpbrack2.awk, regexpbrack2.in, regexpbrack2.ok: New files.
+ Thanks to Nelson Beebe.
+
2015-04-16 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (shadowbuiltin): New test.
diff --git a/test/Makefile.am b/test/Makefile.am
index d700f475..c53e65c1 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -411,6 +411,9 @@ EXTRA_DIST = \
icasers.awk \
icasers.in \
icasers.ok \
+ inpref.awk \
+ inpref.in \
+ inpref.ok \
id.awk \
id.ok \
igncdym.awk \
@@ -783,6 +786,9 @@ EXTRA_DIST = \
regexpbrack.awk \
regexpbrack.in \
regexpbrack.ok \
+ regexpbrack2.awk \
+ regexpbrack2.in \
+ regexpbrack2.ok \
regexprange.awk \
regexprange.ok \
reginttrad.awk \
@@ -1034,7 +1040,7 @@ BASIC_TESTS = \
gsubasgn gsubtest gsubtst2 gsubtst3 gsubtst4 gsubtst5 gsubtst6 \
gsubtst7 gsubtst8 \
hex hsprint \
- inputred intest intprec iobug1 \
+ inpref inputred intest intprec iobug1 \
leaddig leadnl litoct longsub longwrds \
manglprm math membug1 messages minusstr mmap8k mtchi18n \
nasty nasty2 negexp negrange nested nfldstr nfloop nfneg nfset nlfldsep \
@@ -1045,7 +1051,7 @@ BASIC_TESTS = \
paramdup paramres paramtyp paramuninitglobal parse1 parsefld parseme \
pcntplus posix2008sub prdupval prec printf0 printf1 prmarscl prmreuse \
prt1eval prtoeval \
- rand randtest range1 rebt8b1 redfilnm regeq regexpbrack regexprange regrange reindops \
+ rand randtest range1 rebt8b1 redfilnm regeq regexpbrack regexpbrack2 regexprange regrange reindops \
reparse resplit rri1 rs rsnul1nl rsnulbig rsnulbig2 rstest1 rstest2 \
rstest3 rstest4 rstest5 rswhite \
scalar sclforin sclifin sortempty sortglos splitargv splitarr splitdef \
diff --git a/test/Makefile.in b/test/Makefile.in
index b3a07283..caae2ba5 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -668,6 +668,9 @@ EXTRA_DIST = \
icasers.awk \
icasers.in \
icasers.ok \
+ inpref.awk \
+ inpref.in \
+ inpref.ok \
id.awk \
id.ok \
igncdym.awk \
@@ -1040,6 +1043,9 @@ EXTRA_DIST = \
regexpbrack.awk \
regexpbrack.in \
regexpbrack.ok \
+ regexpbrack2.awk \
+ regexpbrack2.in \
+ regexpbrack2.ok \
regexprange.awk \
regexprange.ok \
reginttrad.awk \
@@ -1290,7 +1296,7 @@ BASIC_TESTS = \
gsubasgn gsubtest gsubtst2 gsubtst3 gsubtst4 gsubtst5 gsubtst6 \
gsubtst7 gsubtst8 \
hex hsprint \
- inputred intest intprec iobug1 \
+ inpref inputred intest intprec iobug1 \
leaddig leadnl litoct longsub longwrds \
manglprm math membug1 messages minusstr mmap8k mtchi18n \
nasty nasty2 negexp negrange nested nfldstr nfloop nfneg nfset nlfldsep \
@@ -1301,7 +1307,7 @@ BASIC_TESTS = \
paramdup paramres paramtyp paramuninitglobal parse1 parsefld parseme \
pcntplus posix2008sub prdupval prec printf0 printf1 prmarscl prmreuse \
prt1eval prtoeval \
- rand randtest range1 rebt8b1 redfilnm regeq regexpbrack regexprange regrange reindops \
+ rand randtest range1 rebt8b1 redfilnm regeq regexpbrack regexpbrack2 regexprange regrange reindops \
reparse resplit rri1 rs rsnul1nl rsnulbig rsnulbig2 rstest1 rstest2 \
rstest3 rstest4 rstest5 rswhite \
scalar sclforin sclifin sortempty sortglos splitargv splitarr splitdef \
@@ -2947,6 +2953,11 @@ hsprint:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+inpref:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
inputred:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3254,6 +3265,11 @@ regexpbrack:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+regexpbrack2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
regexprange:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index aa328bf7..61b0ec8e 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -405,6 +405,11 @@ hsprint:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+inpref:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
inputred:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -712,6 +717,11 @@ regexpbrack:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+regexpbrack2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
regexprange:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/inpref.awk b/test/inpref.awk
new file mode 100644
index 00000000..d64ffe7f
--- /dev/null
+++ b/test/inpref.awk
@@ -0,0 +1,9 @@
+function test(x) {
+ print x
+ getline
+ print x
+}
+
+{
+ test($0)
+}
diff --git a/test/inpref.in b/test/inpref.in
new file mode 100644
index 00000000..a32119c8
--- /dev/null
+++ b/test/inpref.in
@@ -0,0 +1,2 @@
+hello
+goodbye
diff --git a/test/inpref.ok b/test/inpref.ok
new file mode 100644
index 00000000..317e9677
--- /dev/null
+++ b/test/inpref.ok
@@ -0,0 +1,2 @@
+hello
+hello
diff --git a/test/regexpbrack2.awk b/test/regexpbrack2.awk
new file mode 100644
index 00000000..81424844
--- /dev/null
+++ b/test/regexpbrack2.awk
@@ -0,0 +1,2 @@
+NR == 1 { gsub(/\\\\[;?!,()<>|+@%\]\[]/, " ") ; print "\"" $0 "\"" }
+NR == 2 { gsub(/\\\\[;?!,()<>|+@%\]\[^]/, " ") ; print "\"" $0 "\"" }
diff --git a/test/regexpbrack2.in b/test/regexpbrack2.in
new file mode 100644
index 00000000..42888dd0
--- /dev/null
+++ b/test/regexpbrack2.in
@@ -0,0 +1,2 @@
+test: \\; \\? \\!
+test: \\; \\? \\!
diff --git a/test/regexpbrack2.ok b/test/regexpbrack2.ok
new file mode 100644
index 00000000..9c2a2922
--- /dev/null
+++ b/test/regexpbrack2.ok
@@ -0,0 +1,2 @@
+"test: "
+"test: "