source: trunk/minix/commands/awk/v.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 12.7 KB
Line 
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#define PI 3.14159265358979323846
22
23#define HASHSIZE 50
24#define MAXFIELD 100
25
26double atof();
27char *getsval(), *jStrchar();
28extern CELL *execute(), *_Arg();
29
30extern char record[];
31extern CELL *field[];
32
33extern CELL truecell, falsecell;
34extern prmflg;
35
36SYMBOL *hashtab[HASHSIZE];
37SYMBOL *funtab[HASHSIZE];
38SYMBOL *argtab[HASHSIZE];
39
40char *strsave(), *emalloc(), *strchr();
41CELL *lookup(), *install(), *_install(), *mkcell(), *mktmp(), *getvar();
42
43char **FS, **RS, **OFS, **ORS, **OFMT, **FILENAME;
44char **SUBSEP;
45double *NR, *NF;
46double *FNR, *ARGC, *RSTART, *RLENGTH;
47
48init()
49{
50 FS = &install("FS", VAR|STR, " ", 0.0, hashtab)->c_sval;
51 RS = &install("RS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
52 OFS = &install("OFS", VAR|STR , " ", 0.0, hashtab)->c_sval;
53 ORS = &install("ORS", VAR|STR, "\n", 0.0, hashtab)->c_sval;
54 OFMT = &install("OFMT", VAR|STR, "%.6g", 0.0, hashtab)->c_sval;
55 NR = &install("NR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
56 NF = &install("NF", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
57 FILENAME = &install("FILENAME", VAR|STR, (char *)NULL, 0.0, hashtab)->c_sval;
58 install("PI", VAR|NUM, (char *)NULL, PI, hashtab);
59 field[0] = mkcell(REC|STR, (char *)NULL, 0.0); /* $0 */
60 field[0]->c_sval = record;
61 SUBSEP = &install("SUBSEP", VAR|STR, "\034", 0.0, hashtab)->c_sval;
62 FNR = &install("FNR", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
63 RSTART = &install("RSTART", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
64 RLENGTH = &install("RLENGTH", VAR|NUM, (char *)NULL, 0.0, hashtab)->c_fval;
65}
66
67setvar(s) char *s;
68{
69 CELL *u;
70 char *t;
71
72 for (t = s; *t && *t != '='; t++)
73 ;
74 *t++ = '\0';
75 if ((u = lookup(s, hashtab)) == (CELL *)NULL) {
76 if (isnum(t))
77 install(s, VAR|NUM|STR, t, atof(t), hashtab);
78 else
79 install(s, VAR|STR, t, 0.0, hashtab);
80 }
81 else {
82 if (isnum(t))
83 setfval(u, atof(t));
84 else
85 setsval(u, t);
86 }
87}
88
89initarg(arg0, argc, argv) char *arg0, **argv;
90{
91 CELL *u;
92 register int i;
93 register char str[4];
94
95 ARGC = &install("ARGC", VAR|NUM, (char *)NULL, (double)argc+1, hashtab)->c_fval;
96 u = install("ARGV", ARR, (char *)NULL, 0.0, hashtab);
97 u->c_sval = (char *) argtab;
98 install("0", VAR|STR, arg0, 0.0, argtab);
99 for (i = 0; i < argc; i++) {
100 sprintf(str, "%d", i+1);
101 if (isnum(argv[i]))
102 install(str, VAR|STR|NUM, argv[i], atof(argv[i]), argtab);
103 else
104 install(str, VAR|STR, argv[i], 0.0, argtab);
105 }
106}
107
108static
109hash(s) unsigned char *s;
110{
111 register unsigned int h;
112
113 for (h = 0; *s; )
114 h += *s++;
115 return h % HASHSIZE;
116}
117
118CELL *
119lookup(s, h) char *s; SYMBOL *h[];
120{
121 register SYMBOL *p;
122
123 for (p = h[hash(s)]; p; p = p->s_next)
124 if (strcmp(s, p->s_name) == 0)
125 return p->s_val;
126 return (CELL *)NULL;
127}
128
129static CELL *
130install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];
131{
132 CELL *u;
133
134 if ((u = lookup(name, h)) == (CELL *)NULL)
135 u = _install(name, type, sval, fval, h);
136 else
137 error("%s is doubly defined", name);
138 return u;
139}
140
141static CELL *
142_install(name, type, sval, fval, h) char *name, *sval; double fval; SYMBOL *h[];{
143 register SYMBOL *p;
144 CELL *u;
145 int hval;
146
147 p = (SYMBOL *) emalloc(sizeof(*p));
148 u = (CELL *) emalloc(sizeof(*u));
149 p->s_name = strsave(name);
150 p->s_val = u;
151 hval = hash(name);
152 p->s_next = h[hval];
153 h[hval] = p;
154 u->c_type = type;
155 u->c_sval = strsave(sval);
156#if 0
157 if (!(type & NUM) && isnum(sval)) {
158 u->c_fval = atof(sval);
159 u->c_type |= NUM;
160 }
161 else
162#endif
163 u->c_fval = fval;
164 return u;
165}
166
167CELL *
168getvar(s, h, typ) char *s; SYMBOL *h[];
169{
170 CELL *u;
171 SYMBOL *p;
172 char *t;
173 int i, hval;
174
175 if ((u = lookup(s, h)) == (CELL *)NULL) {
176 if (prmflg) {
177 u = _install(s, UDF, "", 0.0, h);
178 goto rtn;
179 }
180 else if (typ & ARR) {
181 t = emalloc(sizeof(SYMBOL *) * HASHSIZE);
182 for (i = 0; i < HASHSIZE; i++)
183 ((SYMBOL **) t)[i] = (SYMBOL *)NULL;
184 u = (CELL *) emalloc(sizeof(*u));
185 u->c_type = typ;
186 u->c_sval = t;
187 u->c_fval = 0.0;
188 p = (SYMBOL *) emalloc(sizeof(*p));
189 p->s_name = strsave(s);
190 p->s_val = u;
191 hval = hash(s);
192 p->s_next = h[hval];
193 h[hval] = p;
194 }
195 else
196 u = _install(s, typ, "", 0.0, h);
197 }
198 else if (!prmflg && (u->c_type == UDF) && (typ != UDF)) {
199 /* fix up local_var/forward_function */
200 if (typ == ARR) {
201/*
202printf("getvar_correct_to_array\n");
203*/
204 u->c_type = typ;
205 sfree(u->c_sval);
206 u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
207 for (i = 0; i < HASHSIZE; i++)
208 ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
209 u->c_fval = 0.0;
210 }
211 else if (typ != UDF) {
212 u->c_type = typ;
213 }
214 }
215rtn:
216 return u;
217}
218
219fixarray(u) CELL *u;
220{
221 int i;
222
223 if (u->c_type == UDF) { /* fix up local var */
224/*
225printf("fixarray\n");
226*/
227 u->c_type = ARR;
228 sfree(u->c_sval);
229 u->c_sval = emalloc(sizeof(SYMBOL *) * HASHSIZE);
230 for (i = 0; i < HASHSIZE; i++)
231 ((SYMBOL **) u->c_sval)[i] = (SYMBOL *)NULL;
232 u->c_fval = 0.0;
233 }
234}
235
236a_free(u) CELL *u;
237{ /* free local array */
238 SYMBOL **h, *q, *r;
239 CELL *v;
240 int i;
241
242 if (!(u->c_type & ARR))
243 error("try to free non array variable", (char *)0);
244 h = (SYMBOL **) u->c_sval;
245 for (i = 0; i < HASHSIZE; i++)
246 for (q = h[i]; q; q = r) {
247 r = q->s_next;
248 sfree(q->s_name);
249 v = q->s_val; /* CELL */
250 c_free(v);
251 sfree(q); /* SYMBOL */
252 }
253
254 sfree(u->c_sval); /* symbol table */
255 c_free(u);
256}
257
258CELL *
259Array(p) NODE *p;
260{
261 CELL *u;
262 char str[BUFSIZ];
263 int i, n;
264
265 CELL *v;
266
267 u = (CELL *) p->n_arg[0];
268 if (u->c_type == POS) {
269 i = (int)u->c_fval;
270/*
271printf("**ARG_ARRAY(%d)*\n", i);
272*/
273 u = _Arg(i);
274 if (u->c_type == UDF) { /* fix up local array */
275/*
276printf("local_var_to_array\n");
277*/
278 fixarray(u);
279 }
280 }
281 else if (!(u->c_type & ARR))
282 error("non array refference");
283 arrayelm(p, str);
284 u = getvar(str, u->c_sval, VAR|NUM|STR); /* "rtsort in AWK book */
285 return u;
286}
287
288static
289arrayelm(p, s) NODE *p; char *s;
290{
291 CELL *u;
292 int i, n;
293 char *t;
294
295/*
296char *tt = s;
297*/
298 n = (int) p->n_arg[1] + 2;
299 for (i = 2; i < n; i++) {
300 if (i > 2)
301 *s++ = **SUBSEP;
302 u = execute(p->n_arg[i]);
303 for (t = getsval(u); *t; )
304 *s++ = *t++;
305 c_free(u);
306 }
307 *s = '\0';
308/*
309printf("array_elm(%s)\n", tt);
310*/
311}
312
313CELL *
314Element(p) NODE *p;
315{
316 char str[BUFSIZ];
317
318 arrayelm(p, str);
319 return mktmp(STR, str, 0.0);
320}
321
322CELL *
323Delete(p) NODE *p;
324{
325 CELL *u;
326 char str[BUFSIZ];
327 int i;
328 SYMBOL *q, *r, **h;
329
330 u = (CELL *) p->n_arg[0];
331 if (!(u->c_type & ARR))
332 error("can't delete non array variable");
333 arrayelm(p, str);
334 h = (SYMBOL **) u->c_sval;
335 for (r = (SYMBOL *)NULL, i = hash(str), q = h[i]; q; r = q, q = q->s_next)
336 if (strcmp(str, q->s_name) == 0)
337 break;
338 if (q) {
339 sfree(q->s_val->c_sval);
340 sfree(q->s_name);
341 if (r)
342 r->s_next = q->s_next;
343 if (q == h[i])
344 h[i] = (SYMBOL *)NULL;
345 }
346 return &truecell;
347}
348
349CELL *
350In(p) NODE *p;
351{
352 SYMBOL **h, *q;
353 CELL *u, *v;
354 char *s;
355 int i;
356
357 u = (CELL *) p->n_arg[1]; /* array */
358 if (!(u->c_type & ARR))
359 error("%s is not an array", u->c_sval);
360 h = (SYMBOL **) u->c_sval;
361 if (u->c_sval != (char *)NULL) {
362 v = execute(p->n_arg[0]); /* var */
363 s = getsval(v);
364 for (i = 0; i < HASHSIZE; i++)
365 for (q = h[i]; q; q = q->s_next) {
366 if (strcmp(s, q->s_name) == 0) {
367 c_free(v);
368 return &truecell;
369 }
370 }
371 c_free(v);
372 }
373 return &falsecell;
374}
375
376CELL *
377Split(p) NODE *p;
378{
379 CELL *u, *v, *w;
380 char *s, *t, *h, *name, *sep;
381 int i, n, skip;
382 char elm[8], str[BUFSIZ];
383 static char *s_str;
384 static regexp *s_pat;
385 regexp *mkpat();
386 extern int r_start, r_length;
387
388 n = (int) p->n_arg[1];
389 if (n > 1) {
390 u = execute(p->n_arg[2]);
391 s = getsval(u); /* str */
392 v = execute(p->n_arg[3]); /* array */
393 if (!(v->c_type & ARR)) {
394/*
395printf("Split fix_to_array(%d)\n", v->c_type);
396*/
397 if (v->c_type == UDF) /* fix up local array */
398 fixarray(v);
399 else
400 error("split to non array variable", (char *)0);
401 }
402 h = v->c_sval;
403 c_free(v);
404 if (n > 2) {
405 v = execute(p->n_arg[4]);
406 sep = getsval(v);
407 }
408 else {
409 v = (CELL *)NULL;
410 sep = *FS;
411 }
412 if (strlen(sep) > 1) { /* reg_exp */
413 if (strcmp(sep, s_str) != 0) {
414 sfree(s_str); sfree(s_pat);
415 s_str = strsave(sep);
416 s_pat = mkpat(s_str);
417 }
418 for (i = 0, t = str; *s; ) {
419 if (match(s_pat, s)) {
420 for (n = r_start; --n > 0; )
421 *t++ = *s++;
422 }
423 else {
424 while(*s)
425 *t++ = *s++;
426 }
427 *t = '\0';
428 t = str;
429 sprintf(elm, "%d", ++i);
430 w = getvar(elm, h, VAR);
431 if (isnum(str))
432 setfval(w, atof(str));
433 else
434 setsval(w, str);
435 if (*s)
436 s += r_length;
437 }
438 }
439 else {
440 skip = *sep == ' ';
441 for (i = 0; t = str, *s; ) {
442 if (skip)
443 while (jStrchr(" \t\n", *s))
444 s++;
445 if (!(*s))
446 break;
447 while (*s && !jStrchr(sep, *s)) {
448 if (isKanji(*s))
449 *t++ = *s++;
450 *t++ = *s++;
451 }
452 *t = '\0';
453 sprintf(elm, "%d", ++i);
454 w = getvar(elm, h, VAR);
455 if (isnum(str))
456 setfval(w, atof(str));
457 else
458 setsval(w, str);
459 if (*s && !skip)
460 s++;
461 }
462 }
463 c_free(v); /* sep */
464 c_free(u); /* str may be CATed */
465 }
466 else
467 i = 0;
468 return mktmp(NUM, (char *)NULL, (double) i);
469}
470
471CELL *
472Forin(p) NODE *p;
473{
474 CELL *u, *v;
475 SYMBOL **h, *q;
476 char *name;
477 int i;
478
479 u = execute(p->n_arg[1]);
480 if (!(u->c_type & ARR))
481 synerr(
482 "non array variable is specified in 'for (. in var)'", (char *)0);
483 h = (SYMBOL **) u->c_sval;
484 c_free(u);
485 u = execute(p->n_arg[0]);
486 if (u->c_type == UDF) {
487/*
488printf("Forin_fix_to_VAR|NUM\n");
489*/
490 u->c_type = VAR|NUM;
491 }
492 if (!(u->c_type & VAR))
493 error("'for (VAR in .)' is not variable (%d)", name, u->c_type);
494 for (i = 0; i < HASHSIZE; i++) {
495 for (q = h[i]; q; q = q->s_next) {
496 setsval(u, q->s_name);
497 v = execute(p->n_arg[2]);
498 c_free(v);
499 }
500 }
501 c_free(u);
502 return &truecell;
503}
504
505char *
506strsave(s) char *s;
507{
508 register int n;
509 char *emalloc(), *strcpy();
510
511 if (s == (char *)NULL)
512 return (char *)NULL;
513 n = strlen(s) + 1;
514 return strcpy(emalloc(n), s);
515}
516
517sfree(p) char *p;
518{
519 if (p != (char *)NULL)
520 Free(p);
521}
522
523isnum(s) char *s;
524{
525 char *strchr();
526
527 if (s == NULL || *s == '\0' || !strcmp(s, "."))
528 return 0;
529 if (*s && strchr("+-", *s) != (char *)NULL)
530 s++;
531 if (*s == '\0')
532 return 0;
533 while (isdigit(*s))
534 s++;
535 if (*s == '.') {
536 s++;
537 while (isdigit(*s))
538 s++;
539 }
540 if (*s && strchr("eE", *s) != (char *)NULL) {
541 s++;
542 if (*s == '\0')
543 return 0;
544 if (*s && strchr("+-", *s) != (char *)NULL)
545 s++;
546 while (isdigit(*s))
547 s++;
548 }
549 return *s == '\0';
550}
551
552setfval(u, f) CELL *u; double f;
553{
554 if (u->c_type == UDF) { /* fix up local var */
555/*
556printf("setfval_fix_to_VAR\n");
557*/
558 u->c_type |= VAR;
559 }
560 if (u->c_type & (VAR|FLD|REC|TMP)) {
561 u->c_type &= ~STR;
562 u->c_type |= NUM;
563 sfree(u->c_sval);
564 u->c_sval = (char *)NULL;
565 u->c_fval = f;
566 if (u->c_type & FLD)
567 mkrec(u);
568 }
569 else
570 fprintf(stderr, "assign to nonvariable (%d)\n", u->c_type);
571}
572
573setsval(u, s) CELL *u; char *s;
574{
575 double atof();
576
577 if (u->c_type == UDF) { /* fix up local var */
578/*
579printf("setsval_fix_to_VAR\n");
580*/
581 u->c_type |= VAR;
582 }
583 if (u->c_type & (VAR|FLD|REC|TMP)) {
584 u->c_type &= ~NUM;
585 u->c_type |= STR;
586 sfree(u->c_sval);
587 u->c_sval = strsave(s);
588#if 0 /* "table2" in AWK book */
589 if (isnum(u->c_sval)) {
590 u->c_fval = atof(u->c_sval);
591 u->c_type |= NUM;
592 }
593 else
594#endif
595 u->c_fval = 0.0;
596 if (u->c_type & FLD)
597 mkrec(u);
598 }
599 else
600 fprintf(stderr, "assign to constant (%d)\n", u->c_type);
601}
602
603double
604getfval(u) CELL *u;
605{
606 double x, atof();
607
608 if (u->c_type == UDF) { /* local var */
609 u->c_type |= VAR|STR|NUM;
610 u->c_sval = strsave("");
611 x = u->c_fval = 0.0;
612 }
613 else if (u->c_type & NUM)
614 x = u->c_fval;
615#if 1
616 else {
617 x = atof(u->c_sval);
618#else
619 else {
620 if (isnum(u->c_sval))
621 x = atof(u->c_sval);
622 else
623 x = 0.0;
624#endif
625 }
626 return x;
627}
628
629char *
630getsval(u) CELL *u;
631{
632 char *s, str[80];
633
634 if (u->c_type & STR)
635 s = u->c_sval;
636 else if (u->c_type & NUM) {
637/* if (u->c_fval >= -2147483648.0 && u->c_fval <= 2147483647.0)*/
638 if ((long)u->c_fval == u->c_fval)
639 s = "%.16g";
640 else
641 s = *OFMT;
642 sprintf(str, s, u->c_fval);
643 sfree(u->c_sval);
644 s = u->c_sval = strsave(str);
645 }
646#if 1
647 else if (u->c_type == UDF) { /* local var */
648/*
649printf("getsval_fix_to_VAR|STR\n");
650*/
651 u->c_type |= VAR|STR|NUM;
652 s = u->c_sval = strsave("");
653 u->c_fval = 0.0;
654 }
655#endif
656 else
657 fprintf(stderr, "abnormal value (STR|NUM == 0)(%d)\n", u->c_type);
658 return s;
659}
660
661char *
662emalloc(n) unsigned n;
663{
664 char *p;
665#if 0
666 char far *_fmalloc();
667#else
668 char *malloc();
669#endif
670
671#if 0
672 if ((p = _fmalloc(n)) == (char *)NULL)
673#else
674 if ((p = malloc(n)) == (char *)NULL)
675#endif
676 error("memory over");
677 return p;
678}
679
680Free(s) char *s;
681{
682#if DOS
683 void _ffree();
684
685 _ffree(s);
686#else
687 free(s);
688#endif
689}
Note: See TracBrowser for help on using the repository browser.