diff options
Diffstat (limited to 'usr/src/cmd/awk/lib.c')
| -rw-r--r-- | usr/src/cmd/awk/lib.c | 810 |
1 files changed, 457 insertions, 353 deletions
diff --git a/usr/src/cmd/awk/lib.c b/usr/src/cmd/awk/lib.c index ded064c6c3..bde265e273 100644 --- a/usr/src/cmd/awk/lib.c +++ b/usr/src/cmd/awk/lib.c @@ -1,4 +1,28 @@ /* + * 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. + */ + +/* * CDDL HEADER START * * The contents of this file are subject to the terms of the @@ -27,63 +51,131 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* Copyright (c) Lucent Technologies 1997 */ +/* All Rights Reserved */ +#include <stdio.h> +#include <string.h> +#include <ctype.h> #include <errno.h> +#include <stdlib.h> +#include <stdarg.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 FILE *infile = NULL; +static char *file = ""; +char *record; +size_t recsize = RECSIZE; +static char *fields; +static size_t fieldssize = RECSIZE; +static char *rtbuf; +static size_t rtbufsize = RECSIZE; -static struct fldtab_chunk { - struct fldtab_chunk *next; - Cell fields[FLD_INCR]; -} *fldtab_head, *fldtab_tail; +Cell **fldtab; /* pointers to Cells */ +char inputFS[100] = " "; -static size_t fldtab_maxidx; +#define MAXFLD 2 +int nfields = MAXFLD; /* last allocated slot for $i */ -static FILE *infile = NULL; -static uchar *file = (uchar*) ""; -static uchar *fields; -static size_t fields_size = LINE_INCR; +int donefld; /* 1 = implies rec broken into fields */ +int donerec; /* 1 = record is valid (no flds have changed) */ -static int maxfld = 0; /* last used field */ +static int lastfld = 0; /* last used field */ static int argno = 1; /* current input argument number */ -static uchar *getargv(int); +static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; +static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; + +static char *getargv(int); static void cleanfld(int, int); -static int refldbld(uchar *, uchar *); +static int refldbld(const char *, const char *); static void bcheck2(int, int, int); static void eprint(void); static void bclass(int); +void +recinit(unsigned int n) +{ + if ((record = (char *)malloc(n)) == NULL || + (fields = (char *)malloc(n+2)) == 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("0"); + makefields(1, nfields); +} + +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 (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(temp); + } +} + static void initgetrec(void) { int i; - uchar *p; + char *p; for (i = 1; i < *ARGC; i++) { - if (!isclvar(p = getargv(i))) /* find 1st real filename */ + p = getargv(i); /* find 1st real filename */ + if (p == NULL || *p == '\0') { /* deleted or zapped */ + argno++; + continue; + } + if (!isclvar(p)) { + (void) setsval(lookup("FILENAME", symtab), p); return; + } setclvar(p); /* a commandline assignment before filename */ argno++; } infile = stdin; /* no filenames, so use stdin */ - /* *FILENAME = file = (uchar*) "-"; */ } +/* + * 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); + (void) strcpy(inputFS, *FS); +} + +static int firsttime = 1; + +/* + * get next input record + * note: cares whether buf == record + */ int -getrec(uchar **bufp, size_t *bufsizep) +getrec(char **pbuf, size_t *pbufsize, int isrecord) { int c; - static int firsttime = 1; - uchar_t *buf, *nbuf; - size_t len; + char *buf = *pbuf; + uschar saveb0; + size_t bufsize = *pbufsize, savebufsize = bufsize; if (firsttime) { firsttime = 0; @@ -91,17 +183,24 @@ getrec(uchar **bufp, size_t *bufsizep) } dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n", *RS, *FS, *ARGC, *FILENAME)); - donefld = 0; - donerec = 1; + if (isrecord) { + donefld = 0; + donerec = 1; + savefs(); + } + 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); - if (*file == '\0') { /* it's been zapped */ + if (file == NULL || *file == '\0') { + /* deleted or zapped */ argno++; continue; } - if (isclvar(file)) { /* a var=value arg */ + if (isclvar(file)) { + /* a var=value arg */ setclvar(file); argno++; continue; @@ -110,31 +209,28 @@ getrec(uchar **bufp, size_t *bufsizep) 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; + else if ((infile = fopen(file, "rF")) == NULL) + FATAL("can't open file %s", file); (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); + c = readrec(&buf, &bufsize, infile); if (c != 0 || buf[0] != '\0') { /* normal record */ - if (bufp == &record) { - if (!(recloc->tval & DONTFREE)) + if (isrecord) { + if (freeable(recloc)) xfree(recloc->sval); - recloc->sval = record; + recloc->sval = buf; /* buf == record */ recloc->tval = REC | STR | DONTFREE; if (is_number(recloc->sval)) { recloc->fval = - atof((const char *)recloc->sval); + atof(recloc->sval); recloc->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 */ @@ -143,19 +239,36 @@ getrec(uchar **bufp, size_t *bufsizep) 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++; +} + int -readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */ +readrec(char **pbuf, size_t *pbufsize, FILE *inf) /* read one record into buf */ { int sep, c; - uchar *buf; - int count; - size_t bufsize; + char *rr, *rt, *buf = *pbuf; + size_t bufsize = *pbufsize; + char *rs = getsval(rsloc); - init_buf(&buf, &bufsize, LINE_INCR); - if ((sep = **RS) == 0) { + if (rtbuf == NULL && (rtbuf = malloc(rtbufsize)) == NULL) + FATAL("out of memory in readrec"); + + rr = buf; + rt = rtbuf; + + if ((sep = *rs) == '\0') { sep = '\n'; /* skip leading \n's */ while ((c = getc(inf)) == '\n' && c != EOF) @@ -163,47 +276,90 @@ readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */ 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; + while ((c = getc(inf)) != EOF) { + if (c != sep) { + if (rr-buf+1 > bufsize) { + (void) adjbuf(&buf, &bufsize, + 1+rr-buf, recsize, &rr, "readrec1"); + } + *rr++ = c; + continue; + } + + /* + * Ensure enough space for either a single separator + * character, or at least two '\n' chars (when RS is + * the empty string). + */ + (void) adjbuf(&rtbuf, &rtbufsize, + 2+rt-rtbuf, recsize, &rt, "readrec2"); + + if (*rs == sep) { + *rt++ = sep; + break; } - if (**RS == sep || c == EOF) + + if ((c = getc(inf)) == '\n') { /* 2 in a row */ + *rt++ = '\n'; + *rt++ = '\n'; + while ((c = getc(inf)) == '\n' && c != EOF) { + /* Read any further \n's and add them to RT. */ + (void) adjbuf(&rtbuf, &rtbufsize, + 1+rt-rtbuf, recsize, &rt, "readrec3"); + *rt++ = '\n'; + } + if (c != EOF) + (void) ungetc(c, inf); break; - if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ + } + + if (c == EOF) { + *rt++ = '\n'; break; - expand_buf(&buf, &bufsize, count + 1); - buf[count++] = '\n'; - buf[count++] = c; + } + + (void) adjbuf(&buf, &bufsize, + 2+rr-buf, recsize, &rr, "readrec4"); + *rr++ = '\n'; + *rr++ = c; } - buf[count] = '\0'; + (void) adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec5"); + (void) adjbuf(&rtbuf, &rtbufsize, 1+rt-rtbuf, recsize, &rt, "readrec6"); + *rr = '\0'; + *rt = '\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); + buf, c == EOF && rr == buf ? 0 : 1)); + *pbuf = buf; + *pbufsize = bufsize; + if (c == EOF && rr == buf) { + return (0); + } else { + (void) setsval(rtloc, rtbuf); + return (1); + } } /* get ARGV[n] */ -static uchar * +static char * getargv(int n) { Cell *x; - uchar *s, temp[11]; + char *s, temp[50]; extern Array *ARGVtab; - (void) sprintf((char *)temp, "%d", n); - x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab); + (void) sprintf(temp, "%d", n); + if (lookup(temp, ARGVtab) == NULL) + return (NULL); + x = setsymtab(temp, "", 0.0, STR, ARGVtab); s = getsval(x); dprintf(("getargv(%d) returns |%s|\n", n, s)); return (s); } void -setclvar(uchar *s) /* set var=value from s */ +setclvar(char *s) /* set var=value from s */ { - uchar *p; + char *p; Cell *q; for (p = s; *p != '='; p++) @@ -213,7 +369,7 @@ setclvar(uchar *s) /* set var=value from s */ q = setsymtab(s, p, 0.0, STR, symtab); (void) setsval(q, p); if (is_number(q->sval)) { - q->fval = atof((const char *)q->sval); + q->fval = atof(q->sval); q->tval |= NUM; } dprintf(("command line set %s to |%s|\n", s, p)); @@ -221,236 +377,232 @@ setclvar(uchar *s) /* set var=value from s */ } void -fldbld(void) +fldbld(void) /* create fields from current record */ { - uchar *r, *fr, sep; + /* 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 */ + char *r, *fr, sep; Cell *p; - int i; - size_t len; + int i, j, n; 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); + if (!isstr(fldtab[0])) + (void) getsval(fldtab[0]); + r = fldtab[0]->sval; + n = strlen(r); + if (n > fieldssize) { + xfree(fields); + /* possibly 2 final \0s */ + if ((fields = (char *)malloc(n + 2)) == NULL) + FATAL("out of space for fields in fldbld %d", n); + fieldssize = n; + } 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) == ' ') { + if (strlen(inputFS) > 1) { /* it's a regular expression */ + i = refldbld(r, inputFS); + } else if ((sep = *inputFS) == ' ') { /* default whitespace */ for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; - if (*r == 0) + if (*r == '\0') break; i++; - p = getfld(i); - if (!(p->tval & DONTFREE)) - xfree(p->sval); - p->sval = fr; - p->tval = FLD | STR | DONTFREE; + 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'; + } + *fr = '\0'; + } else if ((sep = *inputFS) == '\0') { + /* new: FS="" => 1 char/field */ + for (i = 0; *r != '\0'; r++) { + char 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 */ + *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(*RS) > 0) + rtest = '\0'; 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') + 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) + *fr++ = '\0'; + if (*r++ == '\0') break; } - *fr = 0; + *fr = '\0'; } + if (i > nfields) + FATAL("record `%.30s...' has too many fields; can't happen", r); /* clean out junk from previous record */ - cleanfld(i, maxfld); - maxfld = i; + cleanfld(i+1, lastfld); + lastfld = i; donefld = 1; - for (i = 1; i <= maxfld; i++) { - p = getfld(i); + for (j = 1; j <= lastfld; j++) { + p = fldtab[j]; if (is_number(p->sval)) { - p->fval = atof((const char *)p->sval); + p->fval = atof(p->sval); p->tval |= NUM; } } - - (void) setfval(nfloc, (Awkfloat) maxfld); + (void) setfval(nfloc, (Awkfloat)lastfld); + donerec = 1; /* restore */ if (dbg) { - for (i = 0; i <= maxfld; i++) { - p = getfld(i); - (void) printf("field %d: |%s|\n", i, p->sval); + for (j = 0; j <= lastfld; j++) { + p = fldtab[j]; + (void) printf("field %d (%s): |%s|\n", + j, p->nval, p->sval); } } } +/* clean out fields n1 .. n2 inclusive; nvals remain intact */ static void -cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ +cleanfld(int n1, int n2) { - static uchar *nullstat = (uchar *) ""; Cell *p; - int i; + int i; - for (i = n2; i > n1; i--) { - p = getfld(i); - if (!(p->tval & DONTFREE)) + for (i = n1; i <= n2; i++) { + p = fldtab[i]; + if (freeable(p)) xfree(p->sval); + p->sval = ""; p->tval = FLD | STR | DONTFREE; - p->sval = nullstat; } } void -newfld(int n) /* add field n (after end) */ +newfld(int n) /* add field n after end of existing lastfld */ { - if (n < 0) - ERROR "accessing invalid field", record FATAL; - (void) getfld(n); - cleanfld(maxfld, n); - maxfld = n; - (void) setfval(nfloc, (Awkfloat) n); + if (n > nfields) + growfldtab(n); + cleanfld(lastfld+1, n); + lastfld = 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) +void +setlastfld(int n) /* set lastfld cleaning fldtab cells if necessary */ { - 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; + if (n < 0) + FATAL("cannot set NF to a negative value"); + if (n > nfields) + growfldtab(n); + + if (lastfld < n) + cleanfld(lastfld+1, n); else - fldtab_tail->next = fldcp; - fldtab_tail = fldcp; - fldcp->next = NULL; + cleanfld(n+1, lastfld); - fldtab_maxidx += FLD_INCR; + lastfld = n; } Cell * -getfld(int idx) +fieldadr(int n) /* get nth field */ { - 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); + 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]); } -int -fldidx(Cell *vp) +void +growfldtab(int n) /* make new fields up to at least $n */ { - 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); + int nf = 2 * nfields; + size_t s; + + if (n > nf) + nf = n; + s = (nf+1) * (sizeof (Cell *)); /* freebsd: how much do we need? */ + if (s / sizeof (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; } +/* build fields from reg expr in FS */ static int -refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ +refldbld(const char *rec, const char *fs) { - uchar *fr; - int i, tempstat; + /* this relies on having fields[] the same length as $0 */ + /* the fields are all stored in this one array with \0's */ + char *fr; + int i, tempstat, n; fa *pfa; - Cell *p; - size_t len; - /* make sure fields is allocated */ - adjust_buf(&fields, fields_size); + n = strlen(rec); + if (n > fieldssize) { + xfree(fields); + if ((fields = (char *)malloc(n+1)) == NULL) + FATAL("out of space for fields in refldbld %d", n); + fieldssize = n; + } 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; + 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; + pfa->initstat = 2; /* horrible coupling to b.c */ dprintf(("match %s (%d chars)\n", patbeg, patlen)); - (void) strncpy((char *)fr, (char *)rec, patbeg-rec); + (void) strncpy(fr, rec, patbeg-rec); fr += patbeg - rec + 1; *(fr-1) = '\0'; rec = patbeg + patlen; } else { dprintf(("no match %s\n", rec)); - (void) strcpy((char *)fr, (char *)rec); + (void) strcpy(fr, rec); pfa->initstat = tempstat; break; } @@ -459,71 +611,74 @@ refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */ } void -recbld(void) +recbld(void) /* create $0 from $1..$NF if necessary */ { int i; - uchar *p; + char *p; size_t cnt, len, olen; + char *sep = getsval(ofsloc); if (donerec == 1) return; cnt = 0; - olen = strlen((char *)*OFS); + olen = strlen(sep); for (i = 1; i <= *NF; i++) { - p = getsval(getfld(i)); - len = strlen((char *)p); - expand_buf(&record, &record_size, cnt + len + olen); + p = getsval(fldtab[i]); + len = strlen(p); + expand_buf(&record, &recsize, cnt + len + olen); (void) memcpy(&record[cnt], p, len); cnt += len; if (i < *NF) { - (void) memcpy(&record[cnt], *OFS, olen); + (void) memcpy(&record[cnt], sep, olen); cnt += olen; } } record[cnt] = '\0'; - dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc)); - if (!(recloc->tval & DONTFREE)) + dprintf(("in recbld inputFS=%s, recloc=%p\n", inputFS, (void *)recloc)); + if (freeable(recloc)) xfree(recloc->sval); recloc->tval = REC | STR | DONTFREE; recloc->sval = record; - dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc)); + dprintf(("in recbld inputFS=%s, recloc=%p\n", inputFS, (void *)recloc)); dprintf(("recbld = |%s|\n", record)); donerec = 1; } -Cell * -fieldadr(int n) +int errorflag = 0; + +void +yyerror(const char *s) { - if (n < 0) - ERROR "trying to access field %d", n FATAL; - return (getfld(n)); + SYNTAX("%s", s); } -int errorflag = 0; -char errbuf[200]; - void -yyerror(char *s) +SYNTAX(const char *fmt, ...) { - extern uchar *cmdname, *curfname; + extern char *cmdname, *curfname; static int been_here = 0; + va_list varg; if (been_here++ > 2) return; - (void) fprintf(stderr, "%s: %s", cmdname, s); - (void) fprintf(stderr, gettext(" at source line %lld"), lineno); + (void) fprintf(stderr, "%s: ", cmdname); + va_start(varg, fmt); + (void) vfprintf(stderr, fmt, varg); + va_end(varg); + (void) fprintf(stderr, " at source line %lld", lineno); if (curfname != NULL) - (void) fprintf(stderr, gettext(" in function %s"), curfname); + (void) fprintf(stderr, " in function %s", curfname); + if (compile_time == 1 && cursource() != NULL) + (void) fprintf(stderr, " source file %s", cursource()); (void) fprintf(stderr, "\n"); errorflag = 2; eprint(); } -/*ARGSUSED*/ void -fpecatch(int sig) +fpecatch(int n) { - ERROR "floating point exception" FATAL; + FATAL("floating point exception %d", n); } extern int bracecnt, brackcnt, parencnt; @@ -558,47 +713,74 @@ bcheck2(int n, int c1, int c2) } void -error(int f, char *s) +FATAL(const char *fmt, ...) { - extern Node *curnode; - extern uchar *cmdname; + extern char *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 char *cmdname; + va_list varg; (void) fflush(stdout); (void) fprintf(stderr, "%s: ", cmdname); - (void) fprintf(stderr, "%s", s); + 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"), *FNR); - if (strcmp((char *)*FILENAME, "-") != 0) + if (strcmp(*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"), + (void) fprintf(stderr, gettext(" source line number %lld"), curnode->lineno); else if (compile_time != 2 && lineno) { (void) fprintf(stderr, - gettext(" source line number %lld\n"), lineno); + gettext(" source line number %lld"), lineno); } + if (compile_time == 1 && cursource() != NULL) + (void) fprintf(stderr, gettext(" source file %s"), cursource()); + (void) fprintf(stderr, "\n"); eprint(); - if (f) { - if (dbg) - abort(); - exit(2); - } } static void eprint(void) /* try to print context around error */ { - uchar *p, *q; + char *p, *q; int c; static int been_here = 0; - extern uchar ebuf[300], *ep; + extern char ebuf[], *ep; if (compile_time == 2 || compile_time == 0 || been_here++ > 0) return; + if (ebuf == ep) + return; p = ep - 1; if (p > ebuf && *p == '\n') p--; @@ -640,30 +822,22 @@ bclass(int c) } double -errcheck(double x, char *s) +errcheck(double x, const char *s) { - extern int errno; - if (errno == EDOM) { errno = 0; - ERROR "%s argument out of domain", s WARNING; + WARNING("%s argument out of domain", s); x = 1; } else if (errno == ERANGE) { errno = 0; - ERROR "%s result out of range", s WARNING; + WARNING("%s result out of range", s); x = 1; } return (x); } -void -PUTS(uchar *s) -{ - dprintf(("%s\n", s)); -} - int -isclvar(uchar *s) /* is s of form var=something? */ +isclvar(const char *s) /* is s of form var=something ? */ { if (s != NULL) { @@ -686,88 +860,28 @@ isclvar(uchar *s) /* is s of form var=something? */ return (0); } -#define MAXEXPON 38 /* maximum exponent for fp number */ - +#include <math.h> int -is_number(uchar *s) +is_number(const char *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)) + double r; + char *ep; + errno = 0; + r = strtod(s, &ep); + if (ep == s || r == HUGE_VAL || errno == ERANGE) 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') + while (*ep == ' ' || *ep == '\t' || *ep == '\n') + ep++; + if (*ep == '\0') return (1); else return (0); } void -init_buf(uchar **optr, size_t *sizep, size_t amt) +r_expand_buf(char **optr, size_t *sizep, size_t req) { - 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; + char *nptr; size_t amt, size = *sizep; if (size != 0 && req < (size - 1)) @@ -776,20 +890,10 @@ r_expand_buf(uchar **optr, size_t *sizep, size_t req) amt = (amt / LINE_INCR + 1) * LINE_INCR; if ((nptr = realloc(*optr, size + amt)) == NULL) - ERROR "out of space in expand_buf" FATAL; + FATAL("out of space in expand_buf"); /* 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; -} |
