1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 2.13 */ 32 33 #define tempfree(x,s) if (istemp(x)) tfree(x,s); else 34 35 /* #define execute(p) (isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */ 36 #define execute(p) r_execute(p) 37 38 #define DEBUG 39 #include "awk.h" 40 #include <math.h> 41 #include "y.tab.h" 42 #include <stdio.h> 43 #include <ctype.h> 44 #include <setjmp.h> 45 #include <time.h> 46 47 #ifndef FOPEN_MAX 48 #define FOPEN_MAX 15 /* max number of open files, from ANSI std. */ 49 #endif 50 51 52 jmp_buf env; 53 54 #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p)) 55 #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p)) 56 57 extern Awkfloat r_getfval(); 58 extern uchar *r_getsval(); 59 extern Cell *r_execute(), *fieldel(), *dopa2(), *gettemp(), *copycell(); 60 extern FILE *openfile(), *redirect(); 61 extern double errcheck(); 62 63 int paircnt; 64 Node *winner = NULL; 65 Cell *tmps; 66 67 static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM }; 68 Cell *true = &truecell; 69 static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM }; 70 Cell *false = &falsecell; 71 static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM }; 72 Cell *jbreak = &breakcell; 73 static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM }; 74 Cell *jcont = &contcell; 75 static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM }; 76 Cell *jnext = &nextcell; 77 static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM }; 78 Cell *jexit = &exitcell; 79 static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM }; 80 Cell *jret = &retcell; 81 static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM }; 82 83 Node *curnode = NULL; /* the node being executed, for debugging */ 84 85 run(a) Node *a; 86 { 87 execute(a); 88 closeall(); 89 } 90 91 Cell *r_execute(u) Node *u; 92 { 93 register Cell *(*proc)(); 94 register Cell *x; 95 register Node *a; 96 97 if (u == NULL) 98 return(true); 99 for (a = u; ; a = a->nnext) { 100 curnode = a; 101 if (isvalue(a)) { 102 x = (Cell *) (a->narg[0]); 103 if ((x->tval & FLD) && !donefld) 104 fldbld(); 105 else if ((x->tval & REC) && !donerec) 106 recbld(); 107 return(x); 108 } 109 if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */ 110 ERROR "illegal statement" FATAL; 111 proc = proctab[a->nobj-FIRSTTOKEN]; 112 x = (*proc)(a->narg, a->nobj); 113 if ((x->tval & FLD) && !donefld) 114 fldbld(); 115 else if ((x->tval & REC) && !donerec) 116 recbld(); 117 if (isexpr(a)) 118 return(x); 119 /* a statement, goto next statement */ 120 if (isjump(x)) 121 return(x); 122 if (a->nnext == (Node *)NULL) 123 return(x); 124 tempfree(x, "execute"); 125 } 126 } 127 128 129 Cell *program(a, n) register Node **a; 130 { 131 register Cell *x; 132 133 if (setjmp(env) != 0) 134 goto ex; 135 if (a[0]) { /* BEGIN */ 136 x = execute(a[0]); 137 if (isexit(x)) 138 return(true); 139 if (isjump(x)) 140 ERROR "illegal break, continue or next from BEGIN" FATAL; 141 tempfree(x, ""); 142 } 143 loop: 144 if (a[1] || a[2]) 145 while (getrec(record) > 0) { 146 x = execute(a[1]); 147 if (isexit(x)) 148 break; 149 tempfree(x, ""); 150 } 151 ex: 152 if (setjmp(env) != 0) 153 goto ex1; 154 if (a[2]) { /* END */ 155 x = execute(a[2]); 156 if (iscont(x)) /* read some more */ 157 goto loop; 158 if (isbreak(x) || isnext(x)) 159 ERROR "illegal break or next from END" FATAL; 160 tempfree(x, ""); 161 } 162 ex1: 163 return(true); 164 } 165 166 struct Frame { 167 int nargs; /* number of arguments in this call */ 168 Cell *fcncell; /* pointer to Cell for function */ 169 Cell **args; /* pointer to array of arguments after execute */ 170 Cell *retval; /* return value */ 171 }; 172 173 #define NARGS 30 174 175 struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ 176 int nframe = 0; /* number of frames allocated */ 177 struct Frame *fp = NULL; /* frame pointer. bottom level unused */ 178 179 Cell *call(a, n) Node **a; 180 { 181 static Cell newcopycell = { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE }; 182 int i, ncall, ndef, freed = 0; 183 Node *x; 184 Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; 185 uchar *s; 186 187 fcn = execute(a[0]); /* the function itself */ 188 s = fcn->nval; 189 if (!isfunc(fcn)) 190 ERROR "calling undefined function %s", s FATAL; 191 if (frame == NULL) { 192 fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame)); 193 if (frame == NULL) 194 ERROR "out of space for stack frames calling %s", s FATAL; 195 } 196 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ 197 ncall++; 198 ndef = (int) fcn->fval; /* args in defn */ 199 dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame) ); 200 if (ncall > ndef) 201 ERROR "function %s called with %d args, uses only %d", 202 s, ncall, ndef WARNING; 203 if (ncall + ndef > NARGS) 204 ERROR "function %s has %d arguments, limit %d", s, ncall+ndef, NARGS FATAL; 205 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */ 206 dprintf( ("evaluate args[%d], fp=%d:\n", i, fp-frame) ); 207 y = execute(x); 208 oargs[i] = y; 209 dprintf( ("args[%d]: %s %f <%s>, t=%o\n", 210 i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval) ); 211 if (isfunc(y)) 212 ERROR "can't use function %s as argument in %s", y->nval, s FATAL; 213 if (isarr(y)) 214 args[i] = y; /* arrays by ref */ 215 else 216 args[i] = copycell(y); 217 tempfree(y, "callargs"); 218 } 219 for ( ; i < ndef; i++) { /* add null args for ones not provided */ 220 args[i] = gettemp("nullargs"); 221 *args[i] = newcopycell; 222 } 223 fp++; /* now ok to up frame */ 224 if (fp >= frame + nframe) { 225 int dfp = fp - frame; /* old index */ 226 frame = (struct Frame *) 227 realloc(frame, (nframe += 100) * sizeof(struct Frame)); 228 if (frame == NULL) 229 ERROR "out of space for stack frames in %s", s FATAL; 230 fp = frame + dfp; 231 } 232 fp->fcncell = fcn; 233 fp->args = args; 234 fp->nargs = ndef; /* number defined with (excess are locals) */ 235 fp->retval = gettemp("retval"); 236 237 dprintf( ("start exec of %s, fp=%d\n", s, fp-frame) ); 238 y = execute((Node *)(fcn->sval)); /* execute body */ 239 dprintf( ("finished exec of %s, fp=%d\n", s, fp-frame) ); 240 241 for (i = 0; i < ndef; i++) { 242 Cell *t = fp->args[i]; 243 if (isarr(t)) { 244 if (t->csub == CCOPY) { 245 if (i >= ncall) { 246 freesymtab(t); 247 t->csub = CTEMP; 248 } else { 249 oargs[i]->tval = t->tval; 250 oargs[i]->tval &= ~(STR|NUM|DONTFREE); 251 oargs[i]->sval = t->sval; 252 tempfree(t, "oargsarr"); 253 } 254 } 255 } else { 256 t->csub = CTEMP; 257 tempfree(t, "fp->args"); 258 if (t == y) freed = 1; 259 } 260 } 261 tempfree(fcn, "call.fcn"); 262 if (isexit(y) || isnext(y)) 263 return y; 264 if (!freed) tempfree(y, "fcn ret"); /* should not free twice! */ 265 z = fp->retval; /* return value */ 266 dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) ); 267 fp--; 268 return(z); 269 } 270 271 Cell *copycell(x) /* make a copy of a cell in a temp */ 272 Cell *x; 273 { 274 Cell *y; 275 276 y = gettemp("copycell"); 277 y->csub = CCOPY; /* prevents freeing until call is over */ 278 y->nval = x->nval; 279 y->sval = x->sval ? tostring(x->sval) : NULL; 280 y->fval = x->fval; 281 y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */ 282 /* is DONTFREE right? */ 283 return y; 284 } 285 286 Cell *arg(a) Node **a; 287 { 288 int n; 289 290 n = (int) a[0]; /* argument number, counting from 0 */ 291 dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) ); 292 if (n+1 > fp->nargs) 293 ERROR "argument #%d of function %s was not supplied", 294 n+1, fp->fcncell->nval FATAL; 295 return fp->args[n]; 296 } 297 298 Cell *jump(a, n) Node **a; 299 { 300 register Cell *y; 301 302 switch (n) { 303 case EXIT: 304 if (a[0] != NULL) { 305 y = execute(a[0]); 306 errorflag = getfval(y); 307 tempfree(y, ""); 308 } 309 longjmp(env, 1); 310 case RETURN: 311 if (a[0] != NULL) { 312 y = execute(a[0]); 313 if ((y->tval & (STR|NUM)) == (STR|NUM)) { 314 setsval(fp->retval, getsval(y)); 315 fp->retval->fval = getfval(y); 316 fp->retval->tval |= NUM; 317 } 318 else if (y->tval & STR) 319 setsval(fp->retval, getsval(y)); 320 else if (y->tval & NUM) 321 setfval(fp->retval, getfval(y)); 322 tempfree(y, ""); 323 } 324 return(jret); 325 case NEXT: 326 return(jnext); 327 case BREAK: 328 return(jbreak); 329 case CONTINUE: 330 return(jcont); 331 default: /* can't happen */ 332 ERROR "illegal jump type %d", n FATAL; 333 } 334 } 335 336 Cell *getline(a, n) Node **a; int n; 337 { 338 /* a[0] is variable, a[1] is operator, a[2] is filename */ 339 register Cell *r, *x; 340 uchar buf[RECSIZE]; 341 FILE *fp; 342 343 fflush(stdout); /* in case someone is waiting for a prompt */ 344 r = gettemp(""); 345 if (a[1] != NULL) { /* getline < file */ 346 x = execute(a[2]); /* filename */ 347 if ((int) a[1] == '|') /* input pipe */ 348 a[1] = (Node *) LE; /* arbitrary flag */ 349 fp = openfile((int) a[1], getsval(x)); 350 tempfree(x, ""); 351 if (fp == NULL) 352 n = -1; 353 else 354 n = readrec(buf, sizeof(buf), fp); 355 if (n <= 0) { 356 ; 357 } else if (a[0] != NULL) { /* getline var <file */ 358 setsval(execute(a[0]), buf); 359 } else { /* getline <file */ 360 if (!(recloc->tval & DONTFREE)) 361 xfree(recloc->sval); 362 strcpy(record, buf); 363 recloc->sval = record; 364 recloc->tval = REC | STR | DONTFREE; 365 donerec = 1; donefld = 0; 366 } 367 } else { /* bare getline; use current input */ 368 if (a[0] == NULL) /* getline */ 369 n = getrec(record); 370 else { /* getline var */ 371 n = getrec(buf); 372 setsval(execute(a[0]), buf); 373 } 374 } 375 setfval(r, (Awkfloat) n); 376 return r; 377 } 378 379 Cell *getnf(a,n) register Node **a; 380 { 381 if (donefld == 0) 382 fldbld(); 383 return (Cell *) a[0]; 384 } 385 386 Cell *array(a,n) register Node **a; 387 { 388 register Cell *x, *y, *z; 389 register uchar *s; 390 register Node *np; 391 uchar buf[RECSIZE]; 392 393 x = execute(a[0]); /* Cell* for symbol table */ 394 buf[0] = 0; 395 for (np = a[1]; np; np = np->nnext) { 396 y = execute(np); /* subscript */ 397 s = getsval(y); 398 strcat(buf, s); 399 if (np->nnext) 400 strcat(buf, *SUBSEP); 401 tempfree(y, ""); 402 } 403 if (!isarr(x)) { 404 dprintf( ("making %s into an array\n", x->nval) ); 405 if (freeable(x)) 406 xfree(x->sval); 407 x->tval &= ~(STR|NUM|DONTFREE); 408 x->tval |= ARR; 409 x->sval = (uchar *) makesymtab(NSYMTAB); 410 } 411 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval); 412 z->ctype = OCELL; 413 z->csub = CVAR; 414 tempfree(x, ""); 415 return(z); 416 } 417 418 Cell *delete(a, n) Node **a; 419 { 420 Cell *x, *y; 421 Node *np; 422 uchar buf[RECSIZE], *s; 423 424 x = execute(a[0]); /* Cell* for symbol table */ 425 if (!isarr(x)) 426 return true; 427 buf[0] = 0; 428 for (np = a[1]; np; np = np->nnext) { 429 y = execute(np); /* subscript */ 430 s = getsval(y); 431 strcat(buf, s); 432 if (np->nnext) 433 strcat(buf, *SUBSEP); 434 tempfree(y, ""); 435 } 436 freeelem(x, buf); 437 tempfree(x, ""); 438 return true; 439 } 440 441 Cell *intest(a, n) Node **a; 442 { 443 register Cell *x, *ap, *k; 444 Node *p; 445 char buf[RECSIZE]; 446 uchar *s; 447 448 ap = execute(a[1]); /* array name */ 449 if (!isarr(ap)) 450 ERROR "%s is not an array", ap->nval FATAL; 451 buf[0] = 0; 452 for (p = a[0]; p; p = p->nnext) { 453 x = execute(p); /* expr */ 454 s = getsval(x); 455 strcat(buf, s); 456 tempfree(x, ""); 457 if (p->nnext) 458 strcat(buf, *SUBSEP); 459 } 460 k = lookup(buf, (Array *) ap->sval); 461 tempfree(ap, ""); 462 if (k == NULL) 463 return(false); 464 else 465 return(true); 466 } 467 468 469 Cell *matchop(a,n) Node **a; 470 { 471 register Cell *x, *y; 472 register uchar *s, *t; 473 register int i; 474 extern int match(), pmatch(); 475 fa *pfa; 476 int (*mf)() = match, mode = 0; 477 478 if (n == MATCHFCN) { 479 mf = pmatch; 480 mode = 1; 481 } 482 x = execute(a[1]); 483 s = getsval(x); 484 if (a[0] == 0) 485 i = (*mf)(a[2], s); 486 else { 487 y = execute(a[2]); 488 t = getsval(y); 489 pfa = makedfa(t, mode); 490 i = (*mf)(pfa, s); 491 tempfree(y, ""); 492 } 493 tempfree(x, ""); 494 if (n == MATCHFCN) { 495 int start = patbeg - s + 1; 496 if (patlen < 0) 497 start = 0; 498 setfval(rstartloc, (Awkfloat) start); 499 setfval(rlengthloc, (Awkfloat) patlen); 500 x = gettemp(""); 501 x->tval = NUM; 502 x->fval = start; 503 return x; 504 } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0) 505 return(true); 506 else 507 return(false); 508 } 509 510 511 Cell *boolop(a,n) Node **a; 512 { 513 register Cell *x, *y; 514 register int i; 515 516 x = execute(a[0]); 517 i = istrue(x); 518 tempfree(x, ""); 519 switch (n) { 520 case BOR: 521 if (i) return(true); 522 y = execute(a[1]); 523 i = istrue(y); 524 tempfree(y, ""); 525 if (i) return(true); 526 else return(false); 527 case AND: 528 if ( !i ) return(false); 529 y = execute(a[1]); 530 i = istrue(y); 531 tempfree(y, ""); 532 if (i) return(true); 533 else return(false); 534 case NOT: 535 if (i) return(false); 536 else return(true); 537 default: /* can't happen */ 538 ERROR "unknown boolean operator %d", n FATAL; 539 } 540 /*NOTREACHED*/ 541 } 542 543 Cell *relop(a,n) Node **a; 544 { 545 register int i; 546 register Cell *x, *y; 547 Awkfloat j; 548 549 x = execute(a[0]); 550 y = execute(a[1]); 551 if (x->tval&NUM && y->tval&NUM) { 552 j = x->fval - y->fval; 553 i = j<0? -1: (j>0? 1: 0); 554 } else { 555 i = strcmp(getsval(x), getsval(y)); 556 } 557 tempfree(x, ""); 558 tempfree(y, ""); 559 switch (n) { 560 case LT: if (i<0) return(true); 561 else return(false); 562 case LE: if (i<=0) return(true); 563 else return(false); 564 case NE: if (i!=0) return(true); 565 else return(false); 566 case EQ: if (i == 0) return(true); 567 else return(false); 568 case GE: if (i>=0) return(true); 569 else return(false); 570 case GT: if (i>0) return(true); 571 else return(false); 572 default: /* can't happen */ 573 ERROR "unknown relational operator %d", n FATAL; 574 } 575 /*NOTREACHED*/ 576 } 577 578 tfree(a, s) register Cell *a; char *s; 579 { 580 if (dbg>1) printf("## tfree %.8s %06o %s\n", s, a, a->sval ? a->sval : (uchar *)""); 581 if (freeable(a)) 582 xfree(a->sval); 583 if (a == tmps) 584 ERROR "tempcell list is curdled" FATAL; 585 a->cnext = tmps; 586 tmps = a; 587 } 588 589 Cell *gettemp(s) char *s; 590 { int i; 591 register Cell *x; 592 593 if (!tmps) { 594 tmps = (Cell *) calloc(100, sizeof(Cell)); 595 if (!tmps) 596 ERROR "no space for temporaries" FATAL; 597 for(i = 1; i < 100; i++) 598 tmps[i-1].cnext = &tmps[i]; 599 tmps[i-1].cnext = 0; 600 } 601 x = tmps; 602 tmps = x->cnext; 603 *x = tempcell; 604 if (dbg>1) printf("## gtemp %.8s %06o\n", s, x); 605 return(x); 606 } 607 608 Cell *indirect(a,n) Node **a; 609 { 610 register Cell *x; 611 register int m; 612 register uchar *s; 613 Cell *fieldadr(); 614 615 x = execute(a[0]); 616 m = getfval(x); 617 if (m == 0 && !isnumber(s = getsval(x))) /* suspicion! */ 618 ERROR "illegal field $(%s)", s FATAL; 619 tempfree(x, ""); 620 x = fieldadr(m); 621 x->ctype = OCELL; 622 x->csub = CFLD; 623 return(x); 624 } 625 626 Cell *substr(a, nnn) Node **a; 627 { 628 register int k, m, n; 629 register uchar *s; 630 int temp; 631 register Cell *x, *y, *z; 632 633 x = execute(a[0]); 634 y = execute(a[1]); 635 if (a[2] != 0) 636 z = execute(a[2]); 637 s = getsval(x); 638 k = strlen(s) + 1; 639 if (k <= 1) { 640 tempfree(x, ""); 641 tempfree(y, ""); 642 if (a[2] != 0) 643 tempfree(z, ""); 644 x = gettemp(""); 645 setsval(x, ""); 646 return(x); 647 } 648 m = getfval(y); 649 if (m <= 0) 650 m = 1; 651 else if (m > k) 652 m = k; 653 tempfree(y, ""); 654 if (a[2] != 0) { 655 n = getfval(z); 656 tempfree(z, ""); 657 } else 658 n = k - 1; 659 if (n < 0) 660 n = 0; 661 else if (n > k - m) 662 n = k - m; 663 dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) ); 664 y = gettemp(""); 665 temp = s[n+m-1]; /* with thanks to John Linderman */ 666 s[n+m-1] = '\0'; 667 setsval(y, s + m - 1); 668 s[n+m-1] = temp; 669 tempfree(x, ""); 670 return(y); 671 } 672 673 Cell *sindex(a, nnn) Node **a; 674 { 675 register Cell *x, *y, *z; 676 register uchar *s1, *s2, *p1, *p2, *q; 677 Awkfloat v = 0.0; 678 679 x = execute(a[0]); 680 s1 = getsval(x); 681 y = execute(a[1]); 682 s2 = getsval(y); 683 684 z = gettemp(""); 685 for (p1 = s1; *p1 != '\0'; p1++) { 686 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) 687 ; 688 if (*p2 == '\0') { 689 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ 690 break; 691 } 692 } 693 tempfree(x, ""); 694 tempfree(y, ""); 695 setfval(z, v); 696 return(z); 697 } 698 699 format(buf, bufsize, s, a) uchar *buf, *s; int bufsize; Node *a; 700 { 701 uchar fmt[RECSIZE]; 702 register uchar *p, *t, *os; 703 register Cell *x; 704 int flag = 0; 705 706 os = s; 707 p = buf; 708 while (*s) { 709 if (p - buf >= bufsize) 710 return -1; 711 if (*s != '%') { 712 *p++ = *s++; 713 continue; 714 } 715 if (*(s+1) == '%') { 716 *p++ = '%'; 717 s += 2; 718 continue; 719 } 720 for (t=fmt; (*t++ = *s) != '\0'; s++) { 721 if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') 722 break; /* the ansi panoply */ 723 if (*s == '*') { 724 if (a == NULL) { 725 ERROR 726 "not enough args in printf(%s) or sprintf(%s)", os, os FATAL; 727 } 728 x = execute(a); 729 a = a->nnext; 730 sprintf((char *)t-1, "%d", (int) getfval(x)); 731 t = fmt + strlen(fmt); 732 tempfree(x, ""); 733 } 734 } 735 *t = '\0'; 736 if (t >= fmt + sizeof(fmt)) 737 ERROR "format item %.20s... too long", os FATAL; 738 switch (*s) { 739 case 'f': case 'e': case 'g': case 'E': case 'G': 740 flag = 1; 741 break; 742 case 'd': case 'i': 743 flag = 2; 744 if(*(s-1) == 'l') break; 745 *(t-1) = 'l'; 746 *t = 'd'; 747 *++t = '\0'; 748 break; 749 case 'o': case 'x': case 'X': case 'u': 750 flag = *(s-1) == 'l' ? 2 : 3; 751 break; 752 case 's': 753 flag = 4; 754 break; 755 case 'c': 756 flag = 5; 757 break; 758 default: 759 flag = 0; 760 break; 761 } 762 if (flag == 0) { 763 sprintf((char *)p, "%s", fmt); 764 p += strlen(p); 765 continue; 766 } 767 if (a == NULL) { 768 ERROR 769 "not enough args in printf(%s) or sprintf(%s)", os, os FATAL; 770 } 771 x = execute(a); 772 a = a->nnext; 773 switch (flag) { 774 case 1: sprintf((char *)p, (char *)fmt, getfval(x)); break; 775 case 2: sprintf((char *)p, (char *)fmt, (long) getfval(x)); break; 776 case 3: sprintf((char *)p, (char *)fmt, (int) getfval(x)); break; 777 case 4: sprintf((char *)p, (char *)fmt, getsval(x)); break; 778 case 5: isnum(x) ? sprintf((char *)p, (char *)fmt, (int) getfval(x)) 779 : sprintf((char *)p, (char *)fmt, getsval(x)[0]); 780 break; 781 } 782 tempfree(x, ""); 783 p += strlen(p); 784 s++; 785 } 786 *p = '\0'; 787 for ( ; a; a = a->nnext) /* evaluate any remaining args */ 788 execute(a); 789 return 0; 790 } 791 792 Cell *asprintf(a,n) Node **a; 793 { 794 register Cell *x; 795 register Node *y; 796 uchar buf[3*RECSIZE]; 797 798 y = a[0]->nnext; 799 x = execute(a[0]); 800 if (format(buf, sizeof buf, getsval(x), y) == -1) 801 ERROR "sprintf string %.40s... too long", buf FATAL; 802 tempfree(x, ""); 803 x = gettemp(""); 804 x->sval = tostring(buf); 805 x->tval = STR; 806 return(x); 807 } 808 809 Cell *aprintf(a,n) Node **a; 810 { 811 FILE *fp; 812 register Cell *x; 813 register Node *y; 814 uchar buf[3*RECSIZE]; 815 816 y = a[0]->nnext; 817 x = execute(a[0]); 818 if (format(buf, sizeof buf, getsval(x), y) == -1) 819 ERROR "printf string %.40s... too long", buf FATAL; 820 tempfree(x, ""); 821 if (a[1] == NULL) 822 fputs((char *)buf, stdout); 823 else { 824 fp = redirect((int)a[1], a[2]); 825 fputs((char *)buf, fp); 826 fflush(fp); 827 } 828 return(true); 829 } 830 831 Cell *arith(a,n) Node **a; 832 { 833 Awkfloat i, j; 834 double v, ipow(); 835 register Cell *x, *y, *z; 836 837 x = execute(a[0]); 838 i = getfval(x); 839 tempfree(x, ""); 840 if (n != UMINUS) { 841 y = execute(a[1]); 842 j = getfval(y); 843 tempfree(y, ""); 844 } 845 z = gettemp(""); 846 switch (n) { 847 case ADD: 848 i += j; 849 break; 850 case MINUS: 851 i -= j; 852 break; 853 case MULT: 854 i *= j; 855 break; 856 case DIVIDE: 857 if (j == 0) 858 ERROR "division by zero" FATAL; 859 i /= j; 860 break; 861 case MOD: 862 if (j == 0) 863 ERROR "division by zero in mod" FATAL; 864 modf(i/j, &v); 865 i = i - j * v; 866 break; 867 case UMINUS: 868 i = -i; 869 break; 870 case POWER: 871 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 872 i = ipow(i, (int) j); 873 else 874 i = errcheck(pow(i, j), "pow"); 875 break; 876 default: /* can't happen */ 877 ERROR "illegal arithmetic operator %d", n FATAL; 878 } 879 setfval(z, i); 880 return(z); 881 } 882 883 double ipow(x, n) 884 double x; 885 int n; 886 { 887 double v; 888 889 if (n <= 0) 890 return 1; 891 v = ipow(x, n/2); 892 if (n % 2 == 0) 893 return v * v; 894 else 895 return x * v * v; 896 } 897 898 Cell *incrdecr(a, n) Node **a; 899 { 900 register Cell *x, *z; 901 register int k; 902 Awkfloat xf; 903 904 x = execute(a[0]); 905 xf = getfval(x); 906 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 907 if (n == PREINCR || n == PREDECR) { 908 setfval(x, xf + k); 909 return(x); 910 } 911 z = gettemp(""); 912 setfval(z, xf); 913 setfval(x, xf + k); 914 tempfree(x, ""); 915 return(z); 916 } 917 918 Cell *assign(a,n) Node **a; 919 { 920 register Cell *x, *y; 921 Awkfloat xf, yf; 922 double v, ipow(); 923 924 y = execute(a[1]); 925 x = execute(a[0]); /* order reversed from before... */ 926 if (n == ASSIGN) { /* ordinary assignment */ 927 if ((y->tval & (STR|NUM)) == (STR|NUM)) { 928 setsval(x, getsval(y)); 929 x->fval = getfval(y); 930 x->tval |= NUM; 931 } 932 else if (y->tval & STR) 933 setsval(x, getsval(y)); 934 else if (y->tval & NUM) 935 setfval(x, getfval(y)); 936 else 937 funnyvar(y, "read value of"); 938 tempfree(y, ""); 939 return(x); 940 } 941 xf = getfval(x); 942 yf = getfval(y); 943 switch (n) { 944 case ADDEQ: 945 xf += yf; 946 break; 947 case SUBEQ: 948 xf -= yf; 949 break; 950 case MULTEQ: 951 xf *= yf; 952 break; 953 case DIVEQ: 954 if (yf == 0) 955 ERROR "division by zero in /=" FATAL; 956 xf /= yf; 957 break; 958 case MODEQ: 959 if (yf == 0) 960 ERROR "division by zero in %%=" FATAL; 961 modf(xf/yf, &v); 962 xf = xf - yf * v; 963 break; 964 case POWEQ: 965 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 966 xf = ipow(xf, (int) yf); 967 else 968 xf = errcheck(pow(xf, yf), "pow"); 969 break; 970 default: 971 ERROR "illegal assignment operator %d", n FATAL; 972 break; 973 } 974 tempfree(y, ""); 975 setfval(x, xf); 976 return(x); 977 } 978 979 Cell *cat(a,q) Node **a; 980 { 981 register Cell *x, *y, *z; 982 register int n1, n2; 983 register uchar *s; 984 985 x = execute(a[0]); 986 y = execute(a[1]); 987 getsval(x); 988 getsval(y); 989 n1 = strlen(x->sval); 990 n2 = strlen(y->sval); 991 s = (uchar *) malloc(n1 + n2 + 1); 992 if (s == NULL) 993 ERROR "out of space concatenating %.15s and %.15s", 994 x->sval, y->sval FATAL; 995 strcpy(s, x->sval); 996 strcpy(s+n1, y->sval); 997 tempfree(y, ""); 998 z = gettemp(""); 999 z->sval = s; 1000 z->tval = STR; 1001 tempfree(x, ""); 1002 return(z); 1003 } 1004 1005 Cell *pastat(a,n) Node **a; 1006 { 1007 register Cell *x; 1008 1009 if (a[0] == 0) 1010 x = execute(a[1]); 1011 else { 1012 x = execute(a[0]); 1013 if (istrue(x)) { 1014 tempfree(x, ""); 1015 x = execute(a[1]); 1016 } 1017 } 1018 return x; 1019 } 1020 1021 Cell *dopa2(a,n) Node **a; 1022 { 1023 Cell *x; 1024 int pair; 1025 static int *pairstack = NULL; 1026 1027 if (!pairstack) { 1028 /* first time */ 1029 dprintf(("paircnt: %d\n", paircnt)); 1030 pairstack = (int *)malloc(sizeof (int) * paircnt); 1031 if (!pairstack) 1032 ERROR "out of space in dopa2" FATAL; 1033 (void) memset(pairstack, 0, sizeof (int) * paircnt); 1034 } 1035 1036 pair = (int) a[3]; 1037 if (pairstack[pair] == 0) { 1038 x = execute(a[0]); 1039 if (istrue(x)) 1040 pairstack[pair] = 1; 1041 tempfree(x, ""); 1042 } 1043 if (pairstack[pair] == 1) { 1044 x = execute(a[1]); 1045 if (istrue(x)) 1046 pairstack[pair] = 0; 1047 tempfree(x, ""); 1048 x = execute(a[2]); 1049 return(x); 1050 } 1051 return(false); 1052 } 1053 1054 Cell *split(a,nnn) Node **a; 1055 { 1056 Cell *x, *y, *ap; 1057 register uchar *s; 1058 register int sep; 1059 uchar *t, temp, num[5], *fs; 1060 int n, tempstat; 1061 1062 y = execute(a[0]); /* source string */ 1063 s = getsval(y); 1064 if (a[2] == 0) /* fs string */ 1065 fs = *FS; 1066 else if ((int) a[3] == STRING) { /* split(str,arr,"string") */ 1067 x = execute(a[2]); 1068 fs = getsval(x); 1069 } else if ((int) a[3] == REGEXPR) 1070 fs = (uchar*) "(regexpr)"; /* split(str,arr,/regexpr/) */ 1071 else 1072 ERROR "illegal type of split()" FATAL; 1073 sep = *fs; 1074 ap = execute(a[1]); /* array name */ 1075 freesymtab(ap); 1076 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) ); 1077 ap->tval &= ~STR; 1078 ap->tval |= ARR; 1079 ap->sval = (uchar *) makesymtab(NSYMTAB); 1080 1081 n = 0; 1082 if (*s != '\0' && strlen(fs) > 1 || (int) a[3] == REGEXPR) { /* reg expr */ 1083 fa *pfa; 1084 if ((int) a[3] == REGEXPR) { /* it's ready already */ 1085 pfa = (fa *) a[2]; 1086 } else { 1087 pfa = makedfa(fs, 1); 1088 } 1089 if (nematch(pfa,s)) { 1090 tempstat = pfa->initstat; 1091 pfa->initstat = 2; 1092 do { 1093 n++; 1094 sprintf((char *)num, "%d", n); 1095 temp = *patbeg; 1096 *patbeg = '\0'; 1097 if (isnumber(s)) 1098 setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); 1099 else 1100 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1101 *patbeg = temp; 1102 s = patbeg + patlen; 1103 if (*(patbeg+patlen-1) == 0 || *s == 0) { 1104 n++; 1105 sprintf((char *)num, "%d", n); 1106 setsymtab(num, "", 0.0, STR, (Array *) ap->sval); 1107 pfa->initstat = tempstat; 1108 goto spdone; 1109 } 1110 } while (nematch(pfa,s)); 1111 } 1112 n++; 1113 sprintf((char *)num, "%d", n); 1114 if (isnumber(s)) 1115 setsymtab(num, s, atof((char *)s), STR|NUM, (Array *) ap->sval); 1116 else 1117 setsymtab(num, s, 0.0, STR, (Array *) ap->sval); 1118 spdone: 1119 pfa = NULL; 1120 } else if (sep == ' ') { 1121 for (n = 0; ; ) { 1122 while (*s == ' ' || *s == '\t' || *s == '\n') 1123 s++; 1124 if (*s == 0) 1125 break; 1126 n++; 1127 t = s; 1128 do 1129 s++; 1130 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); 1131 temp = *s; 1132 *s = '\0'; 1133 sprintf((char *)num, "%d", n); 1134 if (isnumber(t)) 1135 setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); 1136 else 1137 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1138 *s = temp; 1139 if (*s != 0) 1140 s++; 1141 } 1142 } else if (*s != 0) { 1143 for (;;) { 1144 n++; 1145 t = s; 1146 while (*s != sep && *s != '\n' && *s != '\0') 1147 s++; 1148 temp = *s; 1149 *s = '\0'; 1150 sprintf((char *)num, "%d", n); 1151 if (isnumber(t)) 1152 setsymtab(num, t, atof((char *)t), STR|NUM, (Array *) ap->sval); 1153 else 1154 setsymtab(num, t, 0.0, STR, (Array *) ap->sval); 1155 *s = temp; 1156 if (*s++ == 0) 1157 break; 1158 } 1159 } 1160 tempfree(ap, ""); 1161 tempfree(y, ""); 1162 if (a[2] != 0 && (int) a[3] == STRING) 1163 tempfree(x, ""); 1164 x = gettemp(""); 1165 x->tval = NUM; 1166 x->fval = n; 1167 return(x); 1168 } 1169 1170 Cell *condexpr(a,n) Node **a; 1171 { 1172 register Cell *x; 1173 1174 x = execute(a[0]); 1175 if (istrue(x)) { 1176 tempfree(x, ""); 1177 x = execute(a[1]); 1178 } else { 1179 tempfree(x, ""); 1180 x = execute(a[2]); 1181 } 1182 return(x); 1183 } 1184 1185 Cell *ifstat(a,n) Node **a; 1186 { 1187 register Cell *x; 1188 1189 x = execute(a[0]); 1190 if (istrue(x)) { 1191 tempfree(x, ""); 1192 x = execute(a[1]); 1193 } else if (a[2] != 0) { 1194 tempfree(x, ""); 1195 x = execute(a[2]); 1196 } 1197 return(x); 1198 } 1199 1200 Cell *whilestat(a,n) Node **a; 1201 { 1202 register Cell *x; 1203 1204 for (;;) { 1205 x = execute(a[0]); 1206 if (!istrue(x)) 1207 return(x); 1208 tempfree(x, ""); 1209 x = execute(a[1]); 1210 if (isbreak(x)) { 1211 x = true; 1212 return(x); 1213 } 1214 if (isnext(x) || isexit(x) || isret(x)) 1215 return(x); 1216 tempfree(x, ""); 1217 } 1218 } 1219 1220 Cell *dostat(a,n) Node **a; 1221 { 1222 register Cell *x; 1223 1224 for (;;) { 1225 x = execute(a[0]); 1226 if (isbreak(x)) 1227 return true; 1228 if (isnext(x) || isexit(x) || isret(x)) 1229 return(x); 1230 tempfree(x, ""); 1231 x = execute(a[1]); 1232 if (!istrue(x)) 1233 return(x); 1234 tempfree(x, ""); 1235 } 1236 } 1237 1238 Cell *forstat(a,n) Node **a; 1239 { 1240 register Cell *x; 1241 1242 x = execute(a[0]); 1243 tempfree(x, ""); 1244 for (;;) { 1245 if (a[1]!=0) { 1246 x = execute(a[1]); 1247 if (!istrue(x)) return(x); 1248 else tempfree(x, ""); 1249 } 1250 x = execute(a[3]); 1251 if (isbreak(x)) /* turn off break */ 1252 return true; 1253 if (isnext(x) || isexit(x) || isret(x)) 1254 return(x); 1255 tempfree(x, ""); 1256 x = execute(a[2]); 1257 tempfree(x, ""); 1258 } 1259 } 1260 1261 Cell *instat(a, n) Node **a; 1262 { 1263 register Cell *x, *vp, *arrayp, *cp, *ncp; 1264 Array *tp; 1265 int i; 1266 1267 vp = execute(a[0]); 1268 arrayp = execute(a[1]); 1269 if (!isarr(arrayp)) 1270 ERROR "%s is not an array", arrayp->nval FATAL; 1271 tp = (Array *) arrayp->sval; 1272 tempfree(arrayp, ""); 1273 for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 1274 for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 1275 setsval(vp, cp->nval); 1276 ncp = cp->cnext; 1277 x = execute(a[2]); 1278 if (isbreak(x)) { 1279 tempfree(vp, ""); 1280 return true; 1281 } 1282 if (isnext(x) || isexit(x) || isret(x)) { 1283 tempfree(vp, ""); 1284 return(x); 1285 } 1286 tempfree(x, ""); 1287 } 1288 } 1289 return true; 1290 } 1291 1292 Cell *bltin(a,n) Node **a; 1293 { 1294 register Cell *x, *y; 1295 Awkfloat u; 1296 register int t; 1297 uchar *p, buf[RECSIZE]; 1298 Node *nextarg; 1299 1300 t = (int) a[0]; 1301 x = execute(a[1]); 1302 nextarg = a[1]->nnext; 1303 switch (t) { 1304 case FLENGTH: 1305 u = (Awkfloat) strlen(getsval(x)); break; 1306 case FLOG: 1307 u = errcheck(log(getfval(x)), "log"); break; 1308 case FINT: 1309 modf(getfval(x), &u); break; 1310 case FEXP: 1311 u = errcheck(exp(getfval(x)), "exp"); break; 1312 case FSQRT: 1313 u = errcheck(sqrt(getfval(x)), "sqrt"); break; 1314 case FSIN: 1315 u = sin(getfval(x)); break; 1316 case FCOS: 1317 u = cos(getfval(x)); break; 1318 case FATAN: 1319 if (nextarg == 0) { 1320 ERROR "atan2 requires two arguments; returning 1.0" WARNING; 1321 u = 1.0; 1322 } else { 1323 y = execute(a[1]->nnext); 1324 u = atan2(getfval(x), getfval(y)); 1325 tempfree(y, ""); 1326 nextarg = nextarg->nnext; 1327 } 1328 break; 1329 case FSYSTEM: 1330 fflush(stdout); /* in case something is buffered already */ 1331 u = (Awkfloat) system((char *)getsval(x)) / 256; /* 256 is unix-dep */ 1332 break; 1333 case FRAND: 1334 u = (Awkfloat) (rand() % 32767) / 32767.0; 1335 break; 1336 case FSRAND: 1337 if (x->tval & REC) /* no argument provided */ 1338 u = time((time_t *)0); 1339 else 1340 u = getfval(x); 1341 srand((int) u); u = (int) u; 1342 break; 1343 case FTOUPPER: 1344 case FTOLOWER: 1345 strcpy(buf, getsval(x)); 1346 if (t == FTOUPPER) { 1347 for (p = buf; *p; p++) 1348 if (islower(*p)) 1349 *p = toupper(*p); 1350 } else { 1351 for (p = buf; *p; p++) 1352 if (isupper(*p)) 1353 *p = tolower(*p); 1354 } 1355 tempfree(x, ""); 1356 x = gettemp(""); 1357 setsval(x, buf); 1358 return x; 1359 default: /* can't happen */ 1360 ERROR "illegal function type %d", t FATAL; 1361 break; 1362 } 1363 tempfree(x, ""); 1364 x = gettemp(""); 1365 setfval(x, u); 1366 if (nextarg != 0) { 1367 ERROR "warning: function has too many arguments" WARNING; 1368 for ( ; nextarg; nextarg = nextarg->nnext) 1369 execute(nextarg); 1370 } 1371 return(x); 1372 } 1373 1374 Cell *print(a,n) Node **a; 1375 { 1376 register Node *x; 1377 register Cell *y; 1378 FILE *fp; 1379 1380 if (a[1] == 0) 1381 fp = stdout; 1382 else 1383 fp = redirect((int)a[1], a[2]); 1384 for (x = a[0]; x != NULL; x = x->nnext) { 1385 y = execute(x); 1386 fputs((char *)getsval(y), fp); 1387 tempfree(y, ""); 1388 if (x->nnext == NULL) 1389 fputs((char *)*ORS, fp); 1390 else 1391 fputs((char *)*OFS, fp); 1392 } 1393 if (a[1] != 0) 1394 fflush(fp); 1395 return(true); 1396 } 1397 1398 Cell *nullproc() { return 0; } 1399 1400 1401 struct 1402 { 1403 FILE *fp; 1404 uchar *fname; 1405 int mode; /* '|', 'a', 'w' */ 1406 } files[FOPEN_MAX]; 1407 1408 FILE *redirect(a, b) 1409 Node *b; 1410 { 1411 FILE *fp; 1412 Cell *x; 1413 uchar *fname; 1414 1415 x = execute(b); 1416 fname = getsval(x); 1417 fp = openfile(a, fname); 1418 if (fp == NULL) 1419 ERROR "can't open file %s", fname FATAL; 1420 tempfree(x, ""); 1421 return fp; 1422 } 1423 1424 FILE *openfile(a, s) 1425 uchar *s; 1426 { 1427 register int i, m; 1428 register FILE *fp; 1429 extern FILE *popen(); 1430 1431 if (*s == '\0') 1432 ERROR "null file name in print or getline" FATAL; 1433 for (i=0; i < FOPEN_MAX; i++) 1434 if (files[i].fname && strcmp(s, files[i].fname) == 0) 1435 if (a == files[i].mode || a==APPEND && files[i].mode==GT) 1436 return files[i].fp; 1437 for (i=0; i < FOPEN_MAX; i++) 1438 if (files[i].fp == 0) 1439 break; 1440 if (i >= FOPEN_MAX) 1441 ERROR "%s makes too many open files", s FATAL; 1442 fflush(stdout); /* force a semblance of order */ 1443 m = a; 1444 if (a == GT) { 1445 fp = fopen((char *)s, "w"); 1446 } else if (a == APPEND) { 1447 fp = fopen((char *)s, "a"); 1448 m = GT; /* so can mix > and >> */ 1449 } else if (a == '|') { /* output pipe */ 1450 fp = popen((char *)s, "w"); 1451 } else if (a == LE) { /* input pipe */ 1452 fp = popen((char *)s, "r"); 1453 } else if (a == LT) { /* getline <file */ 1454 fp = strcmp((char *)s, "-") == 0 ? stdin : fopen((char *)s, "r"); /* "-" is stdin */ 1455 } else /* can't happen */ 1456 ERROR "illegal redirection" FATAL; 1457 if (fp != NULL) { 1458 files[i].fname = tostring(s); 1459 files[i].fp = fp; 1460 files[i].mode = m; 1461 } 1462 return fp; 1463 } 1464 1465 Cell *closefile(a) Node **a; 1466 { 1467 register Cell *x; 1468 int i, stat; 1469 1470 x = execute(a[0]); 1471 getsval(x); 1472 for (i = 0; i < FOPEN_MAX; i++) 1473 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) { 1474 if (ferror(files[i].fp)) 1475 ERROR "i/o error occurred on %s", files[i].fname WARNING; 1476 if (files[i].mode == '|' || files[i].mode == LE) 1477 stat = pclose(files[i].fp); 1478 else 1479 stat = fclose(files[i].fp); 1480 if (stat == EOF) 1481 ERROR "i/o error occurred closing %s", files[i].fname WARNING; 1482 xfree(files[i].fname); 1483 files[i].fname = NULL; /* watch out for ref thru this */ 1484 files[i].fp = NULL; 1485 } 1486 tempfree(x, "close"); 1487 return(true); 1488 } 1489 1490 closeall() 1491 { 1492 int i, stat; 1493 1494 for (i = 0; i < FOPEN_MAX; i++) 1495 if (files[i].fp) { 1496 if (ferror(files[i].fp)) 1497 ERROR "i/o error occurred on %s", files[i].fname WARNING; 1498 if (files[i].mode == '|' || files[i].mode == LE) 1499 stat = pclose(files[i].fp); 1500 else 1501 stat = fclose(files[i].fp); 1502 if (stat == EOF) 1503 ERROR "i/o error occurred while closing %s", files[i].fname WARNING; 1504 } 1505 } 1506 1507 Cell *sub(a, nnn) Node **a; 1508 { 1509 register uchar *sptr, *pb, *q; 1510 register Cell *x, *y, *result; 1511 uchar buf[RECSIZE], *t; 1512 fa *pfa; 1513 1514 x = execute(a[3]); /* target string */ 1515 t = getsval(x); 1516 if (a[0] == 0) 1517 pfa = (fa *) a[1]; /* regular expression */ 1518 else { 1519 y = execute(a[1]); 1520 pfa = makedfa(getsval(y), 1); 1521 tempfree(y, ""); 1522 } 1523 y = execute(a[2]); /* replacement string */ 1524 result = false; 1525 if (pmatch(pfa, t)) { 1526 pb = buf; 1527 sptr = t; 1528 while (sptr < patbeg) 1529 *pb++ = *sptr++; 1530 sptr = getsval(y); 1531 while (*sptr != 0 && pb < buf + RECSIZE - 1) 1532 if (*sptr == '\\' && *(sptr+1) == '&') { 1533 sptr++; /* skip \, */ 1534 *pb++ = *sptr++; /* add & */ 1535 } else if (*sptr == '&') { 1536 sptr++; 1537 for (q = patbeg; q < patbeg+patlen; ) 1538 *pb++ = *q++; 1539 } else 1540 *pb++ = *sptr++; 1541 *pb = '\0'; 1542 if (pb >= buf + RECSIZE) 1543 ERROR "sub() result %.20s too big", buf FATAL; 1544 sptr = patbeg + patlen; 1545 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) 1546 while (*pb++ = *sptr++) 1547 ; 1548 if (pb >= buf + RECSIZE) 1549 ERROR "sub() result %.20s too big", buf FATAL; 1550 setsval(x, buf); 1551 result = true;; 1552 } 1553 tempfree(x, ""); 1554 tempfree(y, ""); 1555 return result; 1556 } 1557 1558 Cell *gsub(a, nnn) Node **a; 1559 { 1560 register Cell *x, *y; 1561 register uchar *rptr, *sptr, *t, *pb; 1562 uchar buf[RECSIZE]; 1563 register fa *pfa; 1564 int mflag, tempstat, num; 1565 1566 mflag = 0; /* if mflag == 0, can replace empty string */ 1567 num = 0; 1568 x = execute(a[3]); /* target string */ 1569 t = getsval(x); 1570 if (a[0] == 0) 1571 pfa = (fa *) a[1]; /* regular expression */ 1572 else { 1573 y = execute(a[1]); 1574 pfa = makedfa(getsval(y), 1); 1575 tempfree(y, ""); 1576 } 1577 y = execute(a[2]); /* replacement string */ 1578 if (pmatch(pfa, t)) { 1579 tempstat = pfa->initstat; 1580 pfa->initstat = 2; 1581 pb = buf; 1582 rptr = getsval(y); 1583 do { 1584 /* 1585 uchar *p; 1586 int i; 1587 printf("target string: %s, *patbeg = %o, patlen = %d\n", 1588 t, *patbeg, patlen); 1589 printf(" match found: "); 1590 p=patbeg; 1591 for (i=0; i<patlen; i++) 1592 printf("%c", *p++); 1593 printf("\n"); 1594 */ 1595 if (patlen == 0 && *patbeg != 0) { /* matched empty string */ 1596 if (mflag == 0) { /* can replace empty */ 1597 num++; 1598 sptr = rptr; 1599 while (*sptr != 0 && pb < buf + RECSIZE-1) 1600 if (*sptr == '\\' && *(sptr+1) == '&') { 1601 sptr++; 1602 *pb++ = *sptr++; 1603 } else if (*sptr == '&') { 1604 uchar *q; 1605 sptr++; 1606 for (q = patbeg; q < patbeg+patlen; ) 1607 *pb++ = *q++; 1608 } else 1609 *pb++ = *sptr++; 1610 } 1611 if (*t == 0) /* at end */ 1612 goto done; 1613 *pb++ = *t++; 1614 if (pb >= buf + RECSIZE) 1615 ERROR "gsub() result %.20s too big", buf FATAL; 1616 mflag = 0; 1617 } 1618 else { /* matched nonempty string */ 1619 num++; 1620 sptr = t; 1621 while (sptr < patbeg && pb < buf + RECSIZE-1) 1622 *pb++ = *sptr++; 1623 sptr = rptr; 1624 while (*sptr != 0 && pb < buf + RECSIZE-1) 1625 if (*sptr == '\\' && *(sptr+1) == '&') { 1626 sptr++; 1627 *pb++ = *sptr++; 1628 } else if (*sptr == '&') { 1629 uchar *q; 1630 sptr++; 1631 for (q = patbeg; q < patbeg+patlen; ) 1632 *pb++ = *q++; 1633 } else 1634 *pb++ = *sptr++; 1635 t = patbeg + patlen; 1636 if ((*(t-1) == 0) || (*t == 0)) 1637 goto done; 1638 if (pb >= buf + RECSIZE) 1639 ERROR "gsub() result %.20s too big", buf FATAL; 1640 mflag = 1; 1641 } 1642 } while (pmatch(pfa,t)); 1643 sptr = t; 1644 while (*pb++ = *sptr++) 1645 ; 1646 done: if (pb >= buf + RECSIZE) 1647 ERROR "gsub() result %.20s too big", buf FATAL; 1648 *pb = '\0'; 1649 setsval(x, buf); 1650 pfa->initstat = tempstat; 1651 } 1652 tempfree(x, ""); 1653 tempfree(y, ""); 1654 x = gettemp(""); 1655 x->tval = NUM; 1656 x->fval = num; 1657 return(x); 1658 } 1659