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