[BACK]Return to lib.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / awk

Diff for /src/usr.bin/awk/lib.c between version 1.3 and 1.4

version 1.3, 1997/01/24 23:11:31 version 1.4, 1997/08/25 16:17:11
Line 1 
Line 1 
   /*      $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
Line 7 
Line 8 
 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
Line 29 
Line 30 
 #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;
Line 85 
Line 101 
         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 */
Line 113 
Line 131 
                                 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 */
Line 142 
Line 162 
                 infile = NULL;                  infile = NULL;
                 argno++;                  argno++;
         }          }
           *pbuf = buf;
           *pbufsize = bufsize;
         return 0;       /* true end of file */          return 0;       /* true end of file */
 }  }
   
Line 153 
Line 175 
         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';
Line 167 
Line 191 
                 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;
 }  }
   
Line 213 
Line 244 
                 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 */
Line 239 
Line 279 
                         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');
Line 255 
Line 295 
                 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;
Line 282 
Line 322 
                 }                  }
                 *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;
Line 362 
Line 439 
 {  {
         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)
 {  {
Line 553 
Line 632 
         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  

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4