1 /* 2 * Copyright (C) Lucent Technologies 1997 3 * All Rights Reserved 4 * 5 * Permission to use, copy, modify, and distribute this software and 6 * its documentation for any purpose and without fee is hereby 7 * granted, provided that the above copyright notice appear in all 8 * copies and that both that the copyright notice and this 9 * permission notice and warranty disclaimer appear in supporting 10 * documentation, and that the name Lucent Technologies or any of 11 * its entities not be used in advertising or publicity pertaining 12 * to distribution of the software without specific, written prior 13 * permission. 14 * 15 * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 17 * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 20 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 21 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 22 * THIS SOFTWARE. 23 */ 24 25 /* 26 * CDDL HEADER START 27 * 28 * The contents of this file are subject to the terms of the 29 * Common Development and Distribution License (the "License"). 30 * You may not use this file except in compliance with the License. 31 * 32 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 33 * or http://www.opensolaris.org/os/licensing. 34 * See the License for the specific language governing permissions 35 * and limitations under the License. 36 * 37 * When distributing Covered Code, include this CDDL HEADER in each 38 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 39 * If applicable, add the following below this CDDL HEADER, with the 40 * fields enclosed by brackets "[]" replaced with your own identifying 41 * information: Portions Copyright [yyyy] [name of copyright owner] 42 * 43 * CDDL HEADER END 44 */ 45 46 /* 47 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 48 */ 49 50 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 51 /* All Rights Reserved */ 52 53 #define DEBUG 54 #include <stdio.h> 55 #include <ctype.h> 56 #include <setjmp.h> 57 #include <math.h> 58 #include <time.h> 59 #include <sys/wait.h> 60 #include "awk.h" 61 #include "y.tab.h" 62 63 #define tempfree(x) if (istemp(x)) tfree(x) 64 65 static jmp_buf env; 66 extern Awkfloat srand_seed; 67 68 static Cell *execute(Node *); 69 static Cell *gettemp(void), *copycell(Cell *); 70 static FILE *openfile(int, const char *), *redirect(int, Node *); 71 72 Node *winner = NULL; /* root of parse tree */ 73 static Cell *tmps; /* free temporary cells for execution */ 74 75 static Cell truecell = { OBOOL, BTRUE, NULL, NULL, 1.0, NUM, NULL }; 76 Cell *True = &truecell; 77 static Cell falsecell = { OBOOL, BFALSE, NULL, NULL, 0.0, NUM, NULL }; 78 Cell *False = &falsecell; 79 static Cell breakcell = { OJUMP, JBREAK, NULL, NULL, 0.0, NUM, NULL }; 80 Cell *jbreak = &breakcell; 81 static Cell contcell = { OJUMP, JCONT, NULL, NULL, 0.0, NUM, NULL }; 82 Cell *jcont = &contcell; 83 static Cell nextcell = { OJUMP, JNEXT, NULL, NULL, 0.0, NUM, NULL }; 84 Cell *jnext = &nextcell; 85 static Cell nextfilecell = { OJUMP, JNEXTFILE, NULL, NULL, 0.0, 86 NUM, NULL }; 87 Cell *jnextfile = &nextfilecell; 88 static Cell exitcell = { OJUMP, JEXIT, NULL, NULL, 0.0, NUM, NULL }; 89 Cell *jexit = &exitcell; 90 static Cell retcell = { OJUMP, JRET, NULL, NULL, 0.0, NUM, NULL }; 91 Cell *jret = &retcell; 92 static Cell tempcell = { OCELL, CTEMP, NULL, "", 0.0, 93 NUM|STR|DONTFREE, NULL }; 94 95 Node *curnode = NULL; /* the node being executed, for debugging */ 96 97 static void tfree(Cell *); 98 static void closeall(void); 99 static double ipow(double, int); 100 static void backsub(char **pb_ptr, char **sptr_ptr); 101 102 103 /* 104 * buffer memory management 105 * 106 * pbuf: address of pointer to buffer being managed 107 * psiz: address of buffer size variable 108 * minlen: minimum length of buffer needed 109 * quantum: buffer size quantum 110 * pbptr: address of movable pointer into buffer, or 0 if none 111 * whatrtn: name of the calling routine if failure should cause fatal error 112 * 113 * return 0 for realloc failure, !=0 for success 114 */ 115 int 116 adjbuf(char **pbuf, size_t *psiz, size_t minlen, size_t quantum, char **pbptr, 117 const char *whatrtn) 118 { 119 if (minlen > *psiz) { 120 char *tbuf; 121 int rminlen = quantum ? minlen % quantum : 0; 122 int boff = pbptr ? *pbptr - *pbuf : 0; 123 /* round up to next multiple of quantum */ 124 if (rminlen) 125 minlen += quantum - rminlen; 126 tbuf = (char *)realloc(*pbuf, minlen); 127 dprintf(("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, 128 *psiz, minlen, (void *)*pbuf, (void *)tbuf)); 129 if (tbuf == NULL) { 130 if (whatrtn) 131 FATAL("out of memory in %s", whatrtn); 132 return (0); 133 } 134 *pbuf = tbuf; 135 *psiz = minlen; 136 if (pbptr) 137 *pbptr = tbuf + boff; 138 } 139 return (1); 140 } 141 142 void 143 run(Node *a) /* execution of parse tree starts here */ 144 { 145 extern void stdinit(void); 146 147 stdinit(); 148 (void) execute(a); 149 closeall(); 150 } 151 152 static Cell * 153 execute(Node *u) /* execute a node of the parse tree */ 154 { 155 Cell *(*proc)(Node **, int); 156 Cell *x; 157 Node *a; 158 159 if (u == NULL) 160 return (True); 161 for (a = u; ; a = a->nnext) { 162 curnode = a; 163 if (isvalue(a)) { 164 x = (Cell *) (a->narg[0]); 165 if (isfld(x) && !donefld) 166 fldbld(); 167 else if (isrec(x) && !donerec) 168 recbld(); 169 return (x); 170 } 171 /* probably a Cell* but too risky to print */ 172 if (notlegal(a->nobj)) 173 FATAL("illegal statement"); 174 proc = proctab[a->nobj-FIRSTTOKEN]; 175 x = (*proc)(a->narg, a->nobj); 176 if (isfld(x) && !donefld) 177 fldbld(); 178 else if (isrec(x) && !donerec) 179 recbld(); 180 if (isexpr(a)) 181 return (x); 182 /* a statement, goto next statement */ 183 if (isjump(x)) 184 return (x); 185 if (a->nnext == NULL) 186 return (x); 187 tempfree(x); 188 } 189 } 190 191 /* execute an awk program */ 192 /* a[0] = BEGIN, a[1] = body, a[2] = END */ 193 /*ARGSUSED*/ 194 Cell * 195 program(Node **a, int n) 196 { 197 Cell *x; 198 199 if (setjmp(env) != 0) 200 goto ex; 201 if (a[0]) { /* BEGIN */ 202 x = execute(a[0]); 203 if (isexit(x)) 204 return (True); 205 if (isjump(x)) { 206 FATAL("illegal break, continue, next or nextfile " 207 "from BEGIN"); 208 } 209 tempfree(x); 210 } 211 if (a[1] || a[2]) 212 while (getrec(&record, &recsize, 1) > 0) { 213 x = execute(a[1]); 214 if (isexit(x)) 215 break; 216 tempfree(x); 217 } 218 ex: 219 if (setjmp(env) != 0) /* handles exit within END */ 220 goto ex1; 221 if (a[2]) { /* END */ 222 x = execute(a[2]); 223 if (isbreak(x) || isnext(x) || iscont(x)) 224 FATAL("illegal break, continue, next or nextfile " 225 "from END"); 226 tempfree(x); 227 } 228 ex1: 229 return (True); 230 } 231 232 struct Frame { /* stack frame for awk function calls */ 233 int nargs; /* number of arguments in this call */ 234 Cell *fcncell; /* pointer to Cell for function */ 235 Cell **args; /* pointer to array of arguments after execute */ 236 Cell *retval; /* return value */ 237 }; 238 239 #define NARGS 50 /* max args in a call */ 240 241 struct Frame *frame = NULL; /* base of stack frames; dynamically alloc'd */ 242 int nframe = 0; /* number of frames allocated */ 243 struct Frame *fp = NULL; /* frame pointer. bottom level unused */ 244 245 /*ARGSUSED*/ 246 Cell * 247 call(Node **a, int n) /* function call. very kludgy and fragile */ 248 { 249 static Cell newcopycell = 250 { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL }; 251 int i, ncall, ndef; 252 /* handles potential double freeing when fcn & param share a tempcell */ 253 int freed = 0; 254 Node *x; 255 Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */ 256 Cell *y, *z, *fcn; 257 char *s; 258 259 fcn = execute(a[0]); /* the function itself */ 260 s = fcn->nval; 261 if (!isfcn(fcn)) 262 FATAL("calling undefined function %s", s); 263 if (frame == NULL) { 264 fp = frame = (struct Frame *)calloc(nframe += 100, 265 sizeof (struct Frame)); 266 if (frame == NULL) { 267 FATAL("out of space for stack frames calling %s", s); 268 } 269 } 270 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ 271 ncall++; 272 ndef = (int)fcn->fval; /* args in defn */ 273 dprintf(("calling %s, %d args (%d in defn), fp=%d\n", 274 s, ncall, ndef, fp-frame)); 275 if (ncall > ndef) { 276 WARNING("function %s called with %d args, uses only %d", 277 s, ncall, ndef); 278 } 279 if (ncall + ndef > NARGS) { 280 FATAL("function %s has %d arguments, limit %d", 281 s, ncall+ndef, NARGS); 282 } 283 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { 284 /* get call args */ 285 dprintf(("evaluate args[%d], fp=%d:\n", i, fp-frame)); 286 y = execute(x); 287 oargs[i] = y; 288 dprintf(("args[%d]: %s %f <%s>, t=%o\n", 289 i, NN(y->nval), y->fval, 290 isarr(y) ? "(array)" : NN(y->sval), y->tval)); 291 if (isfcn(y)) { 292 FATAL("can't use function %s as argument in %s", 293 y->nval, s); 294 } 295 if (isarr(y)) 296 args[i] = y; /* arrays by ref */ 297 else 298 args[i] = copycell(y); 299 tempfree(y); 300 } 301 for (; i < ndef; i++) { /* add null args for ones not provided */ 302 args[i] = gettemp(); 303 *args[i] = newcopycell; 304 } 305 fp++; /* now ok to up frame */ 306 if (fp >= frame + nframe) { 307 int dfp = fp - frame; /* old index */ 308 frame = (struct Frame *) 309 realloc(frame, (nframe += 100) * sizeof (struct Frame)); 310 if (frame == NULL) 311 FATAL("out of space for stack frames in %s", s); 312 fp = frame + dfp; 313 } 314 fp->fcncell = fcn; 315 fp->args = args; 316 fp->nargs = ndef; /* number defined with (excess are locals) */ 317 fp->retval = gettemp(); 318 319 dprintf(("start exec of %s, fp=%d\n", s, fp-frame)); 320 /*LINTED align*/ 321 y = execute((Node *)(fcn->sval)); /* execute body */ 322 dprintf(("finished exec of %s, fp=%d\n", s, fp-frame)); 323 324 for (i = 0; i < ndef; i++) { 325 Cell *t = fp->args[i]; 326 if (isarr(t)) { 327 if (t->csub == CCOPY) { 328 if (i >= ncall) { 329 freesymtab(t); 330 t->csub = CTEMP; 331 tempfree(t); 332 } else { 333 oargs[i]->tval = t->tval; 334 oargs[i]->tval &= ~(STR|NUM|DONTFREE); 335 oargs[i]->sval = t->sval; 336 tempfree(t); 337 } 338 } 339 } else if (t != y) { /* kludge to prevent freeing twice */ 340 t->csub = CTEMP; 341 tempfree(t); 342 } else if (t == y && t->csub == CCOPY) { 343 t->csub = CTEMP; 344 tempfree(t); 345 freed = 1; 346 } 347 } 348 tempfree(fcn); 349 if (isexit(y) || isnext(y)) 350 return (y); 351 if (freed == 0) { 352 tempfree(y); /* don't free twice! */ 353 } 354 z = fp->retval; /* return value */ 355 dprintf(("%s returns %g |%s| %o\n", 356 s, getfval(z), getsval(z), z->tval)); 357 fp--; 358 return (z); 359 } 360 361 static Cell * 362 copycell(Cell *x) /* make a copy of a cell in a temp */ 363 { 364 Cell *y; 365 366 /* copy is not constant or field */ 367 368 y = gettemp(); 369 y->tval = x->tval & ~(CON|FLD|REC); 370 y->csub = CCOPY; /* prevents freeing until call is over */ 371 y->nval = x->nval; /* BUG? */ 372 if (isstr(x)) { 373 y->sval = tostring(x->sval); 374 y->tval &= ~DONTFREE; 375 } else 376 y->tval |= DONTFREE; 377 y->fval = x->fval; 378 return (y); 379 } 380 381 /*ARGSUSED*/ 382 Cell * 383 arg(Node **a, int nnn) /* nth argument of a function */ 384 { 385 int n; 386 387 n = ptoi(a[0]); /* argument number, counting from 0 */ 388 dprintf(("arg(%d), fp->nargs=%d\n", n, fp->nargs)); 389 if (n+1 > fp->nargs) { 390 FATAL("argument #%d of function %s was not supplied", 391 n+1, fp->fcncell->nval); 392 } 393 return (fp->args[n]); 394 } 395 396 Cell * 397 jump(Node **a, int n) /* break, continue, next, nextfile, return */ 398 { 399 Cell *y; 400 401 switch (n) { 402 case EXIT: 403 if (a[0] != NULL) { 404 y = execute(a[0]); 405 errorflag = (int)getfval(y); 406 tempfree(y); 407 } 408 longjmp(env, 1); 409 /*NOTREACHED*/ 410 case RETURN: 411 if (a[0] != NULL) { 412 y = execute(a[0]); 413 if ((y->tval & (STR|NUM)) == (STR|NUM)) { 414 (void) setsval(fp->retval, getsval(y)); 415 fp->retval->fval = getfval(y); 416 fp->retval->tval |= NUM; 417 } else if (y->tval & STR) 418 (void) setsval(fp->retval, getsval(y)); 419 else if (y->tval & NUM) 420 (void) setfval(fp->retval, getfval(y)); 421 else /* can't happen */ 422 FATAL("bad type variable %d", y->tval); 423 tempfree(y); 424 } 425 return (jret); 426 case NEXT: 427 return (jnext); 428 case NEXTFILE: 429 nextfile(); 430 return (jnextfile); 431 case BREAK: 432 return (jbreak); 433 case CONTINUE: 434 return (jcont); 435 default: /* can't happen */ 436 FATAL("illegal jump type %d", n); 437 } 438 /*NOTREACHED*/ 439 return (NULL); 440 } 441 442 Cell * 443 awkgetline(Node **a, int n) /* get next line from specific input */ 444 { 445 /* a[0] is variable, a[1] is operator, a[2] is filename */ 446 Cell *r, *x; 447 FILE *fp; 448 char *buf; 449 size_t bufsize = recsize; 450 int mode; 451 452 if ((buf = (char *)malloc(bufsize)) == NULL) 453 FATAL("out of memory in getline"); 454 455 (void) fflush(stdout); /* in case someone is waiting for a prompt */ 456 r = gettemp(); 457 if (a[1] != NULL) { /* getline < file */ 458 x = execute(a[2]); /* filename */ 459 mode = ptoi(a[1]); 460 if (mode == '|') /* input pipe */ 461 mode = LE; /* arbitrary flag */ 462 fp = openfile(mode, getsval(x)); 463 tempfree(x); 464 if (fp == NULL) 465 n = -1; 466 else 467 n = readrec(&buf, &bufsize, fp); 468 /*LINTED if*/ 469 if (n <= 0) { 470 ; 471 } else if (a[0] != NULL) { /* getline var <file */ 472 x = execute(a[0]); 473 (void) setsval(x, buf); 474 tempfree(x); 475 } else { /* getline <file */ 476 (void) setsval(recloc, buf); 477 if (is_number(recloc->sval)) { 478 recloc->fval = atof(recloc->sval); 479 recloc->tval |= NUM; 480 } 481 } 482 } else { /* bare getline; use current input */ 483 if (a[0] == NULL) /* getline */ 484 n = getrec(&record, &recsize, 1); 485 else { /* getline var */ 486 n = getrec(&buf, &bufsize, 0); 487 x = execute(a[0]); 488 (void) setsval(x, buf); 489 tempfree(x); 490 } 491 } 492 (void) setfval(r, (Awkfloat)n); 493 free(buf); 494 return (r); 495 } 496 497 /*ARGSUSED*/ 498 Cell * 499 getnf(Node **a, int n) /* get NF */ 500 { 501 if (donefld == 0) 502 fldbld(); 503 return ((Cell *)a[0]); 504 } 505 506 /*ARGSUSED*/ 507 Cell * 508 array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 509 { 510 Cell *x, *y, *z; 511 char *s; 512 Node *np; 513 char *buf; 514 size_t bufsz = recsize; 515 size_t tlen = 0, len, nsub; 516 517 if ((buf = (char *)malloc(bufsz)) == NULL) 518 FATAL("out of memory in array"); 519 520 x = execute(a[0]); /* Cell* for symbol table */ 521 buf[0] = '\0'; 522 for (np = a[1]; np != NULL; np = np->nnext) { 523 y = execute(np); /* subscript */ 524 s = getsval(y); 525 len = strlen(s); 526 nsub = strlen(getsval(subseploc)); 527 (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1, 528 recsize, 0, "array"); 529 (void) memcpy(&buf[tlen], s, len); 530 tlen += len; 531 if (np->nnext) { 532 (void) memcpy(&buf[tlen], *SUBSEP, nsub); 533 tlen += nsub; 534 } 535 buf[tlen] = '\0'; 536 tempfree(y); 537 } 538 if (!isarr(x)) { 539 dprintf(("making %s into an array\n", NN(x->nval))); 540 if (freeable(x)) 541 xfree(x->sval); 542 x->tval &= ~(STR|NUM|DONTFREE); 543 x->tval |= ARR; 544 x->sval = (char *)makesymtab(NSYMTAB); 545 } 546 /*LINTED align*/ 547 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *)x->sval); 548 z->ctype = OCELL; 549 z->csub = CVAR; 550 tempfree(x); 551 free(buf); 552 return (z); 553 } 554 555 /*ARGSUSED*/ 556 Cell * 557 awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */ 558 { 559 Cell *x, *y; 560 Node *np; 561 char *s; 562 size_t nsub; 563 size_t tlen = 0, len; 564 565 x = execute(a[0]); /* Cell* for symbol table */ 566 if (x == symtabloc) { 567 FATAL("cannot delete SYMTAB or its elements"); 568 } 569 if (!isarr(x)) { 570 dprintf(("making %s into an array\n", x->nval)); 571 if (freeable(x)) 572 xfree(x->sval); 573 x->tval &= ~(STR|NUM|DONTFREE); 574 x->tval |= ARR; 575 x->sval = (char *)makesymtab(NSYMTAB); 576 } 577 if (a[1] == NULL) { /* delete the elements, not the table */ 578 freesymtab(x); 579 x->tval &= ~STR; 580 x->tval |= ARR; 581 x->sval = (char *)makesymtab(NSYMTAB); 582 } else { 583 size_t bufsz = recsize; 584 char *buf; 585 if ((buf = (char *)malloc(bufsz)) == NULL) 586 FATAL("out of memory in awkdelete"); 587 buf[0] = '\0'; 588 for (np = a[1]; np != NULL; np = np->nnext) { 589 y = execute(np); /* subscript */ 590 s = getsval(y); 591 len = strlen(s); 592 nsub = strlen(getsval(subseploc)); 593 (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1, 594 recsize, 0, "awkdelete"); 595 (void) memcpy(&buf[tlen], s, len); 596 tlen += len; 597 if (np->nnext) { 598 (void) memcpy(&buf[tlen], *SUBSEP, nsub); 599 tlen += nsub; 600 } 601 buf[tlen] = '\0'; 602 tempfree(y); 603 } 604 freeelem(x, buf); 605 free(buf); 606 } 607 tempfree(x); 608 return (True); 609 } 610 611 /*ARGSUSED*/ 612 Cell * 613 intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */ 614 { 615 Cell *x, *ap, *k; 616 Node *p; 617 char *buf; 618 char *s; 619 size_t bufsz = recsize; 620 size_t nsub; 621 size_t tlen = 0, len; 622 623 ap = execute(a[1]); /* array name */ 624 if (!isarr(ap)) { 625 dprintf(("making %s into an array\n", ap->nval)); 626 if (freeable(ap)) 627 xfree(ap->sval); 628 ap->tval &= ~(STR|NUM|DONTFREE); 629 ap->tval |= ARR; 630 ap->sval = (char *)makesymtab(NSYMTAB); 631 } 632 if ((buf = (char *)malloc(bufsz)) == NULL) { 633 FATAL("out of memory in intest"); 634 } 635 buf[0] = '\0'; 636 for (p = a[0]; p != NULL; p = p->nnext) { 637 x = execute(p); /* expr */ 638 s = getsval(x); 639 len = strlen(s); 640 nsub = strlen(getsval(subseploc)); 641 (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1, 642 recsize, 0, "intest"); 643 (void) memcpy(&buf[tlen], s, len); 644 tlen += len; 645 tempfree(x); 646 if (p->nnext) { 647 (void) memcpy(&buf[tlen], *SUBSEP, nsub); 648 tlen += nsub; 649 } 650 buf[tlen] = '\0'; 651 } 652 /*LINTED align*/ 653 k = lookup(buf, (Array *)ap->sval); 654 tempfree(ap); 655 free(buf); 656 if (k == NULL) 657 return (False); 658 else 659 return (True); 660 } 661 662 663 Cell * 664 matchop(Node **a, int n) /* ~ and match() */ 665 { 666 Cell *x, *y; 667 char *s, *t; 668 int i; 669 fa *pfa; 670 int (*mf)(fa *, const char *) = match, mode = 0; 671 672 if (n == MATCHFCN) { 673 mf = pmatch; 674 mode = 1; 675 } 676 x = execute(a[1]); /* a[1] = target text */ 677 s = getsval(x); 678 if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */ 679 i = (*mf)((fa *)a[2], s); 680 else { 681 y = execute(a[2]); /* a[2] = regular expr */ 682 t = getsval(y); 683 pfa = makedfa(t, mode); 684 i = (*mf)(pfa, s); 685 tempfree(y); 686 } 687 tempfree(x); 688 if (n == MATCHFCN) { 689 int start = patbeg - s + 1; 690 if (patlen < 0) 691 start = 0; 692 (void) setfval(rstartloc, (Awkfloat)start); 693 (void) setfval(rlengthloc, (Awkfloat)patlen); 694 x = gettemp(); 695 x->tval = NUM; 696 x->fval = start; 697 return (x); 698 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0)) 699 return (True); 700 else 701 return (False); 702 } 703 704 705 Cell * 706 boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */ 707 { 708 Cell *x, *y; 709 int i; 710 711 x = execute(a[0]); 712 i = istrue(x); 713 tempfree(x); 714 switch (n) { 715 case BOR: 716 if (i) 717 return (True); 718 y = execute(a[1]); 719 i = istrue(y); 720 tempfree(y); 721 return (i ? True : False); 722 case AND: 723 if (!i) 724 return (False); 725 y = execute(a[1]); 726 i = istrue(y); 727 tempfree(y); 728 return (i ? True : False); 729 case NOT: 730 return (i ? False : True); 731 default: /* can't happen */ 732 FATAL("unknown boolean operator %d", n); 733 } 734 /*NOTREACHED*/ 735 return (NULL); 736 } 737 738 Cell * 739 relop(Node **a, int n) /* a[0] < a[1], etc. */ 740 { 741 int i; 742 Cell *x, *y; 743 Awkfloat j; 744 745 x = execute(a[0]); 746 y = execute(a[1]); 747 if (x->tval&NUM && y->tval&NUM) { 748 j = x->fval - y->fval; 749 i = j < 0 ? -1: (j > 0 ? 1: 0); 750 } else { 751 i = strcmp(getsval(x), getsval(y)); 752 } 753 tempfree(x); 754 tempfree(y); 755 switch (n) { 756 case LT: return (i < 0 ? True : False); 757 case LE: return (i <= 0 ? True : False); 758 case NE: return (i != 0 ? True : False); 759 case EQ: return (i == 0 ? True : False); 760 case GE: return (i >= 0 ? True : False); 761 case GT: return (i > 0 ? True : False); 762 default: /* can't happen */ 763 FATAL("unknown relational operator %d", n); 764 } 765 /*NOTREACHED*/ 766 return (False); 767 } 768 769 static void 770 tfree(Cell *a) /* free a tempcell */ 771 { 772 if (freeable(a)) { 773 dprintf(("freeing %s %s %o\n", 774 NN(a->nval), NN(a->sval), a->tval)); 775 xfree(a->sval); 776 } 777 if (a == tmps) 778 FATAL("tempcell list is curdled"); 779 a->cnext = tmps; 780 tmps = a; 781 } 782 783 static Cell * 784 gettemp(void) /* get a tempcell */ 785 { 786 int i; 787 Cell *x; 788 789 if (!tmps) { 790 tmps = (Cell *)calloc(100, sizeof (Cell)); 791 if (!tmps) 792 FATAL("out of space for temporaries"); 793 for (i = 1; i < 100; i++) 794 tmps[i-1].cnext = &tmps[i]; 795 tmps[i-1].cnext = NULL; 796 } 797 x = tmps; 798 tmps = x->cnext; 799 *x = tempcell; 800 dprintf(("gtemp %.8s %06lo\n", NN(x->nval), (ulong_t)x)); 801 return (x); 802 } 803 804 /*ARGSUSED*/ 805 Cell * 806 indirect(Node **a, int n) /* $( a[0] ) */ 807 { 808 Awkfloat val; 809 Cell *x; 810 int m; 811 char *s; 812 813 x = execute(a[0]); 814 815 /* freebsd: defend against super large field numbers */ 816 val = getfval(x); 817 if ((Awkfloat)INT_MAX < val) 818 FATAL("trying to access out of range field %s", x->nval); 819 m = (int)val; 820 if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ 821 FATAL("illegal field $(%s), name \"%s\"", s, x->nval); 822 /* BUG: can x->nval ever be null??? */ 823 tempfree(x); 824 x = fieldadr(m); 825 x->ctype = OCELL; /* BUG? why are these needed? */ 826 x->csub = CFLD; 827 return (x); 828 } 829 830 /*ARGSUSED*/ 831 Cell * 832 substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */ 833 { 834 int k, m, n; 835 char *s; 836 int temp; 837 Cell *x, *y, *z = NULL; 838 839 x = execute(a[0]); 840 y = execute(a[1]); 841 if (a[2] != NULL) 842 z = execute(a[2]); 843 s = getsval(x); 844 k = strlen(s) + 1; 845 if (k <= 1) { 846 tempfree(x); 847 tempfree(y); 848 if (a[2] != NULL) { 849 tempfree(z); 850 } 851 x = gettemp(); 852 (void) setsval(x, ""); 853 return (x); 854 } 855 m = (int)getfval(y); 856 if (m <= 0) 857 m = 1; 858 else if (m > k) 859 m = k; 860 tempfree(y); 861 if (a[2] != NULL) { 862 n = (int)getfval(z); 863 tempfree(z); 864 } else 865 n = k - 1; 866 if (n < 0) 867 n = 0; 868 else if (n > k - m) 869 n = k - m; 870 dprintf(("substr: m=%d, n=%d, s=%s\n", m, n, s)); 871 y = gettemp(); 872 temp = s[n + m - 1]; /* with thanks to John Linderman */ 873 s[n + m - 1] = '\0'; 874 (void) setsval(y, s + m - 1); 875 s[n + m - 1] = temp; 876 tempfree(x); 877 return (y); 878 } 879 880 /*ARGSUSED*/ 881 Cell * 882 sindex(Node **a, int nnn) /* index(a[0], a[1]) */ 883 { 884 Cell *x, *y, *z; 885 char *s1, *s2, *p1, *p2, *q; 886 Awkfloat v = 0.0; 887 888 x = execute(a[0]); 889 s1 = getsval(x); 890 y = execute(a[1]); 891 s2 = getsval(y); 892 893 z = gettemp(); 894 for (p1 = s1; *p1 != '\0'; p1++) { 895 for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++) 896 ; 897 if (*p2 == '\0') { 898 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ 899 break; 900 } 901 } 902 tempfree(x); 903 tempfree(y); 904 (void) setfval(z, v); 905 return (z); 906 } 907 908 #define MAXNUMSIZE 50 909 910 /* printf-like conversions */ 911 int 912 format(char **pbuf, int *pbufsize, const char *s, Node *a) 913 { 914 char *fmt; 915 const char *os; 916 Cell *x; 917 int flag = 0, n, len; 918 int fmtwd; /* format width */ 919 char *buf = *pbuf; 920 size_t bufsize = *pbufsize; 921 size_t fmtsz = recsize; 922 size_t cnt, tcnt, ret; 923 924 os = s; 925 cnt = 0; 926 if ((fmt = (char *)malloc(fmtsz)) == NULL) 927 FATAL("out of memory in format()"); 928 while (*s) { 929 if (*s != '%') { 930 expand_buf(&buf, &bufsize, cnt); 931 buf[cnt++] = *s++; 932 continue; 933 } 934 if (*(s+1) == '%') { 935 expand_buf(&buf, &bufsize, cnt); 936 buf[cnt++] = '%'; 937 s += 2; 938 continue; 939 } 940 /* 941 * have to be real careful in case this is a huge number, 942 * eg, "%100000d". 943 */ 944 fmtwd = atoi(s+1); 945 if (fmtwd < 0) 946 fmtwd = -fmtwd; 947 for (tcnt = 0; ; s++) { 948 expand_buf(&fmt, &fmtsz, tcnt); 949 fmt[tcnt++] = *s; 950 if (*s == '\0') 951 break; 952 if (isalpha((uschar)*s) && 953 *s != 'l' && *s != 'h' && *s != 'L') 954 break; /* the ansi panoply */ 955 if (*s == '$') { 956 FATAL("'$' not permitted in awk formats"); 957 } 958 if (*s == '*') { 959 if (a == NULL) { 960 FATAL("not enough args in printf(%s) " 961 "or sprintf(%s)", os, os); 962 } 963 x = execute(a); 964 a = a->nnext; 965 tcnt--; 966 expand_buf(&fmt, &fmtsz, tcnt + 12); 967 fmtwd = (int)getfval(x); 968 ret = sprintf(&fmt[tcnt], "%d", fmtwd); 969 if (fmtwd < 0) 970 fmtwd = -fmtwd; 971 tcnt += ret; 972 tempfree(x); 973 } 974 } 975 fmt[tcnt] = '\0'; 976 if (fmtwd < 0) 977 fmtwd = -fmtwd; 978 979 switch (*s) { 980 case 'a': case 'A': 981 flag = *s; 982 break; 983 case 'f': case 'e': case 'g': case 'E': case 'G': 984 flag = 'f'; 985 break; 986 case 'd': case 'i': 987 flag = 'd'; 988 if (*(s-1) == 'l') 989 break; 990 fmt[tcnt - 1] = 'l'; 991 expand_buf(&fmt, &fmtsz, tcnt); 992 fmt[tcnt++] = 'd'; 993 fmt[tcnt] = '\0'; 994 break; 995 case 'o': case 'x': case 'X': case 'u': 996 flag = *(s-1) == 'l' ? 'd' : 'u'; 997 break; 998 case 's': 999 flag = 's'; 1000 break; 1001 case 'c': 1002 flag = 'c'; 1003 break; 1004 default: 1005 WARNING("weird printf conversion %s", fmt); 1006 flag = '?'; 1007 break; 1008 } 1009 if (flag == '?') { 1010 len = strlen(fmt); 1011 expand_buf(&buf, &bufsize, cnt + len); 1012 (void) memcpy(&buf[cnt], fmt, len); 1013 cnt += len; 1014 buf[cnt] = '\0'; 1015 continue; 1016 } 1017 if (a == NULL) { 1018 FATAL("not enough args in printf(%s) " 1019 "or sprintf(%s)", os, os); 1020 } 1021 x = execute(a); 1022 a = a->nnext; 1023 n = MAXNUMSIZE; 1024 if (fmtwd > n) 1025 n = fmtwd; 1026 retry: 1027 /* make sure we have at least 1 byte space */ 1028 (void) adjbuf(&buf, &bufsize, 1 + n + cnt, 1029 recsize, NULL, "format5"); 1030 len = bufsize - cnt; 1031 switch (flag) { 1032 case 'a': 1033 case 'A': 1034 case 'f': 1035 /*LINTED*/ 1036 ret = snprintf(&buf[cnt], len, 1037 fmt, getfval(x)); 1038 break; 1039 case 'd': 1040 /*LINTED*/ 1041 ret = snprintf(&buf[cnt], len, 1042 fmt, (long)getfval(x)); 1043 break; 1044 case 'u': 1045 /*LINTED*/ 1046 ret = snprintf(&buf[cnt], len, 1047 fmt, (int)getfval(x)); 1048 break; 1049 case 's': 1050 /*LINTED*/ 1051 ret = snprintf(&buf[cnt], len, 1052 fmt, getsval(x)); 1053 break; 1054 case 'c': 1055 if (!isnum(x)) { 1056 /*LINTED*/ 1057 ret = snprintf(&buf[cnt], len, 1058 fmt, getsval(x)[0]); 1059 break; 1060 } 1061 if (getfval(x)) { 1062 /*LINTED*/ 1063 ret = snprintf(&buf[cnt], len, 1064 fmt, (int)getfval(x)); 1065 } else { 1066 /* explicit null byte */ 1067 buf[cnt] = '\0'; 1068 /* next output will start here */ 1069 buf[cnt + 1] = '\0'; 1070 ret = 1; 1071 } 1072 break; 1073 default: 1074 FATAL("can't happen: " 1075 "bad conversion %c in format()", flag); 1076 } 1077 if (ret >= len) { 1078 (void) adjbuf(&buf, &bufsize, cnt + ret + 1, 1079 recsize, NULL, "format6"); 1080 goto retry; 1081 } 1082 tempfree(x); 1083 cnt += ret; 1084 s++; 1085 } 1086 buf[cnt] = '\0'; 1087 free(fmt); 1088 for (; a != NULL; a = a->nnext) /* evaluate any remaining args */ 1089 (void) execute(a); 1090 *pbuf = buf; 1091 *pbufsize = bufsize; 1092 return (cnt); 1093 } 1094 1095 /*ARGSUSED*/ 1096 Cell * 1097 awksprintf(Node **a, int n) /* sprintf(a[0]) */ 1098 { 1099 Cell *x; 1100 Node *y; 1101 char *buf; 1102 int bufsz = 3 * recsize; 1103 1104 if ((buf = (char *)malloc(bufsz)) == NULL) 1105 FATAL("out of memory in awksprintf"); 1106 y = a[0]->nnext; 1107 x = execute(a[0]); 1108 if (format(&buf, &bufsz, getsval(x), y) == -1) 1109 FATAL("sprintf string %.30s... too long. can't happen.", buf); 1110 tempfree(x); 1111 x = gettemp(); 1112 x->sval = buf; 1113 x->tval = STR; 1114 return (x); 1115 } 1116 1117 /*ARGSUSED*/ 1118 Cell * 1119 awkprintf(Node **a, int n) /* printf */ 1120 { 1121 /* a[0] is list of args, starting with format string */ 1122 /* a[1] is redirection operator, a[2] is redirection file */ 1123 FILE *fp; 1124 Cell *x; 1125 Node *y; 1126 char *buf; 1127 int len; 1128 int bufsz = 3 * recsize; 1129 1130 if ((buf = (char *)malloc(bufsz)) == NULL) 1131 FATAL("out of memory in awkprintf"); 1132 y = a[0]->nnext; 1133 x = execute(a[0]); 1134 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1) 1135 FATAL("printf string %.30s... too long. can't happen.", buf); 1136 tempfree(x); 1137 if (a[1] == NULL) { 1138 (void) fwrite(buf, len, 1, stdout); 1139 if (ferror(stdout)) 1140 FATAL("write error on stdout"); 1141 } else { 1142 fp = redirect(ptoi(a[1]), a[2]); 1143 (void) fwrite(buf, len, 1, fp); 1144 (void) fflush(fp); 1145 if (ferror(fp)) 1146 FATAL("write error on %s", filename(fp)); 1147 } 1148 free(buf); 1149 return (True); 1150 } 1151 1152 Cell * 1153 arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */ 1154 { 1155 Awkfloat i, j = 0; 1156 double v; 1157 Cell *x, *y, *z; 1158 1159 x = execute(a[0]); 1160 i = getfval(x); 1161 tempfree(x); 1162 if (n != UMINUS && n != UPLUS) { 1163 y = execute(a[1]); 1164 j = getfval(y); 1165 tempfree(y); 1166 } 1167 z = gettemp(); 1168 switch (n) { 1169 case ADD: 1170 i += j; 1171 break; 1172 case MINUS: 1173 i -= j; 1174 break; 1175 case MULT: 1176 i *= j; 1177 break; 1178 case DIVIDE: 1179 if (j == 0) 1180 FATAL("division by zero"); 1181 i /= j; 1182 break; 1183 case MOD: 1184 if (j == 0) 1185 FATAL("division by zero in mod"); 1186 (void) modf(i/j, &v); 1187 i = i - j * v; 1188 break; 1189 case UMINUS: 1190 i = -i; 1191 break; 1192 case UPLUS: /* handled by getfval(), above */ 1193 break; 1194 case POWER: 1195 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 1196 i = ipow(i, (int)j); 1197 else 1198 i = errcheck(pow(i, j), "pow"); 1199 break; 1200 default: /* can't happen */ 1201 FATAL("illegal arithmetic operator %d", n); 1202 } 1203 (void) setfval(z, i); 1204 return (z); 1205 } 1206 1207 static double 1208 ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */ 1209 { 1210 double v; 1211 1212 if (n <= 0) 1213 return (1.0); 1214 v = ipow(x, n/2); 1215 if (n % 2 == 0) 1216 return (v * v); 1217 else 1218 return (x * v * v); 1219 } 1220 1221 Cell * 1222 incrdecr(Node **a, int n) /* a[0]++, etc. */ 1223 { 1224 Cell *x, *z; 1225 int k; 1226 Awkfloat xf; 1227 1228 x = execute(a[0]); 1229 xf = getfval(x); 1230 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 1231 if (n == PREINCR || n == PREDECR) { 1232 (void) setfval(x, xf + k); 1233 return (x); 1234 } 1235 z = gettemp(); 1236 (void) setfval(z, xf); 1237 (void) setfval(x, xf + k); 1238 tempfree(x); 1239 return (z); 1240 } 1241 1242 /* a[0] = a[1], a[0] += a[1], etc. */ 1243 /* this is subtle; don't muck with it. */ 1244 Cell * 1245 assign(Node **a, int n) 1246 { 1247 Cell *x, *y; 1248 Awkfloat xf, yf; 1249 double v; 1250 1251 y = execute(a[1]); 1252 x = execute(a[0]); /* order reversed from before... */ 1253 if (n == ASSIGN) { /* ordinary assignment */ 1254 /*LINTED if*/ 1255 if (x == y && !(x->tval & (FLD|REC)) && x != nfloc) { 1256 /* 1257 * If this is a self-assignment, we leave things alone, 1258 * unless it's a field or NF. 1259 */ 1260 } else if ((y->tval & (STR|NUM)) == (STR|NUM)) { 1261 (void) setsval(x, getsval(y)); 1262 x->fval = getfval(y); 1263 x->tval |= NUM; 1264 } else if (isstr(y)) 1265 (void) setsval(x, getsval(y)); 1266 else if (isnum(y)) 1267 (void) setfval(x, getfval(y)); 1268 else 1269 funnyvar(y, "read value of"); 1270 tempfree(y); 1271 return (x); 1272 } 1273 xf = getfval(x); 1274 yf = getfval(y); 1275 switch (n) { 1276 case ADDEQ: 1277 xf += yf; 1278 break; 1279 case SUBEQ: 1280 xf -= yf; 1281 break; 1282 case MULTEQ: 1283 xf *= yf; 1284 break; 1285 case DIVEQ: 1286 if (yf == 0) 1287 FATAL("division by zero in /="); 1288 xf /= yf; 1289 break; 1290 case MODEQ: 1291 if (yf == 0) 1292 FATAL("division by zero in %%="); 1293 (void) modf(xf/yf, &v); 1294 xf = xf - yf * v; 1295 break; 1296 case POWEQ: 1297 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 1298 xf = ipow(xf, (int)yf); 1299 else 1300 xf = errcheck(pow(xf, yf), "pow"); 1301 break; 1302 default: 1303 FATAL("illegal assignment operator %d", n); 1304 break; 1305 } 1306 tempfree(y); 1307 (void) setfval(x, xf); 1308 return (x); 1309 } 1310 1311 /*ARGSUSED*/ 1312 Cell * 1313 cat(Node **a, int q) /* a[0] cat a[1] */ 1314 { 1315 Cell *x, *y, *z; 1316 int n1, n2; 1317 char *s = NULL; 1318 size_t ssz = 0; 1319 1320 x = execute(a[0]); 1321 n1 = strlen(getsval(x)); 1322 (void) adjbuf(&s, &ssz, n1 + 1, recsize, 0, "cat1"); 1323 (void) strncpy(s, x->sval, ssz); 1324 1325 y = execute(a[1]); 1326 n2 = strlen(getsval(y)); 1327 (void) adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2"); 1328 (void) strncpy(s + n1, y->sval, ssz - n1); 1329 1330 tempfree(x); 1331 tempfree(y); 1332 1333 z = gettemp(); 1334 z->sval = s; 1335 z->tval = STR; 1336 1337 return (z); 1338 } 1339 1340 /*ARGSUSED*/ 1341 Cell * 1342 pastat(Node **a, int n) /* a[0] { a[1] } */ 1343 { 1344 Cell *x; 1345 1346 if (a[0] == NULL) 1347 x = execute(a[1]); 1348 else { 1349 x = execute(a[0]); 1350 if (istrue(x)) { 1351 tempfree(x); 1352 x = execute(a[1]); 1353 } 1354 } 1355 return (x); 1356 } 1357 1358 /*ARGSUSED*/ 1359 Cell * 1360 dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */ 1361 { 1362 Cell *x; 1363 int pair; 1364 1365 if (!pairstack) { 1366 /* first time */ 1367 dprintf(("paircnt: %d\n", paircnt)); 1368 pairstack = (int *)calloc(paircnt, sizeof (int)); 1369 if (pairstack == NULL) 1370 FATAL("out of space in dopa2"); 1371 } 1372 1373 pair = ptoi(a[3]); 1374 if (pairstack[pair] == 0) { 1375 x = execute(a[0]); 1376 if (istrue(x)) 1377 pairstack[pair] = 1; 1378 tempfree(x); 1379 } 1380 if (pairstack[pair] == 1) { 1381 x = execute(a[1]); 1382 if (istrue(x)) 1383 pairstack[pair] = 0; 1384 tempfree(x); 1385 x = execute(a[2]); 1386 return (x); 1387 } 1388 return (False); 1389 } 1390 1391 /*ARGSUSED*/ 1392 Cell * 1393 split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */ 1394 { 1395 Cell *x = NULL, *y, *ap; 1396 char *s, *origs; 1397 char *fs, *origfs = NULL; 1398 int sep; 1399 char *t, temp, num[50]; 1400 int n, tempstat, arg3type; 1401 1402 y = execute(a[0]); /* source string */ 1403 origs = s = tostring(getsval(y)); 1404 arg3type = ptoi(a[3]); 1405 if (a[2] == NULL) /* fs string */ 1406 fs = getsval(fsloc); 1407 else if (arg3type == STRING) { /* split(str,arr,"string") */ 1408 x = execute(a[2]); 1409 origfs = fs = tostring(getsval(x)); 1410 tempfree(x); 1411 } else if (arg3type == REGEXPR) 1412 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */ 1413 else 1414 FATAL("illegal type of split"); 1415 sep = *fs; 1416 ap = execute(a[1]); /* array name */ 1417 freesymtab(ap); 1418 dprintf(("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs)); 1419 ap->tval &= ~STR; 1420 ap->tval |= ARR; 1421 ap->sval = (char *)makesymtab(NSYMTAB); 1422 1423 n = 0; 1424 if (arg3type == REGEXPR && strlen((char *)((fa*)a[2])->restr) == 0) { 1425 /* 1426 * split(s, a, //); have to arrange things such that it looks 1427 * like an empty separator. 1428 */ 1429 arg3type = 0; 1430 fs = ""; 1431 sep = 0; 1432 } 1433 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { 1434 /* reg expr */ 1435 fa *pfa; 1436 if (arg3type == REGEXPR) { /* it's ready already */ 1437 pfa = (fa *)a[2]; 1438 } else { 1439 pfa = makedfa(fs, 1); 1440 } 1441 if (nematch(pfa, s)) { 1442 tempstat = pfa->initstat; 1443 pfa->initstat = 2; 1444 do { 1445 n++; 1446 (void) sprintf(num, "%d", n); 1447 temp = *patbeg; 1448 *patbeg = '\0'; 1449 if (is_number(s)) { 1450 (void) setsymtab(num, s, 1451 atof(s), 1452 /*LINTED align*/ 1453 STR|NUM, (Array *)ap->sval); 1454 } else { 1455 (void) setsymtab(num, s, 0.0, 1456 /*LINTED align*/ 1457 STR, (Array *)ap->sval); 1458 } 1459 *patbeg = temp; 1460 s = patbeg + patlen; 1461 if (*(patbeg+patlen-1) == 0 || *s == 0) { 1462 n++; 1463 (void) sprintf(num, "%d", n); 1464 (void) setsymtab(num, "", 0.0, 1465 /*LINTED align*/ 1466 STR, (Array *)ap->sval); 1467 pfa->initstat = tempstat; 1468 goto spdone; 1469 } 1470 } while (nematch(pfa, s)); 1471 /* bwk: has to be here to reset */ 1472 /* cf gsub and refldbld */ 1473 pfa->initstat = tempstat; 1474 } 1475 n++; 1476 (void) sprintf(num, "%d", n); 1477 if (is_number(s)) { 1478 (void) setsymtab(num, s, atof(s), 1479 /*LINTED align*/ 1480 STR|NUM, (Array *)ap->sval); 1481 } else { 1482 /*LINTED align*/ 1483 (void) setsymtab(num, s, 0.0, STR, (Array *)ap->sval); 1484 } 1485 spdone: 1486 pfa = NULL; 1487 } else if (sep == ' ') { 1488 for (n = 0; ; ) { 1489 while (*s == ' ' || *s == '\t' || *s == '\n') 1490 s++; 1491 if (*s == '\0') 1492 break; 1493 n++; 1494 t = s; 1495 do 1496 s++; 1497 while (*s != ' ' && *s != '\t' && 1498 *s != '\n' && *s != '\0') 1499 ; 1500 temp = *s; 1501 *s = '\0'; 1502 (void) sprintf(num, "%d", n); 1503 if (is_number(t)) { 1504 (void) setsymtab(num, t, atof(t), 1505 /*LINTED align*/ 1506 STR|NUM, (Array *)ap->sval); 1507 } else { 1508 (void) setsymtab(num, t, 0.0, 1509 /*LINTED align*/ 1510 STR, (Array *)ap->sval); 1511 } 1512 *s = temp; 1513 if (*s != '\0') 1514 s++; 1515 } 1516 } else if (sep == '\0') { /* split(s, a, "") => 1 char/elem */ 1517 for (n = 0; *s != 0; s++) { 1518 char buf[2]; 1519 n++; 1520 (void) sprintf(num, "%d", n); 1521 buf[0] = *s; 1522 buf[1] = '\0'; 1523 if (isdigit((uschar)buf[0])) { 1524 (void) setsymtab(num, buf, atof(buf), 1525 /*LINTED align*/ 1526 STR|NUM, (Array *)ap->sval); 1527 } else { 1528 (void) setsymtab(num, buf, 0.0, 1529 /*LINTED align*/ 1530 STR, (Array *)ap->sval); 1531 } 1532 } 1533 } else if (*s != '\0') { 1534 for (;;) { 1535 n++; 1536 t = s; 1537 while (*s != sep && *s != '\n' && *s != '\0') 1538 s++; 1539 temp = *s; 1540 *s = '\0'; 1541 (void) sprintf(num, "%d", n); 1542 if (is_number(t)) { 1543 (void) setsymtab(num, t, atof(t), 1544 /*LINTED align*/ 1545 STR|NUM, (Array *)ap->sval); 1546 } else { 1547 (void) setsymtab(num, t, 0.0, 1548 /*LINTED align*/ 1549 STR, (Array *)ap->sval); 1550 } 1551 *s = temp; 1552 if (*s++ == '\0') 1553 break; 1554 } 1555 } 1556 tempfree(ap); 1557 tempfree(y); 1558 free(origs); 1559 free(origfs); 1560 x = gettemp(); 1561 x->tval = NUM; 1562 x->fval = n; 1563 return (x); 1564 } 1565 1566 /*ARGSUSED*/ 1567 Cell * 1568 condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */ 1569 { 1570 Cell *x; 1571 1572 x = execute(a[0]); 1573 if (istrue(x)) { 1574 tempfree(x); 1575 x = execute(a[1]); 1576 } else { 1577 tempfree(x); 1578 x = execute(a[2]); 1579 } 1580 return (x); 1581 } 1582 1583 /*ARGSUSED*/ 1584 Cell * 1585 ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */ 1586 { 1587 Cell *x; 1588 1589 x = execute(a[0]); 1590 if (istrue(x)) { 1591 tempfree(x); 1592 x = execute(a[1]); 1593 } else if (a[2] != NULL) { 1594 tempfree(x); 1595 x = execute(a[2]); 1596 } 1597 return (x); 1598 } 1599 1600 /*ARGSUSED*/ 1601 Cell * 1602 whilestat(Node **a, int n) /* while (a[0]) a[1] */ 1603 { 1604 Cell *x; 1605 1606 for (;;) { 1607 x = execute(a[0]); 1608 if (!istrue(x)) 1609 return (x); 1610 tempfree(x); 1611 x = execute(a[1]); 1612 if (isbreak(x)) { 1613 x = True; 1614 return (x); 1615 } 1616 if (isnext(x) || isexit(x) || isret(x)) 1617 return (x); 1618 tempfree(x); 1619 } 1620 } 1621 1622 /*ARGSUSED*/ 1623 Cell * 1624 dostat(Node **a, int n) /* do a[0]; while(a[1]) */ 1625 { 1626 Cell *x; 1627 1628 for (;;) { 1629 x = execute(a[0]); 1630 if (isbreak(x)) 1631 return (True); 1632 if (isnext(x) || isexit(x) || isret(x)) 1633 return (x); 1634 tempfree(x); 1635 x = execute(a[1]); 1636 if (!istrue(x)) 1637 return (x); 1638 tempfree(x); 1639 } 1640 } 1641 1642 /*ARGSUSED*/ 1643 Cell * 1644 forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */ 1645 { 1646 Cell *x; 1647 1648 x = execute(a[0]); 1649 tempfree(x); 1650 for (;;) { 1651 if (a[1] != NULL) { 1652 x = execute(a[1]); 1653 if (!istrue(x)) 1654 return (x); 1655 else 1656 tempfree(x); 1657 } 1658 x = execute(a[3]); 1659 if (isbreak(x)) /* turn off break */ 1660 return (True); 1661 if (isnext(x) || isexit(x) || isret(x)) 1662 return (x); 1663 tempfree(x); 1664 x = execute(a[2]); 1665 tempfree(x); 1666 } 1667 } 1668 1669 /*ARGSUSED*/ 1670 Cell * 1671 instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */ 1672 { 1673 Cell *x, *vp, *arrayp, *cp, *ncp; 1674 Array *tp; 1675 int i; 1676 1677 vp = execute(a[0]); 1678 arrayp = execute(a[1]); 1679 if (!isarr(arrayp)) { 1680 dprintf(("making %s into an array\n", arrayp->nval)); 1681 if (freeable(arrayp)) 1682 xfree(arrayp->sval); 1683 arrayp->tval &= ~(STR|NUM|DONTFREE); 1684 arrayp->tval |= ARR; 1685 arrayp->sval = (char *)makesymtab(NSYMTAB); 1686 } 1687 /*LINTED align*/ 1688 tp = (Array *)arrayp->sval; 1689 tempfree(arrayp); 1690 for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 1691 for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 1692 (void) setsval(vp, cp->nval); 1693 ncp = cp->cnext; 1694 x = execute(a[2]); 1695 if (isbreak(x)) { 1696 tempfree(vp); 1697 return (True); 1698 } 1699 if (isnext(x) || isexit(x) || isret(x)) { 1700 tempfree(vp); 1701 return (x); 1702 } 1703 tempfree(x); 1704 } 1705 } 1706 return (True); 1707 } 1708 1709 /*ARGSUSED*/ 1710 Cell * 1711 bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */ 1712 { 1713 Cell *x, *y; 1714 Awkfloat u; 1715 int t; 1716 Awkfloat tmp; 1717 char *p, *buf; 1718 Node *nextarg; 1719 FILE *fp; 1720 void flush_all(void); 1721 int status = 0; 1722 1723 t = ptoi(a[0]); 1724 x = execute(a[1]); 1725 nextarg = a[1]->nnext; 1726 switch (t) { 1727 case FLENGTH: 1728 if (isarr(x)) { 1729 /* LINTED align */ 1730 u = ((Array *)x->sval)->nelem; 1731 } else { 1732 u = strlen(getsval(x)); 1733 } 1734 break; 1735 case FLOG: 1736 u = errcheck(log(getfval(x)), "log"); break; 1737 case FINT: 1738 (void) modf(getfval(x), &u); break; 1739 case FEXP: 1740 u = errcheck(exp(getfval(x)), "exp"); break; 1741 case FSQRT: 1742 u = errcheck(sqrt(getfval(x)), "sqrt"); break; 1743 case FSIN: 1744 u = sin(getfval(x)); break; 1745 case FCOS: 1746 u = cos(getfval(x)); break; 1747 case FATAN: 1748 if (nextarg == NULL) { 1749 WARNING("atan2 requires two arguments; returning 1.0"); 1750 u = 1.0; 1751 } else { 1752 y = execute(a[1]->nnext); 1753 u = atan2(getfval(x), getfval(y)); 1754 tempfree(y); 1755 nextarg = nextarg->nnext; 1756 } 1757 break; 1758 case FSYSTEM: 1759 /* in case something is buffered already */ 1760 (void) fflush(stdout); 1761 status = system(getsval(x)); 1762 u = status; 1763 if (status != -1) { 1764 if (WIFEXITED(status)) { 1765 u = WEXITSTATUS(status); 1766 } else if (WIFSIGNALED(status)) { 1767 u = WTERMSIG(status) + 256; 1768 if (WCOREDUMP(status)) 1769 u += 256; 1770 } else /* something else?!? */ 1771 u = 0; 1772 } 1773 break; 1774 case FRAND: 1775 /* in principle, rand() returns something in 0..RAND_MAX */ 1776 u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX; 1777 break; 1778 case FSRAND: 1779 if (isrec(x)) /* no argument provided */ 1780 u = time((time_t *)0); 1781 else 1782 u = getfval(x); 1783 tmp = u; 1784 srand((unsigned int) u); 1785 u = srand_seed; 1786 srand_seed = tmp; 1787 break; 1788 case FTOUPPER: 1789 case FTOLOWER: 1790 buf = tostring(getsval(x)); 1791 if (t == FTOUPPER) { 1792 for (p = buf; *p; p++) 1793 if (islower((uschar)*p)) 1794 *p = toupper((uschar)*p); 1795 } else { 1796 for (p = buf; *p; p++) 1797 if (isupper((uschar)*p)) 1798 *p = tolower((uschar)*p); 1799 } 1800 tempfree(x); 1801 x = gettemp(); 1802 (void) setsval(x, buf); 1803 free(buf); 1804 return (x); 1805 case FFLUSH: 1806 if (isrec(x) || strlen(getsval(x)) == 0) { 1807 flush_all(); /* fflush() or fflush("") -> all */ 1808 u = 0; 1809 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL) 1810 u = EOF; 1811 else 1812 u = fflush(fp); 1813 break; 1814 default: /* can't happen */ 1815 FATAL("illegal function type %d", t); 1816 break; 1817 } 1818 tempfree(x); 1819 x = gettemp(); 1820 (void) setfval(x, u); 1821 if (nextarg != NULL) { 1822 WARNING("warning: function has too many arguments"); 1823 for (; nextarg != NULL; nextarg = nextarg->nnext) 1824 (void) execute(nextarg); 1825 } 1826 return (x); 1827 } 1828 1829 /*ARGSUSED*/ 1830 Cell * 1831 printstat(Node **a, int n) /* print a[0] */ 1832 { 1833 Node *x; 1834 Cell *y; 1835 FILE *fp; 1836 1837 if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */ 1838 fp = stdout; 1839 else 1840 fp = redirect(ptoi(a[1]), a[2]); 1841 for (x = a[0]; x != NULL; x = x->nnext) { 1842 y = execute(x); 1843 (void) fputs(getpssval(y), fp); 1844 tempfree(y); 1845 if (x->nnext == NULL) 1846 (void) fputs(getsval(orsloc), fp); 1847 else 1848 (void) fputs(getsval(ofsloc), fp); 1849 } 1850 if (a[1] != NULL) 1851 (void) fflush(fp); 1852 if (ferror(fp)) 1853 FATAL("write error on %s", filename(fp)); 1854 return (True); 1855 } 1856 1857 /*ARGSUSED*/ 1858 Cell * 1859 nullproc(Node **a, int n) 1860 { 1861 return (0); 1862 } 1863 1864 1865 static FILE * 1866 redirect(int a, Node *b) /* set up all i/o redirections */ 1867 { 1868 FILE *fp; 1869 Cell *x; 1870 char *fname; 1871 1872 x = execute(b); 1873 fname = getsval(x); 1874 fp = openfile(a, fname); 1875 if (fp == NULL) 1876 FATAL("can't open file %s", fname); 1877 tempfree(x); 1878 return (fp); 1879 } 1880 1881 struct files { 1882 FILE *fp; 1883 const char *fname; 1884 int mode; /* '|', 'a', 'w' => LE/LT, GT */ 1885 } *files; 1886 1887 int nfiles; 1888 1889 void 1890 stdinit(void) /* in case stdin, etc., are not constants */ 1891 { 1892 nfiles = FOPEN_MAX; 1893 files = calloc(nfiles, sizeof (*files)); 1894 if (files == NULL) 1895 FATAL("can't allocate file memory for %u files", nfiles); 1896 files[0].fp = stdin; 1897 files[0].fname = "/dev/stdin"; 1898 files[0].mode = LT; 1899 files[1].fp = stdout; 1900 files[1].fname = "/dev/stdout"; 1901 files[1].mode = GT; 1902 files[2].fp = stderr; 1903 files[2].fname = "/dev/stderr"; 1904 files[2].mode = GT; 1905 } 1906 1907 static FILE * 1908 openfile(int a, const char *s) 1909 { 1910 int i, m; 1911 FILE *fp = NULL; 1912 1913 if (*s == '\0') 1914 FATAL("null file name in print or getline"); 1915 for (i = 0; i < nfiles; i++) { 1916 if (files[i].fname && strcmp(s, files[i].fname) == 0) { 1917 if (a == files[i].mode || 1918 (a == APPEND && files[i].mode == GT)) { 1919 return (files[i].fp); 1920 } 1921 if (a == FFLUSH) 1922 return (files[i].fp); 1923 } 1924 } 1925 if (a == FFLUSH) /* didn't find it, so don't create it! */ 1926 return (NULL); 1927 1928 for (i = 0; i < nfiles; i++) { 1929 if (files[i].fp == 0) 1930 break; 1931 } 1932 if (i >= nfiles) { 1933 struct files *nf; 1934 int nnf = nfiles + FOPEN_MAX; 1935 nf = realloc(files, nnf * sizeof (*nf)); 1936 if (nf == NULL) 1937 FATAL("cannot grow files for %s and %d files", s, nnf); 1938 (void) memset(&nf[nfiles], 0, FOPEN_MAX * sizeof (*nf)); 1939 nfiles = nnf; 1940 files = nf; 1941 } 1942 (void) fflush(stdout); /* force a semblance of order */ 1943 m = a; 1944 if (a == GT) { 1945 fp = fopen(s, "wF"); 1946 } else if (a == APPEND) { 1947 fp = fopen(s, "aF"); 1948 m = GT; /* so can mix > and >> */ 1949 } else if (a == '|') { /* output pipe */ 1950 fp = popen(s, "wF"); 1951 } else if (a == LE) { /* input pipe */ 1952 fp = popen(s, "rF"); 1953 } else if (a == LT) { /* getline <file */ 1954 fp = strcmp(s, "-") == 0 ? 1955 stdin : fopen(s, "rF"); /* "-" is stdin */ 1956 } else /* can't happen */ 1957 FATAL("illegal redirection %d", a); 1958 if (fp != NULL) { 1959 files[i].fname = tostring(s); 1960 files[i].fp = fp; 1961 files[i].mode = m; 1962 } 1963 return (fp); 1964 } 1965 1966 const char * 1967 filename(FILE *fp) 1968 { 1969 int i; 1970 1971 for (i = 0; i < nfiles; i++) 1972 if (fp == files[i].fp) 1973 return (files[i].fname); 1974 return ("???"); 1975 } 1976 1977 /*ARGSUSED*/ 1978 Cell * 1979 closefile(Node **a, int n) 1980 { 1981 Cell *x; 1982 int i, stat; 1983 1984 x = execute(a[0]); 1985 (void) getsval(x); 1986 stat = -1; 1987 for (i = 0; i < nfiles; i++) { 1988 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 1989 if (ferror(files[i].fp)) { 1990 WARNING("i/o error occurred on %s", 1991 files[i].fname); 1992 } 1993 if (files[i].mode == '|' || files[i].mode == LE) 1994 stat = pclose(files[i].fp); 1995 else 1996 stat = fclose(files[i].fp); 1997 if (stat == EOF) { 1998 WARNING("i/o error occurred closing %s", 1999 files[i].fname); 2000 } 2001 if (i > 2) /* don't do /dev/std... */ 2002 xfree(files[i].fname); 2003 /* watch out for ref thru this */ 2004 files[i].fname = NULL; 2005 files[i].fp = NULL; 2006 } 2007 } 2008 tempfree(x); 2009 x = gettemp(); 2010 (void) setfval(x, (Awkfloat) stat); 2011 return (x); 2012 } 2013 2014 static void 2015 closeall(void) 2016 { 2017 int i, stat; 2018 2019 for (i = 0; i < nfiles; i++) { 2020 if (files[i].fp) { 2021 if (ferror(files[i].fp)) { 2022 WARNING("i/o error occurred on %s", 2023 files[i].fname); 2024 } 2025 if (files[i].mode == '|' || files[i].mode == LE) 2026 stat = pclose(files[i].fp); 2027 else 2028 stat = fclose(files[i].fp); 2029 if (stat == EOF) { 2030 WARNING("i/o error occurred while closing %s", 2031 files[i].fname); 2032 } 2033 } 2034 } 2035 } 2036 2037 void 2038 flush_all(void) 2039 { 2040 int i; 2041 2042 for (i = 0; i < nfiles; i++) 2043 if (files[i].fp) 2044 (void) fflush(files[i].fp); 2045 } 2046 2047 /*ARGSUSED*/ 2048 Cell * 2049 sub(Node **a, int nnn) /* substitute command */ 2050 { 2051 char *sptr, *pb, *q; 2052 Cell *x, *y, *result; 2053 char *t, *buf; 2054 fa *pfa; 2055 size_t bufsz = recsize; 2056 2057 if ((buf = (char *)malloc(bufsz)) == NULL) 2058 FATAL("out of memory in sub"); 2059 x = execute(a[3]); /* target string */ 2060 t = getsval(x); 2061 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ 2062 pfa = (fa *)a[1]; /* regular expression */ 2063 else { 2064 y = execute(a[1]); 2065 pfa = makedfa(getsval(y), 1); 2066 tempfree(y); 2067 } 2068 y = execute(a[2]); /* replacement string */ 2069 result = False; 2070 if (pmatch(pfa, t)) { 2071 sptr = t; 2072 (void) adjbuf(&buf, &bufsz, 2073 1 + patbeg - sptr, recsize, 0, "sub"); 2074 pb = buf; 2075 while (sptr < patbeg) 2076 *pb++ = *sptr++; 2077 sptr = getsval(y); 2078 while (*sptr != '\0') { 2079 (void) adjbuf(&buf, &bufsz, 5 + pb - buf, 2080 recsize, &pb, "sub"); 2081 if (*sptr == '\\') { 2082 backsub(&pb, &sptr); 2083 } else if (*sptr == '&') { 2084 sptr++; 2085 (void) adjbuf(&buf, &bufsz, 2086 1 + patlen + pb - buf, recsize, &pb, "sub"); 2087 for (q = patbeg; q < patbeg+patlen; ) 2088 *pb++ = *q++; 2089 } else { 2090 *pb++ = *sptr++; 2091 } 2092 } 2093 *pb = '\0'; 2094 if (pb > buf + bufsz) 2095 FATAL("sub result1 %.30s too big; can't happen", buf); 2096 sptr = patbeg + patlen; 2097 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 2098 (void) adjbuf(&buf, &bufsz, 2099 1 + strlen(sptr) + pb - buf, 0, &pb, "sub"); 2100 while ((*pb++ = *sptr++) != '\0') 2101 ; 2102 } 2103 if (pb > buf + bufsz) 2104 FATAL("sub result2 %.30s too big; can't happen", buf); 2105 (void) setsval(x, buf); /* BUG: should be able to avoid copy */ 2106 result = True; 2107 } 2108 tempfree(x); 2109 tempfree(y); 2110 free(buf); 2111 return (result); 2112 } 2113 2114 /*ARGSUSED*/ 2115 Cell * 2116 gsub(Node **a, int nnn) /* global substitute */ 2117 { 2118 Cell *x, *y; 2119 char *rptr, *sptr, *t, *pb, *q; 2120 char *buf; 2121 fa *pfa; 2122 int mflag, tempstat, num; 2123 size_t bufsz = recsize; 2124 2125 if ((buf = (char *)malloc(bufsz)) == NULL) 2126 FATAL("out of memory in gsub"); 2127 mflag = 0; /* if mflag == 0, can replace empty string */ 2128 num = 0; 2129 x = execute(a[3]); /* target string */ 2130 t = getsval(x); 2131 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */ 2132 pfa = (fa *)a[1]; /* regular expression */ 2133 else { 2134 y = execute(a[1]); 2135 pfa = makedfa(getsval(y), 1); 2136 tempfree(y); 2137 } 2138 y = execute(a[2]); /* replacement string */ 2139 if (pmatch(pfa, t)) { 2140 tempstat = pfa->initstat; 2141 pfa->initstat = 2; 2142 pb = buf; 2143 rptr = getsval(y); 2144 do { 2145 if (patlen == 0 && *patbeg != '\0') { 2146 /* matched empty string */ 2147 if (mflag == 0) { /* can replace empty */ 2148 num++; 2149 sptr = rptr; 2150 while (*sptr != '\0') { 2151 (void) adjbuf(&buf, &bufsz, 2152 5 + pb - buf, recsize, 2153 &pb, "gsub"); 2154 if (*sptr == '\\') { 2155 backsub(&pb, &sptr); 2156 } else if (*sptr == '&') { 2157 sptr++; 2158 (void) adjbuf(&buf, 2159 &bufsz, 2160 1+patlen+pb-buf, 2161 recsize, 2162 &pb, "gsub"); 2163 for ( 2164 q = patbeg; 2165 q < patbeg+patlen; 2166 *pb++ = *q++) 2167 ; 2168 } else { 2169 *pb++ = *sptr++; 2170 } 2171 } 2172 } 2173 if (*t == '\0') /* at end */ 2174 goto done; 2175 (void) adjbuf(&buf, &bufsz, 2176 2 + pb - buf, recsize, &pb, "gsub"); 2177 *pb++ = *t++; 2178 /* BUG: not sure of this test */ 2179 if (pb > buf + bufsz) 2180 FATAL("gsub result0 %.30s too big; " 2181 "can't happen", buf); 2182 mflag = 0; 2183 } else { /* matched nonempty string */ 2184 num++; 2185 sptr = t; 2186 (void) adjbuf(&buf, &bufsz, 2187 1 + (patbeg - sptr) + pb - buf, 2188 recsize, &pb, "gsub"); 2189 while (sptr < patbeg) 2190 *pb++ = *sptr++; 2191 sptr = rptr; 2192 while (*sptr != '\0') { 2193 (void) adjbuf(&buf, &bufsz, 2194 5 + pb - buf, recsize, &pb, "gsub"); 2195 if (*sptr == '\\') { 2196 backsub(&pb, &sptr); 2197 } else if (*sptr == '&') { 2198 sptr++; 2199 (void) adjbuf(&buf, &bufsz, 2200 1 + patlen + pb - buf, 2201 recsize, &pb, "gsub"); 2202 for ( 2203 q = patbeg; 2204 q < patbeg+patlen; 2205 *pb++ = *q++) 2206 ; 2207 } else { 2208 *pb++ = *sptr++; 2209 } 2210 } 2211 t = patbeg + patlen; 2212 if (patlen == 0 || *(t-1) == '\0' || *t == '\0') 2213 goto done; 2214 if (pb > buf + bufsz) 2215 FATAL("gsub result1 %.30s too big; " 2216 "can't happen", buf); 2217 mflag = 1; 2218 } 2219 } while (pmatch(pfa, t)); 2220 sptr = t; 2221 (void) adjbuf(&buf, &bufsz, 2222 1 + strlen(sptr) + pb - buf, 0, &pb, "gsub"); 2223 while ((*pb++ = *sptr++) != '\0') 2224 ; 2225 done: 2226 if (pb < buf + bufsz) 2227 *pb = '\0'; 2228 else if (*(pb-1) != '\0') 2229 FATAL("gsub result2 %.30s truncated; " 2230 "can't happen", buf); 2231 /* BUG: should be able to avoid copy + free */ 2232 (void) setsval(x, buf); 2233 pfa->initstat = tempstat; 2234 } 2235 tempfree(x); 2236 tempfree(y); 2237 x = gettemp(); 2238 x->tval = NUM; 2239 x->fval = num; 2240 free(buf); 2241 return (x); 2242 } 2243 2244 /* 2245 * handle \\& variations; sptr[0] == '\\' 2246 */ 2247 static void 2248 backsub(char **pb_ptr, char **sptr_ptr) 2249 { 2250 char *pb = *pb_ptr, *sptr = *sptr_ptr; 2251 2252 if (sptr[1] == '\\') { 2253 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */ 2254 *pb++ = '\\'; 2255 *pb++ = '&'; 2256 sptr += 4; 2257 } else if (sptr[2] == '&') { /* \\& -> \ + matched */ 2258 *pb++ = '\\'; 2259 sptr += 2; 2260 } else { /* \\x -> \\x */ 2261 *pb++ = *sptr++; 2262 *pb++ = *sptr++; 2263 } 2264 } else if (sptr[1] == '&') { /* literal & */ 2265 sptr++; 2266 *pb++ = *sptr++; 2267 } else /* literal \ */ 2268 *pb++ = *sptr++; 2269 2270 *pb_ptr = pb; 2271 *sptr_ptr = sptr; 2272 } 2273