Update field-splitting behaviour to match POSIX definition
diff --git a/lib.c b/lib.c
index a365245..00359ac 100644
--- a/lib.c
+++ b/lib.c
@@ -104,6 +104,22 @@
infile = stdin; /* no filenames, so use stdin */
}
+/*
+ * POSIX specifies that fields are supposed to be evaluated as if they were
+ * split using the value of FS at the time that the record's value ($0) was
+ * read.
+ *
+ * Since field-splitting is done lazily, we save the current value of FS
+ * whenever a new record is read in (implicitly or via getline), or when
+ * a new value is assigned to $0.
+ */
+void savefs(void)
+{
+ if (strlen(getsval(fsloc)) >= sizeof (inputFS))
+ FATAL("field separator %.10s... is too long", *FS);
+ strcpy(inputFS, *FS);
+}
+
static int firsttime = 1;
int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */
@@ -122,6 +138,7 @@
if (isrecord) {
donefld = 0;
donerec = 1;
+ savefs();
}
saveb0 = buf[0];
buf[0] = 0;
@@ -191,10 +208,6 @@
int bufsize = *pbufsize;
char *rs = getsval(rsloc);
- if (strlen(getsval(fsloc)) >= sizeof (inputFS))
- FATAL("field separator %.10s... is too long", *FS);
- /*fflush(stdout); avoids some buffering problem but makes it 25% slower*/
- strcpy(inputFS, *FS); /* for subsequent field splitting */
if ((sep = *rs) == 0) {
sep = '\n';
while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
@@ -284,9 +297,6 @@
}
fr = fields;
i = 0; /* number of fields accumulated here */
- if (strlen(getsval(fsloc)) >= sizeof (inputFS))
- FATAL("field separator %.10s... is too long", *FS);
- strcpy(inputFS, *FS);
if (strlen(inputFS) > 1) { /* it's a regular expression */
i = refldbld(r, inputFS);
} else if ((sep = *inputFS) == ' ') { /* default whitespace */