version 1.3, 1997/01/24 23:11:31 |
version 1.4, 1997/08/25 16:17:11 |
|
|
|
/* $OpenBSD$ */ |
/**************************************************************** |
/**************************************************************** |
Copyright (C) AT&T and Lucent Technologies 1996 |
Copyright (C) Lucent Technologies 1997 |
All Rights Reserved |
All Rights Reserved |
|
|
Permission to use, copy, modify, and distribute this software and |
Permission to use, copy, modify, and distribute this software and |
|
|
granted, provided that the above copyright notice appear in all |
granted, provided that the above copyright notice appear in all |
copies and that both that the copyright notice and this |
copies and that both that the copyright notice and this |
permission notice and warranty disclaimer appear in supporting |
permission notice and warranty disclaimer appear in supporting |
documentation, and that the names of AT&T or Lucent Technologies |
documentation, and that the name Lucent Technologies or any of |
or any of their entities not be used in advertising or publicity |
its entities not be used in advertising or publicity pertaining |
pertaining to distribution of the software without specific, |
to distribution of the software without specific, written prior |
written prior permission. |
permission. |
|
|
AT&T AND LUCENT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. |
FITNESS. IN NO EVENT SHALL AT&T OR LUCENT OR ANY OF THEIR |
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY |
ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL |
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER |
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR |
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE |
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF |
USE OR PERFORMANCE OF THIS SOFTWARE. |
THIS SOFTWARE. |
****************************************************************/ |
****************************************************************/ |
|
|
#define DEBUG |
#define DEBUG |
|
|
#include <errno.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include "awk.h" |
#include "awk.h" |
#include "awkgram.h" |
#include "ytab.h" |
|
|
FILE *infile = NULL; |
FILE *infile = NULL; |
char *file = ""; |
char *file = ""; |
int recsize = RECSIZE; |
|
char *recdata; |
|
char *record; |
char *record; |
|
int recsize = RECSIZE; |
char *fields; |
char *fields; |
Cell *fldtab; |
int fieldssize = RECSIZE; |
char inputFS[100]; /* BUG: unchecked */ |
|
|
|
|
Cell **fldtab; /* pointers to Cells */ |
|
char inputFS[100]; |
|
|
#define MAXFLD 200 |
#define MAXFLD 200 |
int nfields = MAXFLD; /* can be set from commandline in main */ |
int nfields = MAXFLD; /* last allocated slot for $i */ |
|
|
int donefld; /* 1 = implies rec broken into fields */ |
int donefld; /* 1 = implies rec broken into fields */ |
int donerec; /* 1 = record is valid (no flds have changed) */ |
int donerec; /* 1 = record is valid (no flds have changed) */ |
|
|
int maxfld = 0; /* last used field */ |
int lastfld = 0; /* last used field */ |
int argno = 1; /* current input argument number */ |
int argno = 1; /* current input argument number */ |
extern Awkfloat *ARGC; |
extern Awkfloat *ARGC; |
|
|
|
static Cell dollar0 = { OCELL, CFLD, NULL, "", 0.0, REC|STR|DONTFREE }; |
|
static Cell dollar1 = { OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; |
|
|
void recinit(unsigned int n) |
void recinit(unsigned int n) |
{ |
{ |
static Cell dollar0 = { |
record = (char *) malloc(n); |
OCELL, CFLD, "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE }; |
|
static Cell dollar1 = { |
|
OCELL, CFLD, NULL, "", 0.0, FLD|STR|DONTFREE }; |
|
int i; |
|
|
|
record = recdata = (char *) malloc(n); |
|
fields = (char *) malloc(n); |
fields = (char *) malloc(n); |
fldtab = (Cell *) malloc(nfields * sizeof(Cell)); |
fldtab = (Cell **) malloc((nfields+1) * sizeof(Cell *)); |
if (recdata == NULL || fields == NULL || fldtab == NULL) |
if (record == NULL || fields == NULL || fldtab == NULL) |
ERROR "out of space for $0 and fields" FATAL; |
ERROR "out of space for $0 and fields" FATAL; |
fldtab[0] = dollar0; |
|
fldtab[0].sval = recdata; |
fldtab[0] = (Cell *) malloc(sizeof (Cell)); |
for (i = 1; i < nfields; i++) |
*fldtab[0] = dollar0; |
fldtab[i] = dollar1; |
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 (struct Cell)); |
|
if (fldtab[i] == NULL) |
|
ERROR "out of space in makefields %d", i FATAL; |
|
*fldtab[i] = dollar1; |
|
sprintf(temp, "%d", i); |
|
fldtab[i]->nval = tostring(temp); |
|
} |
|
} |
|
|
void initgetrec(void) |
void initgetrec(void) |
{ |
{ |
int i; |
int i; |
|
|
infile = stdin; /* no filenames, so use stdin */ |
infile = stdin; /* no filenames, so use stdin */ |
} |
} |
|
|
int getrec(char *buf) /* get next input record from whatever source */ |
int getrec(char **pbuf, int *pbufsize, int isrecord) /* get next input record */ |
{ /* note: tests whether buf == record */ |
{ /* note: cares whether buf == record */ |
int c; |
int c; |
static int firsttime = 1; |
static int firsttime = 1; |
|
char *buf = *pbuf; |
|
int bufsize = *pbufsize; |
|
|
if (firsttime) { |
if (firsttime) { |
firsttime = 0; |
firsttime = 0; |
initgetrec(); |
initgetrec(); |
} |
} |
dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", |
dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n", |
*RS, *FS, *ARGC, *FILENAME) ); |
*RS, *FS, *ARGC, *FILENAME) ); |
donefld = 0; |
donefld = 0; |
donerec = 1; |
donerec = 1; |
buf[0] = 0; |
buf[0] = 0; |
while (argno < *ARGC || infile == stdin) { |
while (argno < *ARGC || infile == stdin) { |
dprintf( ("argno=%d, file=|%s|\n", argno, file) ); |
dprintf( ("argno=%d, file=|%s|\n", argno, file) ); |
if (infile == NULL) { /* have to open a new file */ |
if (infile == NULL) { /* have to open a new file */ |
file = getargv(argno); |
file = getargv(argno); |
if (*file == '\0') { /* it's been zapped */ |
if (*file == '\0') { /* it's been zapped */ |
|
|
continue; |
continue; |
} |
} |
*FILENAME = file; |
*FILENAME = file; |
dprintf( ("opening file %s\n", file) ); |
dprintf( ("opening file %s\n", file) ); |
if (*file == '-' && *(file+1) == '\0') |
if (*file == '-' && *(file+1) == '\0') |
infile = stdin; |
infile = stdin; |
else if ((infile = fopen((char *)file, "r")) == NULL) |
else if ((infile = fopen(file, "r")) == NULL) |
ERROR "can't open file %s", file FATAL; |
ERROR "can't open file %s", file FATAL; |
setfval(fnrloc, 0.0); |
setfval(fnrloc, 0.0); |
} |
} |
c = readrec(buf, recsize, infile); |
c = readrec(&buf, &bufsize, infile); |
if (c != 0 || buf[0] != '\0') { /* normal record */ |
if (c != 0 || buf[0] != '\0') { /* normal record */ |
if (buf == record) { |
if (isrecord) { |
if (!(recloc->tval & DONTFREE)) |
if (freeable(fldtab[0])) |
xfree(recloc->sval); |
xfree(fldtab[0]->sval); |
recloc->sval = record; |
fldtab[0]->sval = buf; /* buf == record */ |
recloc->tval = REC | STR | DONTFREE; |
fldtab[0]->tval = REC | STR | DONTFREE; |
if (isnumber(recloc->sval)) { |
if (isnumber(fldtab[0]->sval)) { |
recloc->fval = atof(recloc->sval); |
fldtab[0]->fval = atof(fldtab[0]->sval); |
recloc->tval |= NUM; |
fldtab[0]->tval |= NUM; |
} |
} |
} |
} |
setfval(nrloc, nrloc->fval+1); |
setfval(nrloc, nrloc->fval+1); |
setfval(fnrloc, fnrloc->fval+1); |
setfval(fnrloc, fnrloc->fval+1); |
|
*pbuf = buf; |
|
*pbufsize = bufsize; |
return 1; |
return 1; |
} |
} |
/* EOF arrived on this file; set up next */ |
/* EOF arrived on this file; set up next */ |
|
|
infile = NULL; |
infile = NULL; |
argno++; |
argno++; |
} |
} |
|
*pbuf = buf; |
|
*pbufsize = bufsize; |
return 0; /* true end of file */ |
return 0; /* true end of file */ |
} |
} |
|
|
|
|
argno++; |
argno++; |
} |
} |
|
|
int readrec(char *buf, int bufsize, FILE *inf) /* read one record into buf */ |
int readrec(char **pbuf, int *pbufsize, FILE *inf) /* read one record into buf */ |
{ |
{ |
int sep, c; |
int sep, c; |
char *rr; |
char *rr, *buf = *pbuf; |
int nrr; |
int bufsize = *pbufsize; |
|
|
|
if (strlen(*FS) >= sizeof(inputFS)) |
|
ERROR "field separator %.10s... is too long", *FS FATAL; |
strcpy(inputFS, *FS); /* for subsequent field splitting */ |
strcpy(inputFS, *FS); /* for subsequent field splitting */ |
if ((sep = **RS) == 0) { |
if ((sep = **RS) == 0) { |
sep = '\n'; |
sep = '\n'; |
|
|
if (c != EOF) |
if (c != EOF) |
ungetc(c, inf); |
ungetc(c, inf); |
} |
} |
for (rr = buf, nrr = bufsize; ; ) { |
for (rr = buf; ; ) { |
for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c) |
for (; (c=getc(inf)) != sep && c != EOF; ) { |
if (--nrr < 0) |
if (rr-buf+1 > bufsize) |
ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; |
if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 1")) |
|
ERROR "input record `%.30s...' too long", buf FATAL; |
|
*rr++ = c; |
|
} |
if (**RS == sep || c == EOF) |
if (**RS == sep || c == EOF) |
break; |
break; |
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ |
if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */ |
break; |
break; |
|
if (!adjbuf(&buf, &bufsize, 2+rr-buf, recsize, &rr, "readrec 2")) |
|
ERROR "input record `%.30s...' too long", buf FATAL; |
*rr++ = '\n'; |
*rr++ = '\n'; |
*rr++ = c; |
*rr++ = c; |
} |
} |
if (rr > buf + bufsize) |
if (!adjbuf(&buf, &bufsize, 1+rr-buf, recsize, &rr, "readrec 3")) |
ERROR "input record `%.30s...' too long; try -mr n", buf FATAL; |
ERROR "input record `%.30s...' too long", buf FATAL; |
*rr = 0; |
*rr = 0; |
dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) ); |
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; |
return c == EOF && rr == buf ? 0 : 1; |
} |
} |
|
|
char *getargv(int n) /* get ARGV[n] */ |
char *getargv(int n) /* get ARGV[n] */ |
{ |
{ |
Cell *x; |
Cell *x; |
char *s, temp[10]; |
char *s, temp[50]; |
extern Array *ARGVtab; |
extern Array *ARGVtab; |
|
|
sprintf(temp, "%d", n); |
sprintf(temp, "%d", n); |
x = setsymtab(temp, "", 0.0, STR, ARGVtab); |
x = setsymtab(temp, "", 0.0, STR, ARGVtab); |
s = getsval(x); |
s = getsval(x); |
dprintf( ("getargv(%d) returns |%s|\n", n, s) ); |
dprintf( ("getargv(%d) returns |%s|\n", n, s) ); |
return s; |
return s; |
} |
} |
|
|
|
|
q->fval = atof(q->sval); |
q->fval = atof(q->sval); |
q->tval |= NUM; |
q->tval |= NUM; |
} |
} |
dprintf( ("command line set %s to |%s|\n", s, p) ); |
dprintf( ("command line set %s to |%s|\n", s, p) ); |
} |
} |
|
|
|
|
void fldbld(void) /* create fields from current record */ |
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 */ |
char *r, *fr, sep; |
char *r, *fr, sep; |
Cell *p; |
Cell *p; |
int i; |
int i, j, n; |
|
|
if (donefld) |
if (donefld) |
return; |
return; |
if (!(recloc->tval & STR)) |
if (!isstr(fldtab[0])) |
getsval(recloc); |
getsval(fldtab[0]); |
r = recloc->sval; |
r = fldtab[0]->sval; |
|
n = strlen(r); |
|
if (n > fieldssize) { |
|
xfree(fields); |
|
if ((fields = (char *) malloc(n+1)) == NULL) |
|
ERROR "out of space for fields in fldbld %d", n FATAL; |
|
fieldssize = n; |
|
} |
fr = fields; |
fr = fields; |
i = 0; /* number of fields accumulated here */ |
i = 0; /* number of fields accumulated here */ |
if (strlen(inputFS) > 1) { /* it's a regular expression */ |
if (strlen(inputFS) > 1) { /* it's a regular expression */ |
|
|
if (*r == 0) |
if (*r == 0) |
break; |
break; |
i++; |
i++; |
if (i >= nfields) |
if (i > nfields) |
break; |
growfldtab(i); |
if (!(fldtab[i].tval & DONTFREE)) |
if (freeable(fldtab[i])) |
xfree(fldtab[i].sval); |
xfree(fldtab[i]->sval); |
fldtab[i].sval = fr; |
fldtab[i]->sval = fr; |
fldtab[i].tval = FLD | STR | DONTFREE; |
fldtab[i]->tval = FLD | STR | DONTFREE; |
do |
do |
*fr++ = *r++; |
*fr++ = *r++; |
while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); |
while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); |
|
|
for (i = 0; *r != 0; r++) { |
for (i = 0; *r != 0; r++) { |
char buf[2]; |
char buf[2]; |
i++; |
i++; |
if (i >= nfields) |
if (i > nfields) |
break; |
growfldtab(i); |
if (!(fldtab[i].tval & DONTFREE)) |
if (freeable(fldtab[i])) |
xfree(fldtab[i].sval); |
xfree(fldtab[i]->sval); |
buf[0] = *r; |
buf[0] = *r; |
buf[1] = 0; |
buf[1] = 0; |
fldtab[i].sval = tostring(buf); |
fldtab[i]->sval = tostring(buf); |
fldtab[i].tval = FLD | STR; |
fldtab[i]->tval = FLD | STR; |
} |
} |
*fr = 0; |
*fr = 0; |
} else if (*r != 0) { /* if 0, it's a null field */ |
} else if (*r != 0) { /* if 0, it's a null field */ |
for (;;) { |
for (;;) { |
i++; |
i++; |
if (i >= nfields) |
if (i > nfields) |
break; |
growfldtab(i); |
if (!(fldtab[i].tval & DONTFREE)) |
if (freeable(fldtab[i])) |
xfree(fldtab[i].sval); |
xfree(fldtab[i]->sval); |
fldtab[i].sval = fr; |
fldtab[i]->sval = fr; |
fldtab[i].tval = FLD | STR | DONTFREE; |
fldtab[i]->tval = FLD | STR | DONTFREE; |
while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ |
while (*r != sep && *r != '\n' && *r != '\0') /* \n is always a separator */ |
*fr++ = *r++; |
*fr++ = *r++; |
*fr++ = 0; |
*fr++ = 0; |
|
|
} |
} |
*fr = 0; |
*fr = 0; |
} |
} |
if (i >= nfields) |
if (i > nfields) |
ERROR "record `%.30s...' has too many fields; try -mf n", record FATAL; |
ERROR "record `%.30s...' has too many fields; can't happen", r FATAL; |
/* clean out junk from previous record */ |
cleanfld(i+1, lastfld); /* clean out junk from previous record */ |
cleanfld(i, maxfld); |
lastfld = i; |
maxfld = i; |
|
donefld = 1; |
donefld = 1; |
for (p = fldtab+1; p <= fldtab+maxfld; p++) { |
for (j = 1; j <= lastfld; j++) { |
|
p = fldtab[j]; |
if(isnumber(p->sval)) { |
if(isnumber(p->sval)) { |
p->fval = atof(p->sval); |
p->fval = atof(p->sval); |
p->tval |= NUM; |
p->tval |= NUM; |
} |
} |
} |
} |
setfval(nfloc, (Awkfloat) maxfld); |
setfval(nfloc, (Awkfloat) lastfld); |
if (dbg) |
if (dbg) { |
for (p = fldtab; p <= fldtab+maxfld; p++) |
for (j = 0; j <= lastfld; j++) { |
printf("field %d: |%s|\n", p-fldtab, p->sval); |
p = fldtab[j]; |
|
printf("field %d (%s): |%s|\n", j, p->nval, p->sval); |
|
} |
|
} |
} |
} |
|
|
void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */ |
void cleanfld(int n1, int n2) /* clean out fields n1 .. n2 inclusive */ |
{ |
{ /* nvals remain intact */ |
static char *nullstat = ""; |
Cell *p; |
Cell *p, *q; |
int i; |
|
|
for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) { |
for (i = n1; i <= n2; i++) { |
if (!(p->tval & DONTFREE)) |
p = fldtab[i]; |
|
if (freeable(p)) |
xfree(p->sval); |
xfree(p->sval); |
|
p->sval = ""; |
p->tval = FLD | STR | DONTFREE; |
p->tval = FLD | STR | DONTFREE; |
p->sval = nullstat; |
|
} |
} |
} |
} |
|
|
void newfld(int n) /* add field n (after end) */ |
void newfld(int n) /* add field n after end of existing lastfld */ |
{ |
{ |
if (n >= nfields) |
if (n > nfields) |
ERROR "creating too many fields (%d); try -mf n", n FATAL; |
growfldtab(n); |
cleanfld(maxfld, n); |
cleanfld(lastfld+1, n); |
maxfld = n; |
lastfld = n; |
setfval(nfloc, (Awkfloat) n); |
setfval(nfloc, (Awkfloat) n); |
} |
} |
|
|
|
Cell *fieldadr(int n) /* get nth field */ |
|
{ |
|
if (n < 0) |
|
ERROR "trying to access field %d", n FATAL; |
|
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; |
|
|
|
if (n > nf) |
|
nf = n; |
|
fldtab = (Cell **) realloc(fldtab, (nf+1) * (sizeof (struct Cell *))); |
|
if (fldtab == NULL) |
|
ERROR "out of space creating %d fields", nf FATAL; |
|
makefields(nfields+1, nf); |
|
nfields = nf; |
|
} |
|
|
int refldbld(char *rec, char *fs) /* build fields from reg expr in FS */ |
int refldbld(char *rec, char *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 */ |
char *fr; |
char *fr; |
int i, tempstat; |
int i, tempstat, n; |
fa *pfa; |
fa *pfa; |
|
|
|
n = strlen(rec); |
|
if (n > fieldssize) { |
|
xfree(fields); |
|
if ((fields = (char *) malloc(n+1)) == NULL) |
|
ERROR "out of space for fields in refldbld %d", n FATAL; |
|
fieldssize = n; |
|
} |
fr = fields; |
fr = fields; |
*fr = '\0'; |
*fr = '\0'; |
if (*rec == '\0') |
if (*rec == '\0') |
return 0; |
return 0; |
pfa = makedfa(fs, 1); |
pfa = makedfa(fs, 1); |
dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); |
dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) ); |
tempstat = pfa->initstat; |
tempstat = pfa->initstat; |
for (i = 1; i < nfields; i++) { |
for (i = 1; ; i++) { |
if (!(fldtab[i].tval & DONTFREE)) |
if (i > nfields) |
xfree(fldtab[i].sval); |
growfldtab(i); |
fldtab[i].tval = FLD | STR | DONTFREE; |
if (freeable(fldtab[i])) |
fldtab[i].sval = fr; |
xfree(fldtab[i]->sval); |
dprintf( ("refldbld: i=%d\n", i) ); |
fldtab[i]->tval = FLD | STR | DONTFREE; |
|
fldtab[i]->sval = fr; |
|
dprintf( ("refldbld: i=%d\n", i) ); |
if (nematch(pfa, rec)) { |
if (nematch(pfa, rec)) { |
pfa->initstat = 2; /* horrible coupling */ |
pfa->initstat = 2; /* horrible coupling to b.c */ |
dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); |
dprintf( ("match %s (%d chars)\n", patbeg, patlen) ); |
strncpy(fr, rec, patbeg-rec); |
strncpy(fr, rec, patbeg-rec); |
fr += patbeg - rec + 1; |
fr += patbeg - rec + 1; |
*(fr-1) = '\0'; |
*(fr-1) = '\0'; |
rec = patbeg + patlen; |
rec = patbeg + patlen; |
} else { |
} else { |
dprintf( ("no match %s\n", rec) ); |
dprintf( ("no match %s\n", rec) ); |
strcpy(fr, rec); |
strcpy(fr, rec); |
pfa->initstat = tempstat; |
pfa->initstat = tempstat; |
break; |
break; |
|
|
{ |
{ |
int i; |
int i; |
char *r, *p; |
char *r, *p; |
static char *rec = 0; |
char *buf = record; |
|
int bufsize = recsize; |
|
|
if (donerec == 1) |
if (donerec == 1) |
return; |
return; |
if (rec == 0) { |
r = buf; |
rec = (char *) malloc(recsize); |
|
if (rec == 0) |
|
ERROR "out of space building $0, record size %d", recsize FATAL; |
|
} |
|
r = rec; |
|
for (i = 1; i <= *NF; i++) { |
for (i = 1; i <= *NF; i++) { |
p = getsval(&fldtab[i]); |
p = getsval(fldtab[i]); |
while (r < rec+recsize-1 && (*r = *p++)) |
if (!adjbuf(&buf, &bufsize, 1+strlen(p)+r-buf, recsize, &r, "recbld 1")) |
|
ERROR "created $0 `%.30s...' too long", buf FATAL; |
|
while ((*r = *p++) != 0) |
r++; |
r++; |
if (i < *NF) |
if (i < *NF) { |
for (p = *OFS; r < rec+recsize-1 && (*r = *p++); ) |
if (!adjbuf(&buf, &bufsize, 2+strlen(*OFS)+r-buf, recsize, &r, "recbld 2")) |
|
ERROR "created $0 `%.30s...' too long", buf FATAL; |
|
for (p = *OFS; (*r = *p++) != 0; ) |
r++; |
r++; |
|
} |
} |
} |
if (r > rec + recsize - 1) |
if (!adjbuf(&buf, &bufsize, 2+r-buf, recsize, &r, "recbld 3")) |
ERROR "built giant record `%.30s...'; try -mr n", record FATAL; |
ERROR "built giant record `%.30s...'", buf FATAL; |
*r = '\0'; |
*r = '\0'; |
dprintf( ("in recbld inputFS=%s, recloc=%p\n", inputFS, recloc) ); |
dprintf( ("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS, fldtab[0]) ); |
recloc->tval = REC | STR | DONTFREE; |
|
recloc->sval = record = rec; |
if (buf != record) { /* increased size of record */ |
dprintf( ("in recbld inputFS=%s, recloc=%p\n", inputFS, recloc) ); |
record = buf; /* BUG? memory leak? */ |
dprintf( ("recbld = |%s|\n", record) ); |
recsize = bufsize; |
|
} |
|
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, fldtab[0]) ); |
|
dprintf( ("recbld = |%s|\n", record) ); |
donerec = 1; |
donerec = 1; |
} |
} |
|
|
Cell *fieldadr(int n) |
|
{ |
|
if (n < 0 || n >= nfields) |
|
ERROR "trying to access field %d; try -mf n", n FATAL; |
|
return(&fldtab[n]); |
|
} |
|
|
|
int errorflag = 0; |
int errorflag = 0; |
char errbuf[200]; |
char errbuf[300]; /* used by ERROR macro */ |
|
|
void yyerror(char *s) |
void yyerror(char *s) |
{ |
{ |
|
|
return *s == '=' && s > os && *(s+1) != '='; |
return *s == '=' && s > os && *(s+1) != '='; |
} |
} |
|
|
#define MAXEXPON 38 /* maximum exponent for fp number. should be IEEE */ |
/* strtod is supposed to be a proper test of what's a valid number */ |
|
|
int isnumber(char *s) /* should be done by a library function */ |
#include <math.h> |
|
int isnumber(char *s) |
{ |
{ |
int d1, d2; |
double r; |
int point; |
char *ep; |
char *es; |
errno = 0; |
|
r = strtod(s, &ep); |
d1 = d2 = point = 0; |
if (ep == s || r == HUGE_VAL || errno == ERANGE) |
while (*s == ' ' || *s == '\t' || *s == '\n') |
return 0; |
s++; |
while (*ep == ' ' || *ep == '\t' || *ep == '\n') |
if (*s == '\0') |
ep++; |
return(0); /* empty stuff isn't a number */ |
if (*ep == '\0') |
if (*s == '+' || *s == '-') |
return 1; |
s++; |
|
if (!isdigit(*s) && *s != '.') |
|
return(0); |
|
if (isdigit(*s)) { |
|
do { |
|
d1++; |
|
s++; |
|
} while (isdigit(*s)); |
|
} |
|
if (*s == '.') { |
|
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 |
else |
return(0); |
return 0; |
} |
} |
|
|
#if 0 |
|
/* THIS IS AN EXPERIMENT THAT'S NOT DONE. */ |
|
/* strtod ought to provide a better test of what's */ |
|
/* a valid number, but it doesn't work according to */ |
|
/* the standard on any machine near me! */ |
|
|
|
#include <math.h> |
|
isnumber(char *s) |
|
{ |
|
double r; |
|
char *ep; |
|
errno = 0; |
|
r = strtod(s, &ep); |
|
if (r == HUGE_VAL || errno == ERANGE) |
|
return 0; |
|
while (*ep == ' ' || *ep == '\t' || *ep == '\n') |
|
ep++; |
|
if (*ep == '\0') |
|
return 1; |
|
else |
|
return 0; |
|
} |
|
#endif |
|