[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.80 and 1.81

version 1.80, 2023/10/28 22:38:22 version 1.81, 2023/11/22 01:01:21
Line 2518 
Line 2518 
   
 void backsub(char **pb_ptr, const char **sptr_ptr);  void backsub(char **pb_ptr, const char **sptr_ptr);
   
 Cell *sub(Node **a, int nnn)    /* substitute command */  Cell *dosub(Node **a, int subop)        /* sub and gsub */
 {  {
         const char *sptr, *q;  
         Cell *x, *y, *result;  
         char *t, *buf, *pb;  
         fa *pfa;          fa *pfa;
           int tempstat;
           char *repl;
           Cell *x;
   
           char *buf = NULL;
           char *pb = NULL;
         int bufsz = recsize;          int bufsz = recsize;
   
         if ((buf = (char *) malloc(bufsz)) == NULL)          const char *r, *s;
                 FATAL("out of memory in sub");          const char *start;
         x = execute(a[3]);      /* target string */          const char *noempty = NULL;      /* empty match disallowed here */
         t = getsval(x);          size_t m = 0;                    /* match count */
         if (a[0] == NULL)       /* 0 => a[1] is already-compiled regexpr */          size_t whichm;                   /* which match to select, 0 = global */
                 pfa = (fa *) a[1];      /* regular expression */          int mtype;                       /* match type */
         else {  
                 y = execute(a[1]);          if (a[0] == NULL) {     /* 0 => a[1] is already-compiled regexpr */
                 pfa = makedfa(getsval(y), 1);                  pfa = (fa *) a[1];
                 tempfree(y);          } else {
                   x = execute(a[1]);
                   pfa = makedfa(getsval(x), 1);
                   tempfree(x);
         }          }
         y = execute(a[2]);      /* replacement string */  
         result = False;          x = execute(a[2]);      /* replacement string */
         if (pmatch(pfa, t)) {          repl = tostring(getsval(x));
                 sptr = t;          tempfree(x);
                 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");  
                 pb = buf;          switch (subop) {
                 while (sptr < patbeg)          case SUB:
                         *pb++ = *sptr++;                  whichm = 1;
                 sptr = getsval(y);                  x = execute(a[3]);    /* source string */
                 while (*sptr != '\0') {                  break;
                         adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");          case GSUB:
                         if (*sptr == '\\') {                  whichm = 0;
                                 backsub(&pb, &sptr);                  x = execute(a[3]);    /* source string */
                         } else if (*sptr == '&') {                  break;
                                 sptr++;          default:
                                 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");                  FATAL("dosub: unrecognized subop: %d", subop);
                                 for (q = patbeg; q < patbeg+patlen; )          }
                                         *pb++ = *q++;  
                         } else          start = getsval(x);
                                 *pb++ = *sptr++;          while (pmatch(pfa, start)) {
                   if (buf == NULL) {
                           if ((pb = buf = malloc(bufsz)) == NULL)
                                   FATAL("out of memory in dosub");
                           tempstat = pfa->initstat;
                           pfa->initstat = 2;
                 }                  }
                 *pb = '\0';  
                 if (pb > buf + bufsz)                  /* match types */
                         FATAL("sub result1 %.30s too big; can't happen", buf);                  #define MT_IGNORE  0  /* unselected or invalid */
                 sptr = patbeg + patlen;                  #define MT_INSERT  1  /* selected, empty */
                 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {                  #define MT_REPLACE 2  /* selected, not empty */
                         adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");  
                         while ((*pb++ = *sptr++) != '\0')                  /* an empty match just after replacement is invalid */
                                 continue;  
                   if (patbeg == noempty && patlen == 0) {
                           mtype = MT_IGNORE;    /* invalid, not counted */
                   } else if (whichm == ++m || whichm == 0) {
                           mtype = patlen ? MT_REPLACE : MT_INSERT;
                   } else {
                           mtype = MT_IGNORE;    /* unselected, but counted */
                 }                  }
                 if (pb > buf + bufsz)  
                         FATAL("sub result2 %.30s too big; can't happen", buf);  
                 setsval(x, buf);        /* BUG: should be able to avoid copy */  
                 result = True;  
         }  
         tempfree(x);  
         tempfree(y);  
         free(buf);  
         return result;  
 }  
   
 Cell *gsub(Node **a, int nnn)   /* global substitute */                  /* leading text: */
 {                  if (patbeg > start) {
         Cell *x, *y;                          adjbuf(&buf, &bufsz, (pb - buf) + (patbeg - start),
         char *rptr, *pb;                                  recsize, &pb, "dosub");
         const char *q, *t, *sptr;                          s = start;
         char *buf;                          while (s < patbeg)
         fa *pfa;                                  *pb++ = *s++;
         int mflag, tempstat, num;                  }
         int bufsz = recsize;  
         int charlen = 0;  
   
         if ((buf = (char *) malloc(bufsz)) == NULL)                  if (mtype == MT_IGNORE)
                 FATAL("out of memory in gsub");                          goto matching_text;  /* skip replacement text */
         mflag = 0;      /* if mflag == 0, can replace empty string */  
         num = 0;                  r = repl;
         x = execute(a[3]);      /* target string */                  while (*r != 0) {
         t = getsval(x);                          adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "dosub");
         if (a[0] == NULL)       /* 0 => a[1] is already-compiled regexpr */                          if (*r == '\\') {
                 pfa = (fa *) a[1];      /* regular expression */                                  backsub(&pb, &r);
         else {                          } else if (*r == '&') {
                 y = execute(a[1]);                                  r++;
                 pfa = makedfa(getsval(y), 1);                                  adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize,
                 tempfree(y);                                          &pb, "dosub");
         }                                  for (s = patbeg; s < patbeg+patlen; )
         y = execute(a[2]);      /* replacement string */                                          *pb++ = *s++;
         if (pmatch(pfa, t)) {                          } else {
                 tempstat = pfa->initstat;                                  *pb++ = *r++;
                 pfa->initstat = 2;  
                 pb = buf;  
                 rptr = getsval(y);  
                 do {  
                         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, "gsub");  
                                                 if (*sptr == '\\') {  
                                                         backsub(&pb, &sptr);  
                                                 } else if (*sptr == '&') {  
                                                         sptr++;  
                                                         adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");  
                                                         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, "gsub");  
                                 charlen = u8_nextlen(t);  
                                 while (charlen-- > 0)  
                                         *pb++ = *t++;  
                                 if (pb > buf + bufsz)   /* BUG: not sure of this test */  
                                         FATAL("gsub result0 %.30s too big; can't happen", buf);  
                                 mflag = 0;  
                         }                          }
                         else {  /* matched nonempty string */                  }
                                 num++;  
                                 sptr = t;  matching_text:
                                 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");                  if (mtype == MT_REPLACE || *patbeg == '\0')
                                 while (sptr < patbeg)                          goto next_search;  /* skip matching text */
                                         *pb++ = *sptr++;  
                                 sptr = rptr;                  if (patlen == 0)
                                 while (*sptr != '\0') {                          patlen = u8_nextlen(patbeg);
                                         adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");                  adjbuf(&buf, &bufsz, (pb-buf) + patlen, recsize, &pb, "dosub");
                                         if (*sptr == '\\') {                  s = patbeg;
                                                 backsub(&pb, &sptr);                  while (s < patbeg + patlen)
                                         } else if (*sptr == '&') {                          *pb++ = *s++;
                                                 sptr++;  
                                                 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");  next_search:
                                                 for (q = patbeg; q < patbeg+patlen; )                  start = patbeg + patlen;
                                                         *pb++ = *q++;                  if (m == whichm || *patbeg == '\0')
                                         } else                          break;
                                                 *pb++ = *sptr++;                  if (mtype == MT_REPLACE)
                                 }                          noempty = start;
                                 t = patbeg + patlen;  
                                 if (patlen == 0 || *t == '\0' || *(t-1) == '\0')                  #undef MT_IGNORE
                                         goto done;                  #undef MT_INSERT
                                 if (pb > buf + bufsz)                  #undef MT_REPLACE
                                         FATAL("gsub result1 %.30s too big; can't happen", buf);          }
                                 mflag = 1;  
                         }          xfree(repl);
                 } while (pmatch(pfa,t));  
                 sptr = t;          if (buf != NULL) {
                 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");  
                 while ((*pb++ = *sptr++) != '\0')  
                         continue;  
         done:   if (pb < buf + bufsz)  
                         *pb = '\0';  
                 else if (*(pb-1) != '\0')  
                         FATAL("gsub result2 %.30s truncated; can't happen", buf);  
                 setsval(x, buf);        /* BUG: should be able to avoid copy + free */  
                 pfa->initstat = tempstat;                  pfa->initstat = tempstat;
   
                   /* trailing text */
                   adjbuf(&buf, &bufsz, 1+strlen(start)+pb-buf, 0, &pb, "dosub");
                   while ((*pb++ = *start++) != '\0')
                           ;
   
                   setsval(x, buf);
                   free(buf);
         }          }
   
         tempfree(x);          tempfree(x);
         tempfree(y);  
         x = gettemp();          x = gettemp();
         x->tval = NUM;          x->tval = NUM;
         x->fval = num;          x->fval = m;
         free(buf);          return x;
         return(x);  
 }  }
   
 Cell *gensub(Node **a, int nnn) /* global selective substitute */  Cell *gensub(Node **a, int nnn) /* global selective substitute */

Legend:
Removed from v.1.80  
changed lines
  Added in v.1.81