Print this page
3731 Update nawk to version 20121220

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/awk/lib.c
          +++ new/usr/src/cmd/awk/lib.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28      -/*        All Rights Reserved   */
  29      -
  30      -#pragma ident   "%Z%%M% %I%     %E% SMI"
       27 +/*
       28 + * Copyright (C) Lucent Technologies 1997
       29 + * All Rights Reserved
       30 + *
       31 + * Permission to use, copy, modify, and distribute this software and
       32 + * its documentation for any purpose and without fee is hereby
       33 + * granted, provided that the above copyright notice appear in all
       34 + * copies and that both that the copyright notice and this
       35 + * permission notice and warranty disclaimer appear in supporting
       36 + * documentation, and that the name Lucent Technologies or any of
       37 + * its entities not be used in advertising or publicity pertaining
       38 + * to distribution of the software without specific, written prior
       39 + * permission.
       40 + *
       41 + * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
       42 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
       43 + * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
       44 + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
       45 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
       46 + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
       47 + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
       48 + * THIS SOFTWARE.
       49 + */
  31   50  
  32   51  #include <errno.h>
       52 +#include <stdarg.h>
       53 +#include <math.h>
  33   54  #include "awk.h"
  34   55  #include "y.tab.h"
  35   56  
  36   57  uchar   *record;
  37      -size_t  record_size;
       58 +size_t  record_size = RECSIZE;
       59 +
       60 +Cell    **fldtab;       /* pointers to Cells */
       61 +char    inputFS[100] = " ";
       62 +
       63 +#define MAXFLD  2
       64 +int     nfields = MAXFLD;       /* last allocated slot for $i */
  38   65  
  39   66  int     donefld;        /* 1 = implies rec broken into fields */
  40   67  int     donerec;        /* 1 = record is valid (no flds have changed) */
  41   68  
  42      -static struct fldtab_chunk {
  43      -        struct fldtab_chunk     *next;
  44      -        Cell                    fields[FLD_INCR];
  45      -} *fldtab_head, *fldtab_tail;
  46      -
  47      -static  size_t  fldtab_maxidx;
       69 +int     lastfld = 0;    /* last used field */
  48   70  
  49   71  static FILE     *infile = NULL;
  50   72  static uchar    *file   = (uchar*) "";
  51   73  static uchar    *fields;
  52      -static size_t   fields_size = LINE_INCR;
       74 +static size_t   fields_size = RECSIZE;
  53   75  
  54      -static int      maxfld  = 0;    /* last used field */
  55   76  static int      argno   = 1;    /* current input argument number */
  56   77  
  57   78  static  uchar   *getargv(int);
  58   79  static  void    cleanfld(int, int);
  59   80  static  int     refldbld(uchar *, uchar *);
  60   81  static  void    bcheck2(int, int, int);
  61   82  static  void    eprint(void);
  62   83  static  void    bclass(int);
       84 +static  void    makefields(int, int);
       85 +
       86 +
       87 +static Cell dollar0 = { OCELL, CFLD, NULL, (uchar *)"", 0.0, REC|STR|DONTFREE };
       88 +static Cell dollar1 = { OCELL, CFLD, NULL, (uchar *)"", 0.0, FLD|STR|DONTFREE };
       89 +
       90 +void
       91 +recinit(unsigned int n)
       92 +{
       93 +        if ((record = (uchar *)malloc(n)) == NULL ||
       94 +            (fields = (uchar *)malloc(n+1)) == NULL ||
       95 +            (fldtab = (Cell **)malloc((nfields + 1) *
       96 +            sizeof (Cell *))) == NULL ||
       97 +            (fldtab[0] = (Cell *)malloc(sizeof (Cell))) == NULL)
       98 +                FATAL("out of space for $0 and fields");
       99 +        *fldtab[0] = dollar0;
      100 +        fldtab[0]->sval = record;
      101 +        fldtab[0]->nval = tostring((uchar *)"0");
      102 +        makefields(1, nfields);
      103 +}
      104 +
      105 +static void
      106 +makefields(int n1, int n2)      /* create $n1..$n2 inclusive */
      107 +{
      108 +        char temp[50];
      109 +        int i;
      110 +
      111 +        for (i = n1; i <= n2; i++) {
      112 +                fldtab[i] = (Cell *)malloc(sizeof (struct Cell));
      113 +                if (fldtab[i] == NULL)
      114 +                        FATAL("out of space in makefields %d", i);
      115 +                *fldtab[i] = dollar1;
      116 +                (void) sprintf(temp, "%d", i);
      117 +                fldtab[i]->nval = tostring((uchar *)temp);
      118 +        }
      119 +}
  63  120  
  64  121  static void
  65  122  initgetrec(void)
  66  123  {
  67  124          int i;
  68  125          uchar *p;
  69  126  
  70  127          for (i = 1; i < *ARGC; i++) {
  71      -                if (!isclvar(p = getargv(i)))   /* find 1st real filename */
      128 +                p = getargv(i); /* find 1st real filename */
      129 +                if (p == NULL || *p == '\0') {  /* deleted or zapped */
      130 +                        argno++;
      131 +                        continue;
      132 +                }
      133 +                if (!isclvar(p)) {
      134 +                        (void) setsval(lookup((uchar *)"FILENAME", symtab), p);
  72  135                          return;
      136 +                }
  73  137                  setclvar(p);    /* a commandline assignment before filename */
  74  138                  argno++;
  75  139          }
  76  140          infile = stdin;         /* no filenames, so use stdin */
  77      -        /* *FILENAME = file = (uchar*) "-"; */
  78  141  }
  79  142  
      143 +static int firsttime = 1;
      144 +
  80  145  int
  81      -getrec(uchar **bufp, size_t *bufsizep)
  82      -{
      146 +getrec(uchar **pbuf, size_t *pbufsize, int isrecord)
      147 +{                               /* get next input record */
      148 +                                /* note: cares whether buf == record */
  83  149          int c;
  84      -        static int firsttime = 1;
  85      -        uchar_t *buf, *nbuf;
  86      -        size_t  len;
      150 +        uchar_t *buf = *pbuf;
      151 +        uchar saveb0;
      152 +        size_t bufsize = *pbufsize, savebufsize = bufsize;
  87  153  
  88  154          if (firsttime) {
  89  155                  firsttime = 0;
  90  156                  initgetrec();
  91  157          }
  92  158          dprintf(("RS=<%s>, FS=<%s>, ARGC=%f, FILENAME=%s\n",
  93  159              *RS, *FS, *ARGC, *FILENAME));
  94      -        donefld = 0;
  95      -        donerec = 1;
      160 +        if (isrecord) {
      161 +                donefld = 0;
      162 +                donerec = 1;
      163 +        }
      164 +        saveb0 = buf[0];
      165 +        buf[0] = 0;
  96  166          while (argno < *ARGC || infile == stdin) {
  97  167                  dprintf(("argno=%d, file=|%s|\n", argno, file));
  98  168                  if (infile == NULL) {   /* have to open a new file */
  99  169                          file = getargv(argno);
 100      -                        if (*file == '\0') {    /* it's been zapped */
      170 +                        /* deleted or zapped */
      171 +                        if (file == NULL || *file == '\0') {
 101  172                                  argno++;
 102  173                                  continue;
 103  174                          }
 104  175                          if (isclvar(file)) {    /* a var=value arg */
 105  176                                  setclvar(file);
 106  177                                  argno++;
 107  178                                  continue;
 108  179                          }
 109  180                          *FILENAME = file;
 110  181                          dprintf(("opening file %s\n", file));
 111  182                          if (*file == '-' && *(file+1) == '\0')
 112  183                                  infile = stdin;
 113  184                          else if ((infile = fopen((char *)file, "r")) == NULL)
 114      -                                ERROR "can't open file %s", file FATAL;
      185 +                                FATAL("can't open file %s", file);
 115  186                          (void) setfval(fnrloc, 0.0);
 116  187                  }
 117      -                c = readrec(&nbuf, &len, infile);
 118      -                expand_buf(bufp, bufsizep, len);
 119      -                buf = *bufp;
 120      -                (void) memcpy(buf, nbuf, len);
 121      -                buf[len] = '\0';
 122      -                free(nbuf);
 123      -
      188 +                c = readrec(&buf, &bufsize, infile);
 124  189                  if (c != 0 || buf[0] != '\0') { /* normal record */
 125      -                        if (bufp == &record) {
 126      -                                if (!(recloc->tval & DONTFREE))
 127      -                                        xfree(recloc->sval);
 128      -                                recloc->sval = record;
 129      -                                recloc->tval = REC | STR | DONTFREE;
 130      -                                if (is_number(recloc->sval)) {
 131      -                                        recloc->fval =
 132      -                                            atof((const char *)recloc->sval);
 133      -                                        recloc->tval |= NUM;
      190 +                        if (isrecord) {
      191 +                                if (freeable(fldtab[0]))
      192 +                                        xfree(fldtab[0]->sval);
      193 +                                fldtab[0]->sval = buf;  /* buf == record */
      194 +                                fldtab[0]->tval = REC | STR | DONTFREE;
      195 +                                if (is_number(fldtab[0]->sval)) {
      196 +                                        fldtab[0]->fval =
      197 +                                            atof((const char *)fldtab[0]->sval);
      198 +                                        fldtab[0]->tval |= NUM;
 134  199                                  }
 135  200                          }
 136  201                          (void) setfval(nrloc, nrloc->fval+1);
 137  202                          (void) setfval(fnrloc, fnrloc->fval+1);
      203 +                        *pbuf = buf;
      204 +                        *pbufsize = bufsize;
 138  205                          return (1);
 139  206                  }
 140  207                  /* EOF arrived on this file; set up next */
 141  208                  if (infile != stdin)
 142  209                          (void) fclose(infile);
 143  210                  infile = NULL;
 144  211                  argno++;
 145  212          }
      213 +        buf[0] = saveb0;
      214 +        *pbuf = buf;
      215 +        *pbufsize = savebufsize;
 146  216          return (0);     /* true end of file */
 147  217  }
 148  218  
      219 +void
      220 +nextfile(void)
      221 +{
      222 +        if (infile != NULL && infile != stdin)
      223 +                (void) fclose(infile);
      224 +        infile = NULL;
      225 +        argno++;
      226 +}
      227 +
      228 +/*
      229 + * read one record into buf
      230 + */
 149  231  int
 150      -readrec(uchar **bufp, size_t *sizep, FILE *inf) /* read one record into buf */
      232 +readrec(uchar **pbuf, size_t *pbufsize, FILE *inf)
 151  233  {
 152  234          int sep, c;
 153      -        uchar   *buf;
 154      -        int     count;
 155      -        size_t  bufsize;
      235 +        uchar *rr, *buf = *pbuf;
      236 +        size_t bufsize = *pbufsize;
      237 +
      238 +        if (strlen((char *)*FS) >= sizeof (inputFS))
      239 +                FATAL("field separator %.10s... is too long", *FS);
      240 +        /*
      241 +         * fflush(stdout); avoids some buffering problem
      242 +         * but makes it 25% slower
      243 +         */
 156  244  
 157      -        init_buf(&buf, &bufsize, LINE_INCR);
      245 +        /* for subsequent field splitting */
      246 +        (void) strcpy(inputFS, (char *)*FS);
 158  247          if ((sep = **RS) == 0) {
 159  248                  sep = '\n';
 160  249                  /* skip leading \n's */
 161  250                  while ((c = getc(inf)) == '\n' && c != EOF)
 162  251                          ;
 163  252                  if (c != EOF)
 164  253                          (void) ungetc(c, inf);
 165  254          }
 166      -        count = 0;
 167      -        for (;;) {
 168      -                while ((c = getc(inf)) != sep && c != EOF) {
 169      -                        expand_buf(&buf, &bufsize, count);
 170      -                        buf[count++] = c;
      255 +        for (rr = buf; ; ) {
      256 +                for (; (c = getc(inf)) != sep && c != EOF; ) {
      257 +                        if (rr-buf+1 > bufsize)
      258 +                                if (!adjbuf(&buf, &bufsize, 1+rr-buf,
      259 +                                    record_size, &rr, "readrec 1"))
      260 +                                        FATAL(
      261 +                                "input record `%.30s...' too long", buf);
      262 +                        *rr++ = c;
 171  263                  }
 172  264                  if (**RS == sep || c == EOF)
 173  265                          break;
 174  266                  if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
 175  267                          break;
 176      -                expand_buf(&buf, &bufsize, count + 1);
 177      -                buf[count++] = '\n';
 178      -                buf[count++] = c;
 179      -        }
 180      -        buf[count] = '\0';
      268 +                if (!adjbuf(&buf, &bufsize, 2+rr-buf, record_size, &rr,
      269 +                    "readrec 2"))
      270 +                        FATAL("input record `%.30s...' too long", buf);
      271 +                *rr++ = '\n';
      272 +                *rr++ = c;
      273 +        }
      274 +        if (!adjbuf(&buf, &bufsize, 1+rr-buf, record_size, &rr, "readrec 3"))
      275 +                FATAL("input record `%.30s...' too long", buf);
      276 +        *rr = 0;
 181  277          dprintf(("readrec saw <%s>, returns %d\n",
 182      -            buf, c == EOF && count == 0 ? 0 : 1));
 183      -        *bufp = buf;
 184      -        *sizep = count;
 185      -        return (c == EOF && count == 0 ? 0 : 1);
      278 +            buf, c == EOF && rr == buf ? 0 : 1));
      279 +        *pbuf = buf;
      280 +        *pbufsize = bufsize;
      281 +        return (c == EOF && rr == buf ? 0 : 1);
 186  282  }
 187  283  
 188      -/* get ARGV[n] */
 189  284  static uchar *
 190      -getargv(int n)
      285 +getargv(int n)          /* get ARGV[n] */
 191  286  {
 192  287          Cell *x;
 193      -        uchar *s, temp[11];
      288 +        uchar *s, temp[50];
 194  289          extern Array *ARGVtab;
 195  290  
 196  291          (void) sprintf((char *)temp, "%d", n);
      292 +        if (lookup(temp, ARGVtab) == NULL)
      293 +                return (NULL);
 197  294          x = setsymtab(temp, (uchar *)"", 0.0, STR, ARGVtab);
 198  295          s = getsval(x);
 199  296          dprintf(("getargv(%d) returns |%s|\n", n, s));
 200  297          return (s);
 201  298  }
 202  299  
 203  300  void
 204  301  setclvar(uchar *s)      /* set var=value from s */
 205  302  {
 206  303          uchar *p;
↓ open down ↓ 3 lines elided ↑ open up ↑
 210  307                  ;
 211  308          *p++ = 0;
 212  309          p = qstring(p, '\0');
 213  310          q = setsymtab(s, p, 0.0, STR, symtab);
 214  311          (void) setsval(q, p);
 215  312          if (is_number(q->sval)) {
 216  313                  q->fval = atof((const char *)q->sval);
 217  314                  q->tval |= NUM;
 218  315          }
 219  316          dprintf(("command line set %s to |%s|\n", s, p));
 220      -        free(p);
 221  317  }
 222  318  
 223  319  void
 224      -fldbld(void)
      320 +fldbld(void)    /* create fields from current record */
 225  321  {
      322 +        /* this relies on having fields[] the same length as $0 */
      323 +        /* the fields are all stored in this one array with \0's */
      324 +        /* possibly with a final trailing \0 not associated with any field */
 226  325          uchar *r, *fr, sep;
 227  326          Cell *p;
 228      -        int i;
 229      -        size_t  len;
      327 +        int i, j;
      328 +        size_t n;
 230  329  
 231  330          if (donefld)
 232  331                  return;
 233      -        if (!(recloc->tval & STR))
 234      -                (void) getsval(recloc);
 235      -        r = recloc->sval;       /* was record! */
 236      -
 237      -        /* make sure fields is always allocated */
 238      -        adjust_buf(&fields, fields_size);
 239      -
 240      -        /*
 241      -         * make sure fields has enough size. We don't expand the buffer
 242      -         * in the middle of the loop, since p->sval has already pointed
 243      -         * the address in the fields.
 244      -         */
 245      -        len = strlen((char *)r) + 1;
 246      -        expand_buf(&fields, &fields_size, len);
      332 +        if (!isstr(fldtab[0]))
      333 +                (void) getsval(fldtab[0]);
      334 +        r = fldtab[0]->sval;
      335 +        n = strlen((char *)r);
      336 +        if (n > fields_size) {
      337 +                xfree(fields);
      338 +                /* possibly 2 final \0s */
      339 +                if ((fields = (uchar *)malloc(n + 2)) == NULL)
      340 +                        FATAL("out of space for fields in fldbld %d", n);
      341 +                fields_size = n;
      342 +        }
 247  343          fr = fields;
 248      -
 249  344          i = 0;  /* number of fields accumulated here */
 250      -        if (strlen((char *)*FS) > 1) {  /* it's a regular expression */
 251      -                i = refldbld(r, *FS);
 252      -        } else if ((sep = **FS) == ' ') {
      345 +        (void) strcpy(inputFS, (char *)*FS);
      346 +        if (strlen(inputFS) > 1) {      /* it's a regular expression */
      347 +                i = refldbld(r, (uchar *)inputFS);
      348 +        } else if ((sep = *inputFS) == ' ') {   /* default whitespace */
 253  349                  for (i = 0; ; ) {
 254  350                          while (*r == ' ' || *r == '\t' || *r == '\n')
 255  351                                  r++;
 256  352                          if (*r == 0)
 257  353                                  break;
 258  354                          i++;
 259      -                        p = getfld(i);
 260      -                        if (!(p->tval & DONTFREE))
 261      -                                xfree(p->sval);
 262      -                        p->sval = fr;
 263      -                        p->tval = FLD | STR | DONTFREE;
      355 +                        if (i > nfields)
      356 +                                growfldtab(i);
      357 +                        if (freeable(fldtab[i]))
      358 +                                xfree(fldtab[i]->sval);
      359 +                        fldtab[i]->sval = fr;
      360 +                        fldtab[i]->tval = FLD | STR | DONTFREE;
 264  361                          do
 265  362                                  *fr++ = *r++;
 266  363                          while (*r != ' ' && *r != '\t' && *r != '\n' &&
 267  364                              *r != '\0')
 268  365                                  ;
 269  366                          *fr++ = 0;
 270  367                  }
 271  368                  *fr = 0;
      369 +        } else if ((sep = *inputFS) == 0) {     /* new: FS="" => 1 char/field */
      370 +                for (i = 0; *r != 0; r++) {
      371 +                        uchar buf[2];
      372 +                        i++;
      373 +                        if (i > nfields)
      374 +                                growfldtab(i);
      375 +                        if (freeable(fldtab[i]))
      376 +                                xfree(fldtab[i]->sval);
      377 +                        buf[0] = *r;
      378 +                        buf[1] = 0;
      379 +                        fldtab[i]->sval = tostring(buf);
      380 +                        fldtab[i]->tval = FLD | STR;
      381 +                }
      382 +                *fr = 0;
 272  383          } else if (*r != 0) {   /* if 0, it's a null field */
      384 +                /*
      385 +                 * subtlecase : if length(FS) == 1 && length(RS > 0)
      386 +                 * \n is NOT a field separator (cf awk book 61,84).
      387 +                 * this variable is tested in the inner while loop.
      388 +                 */
      389 +                int rtest = '\n';  /* normal case */
      390 +                if (strlen((char *)*RS) > 0)
      391 +                        rtest = '\0';
 273  392                  for (;;) {
 274  393                          i++;
 275      -                        p = getfld(i);
 276      -                        if (!(p->tval & DONTFREE))
 277      -                                xfree(p->sval);
 278      -                        p->sval = fr;
 279      -                        p->tval = FLD | STR | DONTFREE;
 280      -                        /* \n always a separator */
 281      -                        while (*r != sep && *r != '\n' && *r != '\0')
      394 +                        if (i > nfields)
      395 +                                growfldtab(i);
      396 +                        if (freeable(fldtab[i]))
      397 +                                xfree(fldtab[i]->sval);
      398 +                        fldtab[i]->sval = fr;
      399 +                        fldtab[i]->tval = FLD | STR | DONTFREE;
      400 +                        /* \n is always a separator */
      401 +                        while (*r != sep && *r != rtest && *r != '\0')
 282  402                                  *fr++ = *r++;
 283  403                          *fr++ = 0;
 284  404                          if (*r++ == 0)
 285  405                                  break;
 286  406                  }
 287  407                  *fr = 0;
 288  408          }
      409 +        if (i > nfields)
      410 +                FATAL("record `%.30s...' has too many fields; can't happen", r);
 289  411          /* clean out junk from previous record */
 290      -        cleanfld(i, maxfld);
 291      -        maxfld = i;
      412 +        cleanfld(i + 1, lastfld);
      413 +        lastfld = i;
 292  414          donefld = 1;
 293      -        for (i = 1; i <= maxfld; i++) {
 294      -                p = getfld(i);
      415 +        for (j = 1; j <= lastfld; j++) {
      416 +                p = fldtab[j];
 295  417                  if (is_number(p->sval)) {
 296  418                          p->fval = atof((const char *)p->sval);
 297  419                          p->tval |= NUM;
 298  420                  }
 299  421          }
 300      -
 301      -        (void) setfval(nfloc, (Awkfloat) maxfld);
      422 +        (void) setfval(nfloc, (Awkfloat)lastfld);
 302  423          if (dbg) {
 303      -                for (i = 0; i <= maxfld; i++) {
 304      -                        p = getfld(i);
 305      -                        (void) printf("field %d: |%s|\n", i, p->sval);
      424 +                for (j = 0; j <= lastfld; j++) {
      425 +                        p = fldtab[j];
      426 +                        (void) printf("field %d (%s): |%s|\n", j, p->nval,
      427 +                            p->sval);
 306  428                  }
 307  429          }
 308  430  }
 309  431  
 310  432  static void
 311  433  cleanfld(int n1, int n2)        /* clean out fields n1..n2 inclusive */
 312      -{
 313      -        static uchar *nullstat = (uchar *) "";
      434 +{                               /* nvals remain intact */
      435 +        static uchar *nullstat = (uchar *)"";
 314  436          Cell *p;
 315      -        int     i;
      437 +        int i;
 316  438  
 317      -        for (i = n2; i > n1; i--) {
 318      -                p = getfld(i);
 319      -                if (!(p->tval & DONTFREE))
      439 +        for (i = n1; i <= n2; i++) {
      440 +                p = fldtab[i];
      441 +                if (freeable(p))
 320  442                          xfree(p->sval);
 321      -                p->tval = FLD | STR | DONTFREE;
 322  443                  p->sval = nullstat;
      444 +                p->tval = FLD | STR | DONTFREE;
 323  445          }
 324  446  }
 325  447  
 326  448  void
 327      -newfld(int n)   /* add field n (after end) */
      449 +newfld(int n)   /* add field n after end of existing lastfld */
 328  450  {
 329      -        if (n < 0)
 330      -                ERROR "accessing invalid field", record FATAL;
 331      -        (void) getfld(n);
 332      -        cleanfld(maxfld, n);
 333      -        maxfld = n;
 334      -        (void) setfval(nfloc, (Awkfloat) n);
 335      -}
 336      -
 337      -/*
 338      - * allocate field table. We don't reallocate the table since there
 339      - * might be somewhere recording the address of the table.
 340      - */
 341      -static void
 342      -morefld(void)
 343      -{
 344      -        int     i;
 345      -        struct fldtab_chunk *fldcp;
 346      -        Cell    *newfld;
 347      -
 348      -        if ((fldcp = calloc(sizeof (struct fldtab_chunk), 1)) == NULL)
 349      -                ERROR "out of space in morefld" FATAL;
 350      -
 351      -        newfld = &fldcp->fields[0];
 352      -        for (i = 0; i < FLD_INCR; i++) {
 353      -                newfld[i].ctype = OCELL;
 354      -                newfld[i].csub = CFLD;
 355      -                newfld[i].nval = NULL;
 356      -                newfld[i].sval = (uchar *)"";
 357      -                newfld[i].fval = 0.0;
 358      -                newfld[i].tval = FLD|STR|DONTFREE;
 359      -                newfld[i].cnext = NULL;
 360      -        }
 361      -        /*
 362      -         * link this field chunk
 363      -         */
 364      -        if (fldtab_head == NULL)
 365      -                fldtab_head = fldcp;
 366      -        else
 367      -                fldtab_tail->next = fldcp;
 368      -        fldtab_tail = fldcp;
 369      -        fldcp->next = NULL;
 370      -
 371      -        fldtab_maxidx += FLD_INCR;
      451 +        if (n > nfields)
      452 +                growfldtab(n);
      453 +        cleanfld(lastfld + 1, n);
      454 +        lastfld = n;
      455 +        (void) setfval(nfloc, (Awkfloat)n);
 372  456  }
 373  457  
 374  458  Cell *
 375      -getfld(int idx)
      459 +fieldadr(int n)         /* get nth field */
 376  460  {
 377      -        struct fldtab_chunk *fldcp;
 378      -        int     cbase;
 379      -
 380      -        if (idx < 0)
 381      -                ERROR "trying to access field %d", idx FATAL;
 382      -        while (idx >= fldtab_maxidx)
 383      -                morefld();
 384      -        cbase = 0;
 385      -        for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
 386      -                if (idx < (cbase + FLD_INCR))
 387      -                        return (&fldcp->fields[idx - cbase]);
 388      -                cbase += FLD_INCR;
 389      -        }
 390      -        /* should never happen */
 391      -        ERROR "trying to access invalid field %d", idx FATAL;
 392      -        return (NULL);
      461 +        if (n < 0)
      462 +                FATAL("trying to access out of range field %d", n);
      463 +        if (n > nfields)        /* fields after NF are empty */
      464 +                growfldtab(n);  /* but does not increase NF */
      465 +        return (fldtab[n]);
 393  466  }
 394  467  
 395      -int
 396      -fldidx(Cell *vp)
 397      -{
 398      -        struct fldtab_chunk *fldcp;
 399      -        Cell    *tbl;
 400      -        int     cbase;
 401      -
 402      -        cbase = 0;
 403      -        for (fldcp = fldtab_head; fldcp != NULL; fldcp = fldcp->next) {
 404      -                tbl = &fldcp->fields[0];
 405      -                if (vp >= tbl && vp < (tbl + FLD_INCR))
 406      -                        return (cbase + (vp - tbl));
 407      -                cbase += FLD_INCR;
 408      -        }
 409      -        /* should never happen */
 410      -        ERROR "trying to access unknown field" FATAL;
 411      -        return (0);
      468 +void
      469 +growfldtab(int n)       /* make new fields up to at least $n */
      470 +{
      471 +        int nf = 2 * nfields;
      472 +        size_t s;
      473 +
      474 +        if (n > nf)
      475 +                nf = n;
      476 +        /* freebsd: how much do we need? */
      477 +        s = (nf + 1) * (sizeof (struct Cell *));
      478 +        if (s / sizeof (struct Cell *) - 1 == nf)       /* didn't overflow */
      479 +                fldtab = (Cell **) realloc(fldtab, s);
      480 +        else    /* overflow sizeof int */
      481 +                xfree(fldtab);  /* make it null */
      482 +        if (fldtab == NULL)
      483 +                FATAL("out of space creating %d fields", nf);
      484 +        makefields(nfields + 1, nf);
      485 +        nfields = nf;
 412  486  }
 413  487  
 414  488  static int
 415  489  refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */
 416  490  {
      491 +        /* this relies on having fields[] the same length as $0 */
      492 +        /* the fields are all stored in this one array with \0's */
 417  493          uchar *fr;
 418  494          int i, tempstat;
 419  495          fa *pfa;
 420      -        Cell    *p;
 421      -        size_t  len;
      496 +        size_t n;
 422  497  
 423      -        /* make sure fields is allocated */
 424      -        adjust_buf(&fields, fields_size);
      498 +        n = strlen((char *)rec);
      499 +        if (n > fields_size) {
      500 +                xfree(fields);
      501 +                if ((fields = (uchar *)malloc(n + 1)) == NULL)
      502 +                        FATAL("out of space for fields in refldbld %d", n);
      503 +                fields_size = n;
      504 +        }
 425  505          fr = fields;
 426  506          *fr = '\0';
 427  507          if (*rec == '\0')
 428  508                  return (0);
 429      -
 430      -        len = strlen((char *)rec) + 1;
 431      -        expand_buf(&fields, &fields_size, len);
 432      -        fr = fields;
 433      -
 434  509          pfa = makedfa(fs, 1);
 435  510          dprintf(("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs));
 436  511          tempstat = pfa->initstat;
 437  512          for (i = 1; ; i++) {
 438      -                p = getfld(i);
 439      -                if (!(p->tval & DONTFREE))
 440      -                        xfree(p->sval);
 441      -                p->tval = FLD | STR | DONTFREE;
 442      -                p->sval = fr;
      513 +                if (i > nfields)
      514 +                        growfldtab(i);
      515 +                if (freeable(fldtab[i]))
      516 +                        xfree(fldtab[i]->sval);
      517 +                fldtab[i]->tval = FLD | STR | DONTFREE;
      518 +                fldtab[i]->sval = fr;
 443  519                  dprintf(("refldbld: i=%d\n", i));
 444  520                  if (nematch(pfa, rec)) {
 445      -                        pfa->initstat = 2;
      521 +                        pfa->initstat = 2;      /* horrible coupling to b.c */
 446  522                          dprintf(("match %s (%d chars)\n", patbeg, patlen));
 447  523                          (void) strncpy((char *)fr, (char *)rec, patbeg-rec);
 448  524                          fr += patbeg - rec + 1;
 449  525                          *(fr-1) = '\0';
 450  526                          rec = patbeg + patlen;
 451  527                  } else {
 452  528                          dprintf(("no match %s\n", rec));
 453  529                          (void) strcpy((char *)fr, (char *)rec);
 454  530                          pfa->initstat = tempstat;
 455  531                          break;
 456  532                  }
 457  533          }
 458  534          return (i);
 459  535  }
 460  536  
 461  537  void
 462      -recbld(void)
      538 +recbld(void)            /* create $0 from $1..$NF if necessary */
 463  539  {
 464  540          int i;
 465      -        uchar *p;
 466      -        size_t cnt, len, olen;
      541 +        uchar *r, *p;
 467  542  
 468  543          if (donerec == 1)
 469  544                  return;
 470      -        cnt = 0;
 471      -        olen = strlen((char *)*OFS);
      545 +        r = record;
 472  546          for (i = 1; i <= *NF; i++) {
 473      -                p = getsval(getfld(i));
 474      -                len = strlen((char *)p);
 475      -                expand_buf(&record, &record_size, cnt + len + olen);
 476      -                (void) memcpy(&record[cnt], p, len);
 477      -                cnt += len;
      547 +                p = getsval(fldtab[i]);
      548 +                if (!adjbuf(&record, &record_size, 1 + strlen((char *)p) + r -
      549 +                    record, record_size, &r, "recbld 1"))
      550 +                        FATAL("created $0 `%.30s...' too long", record);
      551 +                while ((*r = *p++) != 0)
      552 +                        r++;
 478  553                  if (i < *NF) {
 479      -                        (void) memcpy(&record[cnt], *OFS, olen);
 480      -                        cnt += olen;
      554 +                        if (!adjbuf(&record, &record_size, 2 +
      555 +                            strlen((char *)*OFS) + r - record, record_size,
      556 +                            &r, "recbld 2"))
      557 +                                FATAL("created $0 `%.30s...' too long", record);
      558 +                        for (p = *OFS; (*r = *p++) != 0; )
      559 +                                r++;
 481  560                  }
 482  561          }
 483      -        record[cnt] = '\0';
 484      -        dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
 485      -        if (!(recloc->tval & DONTFREE))
 486      -                xfree(recloc->sval);
 487      -        recloc->tval = REC | STR | DONTFREE;
 488      -        recloc->sval = record;
 489      -        dprintf(("in recbld FS=%o, recloc=%p\n", **FS, (void *)recloc));
      562 +        if (!adjbuf(&record, &record_size, 2 + r - record, record_size, &r,
      563 +            "recbld 3"))
      564 +                FATAL("built giant record `%.30s...'", record);
      565 +        *r = '\0';
      566 +        dprintf(("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS,
      567 +            (void *)fldtab[0]));
      568 +
      569 +        if (freeable(fldtab[0]))
      570 +                xfree(fldtab[0]->sval);
      571 +        fldtab[0]->tval = REC | STR | DONTFREE;
      572 +        fldtab[0]->sval = record;
      573 +
      574 +        dprintf(("in recbld inputFS=%s, fldtab[0]=%p\n", inputFS,
      575 +            (void *)fldtab[0]));
 490  576          dprintf(("recbld = |%s|\n", record));
 491  577          donerec = 1;
 492  578  }
 493  579  
 494      -Cell *
 495      -fieldadr(int n)
 496      -{
 497      -        if (n < 0)
 498      -                ERROR "trying to access field %d", n FATAL;
 499      -        return (getfld(n));
 500      -}
 501      -
 502  580  int     errorflag       = 0;
 503      -char    errbuf[200];
 504  581  
 505  582  void
 506  583  yyerror(char *s)
 507  584  {
      585 +        SYNTAX("%s", s);
      586 +}
      587 +
      588 +void
      589 +SYNTAX(const char *fmt, ...)
      590 +{
 508  591          extern uchar *cmdname, *curfname;
 509  592          static int been_here = 0;
      593 +        va_list varg;
 510  594  
 511  595          if (been_here++ > 2)
 512  596                  return;
 513      -        (void) fprintf(stderr, "%s: %s", cmdname, s);
      597 +        (void) fprintf(stderr, "%s: ", cmdname);
      598 +        va_start(varg, fmt);
      599 +        (void) vfprintf(stderr, fmt, varg);
      600 +        va_end(varg);
 514  601          (void) fprintf(stderr, gettext(" at source line %lld"), lineno);
 515  602          if (curfname != NULL)
 516  603                  (void) fprintf(stderr, gettext(" in function %s"), curfname);
      604 +        if (compile_time == 1 && cursource() != NULL)
      605 +                (void) fprintf(stderr, gettext(" source file %s"), cursource());
 517  606          (void) fprintf(stderr, "\n");
 518  607          errorflag = 2;
 519  608          eprint();
 520  609  }
 521  610  
 522      -/*ARGSUSED*/
 523  611  void
 524      -fpecatch(int sig)
      612 +fpecatch(int n)
 525  613  {
 526      -        ERROR "floating point exception" FATAL;
      614 +        FATAL("floating point exception %d", n);
 527  615  }
 528  616  
 529  617  extern int bracecnt, brackcnt, parencnt;
 530  618  
 531  619  void
 532  620  bracecheck(void)
 533  621  {
 534  622          int c;
 535  623          static int beenhere = 0;
 536  624  
↓ open down ↓ 14 lines elided ↑ open up ↑
 551  639                  (void) fprintf(stderr, gettext("\tmissing %c\n"), c2);
 552  640          else if (n > 1)
 553  641                  (void) fprintf(stderr, gettext("\t%d missing %c's\n"), n, c2);
 554  642          else if (n == -1)
 555  643                  (void) fprintf(stderr, gettext("\textra %c\n"), c2);
 556  644          else if (n < -1)
 557  645                  (void) fprintf(stderr, gettext("\t%d extra %c's\n"), -n, c2);
 558  646  }
 559  647  
 560  648  void
 561      -error(int f, char *s)
      649 +FATAL(const char *fmt, ...)
 562  650  {
 563      -        extern Node *curnode;
 564  651          extern uchar *cmdname;
      652 +        va_list varg;
 565  653  
 566  654          (void) fflush(stdout);
 567  655          (void) fprintf(stderr, "%s: ", cmdname);
 568      -        (void) fprintf(stderr, "%s", s);
      656 +        va_start(varg, fmt);
      657 +        (void) vfprintf(stderr, fmt, varg);
      658 +        va_end(varg);
      659 +        error();
      660 +        if (dbg > 1)    /* core dump if serious debugging on */
      661 +                abort();
      662 +        exit(2);
      663 +}
      664 +
      665 +void
      666 +WARNING(const char *fmt, ...)
      667 +{
      668 +        extern uchar *cmdname;
      669 +        va_list varg;
      670 +
      671 +        (void) fflush(stdout);
      672 +        (void) fprintf(stderr, "%s: ", cmdname);
      673 +        va_start(varg, fmt);
      674 +        (void) vfprintf(stderr, fmt, varg);
      675 +        va_end(varg);
      676 +        error();
      677 +}
      678 +
      679 +void
      680 +error(void)
      681 +{
      682 +        extern Node *curnode;
      683 +
 569  684          (void) fprintf(stderr, "\n");
 570  685          if (compile_time != 2 && NR && *NR > 0) {
 571  686                  (void) fprintf(stderr,
 572      -                    gettext(" input record number %g"), *FNR);
      687 +                    gettext(" input record number %g"), (int) (*FNR));
 573  688                  if (strcmp((char *)*FILENAME, "-") != 0)
 574  689                          (void) fprintf(stderr, gettext(", file %s"), *FILENAME);
 575  690                  (void) fprintf(stderr, "\n");
 576  691          }
 577  692          if (compile_time != 2 && curnode)
 578      -                (void) fprintf(stderr, gettext(" source line number %lld\n"),
      693 +                (void) fprintf(stderr, gettext(" source line number %d"),
 579  694                      curnode->lineno);
 580  695          else if (compile_time != 2 && lineno) {
 581  696                  (void) fprintf(stderr,
 582      -                    gettext(" source line number %lld\n"), lineno);
      697 +                    gettext(" source line number %d"), lineno);
 583  698          }
      699 +        if (compile_time == 1 && cursource() != NULL)
      700 +                (void) fprintf(stderr,
      701 +                    gettext(" source file %s"), cursource());
      702 +        (void) fprintf(stderr, "\n");
 584  703          eprint();
 585      -        if (f) {
 586      -                if (dbg)
 587      -                        abort();
 588      -                exit(2);
 589      -        }
 590  704  }
 591  705  
 592  706  static void
 593  707  eprint(void)    /* try to print context around error */
 594  708  {
 595  709          uchar *p, *q;
 596  710          int c;
 597  711          static int been_here = 0;
 598      -        extern uchar ebuf[300], *ep;
      712 +        extern uchar ebuf[], *ep;
 599  713  
 600  714          if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
 601  715                  return;
 602  716          p = ep - 1;
 603  717          if (p > ebuf && *p == '\n')
 604  718                  p--;
 605  719          for (; p > ebuf && *p != '\n' && *p != '\0'; p--)
 606  720                  ;
 607  721          while (*p == '\n')
 608  722                  p++;
↓ open down ↓ 24 lines elided ↑ open up ↑
 633  747          case '{': bracecnt++; break;
 634  748          case '}': bracecnt--; break;
 635  749          case '[': brackcnt++; break;
 636  750          case ']': brackcnt--; break;
 637  751          case '(': parencnt++; break;
 638  752          case ')': parencnt--; break;
 639  753          }
 640  754  }
 641  755  
 642  756  double
 643      -errcheck(double x, char *s)
      757 +errcheck(double x, const char *s)
 644  758  {
 645      -        extern int errno;
 646      -
 647  759          if (errno == EDOM) {
 648  760                  errno = 0;
 649      -                ERROR "%s argument out of domain", s WARNING;
      761 +                WARNING("%s argument out of domain", s);
 650  762                  x = 1;
 651  763          } else if (errno == ERANGE) {
 652  764                  errno = 0;
 653      -                ERROR "%s result out of range", s WARNING;
      765 +                WARNING("%s result out of range", s);
 654  766                  x = 1;
 655  767          }
 656  768          return (x);
 657  769  }
 658  770  
 659      -void
 660      -PUTS(uchar *s)
 661      -{
 662      -        dprintf(("%s\n", s));
 663      -}
 664      -
 665  771  int
 666      -isclvar(uchar *s)       /* is s of form var=something? */
      772 +isclvar(const uchar *s) /* is s of form var=something? */
 667  773  {
 668      -        if (s != NULL) {
      774 +        const uchar *os = s;
 669  775  
 670      -                /* Must begin with an underscore or alphabetic character */
 671      -                if (isalpha(*s) || (*s == '_')) {
 672      -
 673      -                        for (s++; *s; s++) {
 674      -                                /*
 675      -                                 * followed by a sequence of underscores,
 676      -                                 * digits, and alphabetics
 677      -                                 */
 678      -                                if (!(isalnum(*s) || *s == '_')) {
 679      -                                        break;
 680      -                                }
 681      -                        }
 682      -                        return (*s == '=' && *(s + 1) != '=');
 683      -                }
      776 +        if (!isalpha(*s) && *s != '_')
      777 +                return (0);
      778 +        for (; *s; s++) {
      779 +                if (!(isalnum(*s) || *s == '_'))
      780 +                        break;
 684  781          }
 685  782  
 686      -        return (0);
      783 +        return (*s == '=' && s > os && *(s+1) != '=');
 687  784  }
 688  785  
 689      -#define MAXEXPON        38      /* maximum exponent for fp number */
      786 +/* strtod is supposed to be a proper test of what's a valid number */
      787 +/* appears to be broken in gcc on linux: thinks 0x123 is a valid FP number */
      788 +/* wrong: violates 4.10.1.4 of ansi C standard */
 690  789  
 691  790  int
 692      -is_number(uchar *s)
      791 +is_number(const uchar *s)
 693  792  {
 694      -        int d1, d2;
 695      -        int point;
 696      -        uchar *es;
 697      -        extern char     radixpoint;
 698      -
 699      -        d1 = d2 = point = 0;
 700      -        while (*s == ' ' || *s == '\t' || *s == '\n')
 701      -                s++;
 702      -        if (*s == '\0')
 703      -                return (0);     /* empty stuff isn't number */
 704      -        if (*s == '+' || *s == '-')
 705      -                s++;
 706      -        if (!isdigit(*s) && *s != radixpoint)
 707      -                return (0);
 708      -        if (isdigit(*s)) {
 709      -                do {
 710      -                        d1++;
 711      -                        s++;
 712      -                } while (isdigit(*s));
 713      -        }
 714      -        if (d1 >= MAXEXPON)
 715      -                return (0);     /* too many digits to convert */
 716      -        if (*s == radixpoint) {
 717      -                point++;
 718      -                s++;
 719      -        }
 720      -        if (isdigit(*s)) {
 721      -                d2++;
 722      -                do {
 723      -                        s++;
 724      -                } while (isdigit(*s));
 725      -        }
 726      -        if (!(d1 || point && d2))
      793 +        double r;
      794 +        char *ep;
      795 +        errno = 0;
      796 +        r = strtod((const char *)s, &ep);
      797 +        if (ep == (char *)s || r == HUGE_VAL || errno == ERANGE)
 727  798                  return (0);
 728      -        if (*s == 'e' || *s == 'E') {
 729      -                s++;
 730      -                if (*s == '+' || *s == '-')
 731      -                        s++;
 732      -                if (!isdigit(*s))
 733      -                        return (0);
 734      -                es = s;
 735      -                do {
 736      -                        s++;
 737      -                } while (isdigit(*s));
 738      -                if (s - es > 2) {
 739      -                        return (0);
 740      -                } else if (s - es == 2 &&
 741      -                    (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON) {
 742      -                        return (0);
 743      -                }
 744      -        }
 745      -        while (*s == ' ' || *s == '\t' || *s == '\n')
 746      -                s++;
 747      -        if (*s == '\0')
      799 +        while (*ep == ' ' || *ep == '\t' || *ep == '\n')
      800 +                ep++;
      801 +        if (*ep == '\0')
 748  802                  return (1);
 749  803          else
 750  804                  return (0);
 751  805  }
 752      -
 753      -void
 754      -init_buf(uchar **optr, size_t *sizep, size_t amt)
 755      -{
 756      -        uchar   *nptr = NULL;
 757      -
 758      -        if ((nptr = malloc(amt)) == NULL)
 759      -                ERROR "out of space in init_buf" FATAL;
 760      -        /* initial buffer should have NULL terminated */
 761      -        *nptr = '\0';
 762      -        if (sizep != NULL)
 763      -                *sizep = amt;
 764      -        *optr = nptr;
 765      -}
 766      -
 767      -void
 768      -r_expand_buf(uchar **optr, size_t *sizep, size_t req)
 769      -{
 770      -        uchar   *nptr;
 771      -        size_t  amt, size = *sizep;
 772      -
 773      -        if (size != 0 && req < (size - 1))
 774      -                return;
 775      -        amt = req + 1 - size;
 776      -        amt = (amt / LINE_INCR + 1) * LINE_INCR;
 777      -
 778      -        if ((nptr = realloc(*optr, size + amt)) == NULL)
 779      -                ERROR "out of space in expand_buf" FATAL;
 780      -        /* initial buffer should have NULL terminated */
 781      -        if (size == 0)
 782      -                *nptr = '\0';
 783      -        *sizep += amt;
 784      -        *optr = nptr;
 785      -}
 786      -
 787      -void
 788      -adjust_buf(uchar **optr, size_t size)
 789      -{
 790      -        uchar   *nptr;
 791      -
 792      -        if ((nptr = realloc(*optr, size)) == NULL)
 793      -                ERROR "out of space in adjust_buf" FATAL;
 794      -        *optr = nptr;
 795      -}
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX