Repository: benhoyt/goawk (go)

Issue:
srand() initialization without an argument.
The POSIX spec for Awk states:

> `srand([expr])`:
> Set the seed value for rand to expr or use the time of day if expr is omitted. The previous seed value shall be returned.

This makes the expression `srand(srand())` a portable (if rather bizarre) idiom for obtaining the current unix epoch in pure Awk. `gawk`, `mawk`, and the "one-true" `awk` support this idiom, but `goawk` does not appear to:

```
% gawk 'BEGIN{print srand(srand())}'
1714957797
% goawk 'BEGIN{print srand(srand())}'
1
% goawk --version
v1.27.0
```

I think you would be within your rights to declare supporting this idiom undesirable, but I'm not aware of any alternatives that are fully POSIX-compliant. Shelling out to `date +%s`, for example, might seem reasonable, but `%s` as a `date` format character does not appear to be guaranteed as of POSIX 1003.1-2017. Thoughts?

Pull request:
Make srand() use unix time in seconds, and set seed for next srand()
This is more POSIX-compatible. Fixes #231

Patch:
diff --git a/interp/vm.go b/interp/vm.go
index 57d84f1..12bc13e 100644
--- a/interp/vm.go
+++ b/interp/vm.go
@@ -1021,7 +1021,8 @@ func (p *interp) callBuiltin(builtinOp compiler.BuiltinOp) error {
 
 	case compiler.BuiltinSrand:
 		prevSeed := p.randSeed
-		p.random.Seed(time.Now().UnixNano())
+		p.randSeed = float64(time.Now().Unix())
+		p.random.Seed(int64(math.Float64bits(p.randSeed)))
 		p.push(num(prevSeed))
 
 	case compiler.BuiltinSrandSeed:


Test patch:
diff --git a/interp/interp_test.go b/interp/interp_test.go
index 5fbb1e3..5cd38a1 100644
--- a/interp/interp_test.go
+++ b/interp/interp_test.go
@@ -621,6 +621,7 @@ BEGIN {
 	print (a==x, b==y, c==z)
 }
 `, "", "0 0 0 0\n1 1 1\n", "", ""},
+	{`BEGIN { s = srand(srand()); print (s > 1700000000) }`, "", "1\n", "", ""},
 	{`
 BEGIN {
 	for (i = 0; i < 1000; i++) {