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

Diff for /src/usr.bin/awk/run.c between version 1.58 and 1.59

version 1.58, 2020/06/13 01:19:55 version 1.59, 2020/06/13 01:21:01
Line 1581 
Line 1581 
 {  {
         Cell *x, *y;          Cell *x, *y;
         Awkfloat u;          Awkfloat u;
         int t;          int t, sz;
         Awkfloat tmp;          Awkfloat tmp;
         char *buf;          char *buf, *fmt;
         Node *nextarg;          Node *nextarg;
         FILE *fp;          FILE *fp;
         int status = 0;          int status = 0;
           time_t tv;
           struct tm *tm;
   
         t = ptoi(a[0]);          t = ptoi(a[0]);
         x = execute(a[1]);          x = execute(a[1]);
Line 1738 
Line 1740 
                 else                  else
                         u = fflush(fp);                          u = fflush(fp);
                 break;                  break;
           case FSYSTIME:
                   u = time((time_t *) 0);
                   break;
           case FSTRFTIME:
                   /* strftime([format [,timestamp]]) */
                   if (nextarg) {
                           y = execute(nextarg);
                           nextarg = nextarg->nnext;
                           tv = (time_t) getfval(y);
                           tempfree(y);
                   } else
                           tv = time((time_t *) 0);
                   tm = localtime(&tv);
                   if (tm == NULL)
                           FATAL("bad time %ld", (long)tv);
   
                   if (isrec(x)) {
                           /* format argument not provided, use default */
                           fmt = tostring("%a %b %d %H:%M:%S %Z %Y");
                   } else
                           fmt = tostring(getsval(x));
   
                   sz = 32;
                   buf = NULL;
                   do {
                           if ((buf = reallocarray(buf, 2, sz)) == NULL)
                                   FATAL("out of memory in strftime");
                           sz *= 2;
                   } while (strftime(buf, sz, fmt, tm) == 0 && fmt[0] != '\0');
   
                   y = gettemp();
                   setsval(y, buf);
                   free(fmt);
                   free(buf);
   
                   return y;
         default:        /* can't happen */          default:        /* can't happen */
                 FATAL("illegal function type %d", t);                  FATAL("illegal function type %d", t);
                 break;                  break;
Line 2116 
Line 2154 
         x->fval = num;          x->fval = num;
         free(buf);          free(buf);
         return(x);          return(x);
   }
   
   Cell *gensub(Node **a, int nnn) /* global selective substitute */
           /* XXX incomplete - doesn't support backreferences \0 ... \9 */
   {
           Cell *x, *y, *res, *h;
           char *rptr;
           const char *sptr;
           char *buf, *pb;
           const char *t, *q;
           fa *pfa;
           int mflag, tempstat, num, whichm;
           int bufsz = recsize;
   
           if ((buf = malloc(bufsz)) == NULL)
                   FATAL("out of memory in gensub");
           mflag = 0;      /* if mflag == 0, can replace empty string */
           num = 0;
           x = execute(a[4]);      /* source string */
           t = getsval(x);
           res = copycell(x);      /* target string - initially copy of source */
           res->csub = CTEMP;      /* result values are temporary */
           if (a[0] == 0)          /* 0 => a[1] is already-compiled regexpr */
                   pfa = (fa *) a[1];      /* regular expression */
           else {
                   y = execute(a[1]);
                   pfa = makedfa(getsval(y), 1);
                   tempfree(y);
           }
           y = execute(a[2]);      /* replacement string */
           h = execute(a[3]);      /* which matches should be replaced */
           sptr = getsval(h);
           if (sptr[0] == 'g' || sptr[0] == 'G')
                   whichm = -1;
           else {
                   /*
                    * The specified number is index of replacement, starting
                    * from 1. GNU awk treats index lower than 0 same as
                    * 1, we do same for compatibility.
                    */
                   whichm = (int) getfval(h) - 1;
                   if (whichm < 0)
                           whichm = 0;
           }
           tempfree(h);
   
           if (pmatch(pfa, t)) {
                   char *sl;
   
                   tempstat = pfa->initstat;
                   pfa->initstat = 2;
                   pb = buf;
                   rptr = getsval(y);
                   /*
                    * XXX if there are any backreferences in subst string,
                    * complain now.
                    */
                   for (sl = rptr; (sl = strchr(sl, '\\')) && sl[1]; sl++) {
                           if (strchr("0123456789", sl[1])) {
                                   FATAL("gensub doesn't support backreferences (subst \"%s\")", rptr);
                           }
                   }
   
                   do {
                           if (whichm >= 0 && whichm != num) {
                                   num++;
                                   adjbuf(&buf, &bufsz, (pb - buf) + (patbeg - t) + patlen, recsize, &pb, "gensub");
   
                                   /* copy the part of string up to and including
                                    * match to output buffer */
                                   while (t < patbeg + patlen)
                                           *pb++ = *t++;
                                   continue;
                           }
   
                           if (patlen == 0 && *patbeg != 0) {      /* matched empty string */
                                   if (mflag == 0) {       /* can replace empty */
                                           num++;
                                           sptr = rptr;
                                           while (*sptr != 0) {
                                                   adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gensub");
                                                   if (*sptr == '\\') {
                                                           backsub(&pb, &sptr);
                                                   } else if (*sptr == '&') {
                                                           sptr++;
                                                           adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gensub");
                                                           for (q = patbeg; q < patbeg+patlen; )
                                                                   *pb++ = *q++;
                                                   } else
                                                           *pb++ = *sptr++;
                                           }
                                   }
                                   if (*t == 0)    /* at end */
                                           goto done;
                                   adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gensub");
                                   *pb++ = *t++;
                                   if (pb > buf + bufsz)   /* BUG: not sure of this test */
                                           FATAL("gensub result0 %.30s too big; can't happen", buf);
                                   mflag = 0;
                           }
                           else {  /* matched nonempty string */
                                   num++;
                                   sptr = t;
                                   adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gensub");
                                   while (sptr < patbeg)
                                           *pb++ = *sptr++;
                                   sptr = rptr;
                                   while (*sptr != 0) {
                                           adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gensub");
                                           if (*sptr == '\\') {
                                                   backsub(&pb, &sptr);
                                           } else if (*sptr == '&') {
                                                   sptr++;
                                                   adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gensub");
                                                   for (q = patbeg; q < patbeg+patlen; )
                                                           *pb++ = *q++;
                                           } else
                                                   *pb++ = *sptr++;
                                   }
                                   t = patbeg + patlen;
                                   if (patlen == 0 || *t == 0 || *(t-1) == 0)
                                           goto done;
                                   if (pb > buf + bufsz)
                                           FATAL("gensub result1 %.30s too big; can't happen", buf);
                                   mflag = 1;
                           }
                   } while (pmatch(pfa,t));
                   sptr = t;
                   adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gensub");
                   while ((*pb++ = *sptr++) != 0)
                           ;
           done:   if (pb > buf + bufsz)
                           FATAL("gensub result2 %.30s too big; can't happen", buf);
                   *pb = '\0';
                   setsval(res, buf);
                   pfa->initstat = tempstat;
           }
           tempfree(x);
           tempfree(y);
           free(buf);
           return(res);
 }  }
   
 void backsub(char **pb_ptr, const char **sptr_ptr)      /* handle \\& variations */  void backsub(char **pb_ptr, const char **sptr_ptr)      /* handle \\& variations */

Legend:
Removed from v.1.58  
changed lines
  Added in v.1.59