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