[9] | 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 | }
|
---|