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