Print this page
3731 Update nawk to version 20121220

*** 22,105 **** /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ ! /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ ! /* All Rights Reserved */ ! ! #pragma ident "%Z%%M% %I% %E% SMI" #include <errno.h> #include "awk.h" #include "y.tab.h" uchar *record; ! size_t record_size; int donefld; /* 1 = implies rec broken into fields */ int donerec; /* 1 = record is valid (no flds have changed) */ ! static struct fldtab_chunk { ! struct fldtab_chunk *next; ! Cell fields[FLD_INCR]; ! } *fldtab_head, *fldtab_tail; ! ! static size_t fldtab_maxidx; static FILE *infile = NULL; static uchar *file = (uchar*) ""; static uchar *fields; ! static size_t fields_size = LINE_INCR; - static int maxfld = 0; /* last used field */ static int argno = 1; /* current input argument number */ static uchar *getargv(int); static void cleanfld(int, int); static int refldbld(uchar *, uchar *); static void bcheck2(int, int, int); static void eprint(void); static void bclass(int); static void initgetrec(void) { int i; uchar *p; for (i = 1; i < *ARGC; i++) { ! if (!isclvar(p = getargv(i))) /* find 1st real filename */ return; setclvar(p); /* a commandline assignment before filename */ argno++; } infile = stdin; /* no filenames, so use stdin */ - /* *FILENAME = file = (uchar*) "-"; */ } int ! getrec(uchar **bufp, size_t *bufsizep) ! { int c; ! static int firsttime = 1; ! uchar_t *buf, *nbuf; ! size_t len; if (firsttime) { firsttime = 0; initgetrec(); } dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n", *RS, *FS, *ARGC, *FILENAME)); donefld = 0; donerec = 1; while (argno < *ARGC || infile == stdin) { dprintf(("argno=%d, file=|%s|\n", argno, file)); if (infile == NULL) { /* have to open a new file */ file = getargv(argno); ! if (*file == '\0') { /* it's been zapped */ argno++; continue; } if (isclvar(file)) { /* a var=value arg */ setclvar(file); --- 22,176 ---- /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ ! /* ! * Copyright (C) Lucent Technologies 1997 ! * All Rights Reserved ! * ! * Permission to use, copy, modify, and distribute this software and ! * its documentation for any purpose and without fee is hereby ! * granted, provided that the above copyright notice appear in all ! * copies and that both that the copyright notice and this ! * permission notice and warranty disclaimer appear in supporting ! * documentation, and that the name Lucent Technologies or any of ! * its entities not be used in advertising or publicity pertaining ! * to distribution of the software without specific, written prior ! * permission. ! * ! * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, ! * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. ! * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY ! * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ! * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER ! * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ! * THIS SOFTWARE. ! */ #include <errno.h> + #include <stdarg.h> + #include <math.h> #include "awk.h" #include "y.tab.h" uchar *record; ! size_t record_size = RECSIZE; ! ! Cell **fldtab; /* pointers to Cells */ ! char inputFS[100] = " "; ! ! #define MAXFLD 2 ! int nfields = MAXFLD; /* last allocated slot for $i */ int donefld; /* 1 = implies rec broken into fields */ int donerec; /* 1 = record is valid (no flds have changed) */ ! int lastfld = 0; /* last used field */ static FILE *infile = NULL; static uchar *file = (uchar*) ""; static uchar *fields; ! static size_t fields_size = RECSIZE; static int argno = 1; /* current input argument number */ static uchar *getargv(int); static void cleanfld(int, int); static int refldbld(uchar *, uchar *); static void bcheck2(int, int, int); static void eprint(void); static void bclass(int); + static void makefields(int, int); + + + static Cell dollar0 = { OCELL, CFLD, NULL, (uchar *)"", 0.0, REC|STR|DONTFREE }; + static Cell dollar1 = { OCELL, CFLD, NULL, (uchar *)"", 0.0, FLD|STR|DONTFREE }; + + void + recinit(unsigned int n) + { + if ((record = (uchar *)malloc(n)) == NULL || + (fields = (uchar *)malloc(n+1)) == NULL || + (fldtab = (Cell **)malloc((nfields + 1) * + sizeof (Cell *))) == NULL || + (fldtab[0] = (Cell *)malloc(sizeof (Cell))) == NULL) + FATAL("out of space for $0 and fields"); + *fldtab[0] = dollar0; + fldtab[0]->sval = record; + fldtab[0]->nval = tostring((uchar *)"0"); + makefields(1, nfields); + } + + static void + makefields(int n1, int n2) /* create $n1..$n2 inclusive */ + { + char temp[50]; + int i; + + for (i = n1; i <= n2; i++) { + fldtab[i] = (Cell *)malloc(sizeof (struct Cell)); + if (fldtab[i] == NULL) + FATAL("out of space in makefields %d", i); + *fldtab[i] = dollar1; + (void) sprintf(temp, "%d", i); + fldtab[i]->nval = tostring((uchar *)temp); + } + } static void initgetrec(void) { int i; uchar *p; for (i = 1; i < *ARGC; i++) { ! p = getargv(i); /* find 1st real filename */ ! if (p == NULL || *p == '\0') { /* deleted or zapped */ ! argno++; ! continue; ! } ! if (!isclvar(p)) { ! (void) setsval(lookup((uchar *)"FILENAME", symtab), p); return; + } setclvar(p); /* a commandline assignment before filename */ argno++; } infile = stdin; /* no filenames, so use stdin */ } + static int firsttime = 1; + int ! getrec(uchar **pbuf, size_t *pbufsize, int isrecord) ! { /* get next input record */ ! /* note: cares whether buf == record */ int c; ! uchar_t *buf = *pbuf; ! uchar saveb0; ! size_t bufsize = *pbufsize, savebufsize = bufsize; if (firsttime) { firsttime = 0; initgetrec(); } dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n", *RS, *FS, *ARGC, *FILENAME)); + if (isrecord) { donefld = 0; donerec = 1; + } + saveb0 = buf[0]; + buf[0] = 0; while (argno < *ARGC || infile == stdin) { dprintf(("argno=%d, file=|%s|\n", argno, file)); if (infile == NULL) { /* have to open a new file */ file = getargv(argno); ! /* deleted or zapped */ ! if (file == NULL || *file == '\0') { argno++; continue; } if (isclvar(file)) { /* a var=value arg */ setclvar(file);
*** 109,201 **** *FILENAME = file; dprintf(("opening file %s\n", file)); if (*file == '-' && *(file+1) == '\0') infile = stdin; else if ((infile = fopen((char *)file, "r")) == NULL) ! ERROR "can't open file %s", file FATAL; (void) setfval(fnrloc, 0.0); } ! c = readrec(&nbuf, &len, infile); ! expand_buf(bufp, bufsizep, len); ! buf = *bufp; ! (void) memcpy(buf, nbuf, len); ! buf[len] = '\0'; ! free(nbuf); ! if (c != 0 || buf[0] != '\0') { /* normal record */ ! if (bufp == &record) { ! if (!(recloc->tval & DONTFREE)) ! xfree(recloc->sval); ! recloc->sval = record; ! recloc->tval = REC | STR | DONTFREE; ! if (is_number(recloc->sval)) { ! recloc->fval = ! atof((const char *)recloc->sval); ! recloc->tval |= NUM; } } (void) setfval(nrloc, nrloc->fval+1); (void) setfval(fnrloc, fnrloc->fval+1); return (1); } /* EOF arrived on this file; set up next */ if (infile != stdin) (void) fclose(infile); infile = NULL; argno++; } return (0); /* true end of file */ } int ! readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */ { int sep, c; ! uchar *buf; ! int count; ! size_t bufsize; ! init_buf(&buf, &bufsize, LINE_INCR); if ((sep = **RS) == 0) { sep = '\n'; /* skip leading \n's */ while ((c = getc(inf)) == '\n' && c != EOF) ; if (c != EOF) (void) ungetc(c, inf); } ! count = 0; ! for (;;) { ! while ((c = getc(inf)) != sep && c != EOF) { ! expand_buf(&buf, &bufsize, count); ! buf[count++] = c; } if (**RS == sep || c == EOF) break; if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ break; ! expand_buf(&buf, &bufsize, count + 1); ! buf[count++] = '\n'; ! buf[count++] = c; ! } ! buf[count] = '\0'; dprintf(("readrec saw <%s>, returns %d\n", ! buf, c == EOF && count == 0 ? 0 : 1)); ! *bufp = buf; ! *sizep = count; ! return (c == EOF && count == 0 ? 0 : 1); } - /* get ARGV[n] */ static uchar * ! getargv(int n) { Cell *x; ! uchar *s, temp[11]; extern Array *ARGVtab; (void) sprintf((char *)temp, "%d", n); x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab); s = getsval(x); dprintf(("getargv(%d) returns |%s|\n", n, s)); return (s); } --- 180,298 ---- *FILENAME = file; dprintf(("opening file %s\n", file)); if (*file == '-' && *(file+1) == '\0') infile = stdin; else if ((infile = fopen((char *)file, "r")) == NULL) ! FATAL("can't open file %s", file); (void) setfval(fnrloc, 0.0); } ! c = readrec(&buf, &bufsize, infile); if (c != 0 || buf[0] != '\0') { /* normal record */ ! if (isrecord) { ! if (freeable(fldtab[0])) ! xfree(fldtab[0]->sval); ! fldtab[0]->sval = buf; /* buf == record */ ! fldtab[0]->tval = REC | STR | DONTFREE; ! if (is_number(fldtab[0]->sval)) { ! fldtab[0]->fval = ! atof((const char *)fldtab[0]->sval); ! fldtab[0]->tval |= NUM; } } (void) setfval(nrloc, nrloc->fval+1); (void) setfval(fnrloc, fnrloc->fval+1); + *pbuf = buf; + *pbufsize = bufsize; return (1); } /* EOF arrived on this file; set up next */ if (infile != stdin) (void) fclose(infile); infile = NULL; argno++; } + buf[0] = saveb0; + *pbuf = buf; + *pbufsize = savebufsize; return (0); /* true end of file */ } + void + nextfile(void) + { + if (infile != NULL && infile != stdin) + (void) fclose(infile); + infile = NULL; + argno++; + } + + /* + * read one record into buf + */ int ! readrec(uchar **pbuf, size_t *pbufsize, FILE *inf) { int sep, c; ! uchar *rr, *buf = *pbuf; ! size_t bufsize = *pbufsize; ! ! if (strlen((char *)*FS) >= sizeof (inputFS)) ! FATAL("field separator %.10s... is too long", *FS); ! /* ! * fflush(stdout); avoids some buffering problem ! * but makes it 25% slower ! */ ! /* for subsequent field splitting */ ! (void) strcpy(inputFS, (char *)*FS); if ((sep = **RS) == 0) { sep = '\n'; /* skip leading \n's */ while ((c = getc(inf)) == '\n' && c != EOF) ; if (c != EOF) (void) ungetc(c, inf); } ! for (rr = buf; ; ) { ! for (; (c = getc(inf)) != sep && c != EOF; ) { ! if (rr-buf+1 > bufsize) ! if (!adjbuf(&buf, &bufsize, 1+rr-buf, ! record_size, &rr, "readrec 1")) ! FATAL( ! "input record `%.30s...' too long", buf); ! *rr++ = c; } if (**RS == sep || c == EOF) break; if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ break; ! if (!adjbuf(&buf, &bufsize, 2+rr-buf, record_size, &rr, ! "readrec 2")) ! FATAL("input record `%.30s...' too long", buf); ! *rr++ = '\n'; ! *rr++ = c; ! } ! if (!adjbuf(&buf, &bufsize, 1+rr-buf, record_size, &rr, "readrec 3")) ! FATAL("input record `%.30s...' too long", buf); ! *rr = 0; dprintf(("readrec saw <%s>, returns %d\n", ! buf, c == EOF && rr == buf ? 0 : 1)); ! *pbuf = buf; ! *pbufsize = bufsize; ! return (c == EOF && rr == buf ? 0 : 1); } static uchar * ! getargv(int n) /* get ARGV[n] */ { Cell *x; ! uchar *s, temp[50]; extern Array *ARGVtab; (void) sprintf((char *)temp, "%d", n); + if (lookup(temp, ARGVtab) == NULL) + return (NULL); x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab); s = getsval(x); dprintf(("getargv(%d) returns |%s|\n", n, s)); return (s); }
*** 215,450 **** if (is_number(q->sval)) { q->fval = atof((const char *)q->sval); q->tval |= NUM; } dprintf(("command line set %s to |%s|\n", s, p)); - free(p); } void ! fldbld(void) { uchar *r, *fr, sep; Cell *p; ! int i; ! size_t len; if (donefld) return; ! if (!(recloc->tval & STR)) ! (void) getsval(recloc); ! r = recloc->sval; /* was record! */ ! ! /* make sure fields is always allocated */ ! adjust_buf(&fields, fields_size); ! ! /* ! * make sure fields has enough size. We don't expand the buffer ! * in the middle of the loop, since p->sval has already pointed ! * the address in the fields. ! */ ! len = strlen((char *)r) + 1; ! expand_buf(&fields, &fields_size, len); fr = fields; - i = 0; /* number of fields accumulated here */ ! if (strlen((char *)*FS) > 1) { /* it's a regular expression */ ! i = refldbld(r, *FS); ! } else if ((sep = **FS) == ' ') { for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; ! p = getfld(i); ! if (!(p->tval & DONTFREE)) ! xfree(p->sval); ! p->sval = fr; ! p->tval = FLD | STR | DONTFREE; do *fr++ = *r++; while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0') ; *fr++ = 0; } *fr = 0; } else if (*r != 0) { /* if 0, it's a null field */ for (;;) { i++; ! p = getfld(i); ! if (!(p->tval & DONTFREE)) ! xfree(p->sval); ! p->sval = fr; ! p->tval = FLD | STR | DONTFREE; ! /* \n always a separator */ ! while (*r != sep && *r != '\n' && *r != '\0') *fr++ = *r++; *fr++ = 0; if (*r++ == 0) break; } *fr = 0; } /* clean out junk from previous record */ ! cleanfld(i, maxfld); ! maxfld = i; donefld = 1; ! for (i = 1; i <= maxfld; i++) { ! p = getfld(i); if (is_number(p->sval)) { p->fval = atof((const char *)p->sval); p->tval |= NUM; } } ! ! (void) setfval(nfloc, (Awkfloat) maxfld); if (dbg) { ! for (i = 0; i <= maxfld; i++) { ! p = getfld(i); ! (void) printf("field %d: |%s|\n", i, p->sval); } } } static void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ ! { ! static uchar *nullstat = (uchar *) ""; Cell *p; int i; ! for (i = n2; i > n1; i--) { ! p = getfld(i); ! if (!(p->tval & DONTFREE)) xfree(p->sval); - p->tval = FLD | STR | DONTFREE; p->sval = nullstat; } } void ! newfld(int n) /* add field n (after end) */ ! { ! if (n < 0) ! ERROR "accessing invalid field", record FATAL; ! (void) getfld(n); ! cleanfld(maxfld, n); ! maxfld = n; ! (void) setfval(nfloc, (Awkfloat) n); ! } ! ! /* ! * allocate field table. We don't reallocate the table since there ! * might be somewhere recording the address of the table. ! */ ! static void ! morefld(void) { ! int i; ! struct fldtab_chunk *fldcp; ! Cell *newfld; ! ! if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL) ! ERROR "out of space in morefld" FATAL; ! ! newfld = &fldcp->fields[0]; ! for (i = 0; i < FLD_INCR; i++) { ! newfld[i].ctype = OCELL; ! newfld[i].csub = CFLD; ! newfld[i].nval = NULL; ! newfld[i].sval = (uchar *)""; ! newfld[i].fval = 0.0; ! newfld[i].tval = FLD|STR|DONTFREE; ! newfld[i].cnext = NULL; ! } ! /* ! * link this field chunk ! */ ! if (fldtab_head == NULL) ! fldtab_head = fldcp; ! else ! fldtab_tail->next = fldcp; ! fldtab_tail = fldcp; ! fldcp->next = NULL; ! ! fldtab_maxidx += FLD_INCR; } Cell * ! getfld(int idx) { ! struct fldtab_chunk *fldcp; ! int cbase; ! ! if (idx < 0) ! ERROR "trying to access field %d", idx FATAL; ! while (idx >= fldtab_maxidx) ! morefld(); ! cbase = 0; ! for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) { ! if (idx < (cbase + FLD_INCR)) ! return (&fldcp->fields[idx - cbase]); ! cbase += FLD_INCR; ! } ! /* should never happen */ ! ERROR "trying to access invalid field %d", idx FATAL; ! return (NULL); } ! int ! fldidx(Cell *vp) ! { ! struct fldtab_chunk *fldcp; ! Cell *tbl; ! int cbase; ! ! cbase = 0; ! for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) { ! tbl = &fldcp->fields[0]; ! if (vp >= tbl && vp < (tbl + FLD_INCR)) ! return (cbase + (vp - tbl)); ! cbase += FLD_INCR; ! } ! /* should never happen */ ! ERROR "trying to access unknown field" FATAL; ! return (0); } static int refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ { uchar *fr; int i, tempstat; fa *pfa; ! Cell *p; ! size_t len; ! /* make sure fields is allocated */ ! adjust_buf(&fields, fields_size); fr = fields; *fr = '\0'; if (*rec == '\0') return (0); - - len = strlen((char *)rec) + 1; - expand_buf(&fields, &fields_size, len); - fr = fields; - pfa = makedfa(fs, 1); dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs)); tempstat = pfa->initstat; for (i = 1; ; i++) { ! p = getfld(i); ! if (!(p->tval & DONTFREE)) ! xfree(p->sval); ! p->tval = FLD | STR | DONTFREE; ! p->sval = fr; dprintf(("refldbld: i=%d\n", i)); if (nematch(pfa, rec)) { ! pfa->initstat = 2; dprintf(("match %s (%d chars)\n", patbeg, patlen)); (void) strncpy((char *)fr, (char *)rec, patbeg-rec); fr += patbeg - rec + 1; *(fr-1) = '\0'; rec = patbeg + patlen; --- 312,526 ---- if (is_number(q->sval)) { q->fval = atof((const char *)q->sval); q->tval |= NUM; } dprintf(("command line set %s to |%s|\n", s, p)); } void ! fldbld(void) /* create fields from current record */ { + /* this relies on having fields[] the same length as $0 */ + /* the fields are all stored in this one array with \0's */ + /* possibly with a final trailing \0 not associated with any field */ uchar *r, *fr, sep; Cell *p; ! int i, j; ! size_t n; if (donefld) return; ! if (!isstr(fldtab[0])) ! (void) getsval(fldtab[0]); ! r = fldtab[0]->sval; ! n = strlen((char *)r); ! if (n > fields_size) { ! xfree(fields); ! /* possibly 2 final \0s */ ! if ((fields = (uchar *)malloc(n + 2)) == NULL) ! FATAL("out of space for fields in fldbld %d", n); ! fields_size = n; ! } fr = fields; i = 0; /* number of fields accumulated here */ ! (void) strcpy(inputFS, (char *)*FS); ! if (strlen(inputFS) > 1) { /* it's a regular expression */ ! i = refldbld(r, (uchar *)inputFS); ! } else if ((sep = *inputFS) == ' ') { /* default whitespace */ for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; ! if (i > nfields) ! growfldtab(i); ! if (freeable(fldtab[i])) ! xfree(fldtab[i]->sval); ! fldtab[i]->sval = fr; ! fldtab[i]->tval = FLD | STR | DONTFREE; do *fr++ = *r++; while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0') ; *fr++ = 0; } *fr = 0; + } else if ((sep = *inputFS) == 0) { /* new: FS="" => 1 char/field */ + for (i = 0; *r != 0; r++) { + uchar buf[2]; + i++; + if (i > nfields) + growfldtab(i); + if (freeable(fldtab[i])) + xfree(fldtab[i]->sval); + buf[0] = *r; + buf[1] = 0; + fldtab[i]->sval = tostring(buf); + fldtab[i]->tval = FLD | STR; + } + *fr = 0; } else if (*r != 0) { /* if 0, it's a null field */ + /* + * subtlecase : if length(FS) == 1 && length(RS > 0) + * \n is NOT a field separator (cf awk book 61,84). + * this variable is tested in the inner while loop. + */ + int rtest = '\n'; /* normal case */ + if (strlen((char *)*RS) > 0) + rtest = '\0'; for (;;) { i++; ! if (i > nfields) ! growfldtab(i); ! if (freeable(fldtab[i])) ! xfree(fldtab[i]->sval); ! fldtab[i]->sval = fr; ! fldtab[i]->tval = FLD | STR | DONTFREE; ! /* \n is always a separator */ ! while (*r != sep && *r != rtest && *r != '\0') *fr++ = *r++; *fr++ = 0; if (*r++ == 0) break; } *fr = 0; } + if (i > nfields) + FATAL("record `%.30s...' has too many fields; can't happen", r); /* clean out junk from previous record */ ! cleanfld(i + 1, lastfld); ! lastfld = i; donefld = 1; ! for (j = 1; j <= lastfld; j++) { ! p = fldtab[j]; if (is_number(p->sval)) { p->fval = atof((const char *)p->sval); p->tval |= NUM; } } ! (void) setfval(nfloc, (Awkfloat)lastfld); if (dbg) { ! for (j = 0; j <= lastfld; j++) { ! p = fldtab[j]; ! (void) printf("field %d (%s): |%s|\n", j, p->nval, ! p->sval); } } } static void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ ! { /* nvals remain intact */ ! static uchar *nullstat = (uchar *)""; Cell *p; int i; ! for (i = n1; i <= n2; i++) { ! p = fldtab[i]; ! if (freeable(p)) xfree(p->sval); p->sval = nullstat; + p->tval = FLD | STR | DONTFREE; } } void ! newfld(int n) /* add field n after end of existing lastfld */ { ! if (n > nfields) ! growfldtab(n); ! cleanfld(lastfld + 1, n); ! lastfld = n; ! (void) setfval(nfloc, (Awkfloat)n); } Cell * ! fieldadr(int n) /* get nth field */ { ! if (n < 0) ! FATAL("trying to access out of range field %d", n); ! if (n > nfields) /* fields after NF are empty */ ! growfldtab(n); /* but does not increase NF */ ! return (fldtab[n]); } ! void ! growfldtab(int n) /* make new fields up to at least $n */ ! { ! int nf = 2 * nfields; ! size_t s; ! ! if (n > nf) ! nf = n; ! /* freebsd: how much do we need? */ ! s = (nf + 1) * (sizeof (struct Cell *)); ! if (s / sizeof (struct Cell *) - 1 == nf) /* didn't overflow */ ! fldtab = (Cell **) realloc(fldtab, s); ! else /* overflow sizeof int */ ! xfree(fldtab); /* make it null */ ! if (fldtab == NULL) ! FATAL("out of space creating %d fields", nf); ! makefields(nfields + 1, nf); ! nfields = nf; } static int refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ { + /* this relies on having fields[] the same length as $0 */ + /* the fields are all stored in this one array with \0's */ uchar *fr; int i, tempstat; fa *pfa; ! size_t n; ! n = strlen((char *)rec); ! if (n > fields_size) { ! xfree(fields); ! if ((fields = (uchar *)malloc(n + 1)) == NULL) ! FATAL("out of space for fields in refldbld %d", n); ! fields_size = n; ! } fr = fields; *fr = '\0'; if (*rec == '\0') return (0); pfa = makedfa(fs, 1); dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs)); tempstat = pfa->initstat; for (i = 1; ; i++) { ! if (i > nfields) ! growfldtab(i); ! if (freeable(fldtab[i])) ! xfree(fldtab[i]->sval); ! fldtab[i]->tval = FLD | STR | DONTFREE; ! fldtab[i]->sval = fr; dprintf(("refldbld: i=%d\n", i)); if (nematch(pfa, rec)) { ! pfa->initstat = 2; /* horrible coupling to b.c */ dprintf(("match %s (%d chars)\n", patbeg, patlen)); (void) strncpy((char *)fr, (char *)rec, patbeg-rec); fr += patbeg - rec + 1; *(fr-1) = '\0'; rec = patbeg + patlen;
*** 457,531 **** } return (i); } void ! recbld(void) { int i; ! uchar *p; ! size_t cnt, len, olen; if (donerec == 1) return; ! cnt = 0; ! olen = strlen((char *)*OFS); for (i = 1; i <= *NF; i++) { ! p = getsval(getfld(i)); ! len = strlen((char *)p); ! expand_buf(&record, &record_size, cnt + len + olen); ! (void) memcpy(&record[cnt], p, len); ! cnt += len; if (i < *NF) { ! (void) memcpy(&record[cnt], *OFS, olen); ! cnt += olen; } } ! record[cnt] = '\0'; ! dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc)); ! if (!(recloc->tval & DONTFREE)) ! xfree(recloc->sval); ! recloc->tval = REC | STR | DONTFREE; ! recloc->sval = record; ! dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc)); dprintf(("recbld = |%s|\n", record)); donerec = 1; } - Cell * - fieldadr(int n) - { - if (n < 0) - ERROR "trying to access field %d", n FATAL; - return (getfld(n)); - } - int errorflag = 0; - char errbuf[200]; void yyerror(char *s) { extern uchar *cmdname, *curfname; static int been_here = 0; if (been_here++ > 2) return; ! (void) fprintf(stderr, "%s: %s", cmdname, s); (void) fprintf(stderr, gettext(" at source line %lld"), lineno); if (curfname != NULL) (void) fprintf(stderr, gettext(" in function %s"), curfname); (void) fprintf(stderr, "\n"); errorflag = 2; eprint(); } - /*ARGSUSED*/ void ! fpecatch(int sig) { ! ERROR "floating point exception" FATAL; } extern int bracecnt, brackcnt, parencnt; void --- 533,619 ---- } return (i); } void ! recbld(void) /* create $0 from $1..$NF if necessary */ { int i; ! uchar *r, *p; if (donerec == 1) return; ! r = record; for (i = 1; i <= *NF; i++) { ! p = getsval(fldtab[i]); ! if (!adjbuf(&record, &record_size, 1 + strlen((char *)p) + r - ! record, record_size, &r, "recbld 1")) ! FATAL("created $0 `%.30s...' too long", record); ! while ((*r = *p++) != 0) ! r++; if (i < *NF) { ! if (!adjbuf(&record, &record_size, 2 + ! strlen((char *)*OFS) + r - record, record_size, ! &r, "recbld 2")) ! FATAL("created $0 `%.30s...' too long", record); ! for (p = *OFS; (*r = *p++) != 0; ) ! r++; } } ! if (!adjbuf(&record, &record_size, 2 + r - record, record_size, &r, ! "recbld 3")) ! FATAL("built giant record `%.30s...'", record); ! *r = '\0'; ! dprintf(("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, ! (void *)fldtab[0])); ! ! if (freeable(fldtab[0])) ! xfree(fldtab[0]->sval); ! fldtab[0]->tval = REC | STR | DONTFREE; ! fldtab[0]->sval = record; ! ! dprintf(("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, ! (void *)fldtab[0])); dprintf(("recbld = |%s|\n", record)); donerec = 1; } int errorflag = 0; void yyerror(char *s) { + SYNTAX("%s", s); + } + + void + SYNTAX(const char *fmt, ...) + { extern uchar *cmdname, *curfname; static int been_here = 0; + va_list varg; if (been_here++ > 2) return; ! (void) fprintf(stderr, "%s: ", cmdname); ! va_start(varg, fmt); ! (void) vfprintf(stderr, fmt, varg); ! va_end(varg); (void) fprintf(stderr, gettext(" at source line %lld"), lineno); if (curfname != NULL) (void) fprintf(stderr, gettext(" in function %s"), curfname); + if (compile_time == 1 && cursource() != NULL) + (void) fprintf(stderr, gettext(" source file %s"), cursource()); (void) fprintf(stderr, "\n"); errorflag = 2; eprint(); } void ! fpecatch(int n) { ! FATAL("floating point exception %d", n); } extern int bracecnt, brackcnt, parencnt; void
*** 556,603 **** else if (n < -1) (void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2); } void ! error(int f, char *s) { - extern Node *curnode; extern uchar *cmdname; (void) fflush(stdout); (void) fprintf(stderr, "%s: ", cmdname); ! (void) fprintf(stderr, "%s", s); (void) fprintf(stderr, "\n"); if (compile_time != 2 && NR && *NR > 0) { (void) fprintf(stderr, ! gettext(" input record number %g"), *FNR); if (strcmp((char *)*FILENAME, "-") != 0) (void) fprintf(stderr, gettext(", file %s"), *FILENAME); (void) fprintf(stderr, "\n"); } if (compile_time != 2 && curnode) ! (void) fprintf(stderr, gettext(" source line number %lld\n"), curnode->lineno); else if (compile_time != 2 && lineno) { (void) fprintf(stderr, ! gettext(" source line number %lld\n"), lineno); } eprint(); - if (f) { - if (dbg) - abort(); - exit(2); - } } static void eprint(void) /* try to print context around error */ { uchar *p, *q; int c; static int been_here = 0; ! extern uchar ebuf[300], *ep; if (compile_time == 2 || compile_time == 0 || been_here++ > 0) return; p = ep - 1; if (p > ebuf && *p == '\n') --- 644,717 ---- else if (n < -1) (void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2); } void ! FATAL(const char *fmt, ...) { extern uchar *cmdname; + va_list varg; (void) fflush(stdout); (void) fprintf(stderr, "%s: ", cmdname); ! va_start(varg, fmt); ! (void) vfprintf(stderr, fmt, varg); ! va_end(varg); ! error(); ! if (dbg > 1) /* core dump if serious debugging on */ ! abort(); ! exit(2); ! } ! ! void ! WARNING(const char *fmt, ...) ! { ! extern uchar *cmdname; ! va_list varg; ! ! (void) fflush(stdout); ! (void) fprintf(stderr, "%s: ", cmdname); ! va_start(varg, fmt); ! (void) vfprintf(stderr, fmt, varg); ! va_end(varg); ! error(); ! } ! ! void ! error(void) ! { ! extern Node *curnode; ! (void) fprintf(stderr, "\n"); if (compile_time != 2 && NR && *NR > 0) { (void) fprintf(stderr, ! gettext(" input record number %g"), (int) (*FNR)); if (strcmp((char *)*FILENAME, "-") != 0) (void) fprintf(stderr, gettext(", file %s"), *FILENAME); (void) fprintf(stderr, "\n"); } if (compile_time != 2 && curnode) ! (void) fprintf(stderr, gettext(" source line number %d"), curnode->lineno); else if (compile_time != 2 && lineno) { (void) fprintf(stderr, ! gettext(" source line number %d"), lineno); } + if (compile_time == 1 && cursource() != NULL) + (void) fprintf(stderr, + gettext(" source file %s"), cursource()); + (void) fprintf(stderr, "\n"); eprint(); } static void eprint(void) /* try to print context around error */ { uchar *p, *q; int c; static int been_here = 0; ! extern uchar ebuf[], *ep; if (compile_time == 2 || compile_time == 0 || been_here++ > 0) return; p = ep - 1; if (p > ebuf && *p == '\n')
*** 638,795 **** case ')': parencnt--; break; } } double ! errcheck(double x, char *s) { - extern int errno; - if (errno == EDOM) { errno = 0; ! ERROR "%s argument out of domain", s WARNING; x = 1; } else if (errno == ERANGE) { errno = 0; ! ERROR "%s result out of range", s WARNING; x = 1; } return (x); } - void - PUTS(uchar *s) - { - dprintf(("%s\n", s)); - } - int ! isclvar(uchar *s) /* is s of form var=something? */ { ! if (s != NULL) { ! /* Must begin with an underscore or alphabetic character */ ! if (isalpha(*s) || (*s == '_')) { ! ! for (s++; *s; s++) { ! /* ! * followed by a sequence of underscores, ! * digits, and alphabetics ! */ ! if (!(isalnum(*s) || *s == '_')) { break; } - } - return (*s == '=' && *(s + 1) != '='); - } - } ! return (0); } ! #define MAXEXPON 38 /* maximum exponent for fp number */ int ! is_number(uchar *s) { ! int d1, d2; ! int point; ! uchar *es; ! extern char radixpoint; ! ! d1 = d2 = point = 0; ! while (*s == ' ' || *s == '\t' || *s == '\n') ! s++; ! if (*s == '\0') ! return (0); /* empty stuff isn't number */ ! if (*s == '+' || *s == '-') ! s++; ! if (!isdigit(*s) && *s != radixpoint) ! return (0); ! if (isdigit(*s)) { ! do { ! d1++; ! s++; ! } while (isdigit(*s)); ! } ! if (d1 >= MAXEXPON) ! return (0); /* too many digits to convert */ ! if (*s == radixpoint) { ! point++; ! s++; ! } ! if (isdigit(*s)) { ! d2++; ! do { ! s++; ! } while (isdigit(*s)); ! } ! if (!(d1 || point && d2)) ! return (0); ! if (*s == 'e' || *s == 'E') { ! s++; ! if (*s == '+' || *s == '-') ! s++; ! if (!isdigit(*s)) ! return (0); ! es = s; ! do { ! s++; ! } while (isdigit(*s)); ! if (s - es > 2) { ! return (0); ! } else if (s - es == 2 && ! (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) { return (0); ! } ! } ! while (*s == ' ' || *s == '\t' || *s == '\n') ! s++; ! if (*s == '\0') return (1); else return (0); } - - void - init_buf(uchar **optr, size_t *sizep, size_t amt) - { - uchar *nptr = NULL; - - if ((nptr = malloc(amt)) == NULL) - ERROR "out of space in init_buf" FATAL; - /* initial buffer should have NULL terminated */ - *nptr = '\0'; - if (sizep != NULL) - *sizep = amt; - *optr = nptr; - } - - void - r_expand_buf(uchar **optr, size_t *sizep, size_t req) - { - uchar *nptr; - size_t amt, size = *sizep; - - if (size != 0 && req < (size - 1)) - return; - amt = req + 1 - size; - amt = (amt / LINE_INCR + 1) * LINE_INCR; - - if ((nptr = realloc(*optr, size + amt)) == NULL) - ERROR "out of space in expand_buf" FATAL; - /* initial buffer should have NULL terminated */ - if (size == 0) - *nptr = '\0'; - *sizep += amt; - *optr = nptr; - } - - void - adjust_buf(uchar **optr, size_t size) - { - uchar *nptr; - - if ((nptr = realloc(*optr, size)) == NULL) - ERROR "out of space in adjust_buf" FATAL; - *optr = nptr; - } --- 752,805 ---- case ')': parencnt--; break; } } double ! errcheck(double x, const char *s) { if (errno == EDOM) { errno = 0; ! WARNING("%s argument out of domain", s); x = 1; } else if (errno == ERANGE) { errno = 0; ! WARNING("%s result out of range", s); x = 1; } return (x); } int ! isclvar(const uchar *s) /* is s of form var=something? */ { ! const uchar *os = s; ! if (!isalpha(*s) && *s != '_') ! return (0); ! for (; *s; s++) { ! if (!(isalnum(*s) || *s == '_')) break; } ! return (*s == '=' && s > os && *(s+1) != '='); } ! /* strtod is supposed to be a proper test of what's a valid number */ ! /* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */ ! /* wrong: violates 4.10.1.4 of ansi C standard */ int ! is_number(const uchar *s) { ! double r; ! char *ep; ! errno = 0; ! r = strtod((const char *)s, &ep); ! if (ep == (char *)s || r == HUGE_VAL || errno == ERANGE) return (0); ! while (*ep == ' ' || *ep == '\t' || *ep == '\n') ! ep++; ! if (*ep == '\0') return (1); else return (0); }