17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 24*1ee2e5faSnakanon * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 28*1ee2e5faSnakanon /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*1ee2e5faSnakanon /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 31*1ee2e5faSnakanon #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 33*1ee2e5faSnakanon #define tempfree(x, s) if (istemp(x)) tfree(x, s) 34*1ee2e5faSnakanon 357c478bd9Sstevel@tonic-gate #define execute(p) r_execute(p) 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #define DEBUG 387c478bd9Sstevel@tonic-gate #include "awk.h" 397c478bd9Sstevel@tonic-gate #include <math.h> 407c478bd9Sstevel@tonic-gate #include "y.tab.h" 417c478bd9Sstevel@tonic-gate #include <stdio.h> 427c478bd9Sstevel@tonic-gate #include <ctype.h> 437c478bd9Sstevel@tonic-gate #include <setjmp.h> 447c478bd9Sstevel@tonic-gate #include <time.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #ifndef FOPEN_MAX 477c478bd9Sstevel@tonic-gate #define FOPEN_MAX 15 /* max number of open files, from ANSI std. */ 487c478bd9Sstevel@tonic-gate #endif 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate 51*1ee2e5faSnakanon static jmp_buf env; 527c478bd9Sstevel@tonic-gate 53*1ee2e5faSnakanon static Cell *r_execute(Node *); 54*1ee2e5faSnakanon static Cell *gettemp(char *), *copycell(Cell *); 55*1ee2e5faSnakanon static FILE *openfile(int, uchar *), *redirect(int, Node *); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate int paircnt; 587c478bd9Sstevel@tonic-gate Node *winner = NULL; 59*1ee2e5faSnakanon 60*1ee2e5faSnakanon static Cell *tmps; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static Cell truecell = { OBOOL, BTRUE, 0, 0, 1.0, NUM }; 637c478bd9Sstevel@tonic-gate Cell *true = &truecell; 647c478bd9Sstevel@tonic-gate static Cell falsecell = { OBOOL, BFALSE, 0, 0, 0.0, NUM }; 657c478bd9Sstevel@tonic-gate Cell *false = &falsecell; 667c478bd9Sstevel@tonic-gate static Cell breakcell = { OJUMP, JBREAK, 0, 0, 0.0, NUM }; 677c478bd9Sstevel@tonic-gate Cell *jbreak = &breakcell; 687c478bd9Sstevel@tonic-gate static Cell contcell = { OJUMP, JCONT, 0, 0, 0.0, NUM }; 697c478bd9Sstevel@tonic-gate Cell *jcont = &contcell; 707c478bd9Sstevel@tonic-gate static Cell nextcell = { OJUMP, JNEXT, 0, 0, 0.0, NUM }; 717c478bd9Sstevel@tonic-gate Cell *jnext = &nextcell; 727c478bd9Sstevel@tonic-gate static Cell exitcell = { OJUMP, JEXIT, 0, 0, 0.0, NUM }; 737c478bd9Sstevel@tonic-gate Cell *jexit = &exitcell; 747c478bd9Sstevel@tonic-gate static Cell retcell = { OJUMP, JRET, 0, 0, 0.0, NUM }; 757c478bd9Sstevel@tonic-gate Cell *jret = &retcell; 767c478bd9Sstevel@tonic-gate static Cell tempcell = { OCELL, CTEMP, 0, 0, 0.0, NUM }; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate Node *curnode = NULL; /* the node being executed, for debugging */ 797c478bd9Sstevel@tonic-gate 80*1ee2e5faSnakanon static void tfree(Cell *, char *); 81*1ee2e5faSnakanon static void closeall(void); 82*1ee2e5faSnakanon static double ipow(double, int); 83*1ee2e5faSnakanon 84*1ee2e5faSnakanon void 85*1ee2e5faSnakanon run(Node *a) 867c478bd9Sstevel@tonic-gate { 87*1ee2e5faSnakanon (void) execute(a); 887c478bd9Sstevel@tonic-gate closeall(); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 91*1ee2e5faSnakanon static Cell * 92*1ee2e5faSnakanon r_execute(Node *u) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate register Cell *(*proc)(); 957c478bd9Sstevel@tonic-gate register Cell *x; 967c478bd9Sstevel@tonic-gate register Node *a; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (u == NULL) 997c478bd9Sstevel@tonic-gate return (true); 1007c478bd9Sstevel@tonic-gate for (a = u; ; a = a->nnext) { 1017c478bd9Sstevel@tonic-gate curnode = a; 1027c478bd9Sstevel@tonic-gate if (isvalue(a)) { 1037c478bd9Sstevel@tonic-gate x = (Cell *) (a->narg[0]); 1047c478bd9Sstevel@tonic-gate if ((x->tval & FLD) && !donefld) 1057c478bd9Sstevel@tonic-gate fldbld(); 1067c478bd9Sstevel@tonic-gate else if ((x->tval & REC) && !donerec) 1077c478bd9Sstevel@tonic-gate recbld(); 1087c478bd9Sstevel@tonic-gate return (x); 1097c478bd9Sstevel@tonic-gate } 110*1ee2e5faSnakanon /* probably a Cell* but too risky to print */ 111*1ee2e5faSnakanon if (notlegal(a->nobj)) 1127c478bd9Sstevel@tonic-gate ERROR "illegal statement" FATAL; 1137c478bd9Sstevel@tonic-gate proc = proctab[a->nobj-FIRSTTOKEN]; 1147c478bd9Sstevel@tonic-gate x = (*proc)(a->narg, a->nobj); 1157c478bd9Sstevel@tonic-gate if ((x->tval & FLD) && !donefld) 1167c478bd9Sstevel@tonic-gate fldbld(); 1177c478bd9Sstevel@tonic-gate else if ((x->tval & REC) && !donerec) 1187c478bd9Sstevel@tonic-gate recbld(); 1197c478bd9Sstevel@tonic-gate if (isexpr(a)) 1207c478bd9Sstevel@tonic-gate return (x); 1217c478bd9Sstevel@tonic-gate /* a statement, goto next statement */ 1227c478bd9Sstevel@tonic-gate if (isjump(x)) 1237c478bd9Sstevel@tonic-gate return (x); 1247c478bd9Sstevel@tonic-gate if (a->nnext == (Node *)NULL) 1257c478bd9Sstevel@tonic-gate return (x); 1267c478bd9Sstevel@tonic-gate tempfree(x, "execute"); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 130*1ee2e5faSnakanon /*ARGSUSED*/ 131*1ee2e5faSnakanon Cell * 132*1ee2e5faSnakanon program(Node **a, int n) 1337c478bd9Sstevel@tonic-gate { 1347c478bd9Sstevel@tonic-gate register Cell *x; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate if (setjmp(env) != 0) 1377c478bd9Sstevel@tonic-gate goto ex; 1387c478bd9Sstevel@tonic-gate if (a[0]) { /* BEGIN */ 1397c478bd9Sstevel@tonic-gate x = execute(a[0]); 1407c478bd9Sstevel@tonic-gate if (isexit(x)) 1417c478bd9Sstevel@tonic-gate return (true); 142*1ee2e5faSnakanon if (isjump(x)) { 143*1ee2e5faSnakanon ERROR "illegal break, continue or next from BEGIN" 144*1ee2e5faSnakanon FATAL; 145*1ee2e5faSnakanon } 1467c478bd9Sstevel@tonic-gate tempfree(x, ""); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate loop: 1497c478bd9Sstevel@tonic-gate if (a[1] || a[2]) 150*1ee2e5faSnakanon while (getrec(&record, &record_size) > 0) { 1517c478bd9Sstevel@tonic-gate x = execute(a[1]); 1527c478bd9Sstevel@tonic-gate if (isexit(x)) 1537c478bd9Sstevel@tonic-gate break; 1547c478bd9Sstevel@tonic-gate tempfree(x, ""); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate ex: 1577c478bd9Sstevel@tonic-gate if (setjmp(env) != 0) 1587c478bd9Sstevel@tonic-gate goto ex1; 1597c478bd9Sstevel@tonic-gate if (a[2]) { /* END */ 1607c478bd9Sstevel@tonic-gate x = execute(a[2]); 1617c478bd9Sstevel@tonic-gate if (iscont(x)) /* read some more */ 1627c478bd9Sstevel@tonic-gate goto loop; 1637c478bd9Sstevel@tonic-gate if (isbreak(x) || isnext(x)) 1647c478bd9Sstevel@tonic-gate ERROR "illegal break or next from END" FATAL; 1657c478bd9Sstevel@tonic-gate tempfree(x, ""); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate ex1: 1687c478bd9Sstevel@tonic-gate return (true); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate struct Frame { 1727c478bd9Sstevel@tonic-gate int nargs; /* number of arguments in this call */ 1737c478bd9Sstevel@tonic-gate Cell *fcncell; /* pointer to Cell for function */ 1747c478bd9Sstevel@tonic-gate Cell **args; /* pointer to array of arguments after execute */ 1757c478bd9Sstevel@tonic-gate Cell *retval; /* return value */ 1767c478bd9Sstevel@tonic-gate }; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate #define NARGS 30 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */ 1817c478bd9Sstevel@tonic-gate int nframe = 0; /* number of frames allocated */ 1827c478bd9Sstevel@tonic-gate struct Frame *fp = NULL; /* frame pointer. bottom level unused */ 1837c478bd9Sstevel@tonic-gate 184*1ee2e5faSnakanon /*ARGSUSED*/ 185*1ee2e5faSnakanon Cell * 186*1ee2e5faSnakanon call(Node **a, int n) 1877c478bd9Sstevel@tonic-gate { 188*1ee2e5faSnakanon static Cell newcopycell = 189*1ee2e5faSnakanon { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE }; 1907c478bd9Sstevel@tonic-gate int i, ncall, ndef, freed = 0; 1917c478bd9Sstevel@tonic-gate Node *x; 1927c478bd9Sstevel@tonic-gate Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn; 1937c478bd9Sstevel@tonic-gate uchar *s; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate fcn = execute(a[0]); /* the function itself */ 1967c478bd9Sstevel@tonic-gate s = fcn->nval; 1977c478bd9Sstevel@tonic-gate if (!isfunc(fcn)) 1987c478bd9Sstevel@tonic-gate ERROR "calling undefined function %s", s FATAL; 1997c478bd9Sstevel@tonic-gate if (frame == NULL) { 200*1ee2e5faSnakanon fp = frame = (struct Frame *)calloc(nframe += 100, 201*1ee2e5faSnakanon sizeof (struct Frame)); 202*1ee2e5faSnakanon if (frame == NULL) { 203*1ee2e5faSnakanon ERROR "out of space for stack frames calling %s", 204*1ee2e5faSnakanon s FATAL; 205*1ee2e5faSnakanon } 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */ 2087c478bd9Sstevel@tonic-gate ncall++; 2097c478bd9Sstevel@tonic-gate ndef = (int)fcn->fval; /* args in defn */ 210*1ee2e5faSnakanon dprintf(("calling %s, %d args (%d in defn), fp=%d\n", 211*1ee2e5faSnakanon s, ncall, ndef, fp-frame)); 212*1ee2e5faSnakanon if (ncall > ndef) { 2137c478bd9Sstevel@tonic-gate ERROR "function %s called with %d args, uses only %d", 2147c478bd9Sstevel@tonic-gate s, ncall, ndef WARNING; 215*1ee2e5faSnakanon } 216*1ee2e5faSnakanon if (ncall + ndef > NARGS) { 217*1ee2e5faSnakanon ERROR "function %s has %d arguments, limit %d", 218*1ee2e5faSnakanon s, ncall+ndef, NARGS FATAL; 219*1ee2e5faSnakanon } 220*1ee2e5faSnakanon for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { 221*1ee2e5faSnakanon /* get call args */ 2227c478bd9Sstevel@tonic-gate dprintf(("evaluate args[%d], fp=%d:\n", i, fp-frame)); 2237c478bd9Sstevel@tonic-gate y = execute(x); 2247c478bd9Sstevel@tonic-gate oargs[i] = y; 2257c478bd9Sstevel@tonic-gate dprintf(("args[%d]: %s %f <%s>, t=%o\n", 226*1ee2e5faSnakanon i, y->nval, y->fval, 227*1ee2e5faSnakanon isarr(y) ? "(array)" : (char *)y->sval, y->tval)); 228*1ee2e5faSnakanon if (isfunc(y)) { 229*1ee2e5faSnakanon ERROR "can't use function %s as argument in %s", 230*1ee2e5faSnakanon y->nval, s FATAL; 231*1ee2e5faSnakanon } 2327c478bd9Sstevel@tonic-gate if (isarr(y)) 2337c478bd9Sstevel@tonic-gate args[i] = y; /* arrays by ref */ 2347c478bd9Sstevel@tonic-gate else 2357c478bd9Sstevel@tonic-gate args[i] = copycell(y); 2367c478bd9Sstevel@tonic-gate tempfree(y, "callargs"); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate for (; i < ndef; i++) { /* add null args for ones not provided */ 2397c478bd9Sstevel@tonic-gate args[i] = gettemp("nullargs"); 2407c478bd9Sstevel@tonic-gate *args[i] = newcopycell; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate fp++; /* now ok to up frame */ 2437c478bd9Sstevel@tonic-gate if (fp >= frame + nframe) { 2447c478bd9Sstevel@tonic-gate int dfp = fp - frame; /* old index */ 2457c478bd9Sstevel@tonic-gate frame = (struct Frame *) 2467c478bd9Sstevel@tonic-gate realloc(frame, (nframe += 100) * sizeof (struct Frame)); 2477c478bd9Sstevel@tonic-gate if (frame == NULL) 2487c478bd9Sstevel@tonic-gate ERROR "out of space for stack frames in %s", s FATAL; 2497c478bd9Sstevel@tonic-gate fp = frame + dfp; 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate fp->fcncell = fcn; 2527c478bd9Sstevel@tonic-gate fp->args = args; 2537c478bd9Sstevel@tonic-gate fp->nargs = ndef; /* number defined with (excess are locals) */ 2547c478bd9Sstevel@tonic-gate fp->retval = gettemp("retval"); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate dprintf(("start exec of %s, fp=%d\n", s, fp-frame)); 257*1ee2e5faSnakanon /*LINTED align*/ 2587c478bd9Sstevel@tonic-gate y = execute((Node *)(fcn->sval)); /* execute body */ 2597c478bd9Sstevel@tonic-gate dprintf(("finished exec of %s, fp=%d\n", s, fp-frame)); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate for (i = 0; i < ndef; i++) { 2627c478bd9Sstevel@tonic-gate Cell *t = fp->args[i]; 2637c478bd9Sstevel@tonic-gate if (isarr(t)) { 2647c478bd9Sstevel@tonic-gate if (t->csub == CCOPY) { 2657c478bd9Sstevel@tonic-gate if (i >= ncall) { 2667c478bd9Sstevel@tonic-gate freesymtab(t); 2677c478bd9Sstevel@tonic-gate t->csub = CTEMP; 2687c478bd9Sstevel@tonic-gate } else { 2697c478bd9Sstevel@tonic-gate oargs[i]->tval = t->tval; 2707c478bd9Sstevel@tonic-gate oargs[i]->tval &= ~(STR|NUM|DONTFREE); 2717c478bd9Sstevel@tonic-gate oargs[i]->sval = t->sval; 2727c478bd9Sstevel@tonic-gate tempfree(t, "oargsarr"); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate } else { 2767c478bd9Sstevel@tonic-gate t->csub = CTEMP; 2777c478bd9Sstevel@tonic-gate tempfree(t, "fp->args"); 2787c478bd9Sstevel@tonic-gate if (t == y) freed = 1; 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate tempfree(fcn, "call.fcn"); 2827c478bd9Sstevel@tonic-gate if (isexit(y) || isnext(y)) 283*1ee2e5faSnakanon return (y); 284*1ee2e5faSnakanon if (!freed) 285*1ee2e5faSnakanon tempfree(y, "fcn ret"); /* this can free twice! */ 2867c478bd9Sstevel@tonic-gate z = fp->retval; /* return value */ 287*1ee2e5faSnakanon dprintf(("%s returns %g |%s| %o\n", 288*1ee2e5faSnakanon s, getfval(z), getsval(z), z->tval)); 2897c478bd9Sstevel@tonic-gate fp--; 2907c478bd9Sstevel@tonic-gate return (z); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 293*1ee2e5faSnakanon static Cell * 294*1ee2e5faSnakanon copycell(Cell *x) /* make a copy of a cell in a temp */ 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate Cell *y; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate y = gettemp("copycell"); 2997c478bd9Sstevel@tonic-gate y->csub = CCOPY; /* prevents freeing until call is over */ 3007c478bd9Sstevel@tonic-gate y->nval = x->nval; 3017c478bd9Sstevel@tonic-gate y->sval = x->sval ? tostring(x->sval) : NULL; 3027c478bd9Sstevel@tonic-gate y->fval = x->fval; 303*1ee2e5faSnakanon /* copy is not constant or field is DONTFREE right? */ 304*1ee2e5faSnakanon y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); 305*1ee2e5faSnakanon return (y); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 308*1ee2e5faSnakanon /*ARGSUSED*/ 309*1ee2e5faSnakanon Cell * 310*1ee2e5faSnakanon arg(Node **a, int nnn) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate int n; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate n = (int)a[0]; /* argument number, counting from 0 */ 3157c478bd9Sstevel@tonic-gate dprintf(("arg(%d), fp->nargs=%d\n", n, fp->nargs)); 316*1ee2e5faSnakanon if (n+1 > fp->nargs) { 3177c478bd9Sstevel@tonic-gate ERROR "argument #%d of function %s was not supplied", 3187c478bd9Sstevel@tonic-gate n+1, fp->fcncell->nval FATAL; 319*1ee2e5faSnakanon } 320*1ee2e5faSnakanon return (fp->args[n]); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 323*1ee2e5faSnakanon Cell * 324*1ee2e5faSnakanon jump(Node **a, int n) 3257c478bd9Sstevel@tonic-gate { 3267c478bd9Sstevel@tonic-gate register Cell *y; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate switch (n) { 3297c478bd9Sstevel@tonic-gate case EXIT: 3307c478bd9Sstevel@tonic-gate if (a[0] != NULL) { 3317c478bd9Sstevel@tonic-gate y = execute(a[0]); 3327c478bd9Sstevel@tonic-gate errorflag = getfval(y); 3337c478bd9Sstevel@tonic-gate tempfree(y, ""); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate longjmp(env, 1); 336*1ee2e5faSnakanon /*NOTREACHED*/ 3377c478bd9Sstevel@tonic-gate case RETURN: 3387c478bd9Sstevel@tonic-gate if (a[0] != NULL) { 3397c478bd9Sstevel@tonic-gate y = execute(a[0]); 3407c478bd9Sstevel@tonic-gate if ((y->tval & (STR|NUM)) == (STR|NUM)) { 341*1ee2e5faSnakanon (void) setsval(fp->retval, getsval(y)); 3427c478bd9Sstevel@tonic-gate fp->retval->fval = getfval(y); 3437c478bd9Sstevel@tonic-gate fp->retval->tval |= NUM; 344*1ee2e5faSnakanon } else if (y->tval & STR) 345*1ee2e5faSnakanon (void) setsval(fp->retval, getsval(y)); 3467c478bd9Sstevel@tonic-gate else if (y->tval & NUM) 347*1ee2e5faSnakanon (void) setfval(fp->retval, getfval(y)); 3487c478bd9Sstevel@tonic-gate tempfree(y, ""); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate return (jret); 3517c478bd9Sstevel@tonic-gate case NEXT: 3527c478bd9Sstevel@tonic-gate return (jnext); 3537c478bd9Sstevel@tonic-gate case BREAK: 3547c478bd9Sstevel@tonic-gate return (jbreak); 3557c478bd9Sstevel@tonic-gate case CONTINUE: 3567c478bd9Sstevel@tonic-gate return (jcont); 3577c478bd9Sstevel@tonic-gate default: /* can't happen */ 3587c478bd9Sstevel@tonic-gate ERROR "illegal jump type %d", n FATAL; 3597c478bd9Sstevel@tonic-gate } 360*1ee2e5faSnakanon /*NOTREACHED*/ 361*1ee2e5faSnakanon return (NULL); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 364*1ee2e5faSnakanon Cell * 365*1ee2e5faSnakanon getline(Node **a, int n) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate /* a[0] is variable, a[1] is operator, a[2] is filename */ 3687c478bd9Sstevel@tonic-gate register Cell *r, *x; 369*1ee2e5faSnakanon uchar *buf; 3707c478bd9Sstevel@tonic-gate FILE *fp; 371*1ee2e5faSnakanon size_t len; 3727c478bd9Sstevel@tonic-gate 373*1ee2e5faSnakanon (void) fflush(stdout); /* in case someone is waiting for a prompt */ 3747c478bd9Sstevel@tonic-gate r = gettemp(""); 3757c478bd9Sstevel@tonic-gate if (a[1] != NULL) { /* getline < file */ 3767c478bd9Sstevel@tonic-gate x = execute(a[2]); /* filename */ 3777c478bd9Sstevel@tonic-gate if ((int)a[1] == '|') /* input pipe */ 3787c478bd9Sstevel@tonic-gate a[1] = (Node *)LE; /* arbitrary flag */ 3797c478bd9Sstevel@tonic-gate fp = openfile((int)a[1], getsval(x)); 3807c478bd9Sstevel@tonic-gate tempfree(x, ""); 381*1ee2e5faSnakanon buf = NULL; 3827c478bd9Sstevel@tonic-gate if (fp == NULL) 3837c478bd9Sstevel@tonic-gate n = -1; 3847c478bd9Sstevel@tonic-gate else 385*1ee2e5faSnakanon n = readrec(&buf, &len, fp); 386*1ee2e5faSnakanon if (n > 0) { 387*1ee2e5faSnakanon if (a[0] != NULL) { /* getline var <file */ 388*1ee2e5faSnakanon (void) setsval(execute(a[0]), buf); 3897c478bd9Sstevel@tonic-gate } else { /* getline <file */ 3907c478bd9Sstevel@tonic-gate if (!(recloc->tval & DONTFREE)) 3917c478bd9Sstevel@tonic-gate xfree(recloc->sval); 392*1ee2e5faSnakanon expand_buf(&record, &record_size, len); 393*1ee2e5faSnakanon (void) memcpy(record, buf, len); 394*1ee2e5faSnakanon record[len] = '\0'; 3957c478bd9Sstevel@tonic-gate recloc->sval = record; 3967c478bd9Sstevel@tonic-gate recloc->tval = REC | STR | DONTFREE; 3977c478bd9Sstevel@tonic-gate donerec = 1; donefld = 0; 3987c478bd9Sstevel@tonic-gate } 399*1ee2e5faSnakanon } 400*1ee2e5faSnakanon if (buf != NULL) 401*1ee2e5faSnakanon free(buf); 4027c478bd9Sstevel@tonic-gate } else { /* bare getline; use current input */ 4037c478bd9Sstevel@tonic-gate if (a[0] == NULL) /* getline */ 404*1ee2e5faSnakanon n = getrec(&record, &record_size); 4057c478bd9Sstevel@tonic-gate else { /* getline var */ 406*1ee2e5faSnakanon init_buf(&buf, &len, LINE_INCR); 407*1ee2e5faSnakanon n = getrec(&buf, &len); 408*1ee2e5faSnakanon (void) setsval(execute(a[0]), buf); 409*1ee2e5faSnakanon free(buf); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate } 412*1ee2e5faSnakanon (void) setfval(r, (Awkfloat)n); 413*1ee2e5faSnakanon return (r); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 416*1ee2e5faSnakanon /*ARGSUSED*/ 417*1ee2e5faSnakanon Cell * 418*1ee2e5faSnakanon getnf(Node **a, int n) 4197c478bd9Sstevel@tonic-gate { 4207c478bd9Sstevel@tonic-gate if (donefld == 0) 4217c478bd9Sstevel@tonic-gate fldbld(); 422*1ee2e5faSnakanon return ((Cell *)a[0]); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 425*1ee2e5faSnakanon /*ARGSUSED*/ 426*1ee2e5faSnakanon Cell * 427*1ee2e5faSnakanon array(Node **a, int n) 4287c478bd9Sstevel@tonic-gate { 4297c478bd9Sstevel@tonic-gate register Cell *x, *y, *z; 4307c478bd9Sstevel@tonic-gate register uchar *s; 4317c478bd9Sstevel@tonic-gate register Node *np; 432*1ee2e5faSnakanon uchar *buf; 433*1ee2e5faSnakanon size_t bsize, tlen, len, slen; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate x = execute(a[0]); /* Cell* for symbol table */ 436*1ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR); 437*1ee2e5faSnakanon buf[0] = '\0'; 438*1ee2e5faSnakanon tlen = 0; 439*1ee2e5faSnakanon slen = strlen((char *)*SUBSEP); 4407c478bd9Sstevel@tonic-gate for (np = a[1]; np; np = np->nnext) { 4417c478bd9Sstevel@tonic-gate y = execute(np); /* subscript */ 4427c478bd9Sstevel@tonic-gate s = getsval(y); 443*1ee2e5faSnakanon len = strlen((char *)s); 444*1ee2e5faSnakanon expand_buf(&buf, &bsize, tlen + len + slen); 445*1ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len); 446*1ee2e5faSnakanon tlen += len; 447*1ee2e5faSnakanon if (np->nnext) { 448*1ee2e5faSnakanon (void) memcpy(&buf[tlen], *SUBSEP, slen); 449*1ee2e5faSnakanon tlen += slen; 450*1ee2e5faSnakanon } 451*1ee2e5faSnakanon buf[tlen] = '\0'; 4527c478bd9Sstevel@tonic-gate tempfree(y, ""); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate if (!isarr(x)) { 4557c478bd9Sstevel@tonic-gate dprintf(("making %s into an array\n", x->nval)); 4567c478bd9Sstevel@tonic-gate if (freeable(x)) 4577c478bd9Sstevel@tonic-gate xfree(x->sval); 4587c478bd9Sstevel@tonic-gate x->tval &= ~(STR|NUM|DONTFREE); 4597c478bd9Sstevel@tonic-gate x->tval |= ARR; 4607c478bd9Sstevel@tonic-gate x->sval = (uchar *) makesymtab(NSYMTAB); 4617c478bd9Sstevel@tonic-gate } 462*1ee2e5faSnakanon /*LINTED align*/ 463*1ee2e5faSnakanon z = setsymtab(buf, (uchar *)"", 0.0, STR|NUM, (Array *)x->sval); 4647c478bd9Sstevel@tonic-gate z->ctype = OCELL; 4657c478bd9Sstevel@tonic-gate z->csub = CVAR; 4667c478bd9Sstevel@tonic-gate tempfree(x, ""); 467*1ee2e5faSnakanon free(buf); 4687c478bd9Sstevel@tonic-gate return (z); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 471*1ee2e5faSnakanon /*ARGSUSED*/ 472*1ee2e5faSnakanon Cell * 473*1ee2e5faSnakanon delete(Node **a, int n) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate Cell *x, *y; 4767c478bd9Sstevel@tonic-gate Node *np; 477*1ee2e5faSnakanon uchar *buf, *s; 478*1ee2e5faSnakanon size_t bsize, tlen, slen, len; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate x = execute(a[0]); /* Cell* for symbol table */ 4817c478bd9Sstevel@tonic-gate if (!isarr(x)) 482*1ee2e5faSnakanon return (true); 483*1ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR); 484*1ee2e5faSnakanon buf[0] = '\0'; 485*1ee2e5faSnakanon tlen = 0; 486*1ee2e5faSnakanon slen = strlen((char *)*SUBSEP); 4877c478bd9Sstevel@tonic-gate for (np = a[1]; np; np = np->nnext) { 4887c478bd9Sstevel@tonic-gate y = execute(np); /* subscript */ 4897c478bd9Sstevel@tonic-gate s = getsval(y); 490*1ee2e5faSnakanon len = strlen((char *)s); 491*1ee2e5faSnakanon expand_buf(&buf, &bsize, tlen + len + slen); 492*1ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len); 493*1ee2e5faSnakanon tlen += len; 494*1ee2e5faSnakanon if (np->nnext) { 495*1ee2e5faSnakanon (void) memcpy(&buf[tlen], *SUBSEP, slen); 496*1ee2e5faSnakanon tlen += slen; 497*1ee2e5faSnakanon } 498*1ee2e5faSnakanon buf[tlen] = '\0'; 4997c478bd9Sstevel@tonic-gate tempfree(y, ""); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate freeelem(x, buf); 5027c478bd9Sstevel@tonic-gate tempfree(x, ""); 503*1ee2e5faSnakanon free(buf); 504*1ee2e5faSnakanon return (true); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 507*1ee2e5faSnakanon /*ARGSUSED*/ 508*1ee2e5faSnakanon Cell * 509*1ee2e5faSnakanon intest(Node **a, int n) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate register Cell *x, *ap, *k; 5127c478bd9Sstevel@tonic-gate Node *p; 513*1ee2e5faSnakanon uchar *buf; 5147c478bd9Sstevel@tonic-gate uchar *s; 515*1ee2e5faSnakanon size_t bsize, tlen, slen, len; 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate ap = execute(a[1]); /* array name */ 5187c478bd9Sstevel@tonic-gate if (!isarr(ap)) 5197c478bd9Sstevel@tonic-gate ERROR "%s is not an array", ap->nval FATAL; 520*1ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR); 5217c478bd9Sstevel@tonic-gate buf[0] = 0; 522*1ee2e5faSnakanon tlen = 0; 523*1ee2e5faSnakanon slen = strlen((char *)*SUBSEP); 5247c478bd9Sstevel@tonic-gate for (p = a[0]; p; p = p->nnext) { 5257c478bd9Sstevel@tonic-gate x = execute(p); /* expr */ 5267c478bd9Sstevel@tonic-gate s = getsval(x); 527*1ee2e5faSnakanon len = strlen((char *)s); 528*1ee2e5faSnakanon expand_buf(&buf, &bsize, tlen + len + slen); 529*1ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len); 530*1ee2e5faSnakanon tlen += len; 5317c478bd9Sstevel@tonic-gate tempfree(x, ""); 532*1ee2e5faSnakanon if (p->nnext) { 533*1ee2e5faSnakanon (void) memcpy(&buf[tlen], *SUBSEP, slen); 534*1ee2e5faSnakanon tlen += slen; 5357c478bd9Sstevel@tonic-gate } 536*1ee2e5faSnakanon buf[tlen] = '\0'; 537*1ee2e5faSnakanon } 538*1ee2e5faSnakanon /*LINTED align*/ 5397c478bd9Sstevel@tonic-gate k = lookup(buf, (Array *)ap->sval); 5407c478bd9Sstevel@tonic-gate tempfree(ap, ""); 541*1ee2e5faSnakanon free(buf); 5427c478bd9Sstevel@tonic-gate if (k == NULL) 5437c478bd9Sstevel@tonic-gate return (false); 5447c478bd9Sstevel@tonic-gate else 5457c478bd9Sstevel@tonic-gate return (true); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate 549*1ee2e5faSnakanon Cell * 550*1ee2e5faSnakanon matchop(Node **a, int n) 5517c478bd9Sstevel@tonic-gate { 5527c478bd9Sstevel@tonic-gate register Cell *x, *y; 5537c478bd9Sstevel@tonic-gate register uchar *s, *t; 5547c478bd9Sstevel@tonic-gate register int i; 5557c478bd9Sstevel@tonic-gate fa *pfa; 5567c478bd9Sstevel@tonic-gate int (*mf)() = match, mode = 0; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate if (n == MATCHFCN) { 5597c478bd9Sstevel@tonic-gate mf = pmatch; 5607c478bd9Sstevel@tonic-gate mode = 1; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate x = execute(a[1]); 5637c478bd9Sstevel@tonic-gate s = getsval(x); 5647c478bd9Sstevel@tonic-gate if (a[0] == 0) 5657c478bd9Sstevel@tonic-gate i = (*mf)(a[2], s); 5667c478bd9Sstevel@tonic-gate else { 5677c478bd9Sstevel@tonic-gate y = execute(a[2]); 5687c478bd9Sstevel@tonic-gate t = getsval(y); 5697c478bd9Sstevel@tonic-gate pfa = makedfa(t, mode); 5707c478bd9Sstevel@tonic-gate i = (*mf)(pfa, s); 5717c478bd9Sstevel@tonic-gate tempfree(y, ""); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate tempfree(x, ""); 5747c478bd9Sstevel@tonic-gate if (n == MATCHFCN) { 5757c478bd9Sstevel@tonic-gate int start = patbeg - s + 1; 5767c478bd9Sstevel@tonic-gate if (patlen < 0) 5777c478bd9Sstevel@tonic-gate start = 0; 578*1ee2e5faSnakanon (void) setfval(rstartloc, (Awkfloat)start); 579*1ee2e5faSnakanon (void) setfval(rlengthloc, (Awkfloat)patlen); 5807c478bd9Sstevel@tonic-gate x = gettemp(""); 5817c478bd9Sstevel@tonic-gate x->tval = NUM; 5827c478bd9Sstevel@tonic-gate x->fval = start; 583*1ee2e5faSnakanon return (x); 5847c478bd9Sstevel@tonic-gate } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0) 5857c478bd9Sstevel@tonic-gate return (true); 5867c478bd9Sstevel@tonic-gate else 5877c478bd9Sstevel@tonic-gate return (false); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate 591*1ee2e5faSnakanon Cell * 592*1ee2e5faSnakanon boolop(Node **a, int n) 5937c478bd9Sstevel@tonic-gate { 5947c478bd9Sstevel@tonic-gate register Cell *x, *y; 5957c478bd9Sstevel@tonic-gate register int i; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate x = execute(a[0]); 5987c478bd9Sstevel@tonic-gate i = istrue(x); 5997c478bd9Sstevel@tonic-gate tempfree(x, ""); 6007c478bd9Sstevel@tonic-gate switch (n) { 6017c478bd9Sstevel@tonic-gate case BOR: 602*1ee2e5faSnakanon if (i) 603*1ee2e5faSnakanon return (true); 6047c478bd9Sstevel@tonic-gate y = execute(a[1]); 6057c478bd9Sstevel@tonic-gate i = istrue(y); 6067c478bd9Sstevel@tonic-gate tempfree(y, ""); 607*1ee2e5faSnakanon return (i ? true : false); 6087c478bd9Sstevel@tonic-gate case AND: 609*1ee2e5faSnakanon if (!i) 610*1ee2e5faSnakanon return (false); 6117c478bd9Sstevel@tonic-gate y = execute(a[1]); 6127c478bd9Sstevel@tonic-gate i = istrue(y); 6137c478bd9Sstevel@tonic-gate tempfree(y, ""); 614*1ee2e5faSnakanon return (i ? true : false); 6157c478bd9Sstevel@tonic-gate case NOT: 616*1ee2e5faSnakanon return (i ? false : true); 6177c478bd9Sstevel@tonic-gate default: /* can't happen */ 6187c478bd9Sstevel@tonic-gate ERROR "unknown boolean operator %d", n FATAL; 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 621*1ee2e5faSnakanon return (NULL); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 624*1ee2e5faSnakanon Cell * 625*1ee2e5faSnakanon relop(Node **a, int n) 6267c478bd9Sstevel@tonic-gate { 6277c478bd9Sstevel@tonic-gate register int i; 6287c478bd9Sstevel@tonic-gate register Cell *x, *y; 6297c478bd9Sstevel@tonic-gate Awkfloat j; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate x = execute(a[0]); 6327c478bd9Sstevel@tonic-gate y = execute(a[1]); 6337c478bd9Sstevel@tonic-gate if (x->tval&NUM && y->tval&NUM) { 6347c478bd9Sstevel@tonic-gate j = x->fval - y->fval; 6357c478bd9Sstevel@tonic-gate i = j < 0 ? -1: (j > 0 ? 1: 0); 6367c478bd9Sstevel@tonic-gate } else { 637*1ee2e5faSnakanon i = strcmp((char *)getsval(x), (char *)getsval(y)); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate tempfree(x, ""); 6407c478bd9Sstevel@tonic-gate tempfree(y, ""); 6417c478bd9Sstevel@tonic-gate switch (n) { 642*1ee2e5faSnakanon case LT: return (i < 0 ? true : false); 643*1ee2e5faSnakanon case LE: return (i <= 0 ? true : false); 644*1ee2e5faSnakanon case NE: return (i != 0 ? true : false); 645*1ee2e5faSnakanon case EQ: return (i == 0 ? true : false); 646*1ee2e5faSnakanon case GE: return (i >= 0 ? true : false); 647*1ee2e5faSnakanon case GT: return (i > 0 ? true : false); 6487c478bd9Sstevel@tonic-gate default: /* can't happen */ 6497c478bd9Sstevel@tonic-gate ERROR "unknown relational operator %d", n FATAL; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 652*1ee2e5faSnakanon return (false); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 655*1ee2e5faSnakanon static void 656*1ee2e5faSnakanon tfree(Cell *a, char *s) 6577c478bd9Sstevel@tonic-gate { 658*1ee2e5faSnakanon if (dbg > 1) { 659*1ee2e5faSnakanon (void) printf("## tfree %.8s %06lo %s\n", 660*1ee2e5faSnakanon s, (ulong_t)a, a->sval ? a->sval : (uchar *)""); 661*1ee2e5faSnakanon } 6627c478bd9Sstevel@tonic-gate if (freeable(a)) 6637c478bd9Sstevel@tonic-gate xfree(a->sval); 6647c478bd9Sstevel@tonic-gate if (a == tmps) 6657c478bd9Sstevel@tonic-gate ERROR "tempcell list is curdled" FATAL; 6667c478bd9Sstevel@tonic-gate a->cnext = tmps; 6677c478bd9Sstevel@tonic-gate tmps = a; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 670*1ee2e5faSnakanon static Cell * 671*1ee2e5faSnakanon gettemp(char *s) 672*1ee2e5faSnakanon { 673*1ee2e5faSnakanon int i; 6747c478bd9Sstevel@tonic-gate register Cell *x; 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate if (!tmps) { 6777c478bd9Sstevel@tonic-gate tmps = (Cell *)calloc(100, sizeof (Cell)); 6787c478bd9Sstevel@tonic-gate if (!tmps) 6797c478bd9Sstevel@tonic-gate ERROR "no space for temporaries" FATAL; 6807c478bd9Sstevel@tonic-gate for (i = 1; i < 100; i++) 6817c478bd9Sstevel@tonic-gate tmps[i-1].cnext = &tmps[i]; 6827c478bd9Sstevel@tonic-gate tmps[i-1].cnext = 0; 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate x = tmps; 6857c478bd9Sstevel@tonic-gate tmps = x->cnext; 6867c478bd9Sstevel@tonic-gate *x = tempcell; 687*1ee2e5faSnakanon if (dbg > 1) 688*1ee2e5faSnakanon (void) printf("## gtemp %.8s %06lo\n", s, (ulong_t)x); 6897c478bd9Sstevel@tonic-gate return (x); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate 692*1ee2e5faSnakanon /*ARGSUSED*/ 693*1ee2e5faSnakanon Cell * 694*1ee2e5faSnakanon indirect(Node **a, int n) 6957c478bd9Sstevel@tonic-gate { 6967c478bd9Sstevel@tonic-gate register Cell *x; 6977c478bd9Sstevel@tonic-gate register int m; 6987c478bd9Sstevel@tonic-gate register uchar *s; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate x = execute(a[0]); 7017c478bd9Sstevel@tonic-gate m = getfval(x); 702*1ee2e5faSnakanon if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */ 7037c478bd9Sstevel@tonic-gate ERROR "illegal field $(%s)", s FATAL; 7047c478bd9Sstevel@tonic-gate tempfree(x, ""); 7057c478bd9Sstevel@tonic-gate x = fieldadr(m); 7067c478bd9Sstevel@tonic-gate x->ctype = OCELL; 7077c478bd9Sstevel@tonic-gate x->csub = CFLD; 7087c478bd9Sstevel@tonic-gate return (x); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 711*1ee2e5faSnakanon /*ARGSUSED*/ 712*1ee2e5faSnakanon Cell * 713*1ee2e5faSnakanon substr(Node **a, int nnn) 7147c478bd9Sstevel@tonic-gate { 7157c478bd9Sstevel@tonic-gate register int k, m, n; 7167c478bd9Sstevel@tonic-gate register uchar *s; 7177c478bd9Sstevel@tonic-gate int temp; 7187c478bd9Sstevel@tonic-gate register Cell *x, *y, *z; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate x = execute(a[0]); 7217c478bd9Sstevel@tonic-gate y = execute(a[1]); 7227c478bd9Sstevel@tonic-gate if (a[2] != 0) 7237c478bd9Sstevel@tonic-gate z = execute(a[2]); 7247c478bd9Sstevel@tonic-gate s = getsval(x); 725*1ee2e5faSnakanon k = strlen((char *)s) + 1; 7267c478bd9Sstevel@tonic-gate if (k <= 1) { 7277c478bd9Sstevel@tonic-gate tempfree(x, ""); 7287c478bd9Sstevel@tonic-gate tempfree(y, ""); 7297c478bd9Sstevel@tonic-gate if (a[2] != 0) 7307c478bd9Sstevel@tonic-gate tempfree(z, ""); 7317c478bd9Sstevel@tonic-gate x = gettemp(""); 732*1ee2e5faSnakanon (void) setsval(x, (uchar *)""); 7337c478bd9Sstevel@tonic-gate return (x); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate m = getfval(y); 7367c478bd9Sstevel@tonic-gate if (m <= 0) 7377c478bd9Sstevel@tonic-gate m = 1; 7387c478bd9Sstevel@tonic-gate else if (m > k) 7397c478bd9Sstevel@tonic-gate m = k; 7407c478bd9Sstevel@tonic-gate tempfree(y, ""); 7417c478bd9Sstevel@tonic-gate if (a[2] != 0) { 7427c478bd9Sstevel@tonic-gate n = getfval(z); 7437c478bd9Sstevel@tonic-gate tempfree(z, ""); 7447c478bd9Sstevel@tonic-gate } else 7457c478bd9Sstevel@tonic-gate n = k - 1; 7467c478bd9Sstevel@tonic-gate if (n < 0) 7477c478bd9Sstevel@tonic-gate n = 0; 7487c478bd9Sstevel@tonic-gate else if (n > k - m) 7497c478bd9Sstevel@tonic-gate n = k - m; 7507c478bd9Sstevel@tonic-gate dprintf(("substr: m=%d, n=%d, s=%s\n", m, n, s)); 7517c478bd9Sstevel@tonic-gate y = gettemp(""); 7527c478bd9Sstevel@tonic-gate temp = s[n + m - 1]; /* with thanks to John Linderman */ 7537c478bd9Sstevel@tonic-gate s[n + m - 1] = '\0'; 754*1ee2e5faSnakanon (void) setsval(y, s + m - 1); 7557c478bd9Sstevel@tonic-gate s[n + m - 1] = temp; 7567c478bd9Sstevel@tonic-gate tempfree(x, ""); 7577c478bd9Sstevel@tonic-gate return (y); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 760*1ee2e5faSnakanon /*ARGSUSED*/ 761*1ee2e5faSnakanon Cell * 762*1ee2e5faSnakanon sindex(Node **a, int nnn) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate register Cell *x, *y, *z; 7657c478bd9Sstevel@tonic-gate register uchar *s1, *s2, *p1, *p2, *q; 7667c478bd9Sstevel@tonic-gate Awkfloat v = 0.0; 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate x = execute(a[0]); 7697c478bd9Sstevel@tonic-gate s1 = getsval(x); 7707c478bd9Sstevel@tonic-gate y = execute(a[1]); 7717c478bd9Sstevel@tonic-gate s2 = getsval(y); 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate z = gettemp(""); 7747c478bd9Sstevel@tonic-gate for (p1 = s1; *p1 != '\0'; p1++) { 7757c478bd9Sstevel@tonic-gate for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++) 7767c478bd9Sstevel@tonic-gate ; 7777c478bd9Sstevel@tonic-gate if (*p2 == '\0') { 7787c478bd9Sstevel@tonic-gate v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */ 7797c478bd9Sstevel@tonic-gate break; 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate tempfree(x, ""); 7837c478bd9Sstevel@tonic-gate tempfree(y, ""); 784*1ee2e5faSnakanon (void) setfval(z, v); 7857c478bd9Sstevel@tonic-gate return (z); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 788*1ee2e5faSnakanon void 789*1ee2e5faSnakanon format(uchar **bufp, uchar *s, Node *a) 7907c478bd9Sstevel@tonic-gate { 791*1ee2e5faSnakanon uchar *fmt; 792*1ee2e5faSnakanon register uchar *os; 7937c478bd9Sstevel@tonic-gate register Cell *x; 794*1ee2e5faSnakanon int flag = 0, len; 795*1ee2e5faSnakanon uchar_t *buf; 796*1ee2e5faSnakanon size_t bufsize, fmtsize, cnt, tcnt, ret; 7977c478bd9Sstevel@tonic-gate 798*1ee2e5faSnakanon init_buf(&buf, &bufsize, LINE_INCR); 799*1ee2e5faSnakanon init_buf(&fmt, &fmtsize, LINE_INCR); 8007c478bd9Sstevel@tonic-gate os = s; 801*1ee2e5faSnakanon cnt = 0; 8027c478bd9Sstevel@tonic-gate while (*s) { 8037c478bd9Sstevel@tonic-gate if (*s != '%') { 804*1ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt); 805*1ee2e5faSnakanon buf[cnt++] = *s++; 8067c478bd9Sstevel@tonic-gate continue; 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate if (*(s+1) == '%') { 809*1ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt); 810*1ee2e5faSnakanon buf[cnt++] = '%'; 8117c478bd9Sstevel@tonic-gate s += 2; 8127c478bd9Sstevel@tonic-gate continue; 8137c478bd9Sstevel@tonic-gate } 814*1ee2e5faSnakanon for (tcnt = 0; ; s++) { 815*1ee2e5faSnakanon expand_buf(&fmt, &fmtsize, tcnt); 816*1ee2e5faSnakanon fmt[tcnt++] = *s; 817*1ee2e5faSnakanon if (*s == '\0') 818*1ee2e5faSnakanon break; 8197c478bd9Sstevel@tonic-gate if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L') 8207c478bd9Sstevel@tonic-gate break; /* the ansi panoply */ 8217c478bd9Sstevel@tonic-gate if (*s == '*') { 8227c478bd9Sstevel@tonic-gate if (a == NULL) { 8237c478bd9Sstevel@tonic-gate ERROR 8247c478bd9Sstevel@tonic-gate "not enough args in printf(%s) or sprintf(%s)", os, os FATAL; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate x = execute(a); 8277c478bd9Sstevel@tonic-gate a = a->nnext; 828*1ee2e5faSnakanon tcnt--; 829*1ee2e5faSnakanon expand_buf(&fmt, &fmtsize, tcnt + 12); 830*1ee2e5faSnakanon ret = sprintf((char *)&fmt[tcnt], "%d", 831*1ee2e5faSnakanon (int)getfval(x)); 832*1ee2e5faSnakanon tcnt += ret; 8337c478bd9Sstevel@tonic-gate tempfree(x, ""); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate } 836*1ee2e5faSnakanon fmt[tcnt] = '\0'; 837*1ee2e5faSnakanon 8387c478bd9Sstevel@tonic-gate switch (*s) { 8397c478bd9Sstevel@tonic-gate case 'f': case 'e': case 'g': case 'E': case 'G': 8407c478bd9Sstevel@tonic-gate flag = 1; 8417c478bd9Sstevel@tonic-gate break; 8427c478bd9Sstevel@tonic-gate case 'd': case 'i': 8437c478bd9Sstevel@tonic-gate flag = 2; 844*1ee2e5faSnakanon if (*(s-1) == 'l') 845*1ee2e5faSnakanon break; 846*1ee2e5faSnakanon fmt[tcnt - 1] = 'l'; 847*1ee2e5faSnakanon expand_buf(&fmt, &fmtsize, tcnt); 848*1ee2e5faSnakanon fmt[tcnt++] = 'd'; 849*1ee2e5faSnakanon fmt[tcnt] = '\0'; 8507c478bd9Sstevel@tonic-gate break; 8517c478bd9Sstevel@tonic-gate case 'o': case 'x': case 'X': case 'u': 8527c478bd9Sstevel@tonic-gate flag = *(s-1) == 'l' ? 2 : 3; 8537c478bd9Sstevel@tonic-gate break; 8547c478bd9Sstevel@tonic-gate case 's': 8557c478bd9Sstevel@tonic-gate flag = 4; 8567c478bd9Sstevel@tonic-gate break; 8577c478bd9Sstevel@tonic-gate case 'c': 8587c478bd9Sstevel@tonic-gate flag = 5; 8597c478bd9Sstevel@tonic-gate break; 8607c478bd9Sstevel@tonic-gate default: 8617c478bd9Sstevel@tonic-gate flag = 0; 8627c478bd9Sstevel@tonic-gate break; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate if (flag == 0) { 865*1ee2e5faSnakanon len = strlen((char *)fmt); 866*1ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + len); 867*1ee2e5faSnakanon (void) memcpy(&buf[cnt], fmt, len); 868*1ee2e5faSnakanon cnt += len; 869*1ee2e5faSnakanon buf[cnt] = '\0'; 8707c478bd9Sstevel@tonic-gate continue; 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate if (a == NULL) { 8737c478bd9Sstevel@tonic-gate ERROR 8747c478bd9Sstevel@tonic-gate "not enough args in printf(%s) or sprintf(%s)", os, os FATAL; 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate x = execute(a); 8777c478bd9Sstevel@tonic-gate a = a->nnext; 878*1ee2e5faSnakanon for (;;) { 879*1ee2e5faSnakanon /* make sure we have at least 1 byte space */ 880*1ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + 1); 881*1ee2e5faSnakanon len = bufsize - cnt; 8827c478bd9Sstevel@tonic-gate switch (flag) { 883*1ee2e5faSnakanon case 1: 884*1ee2e5faSnakanon /*LINTED*/ 885*1ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len, 886*1ee2e5faSnakanon (char *)fmt, getfval(x)); 8877c478bd9Sstevel@tonic-gate break; 888*1ee2e5faSnakanon case 2: 889*1ee2e5faSnakanon /*LINTED*/ 890*1ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len, 891*1ee2e5faSnakanon (char *)fmt, (long)getfval(x)); 892*1ee2e5faSnakanon break; 893*1ee2e5faSnakanon case 3: 894*1ee2e5faSnakanon /*LINTED*/ 895*1ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len, 896*1ee2e5faSnakanon (char *)fmt, (int)getfval(x)); 897*1ee2e5faSnakanon break; 898*1ee2e5faSnakanon case 4: 899*1ee2e5faSnakanon /*LINTED*/ 900*1ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len, 901*1ee2e5faSnakanon (char *)fmt, getsval(x)); 902*1ee2e5faSnakanon break; 903*1ee2e5faSnakanon case 5: 904*1ee2e5faSnakanon if (isnum(x)) { 905*1ee2e5faSnakanon /*LINTED*/ 906*1ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len, 907*1ee2e5faSnakanon (char *)fmt, (int)getfval(x)); 908*1ee2e5faSnakanon } else { 909*1ee2e5faSnakanon /*LINTED*/ 910*1ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len, 911*1ee2e5faSnakanon (char *)fmt, getsval(x)[0]); 912*1ee2e5faSnakanon } 913*1ee2e5faSnakanon break; 914*1ee2e5faSnakanon default: 915*1ee2e5faSnakanon ret = 0; 916*1ee2e5faSnakanon } 917*1ee2e5faSnakanon if (ret < len) 918*1ee2e5faSnakanon break; 919*1ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + ret); 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate tempfree(x, ""); 922*1ee2e5faSnakanon cnt += ret; 9237c478bd9Sstevel@tonic-gate s++; 9247c478bd9Sstevel@tonic-gate } 925*1ee2e5faSnakanon buf[cnt] = '\0'; 9267c478bd9Sstevel@tonic-gate for (; a; a = a->nnext) /* evaluate any remaining args */ 927*1ee2e5faSnakanon (void) execute(a); 928*1ee2e5faSnakanon *bufp = tostring(buf); 929*1ee2e5faSnakanon free(buf); 930*1ee2e5faSnakanon free(fmt); 9317c478bd9Sstevel@tonic-gate } 9327c478bd9Sstevel@tonic-gate 933*1ee2e5faSnakanon /*ARGSUSED*/ 934*1ee2e5faSnakanon Cell * 935*1ee2e5faSnakanon asprintf(Node **a, int n) 9367c478bd9Sstevel@tonic-gate { 9377c478bd9Sstevel@tonic-gate register Cell *x; 9387c478bd9Sstevel@tonic-gate register Node *y; 939*1ee2e5faSnakanon uchar *buf; 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate y = a[0]->nnext; 9427c478bd9Sstevel@tonic-gate x = execute(a[0]); 943*1ee2e5faSnakanon format(&buf, getsval(x), y); 9447c478bd9Sstevel@tonic-gate tempfree(x, ""); 9457c478bd9Sstevel@tonic-gate x = gettemp(""); 946*1ee2e5faSnakanon x->sval = buf; 9477c478bd9Sstevel@tonic-gate x->tval = STR; 9487c478bd9Sstevel@tonic-gate return (x); 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 951*1ee2e5faSnakanon /*ARGSUSED*/ 952*1ee2e5faSnakanon Cell * 953*1ee2e5faSnakanon aprintf(Node **a, int n) 9547c478bd9Sstevel@tonic-gate { 9557c478bd9Sstevel@tonic-gate FILE *fp; 9567c478bd9Sstevel@tonic-gate register Cell *x; 9577c478bd9Sstevel@tonic-gate register Node *y; 958*1ee2e5faSnakanon uchar *buf; 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate y = a[0]->nnext; 9617c478bd9Sstevel@tonic-gate x = execute(a[0]); 962*1ee2e5faSnakanon format(&buf, getsval(x), y); 9637c478bd9Sstevel@tonic-gate tempfree(x, ""); 9647c478bd9Sstevel@tonic-gate if (a[1] == NULL) 965*1ee2e5faSnakanon (void) fputs((char *)buf, stdout); 9667c478bd9Sstevel@tonic-gate else { 9677c478bd9Sstevel@tonic-gate fp = redirect((int)a[1], a[2]); 968*1ee2e5faSnakanon (void) fputs((char *)buf, fp); 969*1ee2e5faSnakanon (void) fflush(fp); 9707c478bd9Sstevel@tonic-gate } 971*1ee2e5faSnakanon free(buf); 9727c478bd9Sstevel@tonic-gate return (true); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 975*1ee2e5faSnakanon Cell * 976*1ee2e5faSnakanon arith(Node **a, int n) 9777c478bd9Sstevel@tonic-gate { 9787c478bd9Sstevel@tonic-gate Awkfloat i, j; 979*1ee2e5faSnakanon double v; 9807c478bd9Sstevel@tonic-gate register Cell *x, *y, *z; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate x = execute(a[0]); 9837c478bd9Sstevel@tonic-gate i = getfval(x); 9847c478bd9Sstevel@tonic-gate tempfree(x, ""); 9857c478bd9Sstevel@tonic-gate if (n != UMINUS) { 9867c478bd9Sstevel@tonic-gate y = execute(a[1]); 9877c478bd9Sstevel@tonic-gate j = getfval(y); 9887c478bd9Sstevel@tonic-gate tempfree(y, ""); 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate z = gettemp(""); 9917c478bd9Sstevel@tonic-gate switch (n) { 9927c478bd9Sstevel@tonic-gate case ADD: 9937c478bd9Sstevel@tonic-gate i += j; 9947c478bd9Sstevel@tonic-gate break; 9957c478bd9Sstevel@tonic-gate case MINUS: 9967c478bd9Sstevel@tonic-gate i -= j; 9977c478bd9Sstevel@tonic-gate break; 9987c478bd9Sstevel@tonic-gate case MULT: 9997c478bd9Sstevel@tonic-gate i *= j; 10007c478bd9Sstevel@tonic-gate break; 10017c478bd9Sstevel@tonic-gate case DIVIDE: 10027c478bd9Sstevel@tonic-gate if (j == 0) 10037c478bd9Sstevel@tonic-gate ERROR "division by zero" FATAL; 10047c478bd9Sstevel@tonic-gate i /= j; 10057c478bd9Sstevel@tonic-gate break; 10067c478bd9Sstevel@tonic-gate case MOD: 10077c478bd9Sstevel@tonic-gate if (j == 0) 10087c478bd9Sstevel@tonic-gate ERROR "division by zero in mod" FATAL; 1009*1ee2e5faSnakanon (void) modf(i/j, &v); 10107c478bd9Sstevel@tonic-gate i = i - j * v; 10117c478bd9Sstevel@tonic-gate break; 10127c478bd9Sstevel@tonic-gate case UMINUS: 10137c478bd9Sstevel@tonic-gate i = -i; 10147c478bd9Sstevel@tonic-gate break; 10157c478bd9Sstevel@tonic-gate case POWER: 10167c478bd9Sstevel@tonic-gate if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */ 10177c478bd9Sstevel@tonic-gate i = ipow(i, (int)j); 10187c478bd9Sstevel@tonic-gate else 10197c478bd9Sstevel@tonic-gate i = errcheck(pow(i, j), "pow"); 10207c478bd9Sstevel@tonic-gate break; 10217c478bd9Sstevel@tonic-gate default: /* can't happen */ 10227c478bd9Sstevel@tonic-gate ERROR "illegal arithmetic operator %d", n FATAL; 10237c478bd9Sstevel@tonic-gate } 1024*1ee2e5faSnakanon (void) setfval(z, i); 10257c478bd9Sstevel@tonic-gate return (z); 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 1028*1ee2e5faSnakanon static double 1029*1ee2e5faSnakanon ipow(double x, int n) 10307c478bd9Sstevel@tonic-gate { 10317c478bd9Sstevel@tonic-gate double v; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate if (n <= 0) 1034*1ee2e5faSnakanon return (1.0); 10357c478bd9Sstevel@tonic-gate v = ipow(x, n/2); 10367c478bd9Sstevel@tonic-gate if (n % 2 == 0) 1037*1ee2e5faSnakanon return (v * v); 10387c478bd9Sstevel@tonic-gate else 1039*1ee2e5faSnakanon return (x * v * v); 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 1042*1ee2e5faSnakanon Cell * 1043*1ee2e5faSnakanon incrdecr(Node **a, int n) 10447c478bd9Sstevel@tonic-gate { 10457c478bd9Sstevel@tonic-gate register Cell *x, *z; 10467c478bd9Sstevel@tonic-gate register int k; 10477c478bd9Sstevel@tonic-gate Awkfloat xf; 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate x = execute(a[0]); 10507c478bd9Sstevel@tonic-gate xf = getfval(x); 10517c478bd9Sstevel@tonic-gate k = (n == PREINCR || n == POSTINCR) ? 1 : -1; 10527c478bd9Sstevel@tonic-gate if (n == PREINCR || n == PREDECR) { 1053*1ee2e5faSnakanon (void) setfval(x, xf + k); 10547c478bd9Sstevel@tonic-gate return (x); 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate z = gettemp(""); 1057*1ee2e5faSnakanon (void) setfval(z, xf); 1058*1ee2e5faSnakanon (void) setfval(x, xf + k); 10597c478bd9Sstevel@tonic-gate tempfree(x, ""); 10607c478bd9Sstevel@tonic-gate return (z); 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate 1063*1ee2e5faSnakanon Cell * 1064*1ee2e5faSnakanon assign(Node **a, int n) 10657c478bd9Sstevel@tonic-gate { 10667c478bd9Sstevel@tonic-gate register Cell *x, *y; 10677c478bd9Sstevel@tonic-gate Awkfloat xf, yf; 1068*1ee2e5faSnakanon double v; 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate y = execute(a[1]); 10717c478bd9Sstevel@tonic-gate x = execute(a[0]); /* order reversed from before... */ 10727c478bd9Sstevel@tonic-gate if (n == ASSIGN) { /* ordinary assignment */ 10737c478bd9Sstevel@tonic-gate if ((y->tval & (STR|NUM)) == (STR|NUM)) { 1074*1ee2e5faSnakanon (void) setsval(x, getsval(y)); 10757c478bd9Sstevel@tonic-gate x->fval = getfval(y); 10767c478bd9Sstevel@tonic-gate x->tval |= NUM; 1077*1ee2e5faSnakanon } else if (y->tval & STR) 1078*1ee2e5faSnakanon (void) setsval(x, getsval(y)); 10797c478bd9Sstevel@tonic-gate else if (y->tval & NUM) 1080*1ee2e5faSnakanon (void) setfval(x, getfval(y)); 10817c478bd9Sstevel@tonic-gate else 10827c478bd9Sstevel@tonic-gate funnyvar(y, "read value of"); 10837c478bd9Sstevel@tonic-gate tempfree(y, ""); 10847c478bd9Sstevel@tonic-gate return (x); 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate xf = getfval(x); 10877c478bd9Sstevel@tonic-gate yf = getfval(y); 10887c478bd9Sstevel@tonic-gate switch (n) { 10897c478bd9Sstevel@tonic-gate case ADDEQ: 10907c478bd9Sstevel@tonic-gate xf += yf; 10917c478bd9Sstevel@tonic-gate break; 10927c478bd9Sstevel@tonic-gate case SUBEQ: 10937c478bd9Sstevel@tonic-gate xf -= yf; 10947c478bd9Sstevel@tonic-gate break; 10957c478bd9Sstevel@tonic-gate case MULTEQ: 10967c478bd9Sstevel@tonic-gate xf *= yf; 10977c478bd9Sstevel@tonic-gate break; 10987c478bd9Sstevel@tonic-gate case DIVEQ: 10997c478bd9Sstevel@tonic-gate if (yf == 0) 11007c478bd9Sstevel@tonic-gate ERROR "division by zero in /=" FATAL; 11017c478bd9Sstevel@tonic-gate xf /= yf; 11027c478bd9Sstevel@tonic-gate break; 11037c478bd9Sstevel@tonic-gate case MODEQ: 11047c478bd9Sstevel@tonic-gate if (yf == 0) 11057c478bd9Sstevel@tonic-gate ERROR "division by zero in %%=" FATAL; 1106*1ee2e5faSnakanon (void) modf(xf/yf, &v); 11077c478bd9Sstevel@tonic-gate xf = xf - yf * v; 11087c478bd9Sstevel@tonic-gate break; 11097c478bd9Sstevel@tonic-gate case POWEQ: 11107c478bd9Sstevel@tonic-gate if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */ 11117c478bd9Sstevel@tonic-gate xf = ipow(xf, (int)yf); 11127c478bd9Sstevel@tonic-gate else 11137c478bd9Sstevel@tonic-gate xf = errcheck(pow(xf, yf), "pow"); 11147c478bd9Sstevel@tonic-gate break; 11157c478bd9Sstevel@tonic-gate default: 11167c478bd9Sstevel@tonic-gate ERROR "illegal assignment operator %d", n FATAL; 11177c478bd9Sstevel@tonic-gate break; 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate tempfree(y, ""); 1120*1ee2e5faSnakanon (void) setfval(x, xf); 11217c478bd9Sstevel@tonic-gate return (x); 11227c478bd9Sstevel@tonic-gate } 11237c478bd9Sstevel@tonic-gate 1124*1ee2e5faSnakanon /*ARGSUSED*/ 1125*1ee2e5faSnakanon Cell * 1126*1ee2e5faSnakanon cat(Node **a, int q) 11277c478bd9Sstevel@tonic-gate { 11287c478bd9Sstevel@tonic-gate register Cell *x, *y, *z; 11297c478bd9Sstevel@tonic-gate register int n1, n2; 11307c478bd9Sstevel@tonic-gate register uchar *s; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate x = execute(a[0]); 11337c478bd9Sstevel@tonic-gate y = execute(a[1]); 1134*1ee2e5faSnakanon (void) getsval(x); 1135*1ee2e5faSnakanon (void) getsval(y); 1136*1ee2e5faSnakanon n1 = strlen((char *)x->sval); 1137*1ee2e5faSnakanon n2 = strlen((char *)y->sval); 11387c478bd9Sstevel@tonic-gate s = (uchar *)malloc(n1 + n2 + 1); 1139*1ee2e5faSnakanon if (s == NULL) { 11407c478bd9Sstevel@tonic-gate ERROR "out of space concatenating %.15s and %.15s", 11417c478bd9Sstevel@tonic-gate x->sval, y->sval FATAL; 1142*1ee2e5faSnakanon } 1143*1ee2e5faSnakanon (void) strcpy((char *)s, (char *)x->sval); 1144*1ee2e5faSnakanon (void) strcpy((char *)s + n1, (char *)y->sval); 11457c478bd9Sstevel@tonic-gate tempfree(y, ""); 11467c478bd9Sstevel@tonic-gate z = gettemp(""); 11477c478bd9Sstevel@tonic-gate z->sval = s; 11487c478bd9Sstevel@tonic-gate z->tval = STR; 11497c478bd9Sstevel@tonic-gate tempfree(x, ""); 11507c478bd9Sstevel@tonic-gate return (z); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate 1153*1ee2e5faSnakanon /*ARGSUSED*/ 1154*1ee2e5faSnakanon Cell * 1155*1ee2e5faSnakanon pastat(Node **a, int n) 11567c478bd9Sstevel@tonic-gate { 11577c478bd9Sstevel@tonic-gate register Cell *x; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate if (a[0] == 0) 11607c478bd9Sstevel@tonic-gate x = execute(a[1]); 11617c478bd9Sstevel@tonic-gate else { 11627c478bd9Sstevel@tonic-gate x = execute(a[0]); 11637c478bd9Sstevel@tonic-gate if (istrue(x)) { 11647c478bd9Sstevel@tonic-gate tempfree(x, ""); 11657c478bd9Sstevel@tonic-gate x = execute(a[1]); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate } 1168*1ee2e5faSnakanon return (x); 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 1171*1ee2e5faSnakanon /*ARGSUSED*/ 1172*1ee2e5faSnakanon Cell * 1173*1ee2e5faSnakanon dopa2(Node **a, int n) 11747c478bd9Sstevel@tonic-gate { 11757c478bd9Sstevel@tonic-gate Cell *x; 11767c478bd9Sstevel@tonic-gate int pair; 11777c478bd9Sstevel@tonic-gate static int *pairstack = NULL; 11787c478bd9Sstevel@tonic-gate 11797c478bd9Sstevel@tonic-gate if (!pairstack) { 11807c478bd9Sstevel@tonic-gate /* first time */ 11817c478bd9Sstevel@tonic-gate dprintf(("paircnt: %d\n", paircnt)); 11827c478bd9Sstevel@tonic-gate pairstack = (int *)malloc(sizeof (int) * paircnt); 11837c478bd9Sstevel@tonic-gate if (!pairstack) 11847c478bd9Sstevel@tonic-gate ERROR "out of space in dopa2" FATAL; 11857c478bd9Sstevel@tonic-gate (void) memset(pairstack, 0, sizeof (int) * paircnt); 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate pair = (int)a[3]; 11897c478bd9Sstevel@tonic-gate if (pairstack[pair] == 0) { 11907c478bd9Sstevel@tonic-gate x = execute(a[0]); 11917c478bd9Sstevel@tonic-gate if (istrue(x)) 11927c478bd9Sstevel@tonic-gate pairstack[pair] = 1; 11937c478bd9Sstevel@tonic-gate tempfree(x, ""); 11947c478bd9Sstevel@tonic-gate } 11957c478bd9Sstevel@tonic-gate if (pairstack[pair] == 1) { 11967c478bd9Sstevel@tonic-gate x = execute(a[1]); 11977c478bd9Sstevel@tonic-gate if (istrue(x)) 11987c478bd9Sstevel@tonic-gate pairstack[pair] = 0; 11997c478bd9Sstevel@tonic-gate tempfree(x, ""); 12007c478bd9Sstevel@tonic-gate x = execute(a[2]); 12017c478bd9Sstevel@tonic-gate return (x); 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate return (false); 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate 1206*1ee2e5faSnakanon /*ARGSUSED*/ 1207*1ee2e5faSnakanon Cell * 1208*1ee2e5faSnakanon split(Node **a, int nnn) 12097c478bd9Sstevel@tonic-gate { 12107c478bd9Sstevel@tonic-gate Cell *x, *y, *ap; 12117c478bd9Sstevel@tonic-gate register uchar *s; 12127c478bd9Sstevel@tonic-gate register int sep; 1213*1ee2e5faSnakanon uchar *t, temp, num[11], *fs; 12147c478bd9Sstevel@tonic-gate int n, tempstat; 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate y = execute(a[0]); /* source string */ 12177c478bd9Sstevel@tonic-gate s = getsval(y); 12187c478bd9Sstevel@tonic-gate if (a[2] == 0) /* fs string */ 12197c478bd9Sstevel@tonic-gate fs = *FS; 12207c478bd9Sstevel@tonic-gate else if ((int)a[3] == STRING) { /* split(str,arr,"string") */ 12217c478bd9Sstevel@tonic-gate x = execute(a[2]); 12227c478bd9Sstevel@tonic-gate fs = getsval(x); 12237c478bd9Sstevel@tonic-gate } else if ((int)a[3] == REGEXPR) 12247c478bd9Sstevel@tonic-gate fs = (uchar *)"(regexpr)"; /* split(str,arr,/regexpr/) */ 12257c478bd9Sstevel@tonic-gate else 12267c478bd9Sstevel@tonic-gate ERROR "illegal type of split()" FATAL; 12277c478bd9Sstevel@tonic-gate sep = *fs; 12287c478bd9Sstevel@tonic-gate ap = execute(a[1]); /* array name */ 12297c478bd9Sstevel@tonic-gate freesymtab(ap); 12307c478bd9Sstevel@tonic-gate dprintf(("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs)); 12317c478bd9Sstevel@tonic-gate ap->tval &= ~STR; 12327c478bd9Sstevel@tonic-gate ap->tval |= ARR; 12337c478bd9Sstevel@tonic-gate ap->sval = (uchar *)makesymtab(NSYMTAB); 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate n = 0; 1236*1ee2e5faSnakanon if (*s != '\0' && strlen((char *)fs) > 1 || (int)a[3] == REGEXPR) { 1237*1ee2e5faSnakanon /* reg expr */ 12387c478bd9Sstevel@tonic-gate fa *pfa; 12397c478bd9Sstevel@tonic-gate if ((int)a[3] == REGEXPR) { /* it's ready already */ 12407c478bd9Sstevel@tonic-gate pfa = (fa *)a[2]; 12417c478bd9Sstevel@tonic-gate } else { 12427c478bd9Sstevel@tonic-gate pfa = makedfa(fs, 1); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate if (nematch(pfa, s)) { 12457c478bd9Sstevel@tonic-gate tempstat = pfa->initstat; 12467c478bd9Sstevel@tonic-gate pfa->initstat = 2; 12477c478bd9Sstevel@tonic-gate do { 12487c478bd9Sstevel@tonic-gate n++; 1249*1ee2e5faSnakanon (void) sprintf((char *)num, "%d", n); 12507c478bd9Sstevel@tonic-gate temp = *patbeg; 12517c478bd9Sstevel@tonic-gate *patbeg = '\0'; 1252*1ee2e5faSnakanon if (is_number(s)) { 1253*1ee2e5faSnakanon (void) setsymtab(num, s, 1254*1ee2e5faSnakanon atof((char *)s), 1255*1ee2e5faSnakanon /*LINTED align*/ 1256*1ee2e5faSnakanon STR|NUM, (Array *)ap->sval); 1257*1ee2e5faSnakanon } else { 1258*1ee2e5faSnakanon (void) setsymtab(num, s, 0.0, 1259*1ee2e5faSnakanon /*LINTED align*/ 1260*1ee2e5faSnakanon STR, (Array *)ap->sval); 1261*1ee2e5faSnakanon } 12627c478bd9Sstevel@tonic-gate *patbeg = temp; 12637c478bd9Sstevel@tonic-gate s = patbeg + patlen; 12647c478bd9Sstevel@tonic-gate if (*(patbeg+patlen-1) == 0 || *s == 0) { 12657c478bd9Sstevel@tonic-gate n++; 1266*1ee2e5faSnakanon (void) sprintf((char *)num, "%d", n); 1267*1ee2e5faSnakanon (void) setsymtab(num, (uchar *)"", 0.0, 1268*1ee2e5faSnakanon /*LINTED align*/ 1269*1ee2e5faSnakanon STR, (Array *)ap->sval); 12707c478bd9Sstevel@tonic-gate pfa->initstat = tempstat; 12717c478bd9Sstevel@tonic-gate goto spdone; 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate } while (nematch(pfa, s)); 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate n++; 1276*1ee2e5faSnakanon (void) sprintf((char *)num, "%d", n); 1277*1ee2e5faSnakanon if (is_number(s)) { 1278*1ee2e5faSnakanon (void) setsymtab(num, s, atof((char *)s), 1279*1ee2e5faSnakanon /*LINTED align*/ 1280*1ee2e5faSnakanon STR|NUM, (Array *)ap->sval); 1281*1ee2e5faSnakanon } else { 1282*1ee2e5faSnakanon /*LINTED align*/ 1283*1ee2e5faSnakanon (void) setsymtab(num, s, 0.0, STR, (Array *)ap->sval); 1284*1ee2e5faSnakanon } 12857c478bd9Sstevel@tonic-gate spdone: 12867c478bd9Sstevel@tonic-gate pfa = NULL; 12877c478bd9Sstevel@tonic-gate } else if (sep == ' ') { 12887c478bd9Sstevel@tonic-gate for (n = 0; ; ) { 12897c478bd9Sstevel@tonic-gate while (*s == ' ' || *s == '\t' || *s == '\n') 12907c478bd9Sstevel@tonic-gate s++; 12917c478bd9Sstevel@tonic-gate if (*s == 0) 12927c478bd9Sstevel@tonic-gate break; 12937c478bd9Sstevel@tonic-gate n++; 12947c478bd9Sstevel@tonic-gate t = s; 12957c478bd9Sstevel@tonic-gate do 12967c478bd9Sstevel@tonic-gate s++; 1297*1ee2e5faSnakanon while (*s != ' ' && *s != '\t' && 1298*1ee2e5faSnakanon *s != '\n' && *s != '\0') 1299*1ee2e5faSnakanon ; 13007c478bd9Sstevel@tonic-gate temp = *s; 13017c478bd9Sstevel@tonic-gate *s = '\0'; 1302*1ee2e5faSnakanon (void) sprintf((char *)num, "%d", n); 1303*1ee2e5faSnakanon if (is_number(t)) { 1304*1ee2e5faSnakanon (void) setsymtab(num, t, atof((char *)t), 1305*1ee2e5faSnakanon /*LINTED align*/ 1306*1ee2e5faSnakanon STR|NUM, (Array *)ap->sval); 1307*1ee2e5faSnakanon } else { 1308*1ee2e5faSnakanon (void) setsymtab(num, t, 0.0, 1309*1ee2e5faSnakanon /*LINTED align*/ 1310*1ee2e5faSnakanon STR, (Array *)ap->sval); 1311*1ee2e5faSnakanon } 13127c478bd9Sstevel@tonic-gate *s = temp; 13137c478bd9Sstevel@tonic-gate if (*s != 0) 13147c478bd9Sstevel@tonic-gate s++; 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate } else if (*s != 0) { 13177c478bd9Sstevel@tonic-gate for (;;) { 13187c478bd9Sstevel@tonic-gate n++; 13197c478bd9Sstevel@tonic-gate t = s; 13207c478bd9Sstevel@tonic-gate while (*s != sep && *s != '\n' && *s != '\0') 13217c478bd9Sstevel@tonic-gate s++; 13227c478bd9Sstevel@tonic-gate temp = *s; 13237c478bd9Sstevel@tonic-gate *s = '\0'; 1324*1ee2e5faSnakanon (void) sprintf((char *)num, "%d", n); 1325*1ee2e5faSnakanon if (is_number(t)) { 1326*1ee2e5faSnakanon (void) setsymtab(num, t, atof((char *)t), 1327*1ee2e5faSnakanon /*LINTED align*/ 1328*1ee2e5faSnakanon STR|NUM, (Array *)ap->sval); 1329*1ee2e5faSnakanon } else { 1330*1ee2e5faSnakanon (void) setsymtab(num, t, 0.0, 1331*1ee2e5faSnakanon /*LINTED align*/ 1332*1ee2e5faSnakanon STR, (Array *)ap->sval); 1333*1ee2e5faSnakanon } 13347c478bd9Sstevel@tonic-gate *s = temp; 13357c478bd9Sstevel@tonic-gate if (*s++ == 0) 13367c478bd9Sstevel@tonic-gate break; 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate tempfree(ap, ""); 13407c478bd9Sstevel@tonic-gate tempfree(y, ""); 13417c478bd9Sstevel@tonic-gate if (a[2] != 0 && (int)a[3] == STRING) 13427c478bd9Sstevel@tonic-gate tempfree(x, ""); 13437c478bd9Sstevel@tonic-gate x = gettemp(""); 13447c478bd9Sstevel@tonic-gate x->tval = NUM; 13457c478bd9Sstevel@tonic-gate x->fval = n; 13467c478bd9Sstevel@tonic-gate return (x); 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate 1349*1ee2e5faSnakanon /*ARGSUSED*/ 1350*1ee2e5faSnakanon Cell * 1351*1ee2e5faSnakanon condexpr(Node **a, int n) 13527c478bd9Sstevel@tonic-gate { 13537c478bd9Sstevel@tonic-gate register Cell *x; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate x = execute(a[0]); 13567c478bd9Sstevel@tonic-gate if (istrue(x)) { 13577c478bd9Sstevel@tonic-gate tempfree(x, ""); 13587c478bd9Sstevel@tonic-gate x = execute(a[1]); 13597c478bd9Sstevel@tonic-gate } else { 13607c478bd9Sstevel@tonic-gate tempfree(x, ""); 13617c478bd9Sstevel@tonic-gate x = execute(a[2]); 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate return (x); 13647c478bd9Sstevel@tonic-gate } 13657c478bd9Sstevel@tonic-gate 1366*1ee2e5faSnakanon /*ARGSUSED*/ 1367*1ee2e5faSnakanon Cell * 1368*1ee2e5faSnakanon ifstat(Node **a, int n) 13697c478bd9Sstevel@tonic-gate { 13707c478bd9Sstevel@tonic-gate register Cell *x; 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate x = execute(a[0]); 13737c478bd9Sstevel@tonic-gate if (istrue(x)) { 13747c478bd9Sstevel@tonic-gate tempfree(x, ""); 13757c478bd9Sstevel@tonic-gate x = execute(a[1]); 13767c478bd9Sstevel@tonic-gate } else if (a[2] != 0) { 13777c478bd9Sstevel@tonic-gate tempfree(x, ""); 13787c478bd9Sstevel@tonic-gate x = execute(a[2]); 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate return (x); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 1383*1ee2e5faSnakanon /*ARGSUSED*/ 1384*1ee2e5faSnakanon Cell * 1385*1ee2e5faSnakanon whilestat(Node **a, int n) 13867c478bd9Sstevel@tonic-gate { 13877c478bd9Sstevel@tonic-gate register Cell *x; 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate for (;;) { 13907c478bd9Sstevel@tonic-gate x = execute(a[0]); 13917c478bd9Sstevel@tonic-gate if (!istrue(x)) 13927c478bd9Sstevel@tonic-gate return (x); 13937c478bd9Sstevel@tonic-gate tempfree(x, ""); 13947c478bd9Sstevel@tonic-gate x = execute(a[1]); 13957c478bd9Sstevel@tonic-gate if (isbreak(x)) { 13967c478bd9Sstevel@tonic-gate x = true; 13977c478bd9Sstevel@tonic-gate return (x); 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x)) 14007c478bd9Sstevel@tonic-gate return (x); 14017c478bd9Sstevel@tonic-gate tempfree(x, ""); 14027c478bd9Sstevel@tonic-gate } 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 1405*1ee2e5faSnakanon /*ARGSUSED*/ 1406*1ee2e5faSnakanon Cell * 1407*1ee2e5faSnakanon dostat(Node **a, int n) 14087c478bd9Sstevel@tonic-gate { 14097c478bd9Sstevel@tonic-gate register Cell *x; 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate for (;;) { 14127c478bd9Sstevel@tonic-gate x = execute(a[0]); 14137c478bd9Sstevel@tonic-gate if (isbreak(x)) 1414*1ee2e5faSnakanon return (true); 14157c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x)) 14167c478bd9Sstevel@tonic-gate return (x); 14177c478bd9Sstevel@tonic-gate tempfree(x, ""); 14187c478bd9Sstevel@tonic-gate x = execute(a[1]); 14197c478bd9Sstevel@tonic-gate if (!istrue(x)) 14207c478bd9Sstevel@tonic-gate return (x); 14217c478bd9Sstevel@tonic-gate tempfree(x, ""); 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 1425*1ee2e5faSnakanon /*ARGSUSED*/ 1426*1ee2e5faSnakanon Cell * 1427*1ee2e5faSnakanon forstat(Node **a, int n) 14287c478bd9Sstevel@tonic-gate { 14297c478bd9Sstevel@tonic-gate register Cell *x; 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate x = execute(a[0]); 14327c478bd9Sstevel@tonic-gate tempfree(x, ""); 14337c478bd9Sstevel@tonic-gate for (;;) { 14347c478bd9Sstevel@tonic-gate if (a[1] != 0) { 14357c478bd9Sstevel@tonic-gate x = execute(a[1]); 1436*1ee2e5faSnakanon if (!istrue(x)) 1437*1ee2e5faSnakanon return (x); 1438*1ee2e5faSnakanon else 1439*1ee2e5faSnakanon tempfree(x, ""); 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate x = execute(a[3]); 14427c478bd9Sstevel@tonic-gate if (isbreak(x)) /* turn off break */ 1443*1ee2e5faSnakanon return (true); 14447c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x)) 14457c478bd9Sstevel@tonic-gate return (x); 14467c478bd9Sstevel@tonic-gate tempfree(x, ""); 14477c478bd9Sstevel@tonic-gate x = execute(a[2]); 14487c478bd9Sstevel@tonic-gate tempfree(x, ""); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate 1452*1ee2e5faSnakanon /*ARGSUSED*/ 1453*1ee2e5faSnakanon Cell * 1454*1ee2e5faSnakanon instat(Node **a, int n) 14557c478bd9Sstevel@tonic-gate { 14567c478bd9Sstevel@tonic-gate register Cell *x, *vp, *arrayp, *cp, *ncp; 14577c478bd9Sstevel@tonic-gate Array *tp; 14587c478bd9Sstevel@tonic-gate int i; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate vp = execute(a[0]); 14617c478bd9Sstevel@tonic-gate arrayp = execute(a[1]); 14627c478bd9Sstevel@tonic-gate if (!isarr(arrayp)) 14637c478bd9Sstevel@tonic-gate ERROR "%s is not an array", arrayp->nval FATAL; 1464*1ee2e5faSnakanon /*LINTED align*/ 14657c478bd9Sstevel@tonic-gate tp = (Array *)arrayp->sval; 14667c478bd9Sstevel@tonic-gate tempfree(arrayp, ""); 14677c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) { /* this routine knows too much */ 14687c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp != NULL; cp = ncp) { 1469*1ee2e5faSnakanon (void) setsval(vp, cp->nval); 14707c478bd9Sstevel@tonic-gate ncp = cp->cnext; 14717c478bd9Sstevel@tonic-gate x = execute(a[2]); 14727c478bd9Sstevel@tonic-gate if (isbreak(x)) { 14737c478bd9Sstevel@tonic-gate tempfree(vp, ""); 1474*1ee2e5faSnakanon return (true); 14757c478bd9Sstevel@tonic-gate } 14767c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x)) { 14777c478bd9Sstevel@tonic-gate tempfree(vp, ""); 14787c478bd9Sstevel@tonic-gate return (x); 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate tempfree(x, ""); 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate } 1483*1ee2e5faSnakanon return (true); 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 1486*1ee2e5faSnakanon /*ARGSUSED*/ 1487*1ee2e5faSnakanon Cell * 1488*1ee2e5faSnakanon bltin(Node **a, int n) 14897c478bd9Sstevel@tonic-gate { 14907c478bd9Sstevel@tonic-gate register Cell *x, *y; 14917c478bd9Sstevel@tonic-gate Awkfloat u; 14927c478bd9Sstevel@tonic-gate register int t; 1493*1ee2e5faSnakanon uchar *p, *buf; 14947c478bd9Sstevel@tonic-gate Node *nextarg; 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate t = (int)a[0]; 14977c478bd9Sstevel@tonic-gate x = execute(a[1]); 14987c478bd9Sstevel@tonic-gate nextarg = a[1]->nnext; 14997c478bd9Sstevel@tonic-gate switch (t) { 15007c478bd9Sstevel@tonic-gate case FLENGTH: 1501*1ee2e5faSnakanon u = (Awkfloat)strlen((char *)getsval(x)); break; 15027c478bd9Sstevel@tonic-gate case FLOG: 15037c478bd9Sstevel@tonic-gate u = errcheck(log(getfval(x)), "log"); break; 15047c478bd9Sstevel@tonic-gate case FINT: 1505*1ee2e5faSnakanon (void) modf(getfval(x), &u); break; 15067c478bd9Sstevel@tonic-gate case FEXP: 15077c478bd9Sstevel@tonic-gate u = errcheck(exp(getfval(x)), "exp"); break; 15087c478bd9Sstevel@tonic-gate case FSQRT: 15097c478bd9Sstevel@tonic-gate u = errcheck(sqrt(getfval(x)), "sqrt"); break; 15107c478bd9Sstevel@tonic-gate case FSIN: 15117c478bd9Sstevel@tonic-gate u = sin(getfval(x)); break; 15127c478bd9Sstevel@tonic-gate case FCOS: 15137c478bd9Sstevel@tonic-gate u = cos(getfval(x)); break; 15147c478bd9Sstevel@tonic-gate case FATAN: 15157c478bd9Sstevel@tonic-gate if (nextarg == 0) { 1516*1ee2e5faSnakanon ERROR "atan2 requires two arguments; returning 1.0" 1517*1ee2e5faSnakanon WARNING; 15187c478bd9Sstevel@tonic-gate u = 1.0; 15197c478bd9Sstevel@tonic-gate } else { 15207c478bd9Sstevel@tonic-gate y = execute(a[1]->nnext); 15217c478bd9Sstevel@tonic-gate u = atan2(getfval(x), getfval(y)); 15227c478bd9Sstevel@tonic-gate tempfree(y, ""); 15237c478bd9Sstevel@tonic-gate nextarg = nextarg->nnext; 15247c478bd9Sstevel@tonic-gate } 15257c478bd9Sstevel@tonic-gate break; 15267c478bd9Sstevel@tonic-gate case FSYSTEM: 1527*1ee2e5faSnakanon /* in case something is buffered already */ 1528*1ee2e5faSnakanon (void) fflush(stdout); 1529*1ee2e5faSnakanon /* 256 is unix-dep */ 1530*1ee2e5faSnakanon u = (Awkfloat)system((char *)getsval(x)) / 256; 15317c478bd9Sstevel@tonic-gate break; 15327c478bd9Sstevel@tonic-gate case FRAND: 15337c478bd9Sstevel@tonic-gate u = (Awkfloat)(rand() % 32767) / 32767.0; 15347c478bd9Sstevel@tonic-gate break; 15357c478bd9Sstevel@tonic-gate case FSRAND: 15367c478bd9Sstevel@tonic-gate if (x->tval & REC) /* no argument provided */ 15377c478bd9Sstevel@tonic-gate u = time((time_t *)0); 15387c478bd9Sstevel@tonic-gate else 15397c478bd9Sstevel@tonic-gate u = getfval(x); 15407c478bd9Sstevel@tonic-gate srand((int)u); u = (int)u; 15417c478bd9Sstevel@tonic-gate break; 15427c478bd9Sstevel@tonic-gate case FTOUPPER: 15437c478bd9Sstevel@tonic-gate case FTOLOWER: 1544*1ee2e5faSnakanon buf = tostring(getsval(x)); 15457c478bd9Sstevel@tonic-gate if (t == FTOUPPER) { 15467c478bd9Sstevel@tonic-gate for (p = buf; *p; p++) 15477c478bd9Sstevel@tonic-gate if (islower(*p)) 15487c478bd9Sstevel@tonic-gate *p = toupper(*p); 15497c478bd9Sstevel@tonic-gate } else { 15507c478bd9Sstevel@tonic-gate for (p = buf; *p; p++) 15517c478bd9Sstevel@tonic-gate if (isupper(*p)) 15527c478bd9Sstevel@tonic-gate *p = tolower(*p); 15537c478bd9Sstevel@tonic-gate } 15547c478bd9Sstevel@tonic-gate tempfree(x, ""); 15557c478bd9Sstevel@tonic-gate x = gettemp(""); 1556*1ee2e5faSnakanon (void) setsval(x, buf); 1557*1ee2e5faSnakanon free(buf); 1558*1ee2e5faSnakanon return (x); 15597c478bd9Sstevel@tonic-gate default: /* can't happen */ 15607c478bd9Sstevel@tonic-gate ERROR "illegal function type %d", t FATAL; 15617c478bd9Sstevel@tonic-gate break; 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate tempfree(x, ""); 15647c478bd9Sstevel@tonic-gate x = gettemp(""); 1565*1ee2e5faSnakanon (void) setfval(x, u); 15667c478bd9Sstevel@tonic-gate if (nextarg != 0) { 15677c478bd9Sstevel@tonic-gate ERROR "warning: function has too many arguments" WARNING; 15687c478bd9Sstevel@tonic-gate for (; nextarg; nextarg = nextarg->nnext) 1569*1ee2e5faSnakanon (void) execute(nextarg); 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate return (x); 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate 1574*1ee2e5faSnakanon /*ARGSUSED*/ 1575*1ee2e5faSnakanon Cell * 1576*1ee2e5faSnakanon print(Node **a, int n) 15777c478bd9Sstevel@tonic-gate { 15787c478bd9Sstevel@tonic-gate register Node *x; 15797c478bd9Sstevel@tonic-gate register Cell *y; 15807c478bd9Sstevel@tonic-gate FILE *fp; 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate if (a[1] == 0) 15837c478bd9Sstevel@tonic-gate fp = stdout; 15847c478bd9Sstevel@tonic-gate else 15857c478bd9Sstevel@tonic-gate fp = redirect((int)a[1], a[2]); 15867c478bd9Sstevel@tonic-gate for (x = a[0]; x != NULL; x = x->nnext) { 15877c478bd9Sstevel@tonic-gate y = execute(x); 1588*1ee2e5faSnakanon (void) fputs((char *)getsval(y), fp); 15897c478bd9Sstevel@tonic-gate tempfree(y, ""); 15907c478bd9Sstevel@tonic-gate if (x->nnext == NULL) 1591*1ee2e5faSnakanon (void) fputs((char *)*ORS, fp); 15927c478bd9Sstevel@tonic-gate else 1593*1ee2e5faSnakanon (void) fputs((char *)*OFS, fp); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate if (a[1] != 0) 1596*1ee2e5faSnakanon (void) fflush(fp); 15977c478bd9Sstevel@tonic-gate return (true); 15987c478bd9Sstevel@tonic-gate } 15997c478bd9Sstevel@tonic-gate 1600*1ee2e5faSnakanon /*ARGSUSED*/ 1601*1ee2e5faSnakanon Cell * 1602*1ee2e5faSnakanon nullproc(Node **a, int n) 16037c478bd9Sstevel@tonic-gate { 1604*1ee2e5faSnakanon return (0); 1605*1ee2e5faSnakanon } 1606*1ee2e5faSnakanon 1607*1ee2e5faSnakanon struct { 16087c478bd9Sstevel@tonic-gate FILE *fp; 16097c478bd9Sstevel@tonic-gate uchar *fname; 16107c478bd9Sstevel@tonic-gate int mode; /* '|', 'a', 'w' */ 16117c478bd9Sstevel@tonic-gate } files[FOPEN_MAX]; 16127c478bd9Sstevel@tonic-gate 1613*1ee2e5faSnakanon static FILE * 1614*1ee2e5faSnakanon redirect(int a, Node *b) 16157c478bd9Sstevel@tonic-gate { 16167c478bd9Sstevel@tonic-gate FILE *fp; 16177c478bd9Sstevel@tonic-gate Cell *x; 16187c478bd9Sstevel@tonic-gate uchar *fname; 16197c478bd9Sstevel@tonic-gate 16207c478bd9Sstevel@tonic-gate x = execute(b); 16217c478bd9Sstevel@tonic-gate fname = getsval(x); 16227c478bd9Sstevel@tonic-gate fp = openfile(a, fname); 16237c478bd9Sstevel@tonic-gate if (fp == NULL) 16247c478bd9Sstevel@tonic-gate ERROR "can't open file %s", fname FATAL; 16257c478bd9Sstevel@tonic-gate tempfree(x, ""); 1626*1ee2e5faSnakanon return (fp); 16277c478bd9Sstevel@tonic-gate } 16287c478bd9Sstevel@tonic-gate 1629*1ee2e5faSnakanon static FILE * 1630*1ee2e5faSnakanon openfile(int a, uchar *s) 16317c478bd9Sstevel@tonic-gate { 16327c478bd9Sstevel@tonic-gate register int i, m; 16337c478bd9Sstevel@tonic-gate register FILE *fp; 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate if (*s == '\0') 16367c478bd9Sstevel@tonic-gate ERROR "null file name in print or getline" FATAL; 1637*1ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) { 1638*1ee2e5faSnakanon if (files[i].fname && 1639*1ee2e5faSnakanon strcmp((char *)s, (char *)files[i].fname) == 0) { 1640*1ee2e5faSnakanon if (a == files[i].mode || 1641*1ee2e5faSnakanon a == APPEND && files[i].mode == GT) { 1642*1ee2e5faSnakanon return (files[i].fp); 1643*1ee2e5faSnakanon } 1644*1ee2e5faSnakanon } 1645*1ee2e5faSnakanon } 1646*1ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) { 16477c478bd9Sstevel@tonic-gate if (files[i].fp == 0) 16487c478bd9Sstevel@tonic-gate break; 1649*1ee2e5faSnakanon } 16507c478bd9Sstevel@tonic-gate if (i >= FOPEN_MAX) 16517c478bd9Sstevel@tonic-gate ERROR "%s makes too many open files", s FATAL; 1652*1ee2e5faSnakanon (void) fflush(stdout); /* force a semblance of order */ 16537c478bd9Sstevel@tonic-gate m = a; 16547c478bd9Sstevel@tonic-gate if (a == GT) { 16557c478bd9Sstevel@tonic-gate fp = fopen((char *)s, "w"); 16567c478bd9Sstevel@tonic-gate } else if (a == APPEND) { 16577c478bd9Sstevel@tonic-gate fp = fopen((char *)s, "a"); 16587c478bd9Sstevel@tonic-gate m = GT; /* so can mix > and >> */ 16597c478bd9Sstevel@tonic-gate } else if (a == '|') { /* output pipe */ 16607c478bd9Sstevel@tonic-gate fp = popen((char *)s, "w"); 16617c478bd9Sstevel@tonic-gate } else if (a == LE) { /* input pipe */ 16627c478bd9Sstevel@tonic-gate fp = popen((char *)s, "r"); 16637c478bd9Sstevel@tonic-gate } else if (a == LT) { /* getline <file */ 1664*1ee2e5faSnakanon fp = strcmp((char *)s, "-") == 0 ? 1665*1ee2e5faSnakanon stdin : fopen((char *)s, "r"); /* "-" is stdin */ 16667c478bd9Sstevel@tonic-gate } else /* can't happen */ 16677c478bd9Sstevel@tonic-gate ERROR "illegal redirection" FATAL; 16687c478bd9Sstevel@tonic-gate if (fp != NULL) { 16697c478bd9Sstevel@tonic-gate files[i].fname = tostring(s); 16707c478bd9Sstevel@tonic-gate files[i].fp = fp; 16717c478bd9Sstevel@tonic-gate files[i].mode = m; 16727c478bd9Sstevel@tonic-gate } 1673*1ee2e5faSnakanon return (fp); 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate 1676*1ee2e5faSnakanon /*ARGSUSED*/ 1677*1ee2e5faSnakanon Cell * 1678*1ee2e5faSnakanon closefile(Node **a, int n) 16797c478bd9Sstevel@tonic-gate { 16807c478bd9Sstevel@tonic-gate register Cell *x; 16817c478bd9Sstevel@tonic-gate int i, stat; 16827c478bd9Sstevel@tonic-gate 16837c478bd9Sstevel@tonic-gate x = execute(a[0]); 1684*1ee2e5faSnakanon (void) getsval(x); 1685*1ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) { 1686*1ee2e5faSnakanon if (files[i].fname && 1687*1ee2e5faSnakanon strcmp((char *)x->sval, (char *)files[i].fname) == 0) { 1688*1ee2e5faSnakanon if (ferror(files[i].fp)) { 1689*1ee2e5faSnakanon ERROR "i/o error occurred on %s", 1690*1ee2e5faSnakanon files[i].fname WARNING; 1691*1ee2e5faSnakanon } 16927c478bd9Sstevel@tonic-gate if (files[i].mode == '|' || files[i].mode == LE) 16937c478bd9Sstevel@tonic-gate stat = pclose(files[i].fp); 16947c478bd9Sstevel@tonic-gate else 16957c478bd9Sstevel@tonic-gate stat = fclose(files[i].fp); 1696*1ee2e5faSnakanon if (stat == EOF) { 1697*1ee2e5faSnakanon ERROR "i/o error occurred closing %s", 1698*1ee2e5faSnakanon files[i].fname WARNING; 1699*1ee2e5faSnakanon } 17007c478bd9Sstevel@tonic-gate xfree(files[i].fname); 1701*1ee2e5faSnakanon /* watch out for ref thru this */ 1702*1ee2e5faSnakanon files[i].fname = NULL; 17037c478bd9Sstevel@tonic-gate files[i].fp = NULL; 17047c478bd9Sstevel@tonic-gate } 1705*1ee2e5faSnakanon } 17067c478bd9Sstevel@tonic-gate tempfree(x, "close"); 17077c478bd9Sstevel@tonic-gate return (true); 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate 1710*1ee2e5faSnakanon static void 1711*1ee2e5faSnakanon closeall(void) 17127c478bd9Sstevel@tonic-gate { 17137c478bd9Sstevel@tonic-gate int i, stat; 17147c478bd9Sstevel@tonic-gate 1715*1ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) { 17167c478bd9Sstevel@tonic-gate if (files[i].fp) { 1717*1ee2e5faSnakanon if (ferror(files[i].fp)) { 1718*1ee2e5faSnakanon ERROR "i/o error occurred on %s", 1719*1ee2e5faSnakanon files[i].fname WARNING; 1720*1ee2e5faSnakanon } 17217c478bd9Sstevel@tonic-gate if (files[i].mode == '|' || files[i].mode == LE) 17227c478bd9Sstevel@tonic-gate stat = pclose(files[i].fp); 17237c478bd9Sstevel@tonic-gate else 17247c478bd9Sstevel@tonic-gate stat = fclose(files[i].fp); 1725*1ee2e5faSnakanon if (stat == EOF) { 1726*1ee2e5faSnakanon ERROR "i/o error occurred while closing %s", 1727*1ee2e5faSnakanon files[i].fname WARNING; 1728*1ee2e5faSnakanon } 1729*1ee2e5faSnakanon } 17307c478bd9Sstevel@tonic-gate } 17317c478bd9Sstevel@tonic-gate } 17327c478bd9Sstevel@tonic-gate 1733*1ee2e5faSnakanon /*ARGSUSED*/ 1734*1ee2e5faSnakanon Cell * 1735*1ee2e5faSnakanon sub(Node **a, int nnn) 17367c478bd9Sstevel@tonic-gate { 1737*1ee2e5faSnakanon register uchar *sptr; 17387c478bd9Sstevel@tonic-gate register Cell *x, *y, *result; 1739*1ee2e5faSnakanon uchar *buf, *t; 17407c478bd9Sstevel@tonic-gate fa *pfa; 1741*1ee2e5faSnakanon size_t bsize, cnt, len; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate x = execute(a[3]); /* target string */ 17447c478bd9Sstevel@tonic-gate t = getsval(x); 17457c478bd9Sstevel@tonic-gate if (a[0] == 0) 17467c478bd9Sstevel@tonic-gate pfa = (fa *)a[1]; /* regular expression */ 17477c478bd9Sstevel@tonic-gate else { 17487c478bd9Sstevel@tonic-gate y = execute(a[1]); 17497c478bd9Sstevel@tonic-gate pfa = makedfa(getsval(y), 1); 17507c478bd9Sstevel@tonic-gate tempfree(y, ""); 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate y = execute(a[2]); /* replacement string */ 17537c478bd9Sstevel@tonic-gate result = false; 17547c478bd9Sstevel@tonic-gate if (pmatch(pfa, t)) { 1755*1ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR); 1756*1ee2e5faSnakanon cnt = 0; 17577c478bd9Sstevel@tonic-gate sptr = t; 1758*1ee2e5faSnakanon len = patbeg - sptr; 1759*1ee2e5faSnakanon if (len > 0) { 1760*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + len); 1761*1ee2e5faSnakanon (void) memcpy(buf, sptr, len); 1762*1ee2e5faSnakanon cnt += len; 1763*1ee2e5faSnakanon } 17647c478bd9Sstevel@tonic-gate sptr = getsval(y); 1765*1ee2e5faSnakanon while (*sptr != 0) { 1766*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt); 17677c478bd9Sstevel@tonic-gate if (*sptr == '\\' && *(sptr+1) == '&') { 17687c478bd9Sstevel@tonic-gate sptr++; /* skip \, */ 1769*1ee2e5faSnakanon buf[cnt++] = *sptr++; /* add & */ 17707c478bd9Sstevel@tonic-gate } else if (*sptr == '&') { 1771*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + patlen); 17727c478bd9Sstevel@tonic-gate sptr++; 1773*1ee2e5faSnakanon (void) memcpy(&buf[cnt], patbeg, patlen); 1774*1ee2e5faSnakanon cnt += patlen; 1775*1ee2e5faSnakanon } else { 1776*1ee2e5faSnakanon buf[cnt++] = *sptr++; 1777*1ee2e5faSnakanon } 1778*1ee2e5faSnakanon } 17797c478bd9Sstevel@tonic-gate sptr = patbeg + patlen; 1780*1ee2e5faSnakanon if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) { 1781*1ee2e5faSnakanon len = strlen((char *)sptr); 1782*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + len); 1783*1ee2e5faSnakanon (void) memcpy(&buf[cnt], sptr, len); 1784*1ee2e5faSnakanon cnt += len; 1785*1ee2e5faSnakanon } 1786*1ee2e5faSnakanon buf[cnt] = '\0'; 1787*1ee2e5faSnakanon (void) setsval(x, buf); 1788*1ee2e5faSnakanon free(buf); 1789*1ee2e5faSnakanon result = true; 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate tempfree(x, ""); 17927c478bd9Sstevel@tonic-gate tempfree(y, ""); 1793*1ee2e5faSnakanon return (result); 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate 1796*1ee2e5faSnakanon /*ARGSUSED*/ 1797*1ee2e5faSnakanon Cell * 1798*1ee2e5faSnakanon gsub(Node **a, int nnn) 17997c478bd9Sstevel@tonic-gate { 18007c478bd9Sstevel@tonic-gate register Cell *x, *y; 1801*1ee2e5faSnakanon register uchar *rptr, *sptr, *t; 1802*1ee2e5faSnakanon uchar *buf; 18037c478bd9Sstevel@tonic-gate register fa *pfa; 18047c478bd9Sstevel@tonic-gate int mflag, tempstat, num; 1805*1ee2e5faSnakanon size_t bsize, cnt, len; 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate mflag = 0; /* if mflag == 0, can replace empty string */ 18087c478bd9Sstevel@tonic-gate num = 0; 18097c478bd9Sstevel@tonic-gate x = execute(a[3]); /* target string */ 18107c478bd9Sstevel@tonic-gate t = getsval(x); 18117c478bd9Sstevel@tonic-gate if (a[0] == 0) 18127c478bd9Sstevel@tonic-gate pfa = (fa *) a[1]; /* regular expression */ 18137c478bd9Sstevel@tonic-gate else { 18147c478bd9Sstevel@tonic-gate y = execute(a[1]); 18157c478bd9Sstevel@tonic-gate pfa = makedfa(getsval(y), 1); 18167c478bd9Sstevel@tonic-gate tempfree(y, ""); 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate y = execute(a[2]); /* replacement string */ 18197c478bd9Sstevel@tonic-gate if (pmatch(pfa, t)) { 18207c478bd9Sstevel@tonic-gate tempstat = pfa->initstat; 18217c478bd9Sstevel@tonic-gate pfa->initstat = 2; 1822*1ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR); 18237c478bd9Sstevel@tonic-gate rptr = getsval(y); 1824*1ee2e5faSnakanon cnt = 0; 18257c478bd9Sstevel@tonic-gate do { 1826*1ee2e5faSnakanon if (patlen == 0 && *patbeg != 0) { 1827*1ee2e5faSnakanon /* matched empty string */ 18287c478bd9Sstevel@tonic-gate if (mflag == 0) { /* can replace empty */ 18297c478bd9Sstevel@tonic-gate num++; 18307c478bd9Sstevel@tonic-gate sptr = rptr; 1831*1ee2e5faSnakanon while (*sptr != 0) { 1832*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt); 1833*1ee2e5faSnakanon if (*sptr == '\\' && 1834*1ee2e5faSnakanon *(sptr+1) == '&') { 18357c478bd9Sstevel@tonic-gate sptr++; 1836*1ee2e5faSnakanon buf[cnt++] = *sptr++; 18377c478bd9Sstevel@tonic-gate } else if (*sptr == '&') { 1838*1ee2e5faSnakanon expand_buf(&buf, 1839*1ee2e5faSnakanon &bsize, 1840*1ee2e5faSnakanon cnt + patlen); 18417c478bd9Sstevel@tonic-gate sptr++; 1842*1ee2e5faSnakanon (void) memcpy(&buf[cnt], 1843*1ee2e5faSnakanon patbeg, patlen); 1844*1ee2e5faSnakanon cnt += patlen; 1845*1ee2e5faSnakanon } else { 1846*1ee2e5faSnakanon buf[cnt++] = *sptr++; 1847*1ee2e5faSnakanon } 1848*1ee2e5faSnakanon } 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate if (*t == 0) /* at end */ 18517c478bd9Sstevel@tonic-gate goto done; 1852*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt); 1853*1ee2e5faSnakanon buf[cnt++] = *t++; 18547c478bd9Sstevel@tonic-gate mflag = 0; 1855*1ee2e5faSnakanon } else { /* matched nonempty string */ 18567c478bd9Sstevel@tonic-gate num++; 18577c478bd9Sstevel@tonic-gate sptr = t; 1858*1ee2e5faSnakanon len = patbeg - sptr; 1859*1ee2e5faSnakanon if (len > 0) { 1860*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + len); 1861*1ee2e5faSnakanon (void) memcpy(&buf[cnt], sptr, len); 1862*1ee2e5faSnakanon cnt += len; 1863*1ee2e5faSnakanon } 18647c478bd9Sstevel@tonic-gate sptr = rptr; 1865*1ee2e5faSnakanon while (*sptr != 0) { 1866*1ee2e5faSnakanon expand_buf(&buf, &bsize, cnt); 18677c478bd9Sstevel@tonic-gate if (*sptr == '\\' && *(sptr+1) == '&') { 18687c478bd9Sstevel@tonic-gate sptr++; 1869*1ee2e5faSnakanon buf[cnt++] = *sptr++; 18707c478bd9Sstevel@tonic-gate } else if (*sptr == '&') { 1871*1ee2e5faSnakanon expand_buf(&buf, &bsize, 1872*1ee2e5faSnakanon cnt + patlen); 18737c478bd9Sstevel@tonic-gate sptr++; 1874*1ee2e5faSnakanon (void) memcpy(&buf[cnt], 1875*1ee2e5faSnakanon patbeg, patlen); 1876*1ee2e5faSnakanon cnt += patlen; 1877*1ee2e5faSnakanon } else { 1878*1ee2e5faSnakanon buf[cnt++] = *sptr++; 1879*1ee2e5faSnakanon } 1880*1ee2e5faSnakanon } 18817c478bd9Sstevel@tonic-gate t = patbeg + patlen; 18827c478bd9Sstevel@tonic-gate if ((*(t-1) == 0) || (*t == 0)) 18837c478bd9Sstevel@tonic-gate goto done; 18847c478bd9Sstevel@tonic-gate mflag = 1; 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate } while (pmatch(pfa, t)); 18877c478bd9Sstevel@tonic-gate sptr = t; 1888*1ee2e5faSnakanon len = strlen((char *)sptr); 1889*1ee2e5faSnakanon expand_buf(&buf, &bsize, len + cnt); 1890*1ee2e5faSnakanon (void) memcpy(&buf[cnt], sptr, len); 1891*1ee2e5faSnakanon cnt += len; 1892*1ee2e5faSnakanon done: 1893*1ee2e5faSnakanon buf[cnt] = '\0'; 1894*1ee2e5faSnakanon (void) setsval(x, buf); 1895*1ee2e5faSnakanon free(buf); 18967c478bd9Sstevel@tonic-gate pfa->initstat = tempstat; 18977c478bd9Sstevel@tonic-gate } 18987c478bd9Sstevel@tonic-gate tempfree(x, ""); 18997c478bd9Sstevel@tonic-gate tempfree(y, ""); 19007c478bd9Sstevel@tonic-gate x = gettemp(""); 19017c478bd9Sstevel@tonic-gate x->tval = NUM; 19027c478bd9Sstevel@tonic-gate x->fval = num; 19037c478bd9Sstevel@tonic-gate return (x); 19047c478bd9Sstevel@tonic-gate } 1905