PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/usr.bin/awk/run.c

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