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 23 /* 24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #define DEBUG 34 #define tempfree(a) {if (istemp(a)) {xfree(a->sval); a->tval = 0; }} 35 36 #include "awk.def" 37 #include "math.h" 38 #include "awk.h" 39 #include "stdio.h" 40 #include "ctype.h" 41 #include "wctype.h" 42 #include "awktype.h" 43 #include <stdlib.h> 44 45 #define RECSIZE BUFSIZ 46 47 #define FILENUM 10 48 struct 49 { 50 FILE *fp; 51 int type; 52 wchar_t *fname; 53 } files[FILENUM]; 54 FILE *popen(); 55 56 extern CELL *execute(), *nodetoobj(), *fieldel(), *dopa2(), *gettemp(); 57 58 #define PA2NUM 29 59 int pairstack[PA2NUM], paircnt; 60 NODE *winner = NULL; 61 #define MAXTMP 20 62 CELL tmps[MAXTMP]; 63 64 static CELL truecell ={ OBOOL, BTRUE, 0, 0, 0.0, NUM, 0 }; 65 CELL *true = &truecell; 66 static CELL falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, 0 }; 67 CELL *false = &falsecell; 68 static CELL breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, 0 }; 69 CELL *jbreak = &breakcell; 70 static CELL contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, 0 }; 71 CELL *jcont = &contcell; 72 static CELL nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, 0 }; 73 CELL *jnext = &nextcell; 74 static CELL exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, 0 }; 75 CELL *jexit = &exitcell; 76 static CELL tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM, 0 }; 77 78 static void redirprint(wchar_t *s, int a, NODE *b); 79 80 void freesymtab(CELL *ap); 81 void fldbld(void); 82 83 void 84 run(NODE *a) 85 { 86 int i; 87 88 execute(a); 89 /* Wait for children to complete if output to a pipe. */ 90 for (i=0; i<FILENUM; i++) 91 if (files[i].fp && files[i].type == '|') 92 pclose(files[i].fp); 93 } 94 95 96 CELL * 97 execute(NODE *u) 98 { 99 CELL *(*proc)(); 100 CELL *x; 101 NODE *a; 102 103 if (u == NULL) 104 return (true); 105 for (a = u; /* dummy */; a = a->nnext) { 106 if (cantexec(a)) 107 return (nodetoobj(a)); 108 if (notlegal(a->nobj)) 109 error(FATAL, "illegal statement %o", a); 110 proc = proctab[a->nobj-FIRSTTOKEN]; 111 x = (*proc)(a->narg, a->nobj); 112 if (isfld(x)) 113 fldbld(); 114 if (isexpr(a)) 115 return (x); 116 /* a statement, goto next statement */ 117 if (isjump(x)) 118 return (x); 119 if (a->nnext == (NODE *)NULL) 120 return (x); 121 tempfree(x); 122 } 123 } 124 125 126 127 128 CELL * 129 program(NODE **a, int n) 130 { 131 CELL *x; 132 133 if (a[0] != NULL) { 134 x = execute(a[0]); 135 if (isexit(x)) 136 return (true); 137 if (isjump(x)) 138 error(FATAL, "unexpected break, continue or next"); 139 tempfree(x); 140 } 141 while (getrec()) { 142 x = execute(a[1]); 143 if (isexit(x)) { 144 tempfree(x); 145 break; 146 } 147 tempfree(x); 148 } 149 if (a[2] != NULL) { 150 x = execute(a[2]); 151 if (isbreak(x) || isnext(x) || iscont(x)) 152 error(FATAL, "unexpected break, continue or next"); 153 tempfree(x); 154 } 155 return (true); 156 } 157 158 159 160 161 CELL * 162 getline(void) 163 { 164 CELL *x; 165 166 x = gettemp(); 167 setfval(x, (awkfloat) getrec()); 168 return (x); 169 } 170 171 172 173 174 CELL * 175 array(NODE **a, int n) 176 { 177 CELL *x, *y; 178 extern CELL *arrayel(); 179 180 x = execute(a[1]); 181 y = arrayel(a[0], x); 182 tempfree(x); 183 return (y); 184 } 185 186 187 188 189 CELL * 190 arrayel(NODE *a, CELL *b) 191 { 192 wchar_t *s; 193 CELL *x; 194 int i; 195 CELL *y; 196 197 s = getsval(b); 198 x = (CELL *) a; 199 if (!(x->tval&ARR)) { 200 xfree(x->sval); 201 x->tval &= ~STR; 202 x->tval |= ARR; 203 x->sval = (wchar_t *) makesymtab(); 204 } 205 y = setsymtab(s, tostring(L_NULL), 0.0, STR|NUM, x->sval); 206 y->ctype = OCELL; 207 y->csub = CVAR; 208 return (y); 209 } 210 211 CELL * 212 matchop(NODE **a, int n) 213 { 214 CELL *x; 215 wchar_t *s; 216 int i; 217 218 x = execute(a[0]); 219 s = getsval(x); 220 tempfree(x); 221 i = match(a[1], s); 222 if (n == MATCH && i == 1 || n == NOTMATCH && i == 0) 223 return (true); 224 else 225 return (false); 226 } 227 228 229 230 231 CELL * 232 boolop(NODE **a, int n) 233 { 234 CELL *x, *y; 235 int i; 236 237 238 239 240 x = execute(a[0]); 241 i = istrue(x); 242 tempfree(x); 243 switch (n) { 244 case BOR: 245 if (i) return (true); 246 y = execute(a[1]); 247 i = istrue(y); 248 tempfree(y); 249 if (i) return (true); 250 else return (false); 251 case AND: 252 if (!i) return (false); 253 y = execute(a[1]); 254 i = istrue(y); 255 tempfree(y); 256 if (i) return (true); 257 else return (false); 258 case NOT: 259 if (i) return (false); 260 else return (true); 261 default: 262 error(FATAL, "unknown boolean operator %d", n); 263 } 264 return (false); 265 } 266 267 268 269 270 CELL * 271 relop(NODE **a, int n) 272 { 273 int i; 274 CELL *x, *y; 275 awkfloat j; 276 wchar_t *xs, *ys; 277 278 279 280 281 x = execute(a[0]); 282 y = execute(a[1]); 283 if (x->tval&NUM && y->tval&NUM) { 284 j = x->fval - y->fval; 285 i = j<0? -1: (j>0? 1: 0); 286 } else { 287 xs = getsval(x); 288 ys = getsval(y); 289 if (xs && ys) 290 i = wscoll(xs, ys); 291 else 292 return (false); 293 } 294 tempfree(x); 295 tempfree(y); 296 switch (n) { 297 case LT: if (i<0) return (true); 298 else return (false); 299 case LE: if (i<=0) return (true); 300 else return (false); 301 case NE: if (i!=0) return (true); 302 else return (false); 303 case EQ: if (i == 0) return (true); 304 else return (false); 305 case GE: if (i>=0) return (true); 306 else return (false); 307 case GT: if (i>0) return (true); 308 else return (false); 309 default: 310 error(FATAL, "unknown relational operator %d", n); 311 } 312 return (false); 313 } 314 315 316 317 318 319 320 321 322 CELL * 323 gettemp(void) 324 { 325 int i; 326 CELL *x; 327 328 329 330 331 for (i=0; i<MAXTMP; i++) 332 if (tmps[i].tval == 0) 333 break; 334 if (i == MAXTMP) 335 error(FATAL, "out of temporaries in gettemp"); 336 tmps[i] = tempcell; 337 x = &tmps[i]; 338 return (x); 339 } 340 341 342 343 344 CELL * 345 indirect(NODE **a, int n) 346 { 347 CELL *x; 348 int m; 349 CELL *fieldadr(); 350 351 x = execute(a[0]); 352 m = getfval(x); 353 tempfree(x); 354 x = fieldadr(m); 355 x->ctype = OCELL; 356 x->csub = CFLD; 357 return (x); 358 } 359 360 361 362 363 CELL * 364 substr(NODE **a, int nnn) 365 { 366 int k, m, n; 367 wchar_t *s, temp; 368 CELL *x, *y; 369 370 y = execute(a[0]); 371 s = getsval(y); 372 k = wslen(s) + 1; 373 if (k <= 1) { 374 x = gettemp(); 375 setsval(x, L_NULL); 376 return (x); 377 } 378 x = execute(a[1]); 379 m = getfval(x); 380 if (m <= 0) 381 m = 1; 382 else if (m > k) 383 m = k; 384 tempfree(x); 385 if (a[2] != 0) { 386 x = execute(a[2]); 387 n = getfval(x); 388 tempfree(x); 389 } 390 else 391 n = k - 1; 392 if (n < 0) 393 n = 0; 394 else if (n > k - m) 395 n = k - m; 396 dprintf("substr: m=%d, n=%d, s=%ws\n", m, n, s); 397 x = gettemp(); 398 temp = s[n+m-1]; 399 s[n+m-1] = (wchar_t)0x0; 400 setsval(x, s + m - 1); 401 s[n+m-1] = temp; 402 tempfree(y); 403 return (x); 404 } 405 406 407 408 409 CELL * 410 sindex(NODE **a, int nnn) 411 { 412 CELL *x; 413 wchar_t *s1, *s2, *p1, *p2, *q; 414 415 x = execute(a[0]); 416 s1 = getsval(x); 417 tempfree(x); 418 x = execute(a[1]); 419 s2 = getsval(x); 420 tempfree(x); 421 422 x = gettemp(); 423 for (p1 = s1; *p1 != (wchar_t)0x0; p1++) { 424 for (q=p1, p2=s2; *p2 != (wchar_t)0x0 && *q == *p2; q++, p2++) 425 ; 426 if (*p2 == (wchar_t)0x0) { 427 setfval(x, (awkfloat) (p1 - s1 + 1)); /* origin 1 */ 428 return (x); 429 } 430 } 431 setfval(x, 0.0); 432 return (x); 433 } 434 435 436 437 438 wchar_t * 439 format(wchar_t *s, NODE *a) 440 { 441 wchar_t *buf, *ep, *str; 442 wchar_t *p; 443 char *t; 444 wchar_t *os; 445 wchar_t tbuf[2*RECSIZE]; 446 char fmt[200]; 447 CELL *x; 448 int flag = 0; 449 awkfloat xf; 450 451 os = s; 452 p = buf= (wchar_t *)malloc(RECSIZE * sizeof (wchar_t)); 453 454 if (p == NULL) 455 error(FATAL, "out of space in format"); 456 ep = p + RECSIZE; 457 while (*s) { 458 if (*s != '%') { 459 *p++ = *s++; 460 continue; 461 } 462 if (*(s+1) == '%') { 463 *p++ = '%'; 464 s += 2; 465 continue; 466 } 467 for (t=fmt; *s != '\0'; s++) 468 { 469 if (*s == 's' || *s == 'c') 470 *t++ = 'w'; 471 *t++ = *s; 472 if (*s >= 'a' && *s <= 'z' && *s != 'l') 473 break; 474 if (*s == '*') { 475 if (a == NULL) { 476 error(FATAL, 477 "not enough arguments in printf(%ws) or sprintf(%ws)", 478 os, os); 479 } 480 x = execute(a); 481 a = a->nnext; 482 sprintf(t-1, "%d", (int) getfval(x)); 483 t = fmt + strlen(fmt); 484 tempfree(x); 485 } 486 487 } 488 *t = '\0'; 489 if (t >= fmt + sizeof (fmt)) 490 error(FATAL, "format item %.20ws... too long", os); 491 switch (*s) { 492 case 'f': case 'e': case 'g': 493 flag = 1; 494 break; 495 case 'd': 496 flag = 2; 497 if (*(s-1) == 'l') break; 498 *(t-1) = 'l'; 499 *t = 'd'; 500 *++t = '\0'; 501 break; 502 case 'o': case 'x': 503 flag = *(s-1) == 'l' ? 2 : 3; 504 break; 505 case 'c': 506 flag = 3; 507 break; 508 case 's': 509 flag = 4; 510 break; 511 default: 512 flag = 0; 513 break; 514 } 515 if (flag == 0) { 516 wsprintf(p, "%s", fmt); 517 p += wslen(p); 518 continue; 519 } 520 if (a == NULL) { 521 error(FATAL, 522 "not enough arguments in printf(%ws) or sprintf(%ws)", os, os); 523 } 524 x = execute(a); 525 a = a->nnext; 526 527 /* 528 * Get the string to check length; %s is the usual problem; 529 * other conversions can cause overrun if they occur when 530 * the buffer is almost filled. 531 */ 532 if (flag == 4) { /* watch out for converting to numbers! */ 533 str = getsval(x); 534 } 535 else { 536 xf = getfval(x); 537 if (flag == 1) wsprintf(tbuf, fmt, xf); 538 else if (flag == 2) wsprintf(tbuf, fmt, (long)xf); 539 else if (flag == 3) wsprintf(tbuf, fmt, (int)xf); 540 if (wslen(tbuf) >= RECSIZE) 541 error(FATAL, "formatted item %s... too long", 542 tbuf); 543 str = tbuf; 544 } 545 /* 546 * If string overruns the buffer, reallocate; 547 * consider length of format string 548 */ 549 if (p + wslen(str) + wslen(s) + 1 >= ep) { 550 int newlen, oldlen; 551 552 oldlen = p - buf; 553 /* Add RECSIZE for additional space */ 554 newlen = oldlen + wslen(str) + RECSIZE; 555 buf = realloc(buf, (unsigned) newlen * sizeof(wchar_t)); 556 if (buf == NULL) 557 error(FATAL, "out of format space"); 558 p = buf + oldlen; 559 ep = buf + newlen; 560 } 561 /* Transfer string to buffer */ 562 if (flag == 4) 563 wsprintf(p, fmt, str); 564 else 565 wscpy(p, str); 566 567 tempfree(x); 568 p += wslen(p); 569 if (p >= ep) 570 error(FATAL, "formatted string too long"); 571 s++; 572 } 573 *p = '\0'; 574 return (buf); 575 } 576 577 578 CELL * 579 asprintf(NODE **a, int n) 580 { 581 CELL *x; 582 NODE *y; 583 wchar_t *s; 584 585 y = a[0]->nnext; 586 x = execute(a[0]); 587 s = format(getsval(x), y); 588 tempfree(x); 589 x = gettemp(); 590 x->sval = s; 591 x->tval = STR; 592 return (x); 593 } 594 595 596 CELL * 597 arith(NODE **a, int n) 598 { 599 awkfloat i, j; 600 CELL *x, *y, *z; 601 602 x = execute(a[0]); 603 i = getfval(x); 604 tempfree(x); 605 if (n != UMINUS) { 606 y = execute(a[1]); 607 j = getfval(y); 608 tempfree(y); 609 } 610 z = gettemp(); 611 switch (n) { 612 case ADD: 613 i += j; 614 break; 615 case MINUS: 616 i -= j; 617 break; 618 case MULT: 619 i *= j; 620 break; 621 case DIVIDE: 622 if (j == 0) 623 error(FATAL, "division by zero"); 624 i /= j; 625 break; 626 case MOD: 627 if (j == 0) 628 error(FATAL, "division by zero"); 629 i = i - j*(long)(i/j); 630 break; 631 case UMINUS: 632 i = -i; 633 break; 634 default: 635 error(FATAL, "illegal arithmetic operator %d", n); 636 } 637 setfval(z, i); 638 return (z); 639 } 640 641 642 643 644 CELL * 645 incrdecr(NODE **a, int n) 646 { 647 CELL *x, *z; 648 int k; 649 awkfloat xf; 650 651 x = execute(a[0]); 652 xf = getfval(x); 653 k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 654 if (n == PREINCR || n == PREDECR) { 655 setfval(x, xf + k); 656 return (x); 657 } 658 z = gettemp(); 659 setfval(z, xf); 660 setfval(x, xf + k); 661 tempfree(x); 662 return (z); 663 } 664 665 666 667 CELL * 668 assign(NODE **a, int n) 669 { 670 CELL *x, *y; 671 awkfloat xf, yf; 672 673 674 675 676 x = execute(a[0]); 677 y = execute(a[1]); 678 if (n == ASSIGN) { /* ordinary assignment */ 679 if ((y->tval & (STR|NUM)) == (STR|NUM)) { 680 setsval(x, y->sval); 681 x->fval = y->fval; 682 x->tval |= NUM; 683 684 } else if (y->tval & STR) 685 setsval(x, y->sval); 686 else if (y->tval & NUM) 687 setfval(x, y->fval); 688 tempfree(y); 689 return (x); 690 } 691 xf = getfval(x); 692 yf = getfval(y); 693 switch (n) { 694 case ADDEQ: 695 xf += yf; 696 break; 697 case SUBEQ: 698 xf -= yf; 699 break; 700 case MULTEQ: 701 xf *= yf; 702 break; 703 case DIVEQ: 704 if (yf == 0) 705 error(FATAL, "division by zero"); 706 xf /= yf; 707 break; 708 case MODEQ: 709 if (yf == 0) 710 error(FATAL, "division by zero"); 711 xf = xf - yf*(long)(xf/yf); 712 break; 713 default: 714 error(FATAL, "illegal assignment operator %d", n); 715 break; 716 } 717 tempfree(y); 718 setfval(x, xf); 719 return (x); 720 } 721 722 723 724 725 CELL * 726 cat(NODE **a, int q) 727 { 728 CELL *x, *y, *z; 729 int n1, n2; 730 wchar_t *s; 731 732 733 734 735 x = execute(a[0]); 736 y = execute(a[1]); 737 getsval(x); 738 getsval(y); 739 n1 = wslen(x->sval); 740 n2 = wslen(y->sval); 741 if ((s = (wchar_t *) malloc((n1 + n2 + 1) * sizeof (wchar_t))) == NULL) 742 error(FATAL, "out of space in cat"); 743 wscpy(s, x->sval); 744 wscpy(s+n1, y->sval); 745 tempfree(y); 746 z = gettemp(); 747 z->sval = s; 748 z->tval = STR; 749 tempfree(x); 750 return (z); 751 } 752 753 754 755 756 CELL * 757 pastat(NODE **a, int n) 758 { 759 CELL *x; 760 761 762 763 764 if (a[0] == 0) 765 x = true; 766 else 767 x = execute(a[0]); 768 if (istrue(x)) { 769 tempfree(x); 770 x = execute(a[1]); 771 } 772 return (x); 773 } 774 775 776 777 778 CELL * 779 dopa2(NODE **a, int n) 780 { 781 CELL *x; 782 int pair; 783 784 785 786 787 pair = (int) a[3]; 788 if (pairstack[pair] == 0) { 789 x = execute(a[0]); 790 if (istrue(x)) 791 pairstack[pair] = 1; 792 tempfree(x); 793 } 794 if (pairstack[pair] == 1) { 795 x = execute(a[1]); 796 if (istrue(x)) 797 pairstack[pair] = 0; 798 tempfree(x); 799 x = execute(a[2]); 800 return (x); 801 } 802 return (false); 803 } 804 805 806 807 808 CELL * 809 aprintf(NODE **a, int n) 810 { 811 CELL *x; 812 813 814 815 816 x = asprintf(a, n); 817 if (a[1] == NULL) { 818 printf("%ws", x->sval); 819 tempfree(x); 820 return (true); 821 } 822 redirprint(x->sval, (int)a[1], a[2]); 823 return (x); 824 } 825 826 827 828 829 CELL * 830 split(NODE **a, int nnn) 831 { 832 CELL *x; 833 CELL *ap; 834 wchar_t *s, *p, c; 835 wchar_t *t, temp, num[5]; 836 wchar_t sep; 837 int n, flag; 838 839 840 841 842 x = execute(a[0]); 843 s = getsval(x); 844 tempfree(x); 845 if (a[2] == 0) 846 sep = **FS; 847 else { 848 x = execute(a[2]); 849 sep = getsval(x)[0]; 850 tempfree(x); 851 } 852 ap = (CELL *) a[1]; 853 freesymtab(ap); 854 dprintf("split: s=|%ws|, a=%ws, sep=|%wc|\n", s, ap->nval, sep); 855 ap->tval &= ~STR; 856 ap->tval |= ARR; 857 ap->sval = (wchar_t *) makesymtab(); 858 859 860 861 862 n = 0; 863 if (sep == ' ') 864 for (n = 0; /* dummy */; /* dummy */) { 865 c = *s; 866 while (iswblank(c) || c == '\t' || c == '\n') 867 c = *(++s); 868 if (*s == 0) 869 break; 870 n++; 871 t = s; 872 do 873 c = *(++s); 874 while (! iswblank(c) && c != '\t' && 875 c != '\n' && c != '\0'); 876 temp = c; 877 *s = (wchar_t)0x0; 878 wsprintf(num, "%d", n); 879 if (isanumber(t)) 880 setsymtab(num, tostring(t), 881 watof(t), STR|NUM, ap->sval); 882 else 883 setsymtab(num, tostring(t), 0.0, STR, ap->sval); 884 *s = temp; 885 if (*s != 0) 886 s++; 887 888 } else if (*s != 0) 889 for (;;) { 890 n++; 891 t = s; 892 while ((c = *s) != sep && c != '\n' && c != '\0') 893 s++; 894 temp = c; 895 *s = (wchar_t)0x0; 896 wsprintf(num, "%d", n); 897 if (isanumber(t)) 898 setsymtab(num, tostring(t), 899 watof(t), STR|NUM, ap->sval); 900 else 901 setsymtab(num, tostring(t), 0.0, STR, ap->sval); 902 *s = temp; 903 if (*s++ == 0) 904 break; 905 } 906 x = gettemp(); 907 x->tval = NUM; 908 x->fval = n; 909 return (x); 910 } 911 912 913 914 915 CELL * 916 ifstat(NODE **a, int n) 917 { 918 CELL *x; 919 920 921 922 923 x = execute(a[0]); 924 if (istrue(x)) { 925 tempfree(x); 926 x = execute(a[1]); 927 928 } else if (a[2] != 0) { 929 tempfree(x); 930 x = execute(a[2]); 931 } 932 return (x); 933 } 934 935 936 937 938 CELL * 939 whilestat(NODE **a, int n) 940 { 941 CELL *x; 942 943 944 945 946 for (;;) { 947 x = execute(a[0]); 948 if (!istrue(x)) return (x); 949 tempfree(x); 950 x = execute(a[1]); 951 if (isbreak(x)) { 952 x = true; 953 return (x); 954 } 955 if (isnext(x) || isexit(x)) 956 return (x); 957 tempfree(x); 958 } 959 } 960 961 962 963 964 CELL * 965 forstat(NODE **a, int n) 966 { 967 CELL *x; 968 CELL *z; 969 970 971 972 973 z = execute(a[0]); 974 tempfree(z); 975 for (;;) { 976 if (a[1]!=0) { 977 x = execute(a[1]); 978 if (!istrue(x)) return (x); 979 else tempfree(x); 980 } 981 x = execute(a[3]); 982 if (isbreak(x)) { /* turn off break */ 983 x = true; 984 return (x); 985 } 986 if (isnext(x) || isexit(x)) 987 return (x); 988 tempfree(x); 989 z = execute(a[2]); 990 tempfree(z); 991 } 992 } 993 994 995 996 997 CELL * 998 instat(NODE **a, int n) 999 { 1000 CELL *vp, *arrayp, *cp, **tp; 1001 CELL *x; 1002 int i; 1003 1004 1005 1006 1007 vp = (CELL *) a[0]; 1008 arrayp = (CELL *) a[1]; 1009 if (!(arrayp->tval & ARR)) 1010 error(FATAL, "%ws is not an array", arrayp->nval); 1011 tp = (CELL **) arrayp->sval; 1012 for (i = 0; i < MAXSYM; i++) { /* this routine knows too much */ 1013 for (cp = tp[i]; cp != NULL; cp = cp->nextval) { 1014 setsval(vp, cp->nval); 1015 x = execute(a[2]); 1016 if (isbreak(x)) { 1017 x = true; 1018 return (x); 1019 } 1020 if (isnext(x) || isexit(x)) 1021 return (x); 1022 tempfree(x); 1023 } 1024 } 1025 return (true); 1026 } 1027 1028 1029 1030 1031 CELL * 1032 jump(NODE **a, int n) 1033 { 1034 CELL *y; 1035 1036 1037 1038 1039 switch (n) { 1040 case EXIT: 1041 if (a[0] != 0) { 1042 y = execute(a[0]); 1043 errorflag = getfval(y); 1044 } 1045 return (jexit); 1046 case NEXT: 1047 return (jnext); 1048 case BREAK: 1049 return (jbreak); 1050 case CONTINUE: 1051 return (jcont); 1052 default: 1053 error(FATAL, "illegal jump type %d", n); 1054 } 1055 return (NULL); 1056 } 1057 1058 1059 1060 1061 CELL * 1062 fncn(NODE **a, int n) 1063 { 1064 CELL *x; 1065 awkfloat u; 1066 int t; 1067 wchar_t *wp; 1068 1069 t = (int) a[0]; 1070 x = execute(a[1]); 1071 if (t == FLENGTH) 1072 u = (awkfloat) wslen(getsval(x)); 1073 else if (t == FLOG) 1074 u = log(getfval(x)); 1075 else if (t == FINT) 1076 u = (awkfloat) (long) getfval(x); 1077 else if (t == FEXP) 1078 u = exp(getfval(x)); 1079 else if (t == FSQRT) 1080 u = sqrt(getfval(x)); 1081 else 1082 error(FATAL, "illegal function type %d", t); 1083 tempfree(x); 1084 x = gettemp(); 1085 setfval(x, u); 1086 return (x); 1087 } 1088 1089 1090 1091 1092 CELL * 1093 print(NODE **a, int n) 1094 { 1095 NODE *x; 1096 CELL *y; 1097 wchar_t s[RECSIZE]; 1098 wchar_t *ss, *bp, *ep; 1099 1100 s[0] = '\0'; 1101 bp = s; 1102 ep = s + RECSIZE; 1103 for (x=a[0]; x!=NULL; x=x->nnext) { 1104 y = execute(x); 1105 ss = getsval(y); 1106 /* allocate larger buffer if needed */ 1107 if (ep < bp + wslen(bp) + wslen(ss)) { 1108 int newlen; 1109 wchar_t *oldbp; 1110 1111 newlen = wslen(bp) + wslen(ss) + 1 + 1; 1112 oldbp = bp; 1113 bp = malloc(newlen * sizeof(wchar_t)); 1114 if (bp == NULL) 1115 error(FATAL, "out of space in print"); 1116 ep = bp + newlen; 1117 wscpy(bp, oldbp); 1118 if (oldbp != s) 1119 free(oldbp); 1120 } 1121 if (ss) 1122 wscat(bp, ss); 1123 tempfree(y); 1124 if (x->nnext == NULL) 1125 wscat(bp, *ORS); 1126 else 1127 wscat(bp, *OFS); 1128 } 1129 if (a[1] == 0) { 1130 printf("%ws", bp); 1131 if (bp != s) 1132 free(bp); 1133 return (true); 1134 } 1135 1136 redirprint(bp, (int)a[1], a[2]); 1137 if (bp != s) 1138 free(bp); 1139 return (false); 1140 } 1141 1142 1143 1144 CELL * 1145 nullproc(void) 1146 { 1147 return (NULL); 1148 } 1149 1150 1151 1152 CELL * 1153 nodetoobj(NODE *a) 1154 { 1155 CELL *x; 1156 1157 x= (CELL *) a->nobj; 1158 x->ctype = OCELL; 1159 x->csub = a->subtype; 1160 if (isfld(x)) 1161 fldbld(); 1162 return (x); 1163 } 1164 1165 static void 1166 redirprint(wchar_t *s, int a, NODE *b) 1167 { 1168 int i; 1169 CELL *x; 1170 1171 x = execute(b); 1172 getsval(x); 1173 for (i=0; i<FILENUM; i++) 1174 if (files[i].fname && wscmp(x->sval, files[i].fname) == 0) 1175 goto doit; 1176 for (i=0; i<FILENUM; i++) 1177 if (files[i].fp == 0) 1178 break; 1179 if (i >= FILENUM) 1180 error(FATAL, "too many output files %d", i); 1181 if (a == '|') /* a pipe! */ 1182 files[i].fp = popen(toeuccode(x->sval), "w"); 1183 else if (a == APPEND) 1184 files[i].fp = fopen(toeuccode(x->sval), "a"); 1185 else if (a == GT) 1186 files[i].fp = fopen(toeuccode(x->sval), "w"); 1187 else 1188 error(FATAL, "illegal redirection near line %lld", lineno); 1189 if (files[i].fp == NULL) 1190 error(FATAL, "can't open file %ws", x->sval); 1191 files[i].fname = tostring(x->sval); 1192 files[i].type = a; 1193 doit: 1194 fprintf(files[i].fp, "%ws", s); 1195 #ifndef gcos 1196 fflush(files[i].fp); /* in case someone is waiting for the output */ 1197 #endif 1198 tempfree(x); 1199 } 1200