1 | /*
|
---|
2 | * a small awk clone
|
---|
3 | *
|
---|
4 | * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
|
---|
5 | *
|
---|
6 | * Absolutely no warranty. Use this software with your own risk.
|
---|
7 | *
|
---|
8 | * Permission to use, copy, modify and distribute this software for any
|
---|
9 | * purpose and without fee is hereby granted, provided that the above
|
---|
10 | * copyright and disclaimer notice.
|
---|
11 | *
|
---|
12 | * This program was written to fit into 64K+64K memory of the Minix 1.2.
|
---|
13 | */
|
---|
14 |
|
---|
15 |
|
---|
16 | #include <stdio.h>
|
---|
17 | #include <ctype.h>
|
---|
18 | #include "awk.h"
|
---|
19 | #include "regexp.h"
|
---|
20 |
|
---|
21 | extern char **FS, **OFS, **ORS, **OFMT;
|
---|
22 | extern double *RSTART, *RLENGTH;
|
---|
23 | extern char record[];
|
---|
24 | extern CELL *field[];
|
---|
25 |
|
---|
26 | extern int r_start, r_length;
|
---|
27 |
|
---|
28 | double getfval(), atof();
|
---|
29 | char *strsave(), *getsval(), *strcat(), *strstr();
|
---|
30 | CELL *mkcell(), *mktmp();
|
---|
31 | CELL *Field(), *Split(), *Forin();
|
---|
32 | CELL *Arith(), *Assign(), *Stat(), *Mathfun(), *Strfun(), *Cond();
|
---|
33 | CELL *Print(), *Cat(), *Array(), *Element();
|
---|
34 | CELL *If(), *While(), *For(), *Do(), *Jump();
|
---|
35 | CELL *P1stat(), *P2stat(), *Print0();
|
---|
36 | CELL *Arg(), *Call(), *Ret();
|
---|
37 | CELL *Subst(), *In(), *Getline(), *Delete(), *Close();
|
---|
38 | CELL *Nulproc(), *Usrfun();
|
---|
39 | CELL *_Arg();
|
---|
40 |
|
---|
41 | FILE *getfp(); /* r.c */
|
---|
42 |
|
---|
43 | CELL truecell = { NUM, NULL, 1.0 };
|
---|
44 | CELL falsecell = { NUM, NULL, 0.0 };
|
---|
45 | static CELL breakcell = { BRK, NULL, 0.0 };
|
---|
46 | static CELL contcell = { CNT, NULL, 0.0 };
|
---|
47 | static CELL nextcell = { NXT, NULL, 0.0 };
|
---|
48 | static CELL retcell = { RTN, NULL, 0.0 };
|
---|
49 |
|
---|
50 | static CELL *retval; /* function return value */
|
---|
51 |
|
---|
52 | int pateval; /* used in P1STAT & P2STAT */
|
---|
53 | static char *r_str; /* STR in 'str ~ STR */
|
---|
54 | static regexp *r_pat; /* compiled pattern for STR */
|
---|
55 |
|
---|
56 | CELL *(*proctab[])() = {
|
---|
57 | Arg, Arith, Array, Assign, Call, Cat, Cond, Delete, Do, Element,
|
---|
58 | Field, For, Forin, Getline, If, In, Jump, Mathfun, Nulproc, P1stat,
|
---|
59 | P2stat, Print, Print0, Strfun, Subst, Usrfun, While
|
---|
60 | };
|
---|
61 |
|
---|
62 | CELL *
|
---|
63 | execute(p) NODE *p;
|
---|
64 | {
|
---|
65 | int type, i;
|
---|
66 | CELL *r, *(*proc)();
|
---|
67 |
|
---|
68 | type = p->n_type;
|
---|
69 | if (type == VALUE) {
|
---|
70 | if ((r = (CELL *) p->n_arg[0])->c_type & PAT && pateval) {
|
---|
71 | i = match(r->c_sval, (char *)record) ? 1 : 0;
|
---|
72 | r = mktmp(NUM, NULL, (double) i);
|
---|
73 | }
|
---|
74 | return r;
|
---|
75 | }
|
---|
76 | for ( ; p != NULL; p = p->n_next) {
|
---|
77 | #if 0
|
---|
78 | if (p->n_type == VALUE) continue; /* neglect */
|
---|
79 | #endif
|
---|
80 | /*
|
---|
81 | switch ((int) p->n_type) {
|
---|
82 | case ARRAY:
|
---|
83 | r = Array(p);
|
---|
84 | break;
|
---|
85 | case ARITH:
|
---|
86 | r = Arith(p);
|
---|
87 | break;
|
---|
88 | case ASSIGN:
|
---|
89 | r = Assign(p);
|
---|
90 | break;
|
---|
91 | case PRINT:
|
---|
92 | r = Print(p);
|
---|
93 | break;
|
---|
94 | case PRINT0:
|
---|
95 | r = Print0(p);
|
---|
96 | break;
|
---|
97 | case CAT:
|
---|
98 | r = Cat(p);
|
---|
99 | break;
|
---|
100 | case MATHFUN:
|
---|
101 | r = Mathfun(p);
|
---|
102 | break;
|
---|
103 | case STRFUN:
|
---|
104 | r = Strfun(p);
|
---|
105 | break;
|
---|
106 | case COND:
|
---|
107 | r = Cond(p);
|
---|
108 | break;
|
---|
109 | case IF:
|
---|
110 | r = If(p);
|
---|
111 | break;
|
---|
112 | case P1STAT:
|
---|
113 | r = P1stat(p);
|
---|
114 | break;
|
---|
115 | case P2STAT:
|
---|
116 | r = P2stat(p);
|
---|
117 | break;
|
---|
118 | case WHILE:
|
---|
119 | r = While(p);
|
---|
120 | break;
|
---|
121 | case DO:
|
---|
122 | r = Do(p);
|
---|
123 | break;
|
---|
124 | case FOR:
|
---|
125 | r = For(p);
|
---|
126 | break;
|
---|
127 | case FORIN:
|
---|
128 | r = Forin(p);
|
---|
129 | break;
|
---|
130 | case FIELD:
|
---|
131 | r = Field(p);
|
---|
132 | break;
|
---|
133 | case JUMP:
|
---|
134 | r = Jump(p);
|
---|
135 | break;
|
---|
136 | case ARG:
|
---|
137 | r = Arg(p);
|
---|
138 | break;
|
---|
139 | case CALL:
|
---|
140 | r = Call(p);
|
---|
141 | break;
|
---|
142 | case SUBST:
|
---|
143 | r = Subst(p);
|
---|
144 | break;
|
---|
145 | case ELEMENT:
|
---|
146 | r = Element(p);
|
---|
147 | break;
|
---|
148 | case IN:
|
---|
149 | r = In(p);
|
---|
150 | break;
|
---|
151 | case GETLINE:
|
---|
152 | r = Getline(p);
|
---|
153 | break;
|
---|
154 | case DELETE:
|
---|
155 | r = Delete(p);
|
---|
156 | break;
|
---|
157 | case NULPROC:
|
---|
158 | r = &truecell;
|
---|
159 | break;
|
---|
160 | default:
|
---|
161 | printf("PROGRAM ERROR ? ILLEGAL NODE TYPE(%d)\n", type);
|
---|
162 | exit(1);
|
---|
163 | break;
|
---|
164 | }
|
---|
165 | */
|
---|
166 | i = (int) p->n_type;
|
---|
167 | if (i < FIRSTP || i > LASTP)
|
---|
168 | error("ILLEGAL PROC (%d)", i);
|
---|
169 | proc = proctab[i - FIRSTP];
|
---|
170 | r = (*proc)(p);
|
---|
171 | if (r->c_type & (BRK|CNT|NXT|RTN))
|
---|
172 | return r;
|
---|
173 | if (p->n_next != NULL)
|
---|
174 | c_free(r);
|
---|
175 | #ifdef DOS
|
---|
176 | kbhit(); /* needs in MS-DOS */
|
---|
177 | #endif
|
---|
178 | }
|
---|
179 | return r;
|
---|
180 | }
|
---|
181 |
|
---|
182 | static CELL *
|
---|
183 | Arith(p) NODE *p;
|
---|
184 | {
|
---|
185 | int op;
|
---|
186 | CELL *r, *u, *v, *execute();
|
---|
187 | double x, y, fmod(), pow();
|
---|
188 |
|
---|
189 | op = (int) p->n_arg[0];
|
---|
190 | if (op == UMINUS) {
|
---|
191 | u = execute(p->n_arg[1]);
|
---|
192 | x = - getfval(u);
|
---|
193 | }
|
---|
194 | else if (op == INCDEC) {
|
---|
195 | u = execute(p->n_arg[1]);
|
---|
196 | x = getfval(u);
|
---|
197 | setfval(u, x + (int) p->n_arg[2]);
|
---|
198 | if ((int) p->n_arg[3] == PRE)
|
---|
199 | return u;
|
---|
200 | /* return dummy */
|
---|
201 | }
|
---|
202 | else {
|
---|
203 | u = execute(p->n_arg[1]);
|
---|
204 | v = execute(p->n_arg[2]);
|
---|
205 | x = getfval(u);
|
---|
206 | y = getfval(v);
|
---|
207 | if (op == DIV || op == MOD) {
|
---|
208 | if (y == 0.0)
|
---|
209 | fprintf(stderr, "divid by 0\n");
|
---|
210 | }
|
---|
211 | switch (op) {
|
---|
212 | case SUB: x -= y;break;
|
---|
213 | case ADD: x += y; break;
|
---|
214 | case MULT: x *= y; break;
|
---|
215 | case DIV:
|
---|
216 | if (y == 0.0)
|
---|
217 | error("division by zero in \"/\"", (char *)0);
|
---|
218 | x /= y; break;
|
---|
219 | case MOD:
|
---|
220 | if (y == 0.0)
|
---|
221 | error("division by zero in \"%%\"", (char *)0);
|
---|
222 | x = fmod(x, y); break;
|
---|
223 | case POWER: x = pow(x, y); break;
|
---|
224 | default: printf("UNSUPPORTED ARITH OPERATOR !\n"); break;
|
---|
225 | }
|
---|
226 | c_free(v);
|
---|
227 | }
|
---|
228 | c_free(u);
|
---|
229 | r = mktmp(NUM, NULL, x);
|
---|
230 | return r;
|
---|
231 | }
|
---|
232 |
|
---|
233 | static CELL *
|
---|
234 | Assign(p) NODE *p;
|
---|
235 | {
|
---|
236 | CELL *u, *v, *execute();
|
---|
237 | int op;
|
---|
238 | double x, y, fmod(), pow();
|
---|
239 |
|
---|
240 | op = (int) p->n_arg[0];
|
---|
241 | u = execute(p->n_arg[1]);
|
---|
242 |
|
---|
243 | #if 0
|
---|
244 | if (u->c_type == UDF) /* fix up local var */
|
---|
245 | u->c_type |= VAR|STR;
|
---|
246 | #endif
|
---|
247 | if (!(u->c_type & (VAR|FLD|REC)) && (u->c_type != UDF))
|
---|
248 | fprintf(stderr, "ASSIGN TO NON VARIABLE (%d)\n", u->c_type);
|
---|
249 | v = execute(p->n_arg[2]);
|
---|
250 |
|
---|
251 | if (u == v)
|
---|
252 | goto rtn; /* same node */
|
---|
253 |
|
---|
254 | if (op == ASSIGN) {
|
---|
255 | if (v->c_type & NUM/* || isnum(v->c_sval)*/)
|
---|
256 | setfval(u, getfval(v));
|
---|
257 | else
|
---|
258 | setsval(u, getsval(v));
|
---|
259 | }
|
---|
260 | else {
|
---|
261 | x = getfval(u);
|
---|
262 | y = getfval(v);
|
---|
263 | switch (op) {
|
---|
264 | case ADDEQ: x += y; break;
|
---|
265 | case SUBEQ: x -= y; break;
|
---|
266 | case MULTEQ: x *= y; break;
|
---|
267 | case DIVEQ:
|
---|
268 | if (y == 0.0)
|
---|
269 | error("division by zero in \"/=\"", (char *)0);
|
---|
270 | x /= y; break;
|
---|
271 | case MODEQ:
|
---|
272 | if (y == 0.0)
|
---|
273 | error("division by zero in \"%=\"", (char *)0);
|
---|
274 | x = fmod(x, y); break;
|
---|
275 | case POWEQ: x = pow(x, y); break;
|
---|
276 | default:
|
---|
277 | synerr("illegal assign op (%d)", op);
|
---|
278 | break;
|
---|
279 | }
|
---|
280 | setfval(u, x);
|
---|
281 | }
|
---|
282 | rtn:
|
---|
283 | c_free(v);
|
---|
284 | return u;
|
---|
285 | }
|
---|
286 |
|
---|
287 | static CELL *
|
---|
288 | Cat(p) NODE *p;
|
---|
289 | {
|
---|
290 | CELL *u;
|
---|
291 | char *s, *t, str[BUFSIZ];
|
---|
292 |
|
---|
293 | u = execute(p->n_arg[0]);
|
---|
294 | s = getsval(u);
|
---|
295 | for (t = str; *s; )
|
---|
296 | *t++ = *s++;
|
---|
297 | c_free(u);
|
---|
298 | u = execute(p->n_arg[1]);
|
---|
299 | s = getsval(u);
|
---|
300 | while (*s)
|
---|
301 | *t++ = *s++;
|
---|
302 | c_free(u);
|
---|
303 | *t = '\0';
|
---|
304 | return mktmp(STR, str, 0.0);
|
---|
305 | }
|
---|
306 |
|
---|
307 | static CELL *
|
---|
308 | Print(p) NODE *p;
|
---|
309 | {
|
---|
310 | register int i, redir, typ;
|
---|
311 | CELL *u;
|
---|
312 | char *s, str[BUFSIZ];
|
---|
313 | char *file;
|
---|
314 | FILE *fp;
|
---|
315 |
|
---|
316 | redir = (int) p->n_arg[0];
|
---|
317 | if (typ = redir & PRMASK) { /* redirect */
|
---|
318 | u = execute(p->n_arg[1]);
|
---|
319 | file = getsval(u);
|
---|
320 | if (typ == R_PIPE)
|
---|
321 | typ = R_POUT;
|
---|
322 | fp = getfp(file, typ);
|
---|
323 | c_free(u);
|
---|
324 | }
|
---|
325 | else
|
---|
326 | fp = stdout;
|
---|
327 | if (redir & FORMAT) /* format */
|
---|
328 | format(str, p);
|
---|
329 | else {
|
---|
330 | *str = '\0';
|
---|
331 | for (i = 2; p->n_arg[i] != NULL; i++) {
|
---|
332 | if (i > 2)
|
---|
333 | strcat(str, *OFS);
|
---|
334 | u = execute(p->n_arg[i]);
|
---|
335 | s = getsval(u);
|
---|
336 | strcat(str, s);
|
---|
337 | c_free(u);
|
---|
338 | }
|
---|
339 | strcat(str, *ORS);
|
---|
340 | }
|
---|
341 | if (redir & STROUT) /* sprintf */
|
---|
342 | return mktmp(STR, str, 0.0);
|
---|
343 | fputs(str, fp);
|
---|
344 | fflush(fp);
|
---|
345 | return &truecell;
|
---|
346 | }
|
---|
347 |
|
---|
348 | static CELL *
|
---|
349 | Mathfun(p) NODE *p;
|
---|
350 | {
|
---|
351 | CELL *u, *v;
|
---|
352 | double x, y;
|
---|
353 | double atan2(), cos(), exp(), log(), sin(), sqrt(), modf();
|
---|
354 |
|
---|
355 | if ((int) p->n_arg[1] == 0) {
|
---|
356 | u = NULL;
|
---|
357 | x = 0.0;
|
---|
358 | }
|
---|
359 | else {
|
---|
360 | u = execute(p->n_arg[2]);
|
---|
361 | x = getfval(u);
|
---|
362 | }
|
---|
363 | switch ((int) p->n_arg[0]) {
|
---|
364 | case ATAN2:
|
---|
365 | if ((int) p->n_arg[1] == 2) {
|
---|
366 | v = execute(p->n_arg[3]);
|
---|
367 | y = getfval(v);
|
---|
368 | x = atan2(x, y);
|
---|
369 | c_free(v);
|
---|
370 | }
|
---|
371 | else
|
---|
372 | x = 0.0;
|
---|
373 | break;
|
---|
374 | case COS: x = cos(x); break;
|
---|
375 | case EXP: x = exp(x); break;
|
---|
376 | case INT: y = modf(x, &x); break;
|
---|
377 | case LOG: x = log(x); break;
|
---|
378 | case SIN: x = sin(x); break;
|
---|
379 | case SQRT: x = sqrt(x); break;
|
---|
380 | case RAND: x = (double) rand() / 32768.0; break;
|
---|
381 | case SRAND: if (x == 0.0)
|
---|
382 | x = (double) time(0);
|
---|
383 | x = (double) srand((int) x);
|
---|
384 | break;
|
---|
385 | default:
|
---|
386 | fprintf(stderr, "unknown math function (%d)\n", p->n_arg[2]);
|
---|
387 | break;
|
---|
388 | }
|
---|
389 | if (u != NULL)
|
---|
390 | c_free(u);
|
---|
391 | return mktmp(NUM, NULL, x);
|
---|
392 | }
|
---|
393 |
|
---|
394 | static CELL *
|
---|
395 | Strfun(p) NODE *p;
|
---|
396 | {
|
---|
397 | CELL *u, *v, *r;
|
---|
398 | char *s, *t, str[BUFSIZ];
|
---|
399 | int i, m, n;
|
---|
400 | double x;
|
---|
401 | regexp *pat, *getpat();
|
---|
402 |
|
---|
403 | n = (int) p->n_arg[1];
|
---|
404 | if (n > 0 && (int) p->n_arg[0] != SPLIT) {
|
---|
405 | u = execute(p->n_arg[2]);
|
---|
406 | s = getsval(u);
|
---|
407 | }
|
---|
408 | else {
|
---|
409 | s = "";
|
---|
410 | u = NULL;
|
---|
411 | }
|
---|
412 | switch ((int) p->n_arg[0]) {
|
---|
413 | case INDEX:
|
---|
414 | if (n > 1) {
|
---|
415 | v = execute(p->n_arg[3]);
|
---|
416 | t = getsval(v);
|
---|
417 | i = Index(s, t);
|
---|
418 | c_free(v);
|
---|
419 | }
|
---|
420 | else
|
---|
421 | i = 0;
|
---|
422 | r = mktmp(NUM, NULL, (double) i);
|
---|
423 | break;
|
---|
424 | case LENGTH:
|
---|
425 | i = (n > 0) ? jstrlen(s) : jstrlen(record);
|
---|
426 | r = mktmp(NUM, NULL, (double) i);
|
---|
427 | break;
|
---|
428 | case SPLIT:
|
---|
429 | r = Split(p);
|
---|
430 | break;
|
---|
431 | case SUBSTR:
|
---|
432 | if (n > 1) {
|
---|
433 | v = execute(p->n_arg[3]);
|
---|
434 | m = (int) getfval(v) - 1;
|
---|
435 | c_free(v);
|
---|
436 | }
|
---|
437 | else
|
---|
438 | m = 0;
|
---|
439 | if (n > 2) {
|
---|
440 | v = execute(p->n_arg[4]);
|
---|
441 | n = (int) getfval(v);
|
---|
442 | c_free(v);
|
---|
443 | }
|
---|
444 | else
|
---|
445 | n = jstrlen(s) - m;
|
---|
446 | for (t = str; *s && m-- > 0; s++)
|
---|
447 | if (isKanji(*s))
|
---|
448 | s++;
|
---|
449 | while (*s && n-- > 0) {
|
---|
450 | if (isKanji(*s))
|
---|
451 | *t++ = *s++;
|
---|
452 | *t++ = *s++;
|
---|
453 | }
|
---|
454 | *t = '\0';
|
---|
455 | r = mktmp(STR, str, 0.0);
|
---|
456 | break;
|
---|
457 | case RMATCH:
|
---|
458 | if (n > 1) {
|
---|
459 | v = execute(p->n_arg[3]);
|
---|
460 | pat = getpat(v);
|
---|
461 | match(pat, s);
|
---|
462 | c_free(v);
|
---|
463 | if (r_start) { /* change only if match */
|
---|
464 | *RSTART = (double) r_start;
|
---|
465 | *RLENGTH = (double) r_length;
|
---|
466 | }
|
---|
467 | r = mktmp(NUM, NULL, (double) r_start);
|
---|
468 | }
|
---|
469 | else
|
---|
470 | error("missing regexpr in match(str, regexpr)");
|
---|
471 | break;
|
---|
472 | case CLOSE:
|
---|
473 | r = Close(s);
|
---|
474 | break;
|
---|
475 | case SYSTEM:
|
---|
476 | r = mktmp(NUM, NULL, system(s) == -1 ? 0.0 : 1.0);
|
---|
477 | break;
|
---|
478 | default:
|
---|
479 | fprintf(stderr, "unknown string function");
|
---|
480 | break;
|
---|
481 | }
|
---|
482 | c_free(u);
|
---|
483 | return r;
|
---|
484 | }
|
---|
485 |
|
---|
486 | static regexp *
|
---|
487 | getpat(r) CELL *r;
|
---|
488 | {
|
---|
489 | regexp *pat, *mkpat();
|
---|
490 |
|
---|
491 | if (r->c_type & PAT)
|
---|
492 | pat = (regexp *) r->c_sval;
|
---|
493 | else {
|
---|
494 | if (r_str && strcmp(r_str, r->c_sval) == 0)
|
---|
495 | pat = r_pat;
|
---|
496 | else {
|
---|
497 | sfree(r_str); sfree(r_pat);
|
---|
498 | r_str = strsave(getsval(r));
|
---|
499 | pat = r_pat = mkpat(r_str);
|
---|
500 | }
|
---|
501 | }
|
---|
502 | return pat;
|
---|
503 | }
|
---|
504 |
|
---|
505 | static CELL *
|
---|
506 | Subst(p) NODE *p;
|
---|
507 | {
|
---|
508 | CELL *u, *v, *w;
|
---|
509 | char *s, *t, *r, str[BUFSIZ], *strcpy();
|
---|
510 | int i, n;
|
---|
511 |
|
---|
512 | n = (int) p->n_arg[1];
|
---|
513 | if (n > 1) {
|
---|
514 | u = execute(p->n_arg[3]); /* substitute string */
|
---|
515 | s = getsval(u);
|
---|
516 | v = execute(p->n_arg[2]); /* expr */
|
---|
517 | if (n > 2) {
|
---|
518 | w = execute(p->n_arg[4]);
|
---|
519 | t = getsval(w);
|
---|
520 | r = str;
|
---|
521 | }
|
---|
522 | else {
|
---|
523 | t = r = record;
|
---|
524 | w = NULL;
|
---|
525 | }
|
---|
526 | i = (int) p->n_arg[0] == RGSUB ? 0 : 1;
|
---|
527 | if (v->c_type & (PAT|STR))
|
---|
528 | i = Sub(r, v->c_sval, (v->c_type & STR), s, t, i);
|
---|
529 | else
|
---|
530 | error("[g]sub(PAT, .. ) must be /../ or string (%d)",
|
---|
531 | w->c_type);
|
---|
532 | if (n > 2) {
|
---|
533 | if (w->c_type & REC) {
|
---|
534 | strcpy(record, str);
|
---|
535 | mkfld(record, *FS, field);
|
---|
536 | }
|
---|
537 | else
|
---|
538 | setsval(w, str);
|
---|
539 | }
|
---|
540 | else
|
---|
541 | mkfld(record, *FS, field);
|
---|
542 | c_free(u);
|
---|
543 | c_free(v);
|
---|
544 | c_free(w);
|
---|
545 | }
|
---|
546 | else
|
---|
547 | i = 0;
|
---|
548 | return mktmp(NUM, NULL, (double) i);
|
---|
549 | }
|
---|
550 |
|
---|
551 | static CELL *
|
---|
552 | Cond(p) NODE *p;
|
---|
553 | {
|
---|
554 | CELL *u, *v;
|
---|
555 | double x, y;
|
---|
556 | int op, i, j;
|
---|
557 | char *s;
|
---|
558 | int save = pateval;
|
---|
559 |
|
---|
560 | op = (int) p->n_arg[0];
|
---|
561 | u = execute(p->n_arg[1]);
|
---|
562 | x = getfval(u);
|
---|
563 | /*
|
---|
564 | printf("Cond(%d)(%s)\n", u->c_type, u->c_sval);
|
---|
565 | */
|
---|
566 | if (op == AND || op == OR || op == NOT) {
|
---|
567 | if (u->c_type & NUM)
|
---|
568 | i = (x != 0.0);
|
---|
569 | else {
|
---|
570 | s = getsval(u);
|
---|
571 | i = (s != (char *)NULL) && (*s != '\0');
|
---|
572 | }
|
---|
573 | }
|
---|
574 | if (op == AND && !i) {
|
---|
575 | c_free(u);
|
---|
576 | return &falsecell;
|
---|
577 | }
|
---|
578 | if (op == OR && i) {
|
---|
579 | c_free(u);
|
---|
580 | return &truecell;
|
---|
581 | }
|
---|
582 | if (op == NOT)
|
---|
583 | i = i == 0 ? 1 : 0;
|
---|
584 | else {
|
---|
585 | if (op == MATCH || op == NOMATCH)
|
---|
586 | pateval = 0;
|
---|
587 | v = execute(p->n_arg[2]);
|
---|
588 | y = getfval(v);
|
---|
589 | if (op == AND || op == OR || op == BINAND || op == BINOR) {
|
---|
590 | if (v->c_type & NUM)
|
---|
591 | j = (y != 0.0);
|
---|
592 | else {
|
---|
593 | s = getsval(v);
|
---|
594 | j = (s != (char *)NULL) && (*s != '\0');
|
---|
595 | }
|
---|
596 | switch (op) {
|
---|
597 | case AND: i = i && j; break;
|
---|
598 | case OR: i = i || j; break;
|
---|
599 | case BINAND: i = i & j; break;
|
---|
600 | case BINOR: i = i | j; break;
|
---|
601 | }
|
---|
602 | }
|
---|
603 | else if (op == MATCH || op == NOMATCH) {
|
---|
604 | char *s;
|
---|
605 | regexp *pat, *getpat();
|
---|
606 |
|
---|
607 | s = getsval(u);
|
---|
608 | pat = getpat(v);
|
---|
609 | i = match(pat, s) == 0 ? 0 : 1;
|
---|
610 | if (op == NOMATCH)
|
---|
611 | i = i == 0 ? 1 : 0;
|
---|
612 | }
|
---|
613 | else { /* relative operator */
|
---|
614 | /*
|
---|
615 | printf("Cond(%d)(%d)(%s)(%s)\n", u->c_type, v->c_type, u->c_sval, v->c_sval);
|
---|
616 | */
|
---|
617 | if ((u->c_type & NUM) && (v->c_type & NUM))
|
---|
618 | i = x < y ? -1 : (x > y ? 1 : 0);
|
---|
619 | else
|
---|
620 | i = strcmp(getsval(u), getsval(v));
|
---|
621 | /*
|
---|
622 | printf("Cond(%d)(%d)(%g)(%g)(%d)\n", u->c_type, v->c_type, x, y, i);
|
---|
623 | */
|
---|
624 |
|
---|
625 | switch (op) {
|
---|
626 | case LT: i = i < 0 ? 1 : 0; break;
|
---|
627 | case LE: i = i <= 0 ? 1 : 0; break;
|
---|
628 | case EQ: i = i == 0 ? 1 : 0; break;
|
---|
629 | case NE: i = i != 0 ? 1 : 0; break;
|
---|
630 | case GT: i = i > 0 ? 1 : 0; break;
|
---|
631 | case GE: i = i >= 0 ? 1 : 0; break;
|
---|
632 | default:
|
---|
633 | fprintf(stderr, "unknown relative operator (%d)\n", op);
|
---|
634 | break;
|
---|
635 | }
|
---|
636 | }
|
---|
637 | c_free(v);
|
---|
638 | }
|
---|
639 | c_free(u);
|
---|
640 | pateval = save;
|
---|
641 | return mktmp(NUM, NULL, (double) i);
|
---|
642 | }
|
---|
643 |
|
---|
644 | static CELL *
|
---|
645 | If(p) NODE *p;
|
---|
646 | {
|
---|
647 | CELL *u;
|
---|
648 | int i;
|
---|
649 | char *s;
|
---|
650 |
|
---|
651 | u = execute(p->n_arg[0]);
|
---|
652 | if (u->c_type & NUM)
|
---|
653 | i = (getfval(u) != 0.0);
|
---|
654 | else {
|
---|
655 | s = getsval(u);
|
---|
656 | i = (s != (char *)NULL) && (*s != '\0');
|
---|
657 | }
|
---|
658 | c_free(u);
|
---|
659 | if (i)
|
---|
660 | u = execute(p->n_arg[1]);
|
---|
661 | else if (p->n_arg[2])
|
---|
662 | u = execute(p->n_arg[2]);
|
---|
663 | else
|
---|
664 | u = &truecell;
|
---|
665 | return u;
|
---|
666 | }
|
---|
667 |
|
---|
668 | static CELL *
|
---|
669 | While(p) NODE *p;
|
---|
670 | {
|
---|
671 | CELL *u;
|
---|
672 | double x;
|
---|
673 |
|
---|
674 | for (;;) {
|
---|
675 | u = execute(p->n_arg[0]);
|
---|
676 | x = getfval(u);
|
---|
677 | if (x == 0.0)
|
---|
678 | break;
|
---|
679 | c_free(u);
|
---|
680 | u = execute(p->n_arg[1]);
|
---|
681 | switch (u->c_type) {
|
---|
682 | case BRK:
|
---|
683 | goto rtn;
|
---|
684 | case NXT: case EXT: case RTN:
|
---|
685 | return u;
|
---|
686 | }
|
---|
687 | c_free(u);
|
---|
688 | }
|
---|
689 | rtn:
|
---|
690 | c_free(u);
|
---|
691 | return &truecell;
|
---|
692 | }
|
---|
693 |
|
---|
694 | static CELL *
|
---|
695 | Do(p) NODE *p;
|
---|
696 | {
|
---|
697 | CELL *u;
|
---|
698 | double x;
|
---|
699 |
|
---|
700 | for (;;) {
|
---|
701 | u = execute(p->n_arg[0]);
|
---|
702 | switch (u->c_type) {
|
---|
703 | case BRK:
|
---|
704 | goto rtn;
|
---|
705 | case NXT: case EXT: case RTN:
|
---|
706 | return u;
|
---|
707 | }
|
---|
708 | c_free(u);
|
---|
709 | u = execute(p->n_arg[1]);
|
---|
710 | if(getfval(u) == 0.0)
|
---|
711 | break;
|
---|
712 | c_free(u);
|
---|
713 | }
|
---|
714 | rtn:
|
---|
715 | c_free(u);
|
---|
716 | return &truecell;
|
---|
717 | }
|
---|
718 |
|
---|
719 | static CELL *
|
---|
720 | For(p) NODE *p;
|
---|
721 | {
|
---|
722 | CELL *u;
|
---|
723 | double x;
|
---|
724 |
|
---|
725 | if (p->n_arg[0] != NULL) {
|
---|
726 | u = execute(p->n_arg[0]);
|
---|
727 | c_free(u);
|
---|
728 | }
|
---|
729 | for (;;) {
|
---|
730 | if (p->n_arg[1] != NULL) {
|
---|
731 | u = execute(p->n_arg[1]);
|
---|
732 | x = getfval(u);
|
---|
733 | c_free(u);
|
---|
734 | if (x == 0.0)
|
---|
735 | break;
|
---|
736 | }
|
---|
737 | u = execute(p->n_arg[3]);
|
---|
738 | switch (u->c_type) {
|
---|
739 | case BRK:
|
---|
740 | c_free(u);
|
---|
741 | goto rtn;
|
---|
742 | case NXT: case EXT: case RTN:
|
---|
743 | return u;
|
---|
744 | }
|
---|
745 | if (p->n_arg[2] != NULL) {
|
---|
746 | u = execute(p->n_arg[2]);
|
---|
747 | c_free(u);
|
---|
748 | }
|
---|
749 | }
|
---|
750 | rtn:
|
---|
751 | return &truecell;
|
---|
752 | }
|
---|
753 |
|
---|
754 | static CELL *
|
---|
755 | Jump(p) NODE *p;
|
---|
756 | {
|
---|
757 | CELL *u;
|
---|
758 | int i;
|
---|
759 |
|
---|
760 | switch ((int) p->n_arg[0]) {
|
---|
761 | case BREAK: u = &breakcell; break;
|
---|
762 | case CONTIN: u = &contcell; break;
|
---|
763 | case EXIT:
|
---|
764 | if ((int) p->n_arg[1]) {
|
---|
765 | u = execute(p->n_arg[1]);
|
---|
766 | i = (int) getfval(u);
|
---|
767 | }
|
---|
768 | else
|
---|
769 | i = 0;
|
---|
770 | closeall();
|
---|
771 | exit(i);
|
---|
772 | case RETURN:
|
---|
773 | Return(p);
|
---|
774 | u = &retcell;
|
---|
775 | break;
|
---|
776 | case NEXT: u = &nextcell; break;
|
---|
777 | }
|
---|
778 | return u;
|
---|
779 | }
|
---|
780 |
|
---|
781 | static
|
---|
782 | Return(p) NODE *p;
|
---|
783 | {
|
---|
784 | CELL *u;
|
---|
785 | int i;
|
---|
786 | char *s, str[BUFSIZ];
|
---|
787 |
|
---|
788 | c_free(retval);
|
---|
789 | if (p->n_arg[1] != NULL) {
|
---|
790 | if (p->n_arg[2] == NULL) {
|
---|
791 | /*
|
---|
792 | if (0) {
|
---|
793 | */
|
---|
794 | u = execute(p->n_arg[1]);
|
---|
795 | if (u->c_type == UDF)
|
---|
796 | retval = mktmp(STR, "", 0.0);
|
---|
797 | else
|
---|
798 | retval = mktmp(u->c_type, u->c_sval, u->c_fval);
|
---|
799 | c_free(u);
|
---|
800 | }
|
---|
801 | else {
|
---|
802 | for (i = 1; p->n_arg[i] != NULL; i++) {
|
---|
803 | if (i == 1)
|
---|
804 | *str = '\0';
|
---|
805 | else
|
---|
806 | strcat(str, *OFS);
|
---|
807 | u = execute(p->n_arg[i]);
|
---|
808 | s = getsval(u);
|
---|
809 | strcat(str, s);
|
---|
810 | c_free(u);
|
---|
811 | }
|
---|
812 | /*
|
---|
813 | printf("Ret(%s)(%d)\n", str, isnum(str));
|
---|
814 | */
|
---|
815 | if (isnum(str))
|
---|
816 | retval = mktmp(STR|NUM, str, atof(str));
|
---|
817 | else
|
---|
818 | retval = mktmp(STR, str, 0.0);
|
---|
819 | }
|
---|
820 | }
|
---|
821 | else
|
---|
822 | retval = &truecell;
|
---|
823 | }
|
---|
824 |
|
---|
825 | #define MAXFRAME 100
|
---|
826 | CELL **frame[MAXFRAME];
|
---|
827 | static int framep;
|
---|
828 |
|
---|
829 | static CELL *
|
---|
830 | Arg(p) NODE *p;
|
---|
831 | {
|
---|
832 | CELL *u;
|
---|
833 | int i;
|
---|
834 |
|
---|
835 | u = (CELL *)p->n_arg[0];
|
---|
836 | return _Arg((int)u->c_fval);
|
---|
837 | }
|
---|
838 |
|
---|
839 | CELL *
|
---|
840 | _Arg(i)
|
---|
841 | {
|
---|
842 | /*
|
---|
843 | printf("Arg(%d)\n", i);
|
---|
844 | */
|
---|
845 | return frame[framep - 1][i];
|
---|
846 | }
|
---|
847 |
|
---|
848 | static CELL *
|
---|
849 | Call(p) NODE *p;
|
---|
850 | {
|
---|
851 | CELL *u, *v, *r, **arg;
|
---|
852 | NODE *q;
|
---|
853 | int i, j, k, n;
|
---|
854 | char *emalloc();
|
---|
855 |
|
---|
856 | if (framep >= MAXFRAME - 2)
|
---|
857 | error("stack frame overflow", (char *)0);
|
---|
858 | retval = &truecell;
|
---|
859 | r = (CELL *) p->n_arg[0];
|
---|
860 | if (r->c_type != FUN)
|
---|
861 | synerr("called function is not declared", (char *)0);
|
---|
862 | n = (int) r->c_fval; /* # of params */
|
---|
863 | if (n > 0) {
|
---|
864 | arg = (CELL **) emalloc(sizeof(u) * n);
|
---|
865 | for (i = 2, j = 0, k = (int) p->n_arg[1]; j < k; i++) {
|
---|
866 | u = execute(p->n_arg[i]);
|
---|
867 | /*
|
---|
868 | printf("pass, j(%d)typ(%d)\n", j, u->c_type);
|
---|
869 | */
|
---|
870 | if (u->c_type & ARR)
|
---|
871 | v = u; /* pass by reference */
|
---|
872 | else { /* pass by value */
|
---|
873 | v = mkcell(UDF, u->c_sval, u->c_fval);
|
---|
874 | if (u->c_type != UDF) {
|
---|
875 | #if 0
|
---|
876 | v->c_type = u->c_type;
|
---|
877 | if (v->c_type & (NUM|STR))
|
---|
878 | v->c_type |= VAR;
|
---|
879 | v->c_type &= ~TMP; /* dont't free */
|
---|
880 | #else
|
---|
881 | v->c_type |= (u->c_type & (NUM|STR))|VAR;
|
---|
882 | /*v->c_type &= ~TMP;*/
|
---|
883 | #endif
|
---|
884 | /* Don't free original */
|
---|
885 | }
|
---|
886 | /*
|
---|
887 | printf("pass1, j(%d)typ(%d)\n", j, v->c_type);
|
---|
888 | */
|
---|
889 | }
|
---|
890 | arg[j++] = v;
|
---|
891 | }
|
---|
892 | for ( ; j < n; ) /* local var */
|
---|
893 | arg[j++] = mkcell(UDF, NULL, 0.0);
|
---|
894 | }
|
---|
895 | else
|
---|
896 | arg = NULL;
|
---|
897 |
|
---|
898 | frame[framep] = arg;
|
---|
899 | framep++;
|
---|
900 |
|
---|
901 | r = execute(r->c_sval);
|
---|
902 | c_free(r);
|
---|
903 | framep--;
|
---|
904 | if (n > 0) {
|
---|
905 | for (j = n - 1 ; j > k; j--) { /* local var */
|
---|
906 | u = arg[j];
|
---|
907 | if (u->c_type & ARR)
|
---|
908 | a_free(u);
|
---|
909 | else
|
---|
910 | c_free(u);
|
---|
911 | }
|
---|
912 | for ( ; j >= 0; j--) {
|
---|
913 | u = arg[j];
|
---|
914 | if (!(u->c_type & ARR)) {
|
---|
915 | /* c_free(u);*/
|
---|
916 | sfree(u->c_sval);
|
---|
917 | sfree(u);
|
---|
918 | }
|
---|
919 | else {
|
---|
920 | v = execute(p->n_arg[j + 2]);
|
---|
921 | if (v->c_type == UDF) { /* copy back */
|
---|
922 | /*
|
---|
923 | printf("copy_back_UDF(%d)(%d)\n", j, u->c_type);
|
---|
924 | */
|
---|
925 | v->c_type = u->c_type;
|
---|
926 | sfree(v->c_sval);
|
---|
927 | v->c_sval = u->c_sval;
|
---|
928 | v->c_fval = u->c_fval;
|
---|
929 | sfree(u);
|
---|
930 | }
|
---|
931 | }
|
---|
932 | }
|
---|
933 | }
|
---|
934 | sfree(arg);
|
---|
935 | /* return retval;*/
|
---|
936 | u = mktmp(retval->c_type, retval->c_sval, retval->c_fval);
|
---|
937 | return u;
|
---|
938 | }
|
---|
939 |
|
---|
940 | CELL *Nulproc()
|
---|
941 | {
|
---|
942 | return &truecell;
|
---|
943 | }
|
---|
944 |
|
---|
945 | CELL *
|
---|
946 | Usrfun(p) NODE *p;
|
---|
947 | {
|
---|
948 | CELL *u;
|
---|
949 |
|
---|
950 | u = execute(p);
|
---|
951 | return u;
|
---|
952 | }
|
---|