Skip to content

Commit 50ed001

Browse files
committed
Make a[x] array access set the element if not present (per POSIX spec)
This seems very unintuitive to me, but it's very clear in the spec, and awk/gawk/mawk all do this. Also fix delarpm2 gawk test as (again per POSIX) "The results of adding new elements to array within such a for loop are undefined."
1 parent 5bae076 commit 50ed001

7 files changed

Lines changed: 19 additions & 9 deletions

File tree

TODO.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
* "exit" tests, in BEGIN, end, etc (see gawk exitval tests)
2-
* fix new TODO tests in interp_test.go
31
* should interp have a configurable "safe" mode that doesn't run
42
system(), redirection, etc?

goawk.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import (
4444
)
4545

4646
const (
47-
version = "v1.2.0"
47+
version = "v1.2.1"
4848
)
4949

5050
func main() {

interp/interp.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,15 @@ func (p *interp) getArrayIndex(scope VarScope, index int) int {
10371037
// Get a value from given array by key (index)
10381038
func (p *interp) getArrayValue(scope VarScope, arrayIndex int, index string) value {
10391039
resolved := p.getArrayIndex(scope, arrayIndex)
1040-
return p.arrays[resolved][index]
1040+
array := p.arrays[resolved]
1041+
v, ok := array[index]
1042+
if !ok {
1043+
// Strangely, per the POSIX spec, "Any other reference to a
1044+
// nonexistent array element [apart from "in" expressions]
1045+
// shall automatically create it."
1046+
array[index] = v
1047+
}
1048+
return v
10411049
}
10421050

10431051
// Set a value in given array by key (index)

interp/interp_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ BEGIN {
135135
{`BEGIN { a["x"] = 3; print "x" in a, "y" in a }`, "", "1 0\n", "", ""},
136136
{`BEGIN { a["x"] = 3; a["y"] = 4; delete a["x"]; for (k in a) print k, a[k] }`, "", "y 4\n", "", ""},
137137
{`BEGIN { a["x"] = 3; a["y"] = 4; for (k in a) delete a[k]; for (k in a) print k, a[k] }`, "", "", "", ""},
138+
{`BEGIN { a["x"]; "y" in a; for (k in a) print k, a[k] }`, "", "x \n", "", ""},
138139
{`BEGIN { a[] }`, "", "", "parse error at 1:11: expected expression instead of ]", "syntax error"},
139140
{`BEGIN { delete a[] }`, "", "", "parse error at 1:18: expected expression instead of ]", "syntax error"},
140141

interp/io.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,13 @@ func (p *interp) nextLine() (string, error) {
347347
// Done with ARGV args, all done with input
348348
return "", io.EOF
349349
}
350-
// Fetch next filename from ARGV
350+
// Fetch next filename from ARGV. Can't use
351+
// getArrayValue() here as it would set the value if
352+
// not present
351353
index := strconv.Itoa(p.filenameIndex)
352354
argvIndex := p.program.Arrays["ARGV"]
353-
filename := p.toString(p.getArrayValue(ScopeGlobal, argvIndex, index))
355+
argvArray := p.arrays[p.getArrayIndex(ScopeGlobal, argvIndex)]
356+
filename := p.toString(argvArray[index])
354357
p.filenameIndex++
355358

356359
// Is it actually a var=value assignment?

testdata/gawk/delarpm2.awk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
clear_array(table)
5151
foo(table)
5252
for (key in table)
53-
print key, table[k]
53+
print key, table[key]
5454
clear_array(table)
5555
exit(0)
5656
}

testdata/gawk/delarpm2.ok

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1
2-
2
1+
1 one
2+
2 two

0 commit comments

Comments
 (0)