Print this page
3731 Update nawk to version 20121220
@@ -22,84 +22,155 @@
/*
* 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"
+/*
+ * 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;
+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) */
-static struct fldtab_chunk {
- struct fldtab_chunk *next;
- Cell fields[FLD_INCR];
-} *fldtab_head, *fldtab_tail;
-
-static size_t fldtab_maxidx;
+int lastfld = 0; /* last used field */
static FILE *infile = NULL;
static uchar *file = (uchar*) "";
static uchar *fields;
-static size_t fields_size = LINE_INCR;
+static size_t fields_size = RECSIZE;
-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 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++) {
- 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((uchar *)"FILENAME", symtab), p);
return;
+ }
setclvar(p); /* a commandline assignment before filename */
argno++;
}
infile = stdin; /* no filenames, so use stdin */
- /* *FILENAME = file = (uchar*) "-"; */
}
+static int firsttime = 1;
+
int
-getrec(uchar **bufp, size_t *bufsizep)
-{
+getrec(uchar **pbuf, size_t *pbufsize, int isrecord)
+{ /* get next input record */
+ /* note: cares whether buf == record */
int c;
- static int firsttime = 1;
- uchar_t *buf, *nbuf;
- size_t len;
+ 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);
- if (*file == '\0') { /* it's been zapped */
+ /* deleted or zapped */
+ if (file == NULL || *file == '\0') {
argno++;
continue;
}
if (isclvar(file)) { /* a var=value arg */
setclvar(file);
@@ -109,93 +180,119 @@
*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;
+ 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))
- 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;
+ 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 **bufp, size_t *sizep, FILE *inf) /* read one record into buf */
+readrec(uchar **pbuf, size_t *pbufsize, FILE *inf)
{
int sep, c;
- uchar *buf;
- int count;
- size_t bufsize;
+ 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
+ */
- init_buf(&buf, &bufsize, LINE_INCR);
+ /* 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);
}
- count = 0;
- for (;;) {
- while ((c = getc(inf)) != sep && c != EOF) {
- expand_buf(&buf, &bufsize, count);
- buf[count++] = c;
+ 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;
- expand_buf(&buf, &bufsize, count + 1);
- buf[count++] = '\n';
- buf[count++] = c;
- }
- buf[count] = '\0';
+ 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 && 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;
+ return (c == EOF && rr == buf ? 0 : 1);
}
-/* get ARGV[n] */
static uchar *
-getargv(int n)
+getargv(int n) /* get ARGV[n] */
{
Cell *x;
- uchar *s, temp[11];
+ 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,236 +312,215 @@
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)
+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;
- size_t len;
+ int i, j;
+ size_t 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((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 */
- if (strlen((char *)*FS) > 1) { /* it's a regular expression */
- i = refldbld(r, *FS);
- } else if ((sep = **FS) == ' ') {
+ (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++;
- 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;
+ } 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++;
- 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)
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, 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->tval |= NUM;
}
}
-
- (void) setfval(nfloc, (Awkfloat) maxfld);
+ (void) setfval(nfloc, (Awkfloat)lastfld);
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);
}
}
}
static void
cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
-{
- static uchar *nullstat = (uchar *) "";
+{ /* nvals remain intact */
+ static uchar *nullstat = (uchar *)"";
Cell *p;
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->tval = FLD | STR | DONTFREE;
p->sval = nullstat;
+ p->tval = FLD | STR | DONTFREE;
}
}
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)
+newfld(int n) /* add field n after end of existing lastfld */
{
- 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;
+ if (n > nfields)
+ growfldtab(n);
+ cleanfld(lastfld + 1, n);
+ lastfld = n;
+ (void) setfval(nfloc, (Awkfloat)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)
-{
- 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);
+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;
- Cell *p;
- size_t len;
+ size_t n;
- /* make sure fields is allocated */
- adjust_buf(&fields, fields_size);
+ 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);
-
- 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);
fr += patbeg - rec + 1;
*(fr-1) = '\0';
rec = patbeg + patlen;
@@ -457,75 +533,87 @@
}
return (i);
}
void
-recbld(void)
+recbld(void) /* create $0 from $1..$NF if necessary */
{
int i;
- uchar *p;
- size_t cnt, len, olen;
+ uchar *r, *p;
if (donerec == 1)
return;
- cnt = 0;
- olen = strlen((char *)*OFS);
+ r = record;
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;
+ 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) {
- (void) memcpy(&record[cnt], *OFS, olen);
- cnt += olen;
+ 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++;
}
}
- 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));
+ 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;
}
-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)
{
+ 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: %s", cmdname, s);
+ (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();
}
-/*ARGSUSED*/
void
-fpecatch(int sig)
+fpecatch(int n)
{
- ERROR "floating point exception" FATAL;
+ FATAL("floating point exception %d", n);
}
extern int bracecnt, brackcnt, parencnt;
void
@@ -556,48 +644,74 @@
else if (n < -1)
(void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
}
void
-error(int f, char *s)
+FATAL(const char *fmt, ...)
{
- extern Node *curnode;
extern uchar *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();
+ 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"), *FNR);
+ 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 %lld\n"),
+ (void) fprintf(stderr, gettext(" source line number %d"),
curnode->lineno);
else if (compile_time != 2 && lineno) {
(void) fprintf(stderr,
- gettext(" source line number %lld\n"), lineno);
+ 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();
- 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;
+ extern uchar ebuf[], *ep;
if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
return;
p = ep - 1;
if (p > ebuf && *p == '\n')
@@ -638,158 +752,54 @@
case ')': parencnt--; break;
}
}
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 uchar *s) /* is s of form var=something? */
{
- if (s != NULL) {
+ const uchar *os = s;
- /* 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 == '_')) {
+ if (!isalpha(*s) && *s != '_')
+ return (0);
+ for (; *s; s++) {
+ if (!(isalnum(*s) || *s == '_'))
break;
}
- }
- return (*s == '=' && *(s + 1) != '=');
- }
- }
- return (0);
+ return (*s == '=' && s > os && *(s+1) != '=');
}
-#define MAXEXPON 38 /* maximum exponent for fp number */
+/* 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(uchar *s)
+is_number(const 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) {
+ double r;
+ char *ep;
+ errno = 0;
+ r = strtod((const char *)s, &ep);
+ if (ep == (char *)s || r == HUGE_VAL || errno == ERANGE)
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)
-{
- 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;
-}