From b46368059445b51d28d8899ffb8f457c1642b6cb Mon Sep 17 00:00:00 2001 From: Cody Peter Mello Date: Fri, 19 Oct 2018 15:07:53 -0700 Subject: [PATCH] Update field-splitting behaviour to match POSIX definition --- lib.c | 24 +++++++++++++++++------- proto.h | 1 + tran.c | 2 ++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib.c b/lib.c index a365245..00359ac 100644 --- a/lib.c +++ b/lib.c @@ -104,6 +104,22 @@ void initgetrec(void) 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 @@ int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ if (isrecord) { donefld = 0; donerec = 1; + savefs(); } saveb0 = buf[0]; buf[0] = 0; @@ -191,10 +208,6 @@ int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf * 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 @@ void fldbld(void) /* create fields from current record */ } 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 */ diff --git a/proto.h b/proto.h index ad6f2e8..e44370d 100644 --- a/proto.h +++ b/proto.h @@ -116,6 +116,7 @@ extern void recinit(unsigned int); extern void initgetrec(void); extern void makefields(int, int); extern void growfldtab(int n); +extern void savefs(void); extern int getrec(char **, int *, int); extern void nextfile(void); extern int readrec(char **buf, int *bufsize, FILE *inf); diff --git a/tran.c b/tran.c index d1dfe2b..ca103f9 100644 --- a/tran.c +++ b/tran.c @@ -318,6 +318,7 @@ Awkfloat setfval(Cell *vp, Awkfloat f) /* set float val of a Cell */ } else if (isrec(vp)) { donefld = 0; /* mark $1... invalid */ donerec = 1; + savefs(); } else if (vp == ofsloc) { if (donerec == 0) recbld(); @@ -362,6 +363,7 @@ char *setsval(Cell *vp, const char *s) /* set string val of a Cell */ } else if (isrec(vp)) { donefld = 0; /* mark $1... invalid */ donerec = 1; + savefs(); } else if (vp == ofsloc) { if (donerec == 0) recbld();