awk/testdir
Miguel Pineiro Jr 92f9e8a9be Fix readrec's definition of a record
I botched readrec's definition of a record, when I implemented
RS regular expression support. This is the relevant hunk from the
old diff:

```
-	return c == EOF && rr == buf ? 0 : 1;
+	isrec = *buf || !feof(inf);
+	   dprintf( ("readrec saw <%s>, returns %d\n", buf, isrec) );
+	return isrec;
```

Problem #1

Unlike testing with EOF, `*buf || !feof(inf)` is blind to stdio
errors. This can cause an infinite loop whose each iteration fabricates
an empty record.

The following demonstration uses standard terminal access control
policy to produce a persistent error condition. Note that the "i/o
error" message does not come from readrec(). It's produced much later
by closeall() at shutdown.

```
$ trap '' SIGTTIN && awk 'END {print NR}' &
[1] 33517
$ # After fg, type ^D
$ fg
trap '' SIGTTIN && awk 'END {print NR}'
13847376
awk: i/o error occurred on /dev/stdin
 input record number 13847376, file
 source line number 1
```

Each time awk tries to read the terminal from the background,
while ignoring SIGTTIN, the read fails with EIO, getc returns EOF,
the stream's end-of-file indicator remains clear, and `!feof`
erroneously promotoes the empty buffer to an empty record.  So long
as the error persists, the stream's position does not advance and
end-of-file is never set.

Problem #2:

When RS is a regex, `*buf || !feof(inf)` can't see an empty record's
terminator at the end of a stream.

```
$ echo a | awk 1 RS='a\n'
$
```

That pipeline should have found one empty record and printed a blank
line, but `*buf || !feof(inf)` considers reaching the end of the
stream the conclusion of a fruitless search. That's only correct when
the terminator is a single character, because a regex RS search can
set the end-of-file marker even when it succeeds.

The Fix

`isrec` must be 0 **iff** no record is found. The correct definition
of "no record" is a failure to find a record terminator and a
failure to find any data (possibly from a final, unterminated
record). Conceptually, for any RS:

```
isrec = (noTERM && noDATA) ? 0 : 1
```

noDATA is an expression that's true if `buf` is empty, false otherwise.

When RS is null or a single character, noTERM is an expression
that is true when the sought after character is not found, false
otherwise. Since the search for a single character can only end with
that character or EOF, noTERM is `c == EOF`.

```
isrec = (c == EOF && rr == buf) ? 0 : 1
```

When RS is a regular expression: noTERM is an expression that is
true if a match for RS is not found, false otherwise. This is simply
the inverse of the result of the function that conducts the search,
`!found`.

```
isrec = (found == 0 && *buf == '\0') ? 0 : 1
```
2021-04-23 20:08:58 -04:00
..
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
bib
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
ind
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
p.1
2019-06-23 03:13:57 -06:00
p.2
2019-06-23 03:13:57 -06:00
p.3
2019-06-23 03:13:57 -06:00
p.4
2019-06-23 03:13:57 -06:00
p.5
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
p.6
2019-06-23 03:13:57 -06:00
p.7
2019-06-23 03:13:57 -06:00
p.8
2019-06-23 03:13:57 -06:00
p.9
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.0
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.1
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.2
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.3
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.4
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.6
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.a
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2020-02-28 13:23:54 +02:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-11-08 14:36:37 +02:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.e
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-12-11 09:17:34 +02:00
2019-06-23 03:13:57 -06:00
t.f
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2020-01-31 08:40:11 +02:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-11-08 14:36:37 +02:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2021-04-23 20:08:58 -04:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-07-16 20:50:23 +03:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
t.x
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
try
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
2019-06-23 03:13:57 -06:00
xc
2019-06-23 03:13:57 -06:00
yc
2019-06-23 03:13:57 -06:00

The archive of test files contains 

- A shell file called REGRESS that controls the testing process.

- Several shell files called Compare* that control sub-parts
of the testing.

- About 160 small tests called t.* that constitute a random
sampling of awk constructions collected over the years.
Not organized, but they touch almost everything.

- About 60 small tests called p.* that come from the first
two chapters of The AWK Programming Language.  This is
basic stuff -- they have to work.

These two sets are intended as regression tests, to be sure
that a new version produces the same results as a previous one.
There are a couple of standard data files used with them,
test.data and test.countries, but others would work too.

- About 20 files called T.* that are self-contained and
more systematic tests of specific language features.
For example, T.clv tests command-line variable handling.
These tests are not regressions -- they compute the right
answer by separate means, then compare the awk output.
A specific test for each new bug found shows up in at least
one of these, most often T.misc.  There are about 220 tests
total in these files.

- Two of these files, T.re and T.sub, are systematic tests
of the regular expression and substitution code.  They express
tests in a small language, then generate awk programs that
verify behavior.

- About 20 files called tt.* that are used as timing tests;
they use the most common awk constructions in straightforward
ways, against a large input file constructed by Compare.tt.


There is undoubtedly more stuff in the archive;  it's been
collecting for years and may need pruning.  Suggestions for
improvement, additional tests (especially systematic ones),
and the like are all welcome.