forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / awk / v.c
blob072d5a61ac5561fdd8e952e98fae8b8c6ccfe952
1 /*
2 * a small awk clone
4 * (C) 1989 Saeko Hirabauashi & Kouichi Hirabayashi
6 * Absolutely no warranty. Use this software with your own risk.
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.
12 * This program was written to fit into 64K+64K memory of the Minix 1.2.
16 #include <stdio.h>
17 #include <ctype.h>
18 #include "awk.h"
19 #include "regexp.h"
21 #define PI 3.14159265358979323846
23 #define HASHSIZE 50
24 #define MAXFIELD 100
26 double atof();
27 char *getsval(), *jStrchar();
28 extern CELL *execute(), *_Arg();
30 extern char record[];
31 extern CELL *field[];
33 extern CELL truecell, falsecell;
34 extern prmflg;
36 SYMBOL *hashtab[HASHSIZE];
37 SYMBOL *funtab[HASHSIZE];
38 SYMBOL *argtab[HASHSIZE];
39 SYMBOL *envtab[HASHSIZE];
41 char *strsave(), *emalloc(), *strchr();
42 CELL *lookup(), *install(), *_install(), *mkcell(), *mktmp(), *getvar();
44 char **FS, **RS, **OFS, **ORS, **OFMT, **FILENAME;
45 char **SUBSEP;
46 double *NR, *NF;
47 double *FNR, *ARGC, *RSTART, *RLENGTH;
49 init()
51 FS = &install("FS", VAR|STR, " ", 0.0, hashtab)->c_sval;
52 RS = &install("RS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
53 OFS = &install("OFS", VAR|STR , " ", 0.0, hashtab)->c_sval;
54 ORS = &install("ORS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
55 OFMT = &install("OFMT", VAR|STR, "%.6g", 0.0, hashtab)->c_sval;
56 NR = &install("NR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
57 NF = &install("NF", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
58 FILENAME = &install("FILENAME", VAR|STR, (char *)NULL, 0.0, hashtab)->c_sval;
59 install("PI", VAR|NUM, (char *)NULL, PI, hashtab);
60 field[0] = mkcell(REC|STR, (char *)NULL, 0.0); /* $0 */
61 field[0]->c_sval = record;
62 SUBSEP = &install("SUBSEP", VAR|STR, "\034", 0.0, hashtab)->c_sval;
63 FNR = &install("FNR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
64 RSTART = &install("RSTART", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
65 RLENGTH = &install("RLENGTH", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
68 setvar(s) char *s;
70 CELL *u;
71 char *t;
73 for (t = s; *t && *t != '='; t++)
75 *t++ = '\0';
76 if ((u = lookup(s, hashtab)) == (CELL *)NULL) {
77 if (isnum(t))
78 install(s, VAR|NUM|STR, t, atof(t), hashtab);
79 else
80 install(s, VAR|STR, t, 0.0, hashtab);
82 else {
83 if (isnum(t))
84 setfval(u, atof(t));
85 else
86 setsval(u, t);
90 initarg(arg0, argc, argv, envp) char *arg0, **argv, **envp;
92 CELL *u;
93 register int i;
94 register char str[4], *p;
96 ARGC = &install("ARGC", VAR|NUM, (char *)NULL, (double)argc+1, hashtab)->c_fval;
97 u = install("ARGV", ARR, (char *)NULL, 0.0, hashtab);
98 u->c_sval = (char *) argtab;
99 install("0", VAR|STR, arg0, 0.0, argtab);
100 for (i = 0; i < argc; i++) {
101 sprintf(str, "%d", i+1);
102 if (isnum(argv[i]))
103 install(str, VAR|STR|NUM, argv[i], atof(argv[i]), argtab);
104 else
105 install(str, VAR|STR, argv[i], 0.0, argtab);
108 u = install("ENVIRON", ARR, (char *)NULL, 0.0, hashtab);
109 u->c_sval = (char *) envtab;
110 for (i = 0; envp[i] && *envp[i]; i++) {
111 if ((p = strchr(envp[i], '=')) != NULL) {
112 *p = 0;
113 if (isnum(p+1))
114 install(envp[i], VAR|STR|NUM, p+1, atof(p+1), envtab);
115 else
116 install(envp[i], VAR|STR, p+1, 0.0, envtab);
117 *p = '=';
122 static
123 hash(s) unsigned char *s;
125 register unsigned int h;
127 for (h = 0; *s; )
128 h += *s++;
129 return h % HASHSIZE;
132 CELL *
133 lookup(s, h) char *s; SYMBOL *h[];
135 register SYMBOL *p;
137 for (p = h[hash(s)]; p; p = p->s_next)
138 if (strcmp(s, p->s_name) == 0)
139 return p->s_val;
140 return (CELL *)NULL;
143 static CELL *
144 install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];
146 CELL *u;
148 if ((u = lookup(name, h)) == (CELL *)NULL)
149 u = _install(name, type, sval, fval, h);
150 else
151 error("%s is doubly defined", name);
152 return u;
155 static CELL *
156 _install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];{
157 register SYMBOL *p;
158 CELL *u;
159 int hval;
161 p = (SYMBOL *) emalloc(sizeof(*p));
162 u = (CELL *) emalloc(sizeof(*u));
163 p->s_name = strsave(name);
164 p->s_val = u;
165 hval = hash(name);
166 p->s_next = h[hval];
167 h[hval] = p;
168 u->c_type = type;
169 u->c_sval = strsave(sval);
170 #if 0
171 if (!(type & NUM) && isnum(sval)) {
172 u->c_fval = atof(sval);
173 u->c_type |= NUM;
175 else
176 #endif
177 u->c_fval = fval;
178 return u;
181 CELL *
182 getvar(s, h, typ) char *s; SYMBOL *h[];
184 CELL *u;
185 SYMBOL *p;
186 char *t;
187 int i, hval;
189 if ((u = lookup(s, h)) == (CELL *)NULL) {
190 if (prmflg) {
191 u = _install(s, UDF, "", 0.0, h);
192 goto rtn;
194 else if (typ & ARR) {
195 t = emalloc(sizeof(SYMBOL *) * HASHSIZE);
196 for (i = 0; i < HASHSIZE; i++)
197 ((SYMBOL **) t)[i] = (SYMBOL *)NULL;
198 u = (CELL *) emalloc(sizeof(*u));
199 u->c_type = typ;
200 u->c_sval = t;
201 u->c_fval = 0.0;
202 p = (SYMBOL *) emalloc(sizeof(*p));
203 p->s_name = strsave(s);
204 p->s_val = u;
205 hval = hash(s);
206 p->s_next = h[hval];
207 h[hval] = p;
209 else
210 u = _install(s, typ, "", 0.0, h);
212 else if (!prmflg && (u->c_type == UDF) && (typ != UDF)) {
213 /* fix up local_var/forward_function */
214 if (typ == ARR) {
216 printf("getvar_correct_to_array\n");
218 u->c_type = typ;
219 sfree(u->c_sval);
220 u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
221 for (i = 0; i < HASHSIZE; i++)
222 ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
223 u->c_fval = 0.0;
225 else if (typ != UDF) {
226 u->c_type = typ;
229 rtn:
230 return u;
233 fixarray(u) CELL *u;
235 int i;
237 if (u->c_type == UDF) { /* fix up local var */
239 printf("fixarray\n");
241 u->c_type = ARR;
242 sfree(u->c_sval);
243 u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
244 for (i = 0; i < HASHSIZE; i++)
245 ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
246 u->c_fval = 0.0;
250 a_free(u) CELL *u;
251 { /* free local array */
252 SYMBOL **h, *q, *r;
253 CELL *v;
254 int i;
256 if (!(u->c_type & ARR))
257 error("try to free non array variable", (char *)0);
258 h = (SYMBOL **) u->c_sval;
259 for (i = 0; i < HASHSIZE; i++)
260 for (q = h[i]; q; q = r) {
261 r = q->s_next;
262 sfree(q->s_name);
263 v = q->s_val; /* CELL */
264 c_free(v);
265 sfree(q); /* SYMBOL */
268 sfree(u->c_sval); /* symbol table */
269 c_free(u);
272 CELL *
273 Array(p) NODE *p;
275 CELL *u;
276 char str[BUFSIZ];
277 int i, n;
279 CELL *v;
281 u = (CELL *) p->n_arg[0];
282 if (u->c_type == POS) {
283 i = (int)u->c_fval;
285 printf("**ARG_ARRAY(%d)*\n", i);
287 u = _Arg(i);
288 if (u->c_type == UDF) { /* fix up local array */
290 printf("local_var_to_array\n");
292 fixarray(u);
295 else if (!(u->c_type & ARR))
296 error("non array refference");
297 arrayelm(p, str);
298 u = getvar(str, u->c_sval, VAR|NUM|STR); /* "rtsort in AWK book */
299 return u;
302 static
303 arrayelm(p, s) NODE *p; char *s;
305 CELL *u;
306 int i, n;
307 char *t;
310 char *tt = s;
312 n = (int) p->n_arg[1] + 2;
313 for (i = 2; i < n; i++) {
314 if (i > 2)
315 *s++ = **SUBSEP;
316 u = execute(p->n_arg[i]);
317 for (t = getsval(u); *t; )
318 *s++ = *t++;
319 c_free(u);
321 *s = '\0';
323 printf("array_elm(%s)\n", tt);
327 CELL *
328 Element(p) NODE *p;
330 char str[BUFSIZ];
332 arrayelm(p, str);
333 return mktmp(STR, str, 0.0);
336 CELL *
337 Delete(p) NODE *p;
339 CELL *u;
340 char str[BUFSIZ];
341 int i;
342 SYMBOL *q, *r, **h;
344 u = (CELL *) p->n_arg[0];
345 if (!(u->c_type & ARR))
346 error("can't delete non array variable");
347 arrayelm(p, str);
348 h = (SYMBOL **) u->c_sval;
349 for (r = (SYMBOL *)NULL, i = hash(str), q = h[i]; q; r = q, q = q->s_next)
350 if (strcmp(str, q->s_name) == 0)
351 break;
352 if (q) {
353 sfree(q->s_val->c_sval);
354 sfree(q->s_name);
355 if (r)
356 r->s_next = q->s_next;
357 if (q == h[i])
358 h[i] = (SYMBOL *)NULL;
360 return &truecell;
363 CELL *
364 In(p) NODE *p;
366 SYMBOL **h, *q;
367 CELL *u, *v;
368 char *s;
369 int i;
371 u = (CELL *) p->n_arg[1]; /* array */
372 if (!(u->c_type & ARR))
373 error("%s is not an array", u->c_sval);
374 h = (SYMBOL **) u->c_sval;
375 if (u->c_sval != (char *)NULL) {
376 v = execute(p->n_arg[0]); /* var */
377 s = getsval(v);
378 for (i = 0; i < HASHSIZE; i++)
379 for (q = h[i]; q; q = q->s_next) {
380 if (strcmp(s, q->s_name) == 0) {
381 c_free(v);
382 return &truecell;
385 c_free(v);
387 return &falsecell;
390 CELL *
391 Split(p) NODE *p;
393 CELL *u, *v, *w;
394 char *s, *t, *h, *name, *sep;
395 int i, n, skip;
396 char elm[8], str[BUFSIZ];
397 static char *s_str;
398 static regexp *s_pat;
399 regexp *mkpat();
400 extern int r_start, r_length;
402 n = (int) p->n_arg[1];
403 if (n > 1) {
404 u = execute(p->n_arg[2]);
405 s = getsval(u); /* str */
406 v = execute(p->n_arg[3]); /* array */
407 if (!(v->c_type & ARR)) {
409 printf("Split fix_to_array(%d)\n", v->c_type);
411 if (v->c_type == UDF) /* fix up local array */
412 fixarray(v);
413 else
414 error("split to non array variable", (char *)0);
416 h = v->c_sval;
417 c_free(v);
418 if (n > 2) {
419 v = execute(p->n_arg[4]);
420 sep = getsval(v);
422 else {
423 v = (CELL *)NULL;
424 sep = *FS;
426 if (strlen(sep) > 1) { /* reg_exp */
427 if (strcmp(sep, s_str) != 0) {
428 sfree(s_str); sfree(s_pat);
429 s_str = strsave(sep);
430 s_pat = mkpat(s_str);
432 for (i = 0, t = str; *s; ) {
433 if (match(s_pat, s)) {
434 for (n = r_start; --n > 0; )
435 *t++ = *s++;
437 else {
438 while(*s)
439 *t++ = *s++;
441 *t = '\0';
442 t = str;
443 sprintf(elm, "%d", ++i);
444 w = getvar(elm, h, VAR);
445 if (isnum(str))
446 setfval(w, atof(str));
447 else
448 setsval(w, str);
449 if (*s)
450 s += r_length;
453 else {
454 skip = *sep == ' ';
455 for (i = 0; t = str, *s; ) {
456 if (skip)
457 while (jStrchr(" \t\n", *s))
458 s++;
459 if (!(*s))
460 break;
461 while (*s && !jStrchr(sep, *s)) {
462 if (isKanji(*s))
463 *t++ = *s++;
464 *t++ = *s++;
466 *t = '\0';
467 sprintf(elm, "%d", ++i);
468 w = getvar(elm, h, VAR);
469 if (isnum(str))
470 setfval(w, atof(str));
471 else
472 setsval(w, str);
473 if (*s && !skip)
474 s++;
477 c_free(v); /* sep */
478 c_free(u); /* str may be CATed */
480 else
481 i = 0;
482 return mktmp(NUM, (char *)NULL, (double) i);
485 CELL *
486 Forin(p) NODE *p;
488 CELL *u, *v;
489 SYMBOL **h, *q;
490 char *name;
491 int i;
493 u = execute(p->n_arg[1]);
494 if (!(u->c_type & ARR))
495 synerr(
496 "non array variable is specified in 'for (. in var)'", (char *)0);
497 h = (SYMBOL **) u->c_sval;
498 c_free(u);
499 u = execute(p->n_arg[0]);
500 if (u->c_type == UDF) {
502 printf("Forin_fix_to_VAR|NUM\n");
504 u->c_type = VAR|NUM;
506 if (!(u->c_type & VAR))
507 error("'for (VAR in .)' is not variable (%d)", name, u->c_type);
508 for (i = 0; i < HASHSIZE; i++) {
509 for (q = h[i]; q; q = q->s_next) {
510 setsval(u, q->s_name);
511 v = execute(p->n_arg[2]);
512 c_free(v);
515 c_free(u);
516 return &truecell;
519 char *
520 strsave(s) char *s;
522 register int n;
523 char *emalloc(), *strcpy();
525 if (s == (char *)NULL)
526 return (char *)NULL;
527 n = strlen(s) + 1;
528 return strcpy(emalloc(n), s);
531 sfree(p) char *p;
533 if (p != (char *)NULL)
534 Free(p);
537 isnum(s) char *s;
539 char *strchr();
541 if (s == NULL || *s == '\0' || !strcmp(s, "."))
542 return 0;
543 if (*s && strchr("+-", *s) != (char *)NULL)
544 s++;
545 if (*s == '\0')
546 return 0;
547 while (isdigit(*s))
548 s++;
549 if (*s == '.') {
550 s++;
551 while (isdigit(*s))
552 s++;
554 if (*s && strchr("eE", *s) != (char *)NULL) {
555 s++;
556 if (*s == '\0')
557 return 0;
558 if (*s && strchr("+-", *s) != (char *)NULL)
559 s++;
560 while (isdigit(*s))
561 s++;
563 return *s == '\0';
566 setfval(u, f) CELL *u; double f;
568 if (u->c_type == UDF) { /* fix up local var */
570 printf("setfval_fix_to_VAR\n");
572 u->c_type |= VAR;
574 if (u->c_type & (VAR|FLD|REC|TMP)) {
575 u->c_type &= ~STR;
576 u->c_type |= NUM;
577 sfree(u->c_sval);
578 u->c_sval = (char *)NULL;
579 u->c_fval = f;
580 if (u->c_type & FLD)
581 mkrec(u);
583 else
584 fprintf(stderr, "assign to nonvariable (%d)\n", u->c_type);
587 setsval(u, s) CELL *u; char *s;
589 double atof();
591 if (u->c_type == UDF) { /* fix up local var */
593 printf("setsval_fix_to_VAR\n");
595 u->c_type |= VAR;
597 if (u->c_type & (VAR|FLD|REC|TMP)) {
598 u->c_type &= ~NUM;
599 u->c_type |= STR;
600 sfree(u->c_sval);
601 u->c_sval = strsave(s);
602 #if 0 /* "table2" in AWK book */
603 if (isnum(u->c_sval)) {
604 u->c_fval = atof(u->c_sval);
605 u->c_type |= NUM;
607 else
608 #endif
609 u->c_fval = 0.0;
610 if (u->c_type & FLD)
611 mkrec(u);
613 else
614 fprintf(stderr, "assign to constant (%d)\n", u->c_type);
617 double
618 getfval(u) CELL *u;
620 double x, atof();
622 if (u->c_type == UDF) { /* local var */
623 u->c_type |= VAR|STR|NUM;
624 u->c_sval = strsave("");
625 x = u->c_fval = 0.0;
627 else if (u->c_type & NUM)
628 x = u->c_fval;
629 #if 1
630 else {
631 x = atof(u->c_sval);
632 #else
633 else {
634 if (isnum(u->c_sval))
635 x = atof(u->c_sval);
636 else
637 x = 0.0;
638 #endif
640 return x;
643 char *
644 getsval(u) CELL *u;
646 char *s, str[80];
648 if (u->c_type & STR)
649 s = u->c_sval;
650 else if (u->c_type & NUM) {
651 /* if (u->c_fval >= -2147483648.0 && u->c_fval <= 2147483647.0)*/
652 if ((long)u->c_fval == u->c_fval)
653 s = "%.16g";
654 else
655 s = *OFMT;
656 sprintf(str, s, u->c_fval);
657 sfree(u->c_sval);
658 s = u->c_sval = strsave(str);
660 #if 1
661 else if (u->c_type == UDF) { /* local var */
663 printf("getsval_fix_to_VAR|STR\n");
665 u->c_type |= VAR|STR|NUM;
666 s = u->c_sval = strsave("");
667 u->c_fval = 0.0;
669 #endif
670 else
671 fprintf(stderr, "abnormal value (STR|NUM == 0)(%d)\n", u->c_type);
672 return s;
675 char *
676 emalloc(n) unsigned n;
678 char *p;
679 #if 0
680 char far *_fmalloc();
681 #else
682 char *malloc();
683 #endif
685 #if 0
686 if ((p = _fmalloc(n)) == (char *)NULL)
687 #else
688 if ((p = malloc(n)) == (char *)NULL)
689 #endif
690 error("memory over");
691 return p;
694 Free(s) char *s;
696 #if DOS
697 void _ffree();
699 _ffree(s);
700 #else
701 free(s);
702 #endif