source: trunk/minix/commands/awk/y.c@ 15

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

Minix 3.1.2a

File size: 17.2 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 "awk.h"
18
19extern char *mkpat();
20
21extern char *cmd;
22extern char text[];
23extern char funnam[];
24extern int sym;
25extern int sym1;
26extern int regexflg;
27extern int funflg;
28extern int printflg;
29extern int getlineflg;
30
31extern SYMBOL *hashtab[], *funtab[];
32
33extern CELL *field[];
34
35char *emalloc(), *strsave();
36NODE *node0(), *node1(), *node2(), *node3(), *node4();
37NODE *stat(), *pastat();
38NODE *expr(), *expr1(), *expr2(), *expr3(), *expr4();
39NODE *expr5(), *expr6(), *expr7(), *expr8(), *expr9(), *expr10();
40NODE *doprint(), *dofuncn(), *doif(), *dowhile(), *dofor(), *body();
41NODE *doassign(), *dodo(), *doarray(), *doreturn(), *doelement();
42CELL *mkcell(), *getvar();
43CELL *execute(), *lookup();
44
45int forflg; /* parsing for(expr in array), inhibit 'expr in array' */
46int prmflg; /* parsing pass parameters */
47NODE *begin, *loop, *End;
48
49parse()
50{
51 NODE *p, *q, *r, *stat();
52 CELL *u;
53
54 lex();
55 skipeol();
56 while (sym) {
57 switch (sym) {
58 case BEGIN:
59 lex();
60 begin = stat();
61 break;
62 case END:
63 lex();
64 if (End == NULL)
65 End = stat();
66 else {
67 for (p = End; p; p = q) {
68 if ((q = p->n_next) == NULL)
69 p->n_next = stat();
70 }
71 }
72 break;
73 case FUNC:
74 lex();
75 dousrfun();
76 break;
77 default:
78 q = loop = pastat();
79 skipeol();
80 while (sym && sym != BEGIN && sym != END && sym != FUNC) {
81 r = pastat();
82 q->n_next = r;
83 q = r;
84 skipeol();
85 }
86 break;
87 }
88 skipeol();
89 }
90 if (begin) {
91 u = execute(begin);
92 c_free(u);
93 }
94 if (End || loop)
95 while (Getrec(NULL)) {
96 if (loop) {
97 u = execute(loop);
98 c_free(u);
99 }
100 }
101 if (End) {
102 u = execute(End);
103 c_free(u);
104 }
105}
106
107#define MAXARG 100
108static char *argnam[MAXARG];
109static int narg;
110
111static
112dousrfun()
113{
114 CELL *u;
115
116 strcpy(funnam, text);
117 u = getvar(text, funtab, FUN);
118 lex();
119 if (sym != '(')
120 synerr("'(' expected");
121 for (lex(); sym != ')'; narg++) {
122 if (sym != IDENT)
123 synerr("argument expected");
124 argnam[narg] = strsave(text);
125 lex();
126 if (sym == ',')
127 lex();
128 }
129 u->c_fval = (double) narg;
130 lex();
131 skipeol();
132 funflg++;
133 u->c_sval = (char *) stat();
134 funflg--;
135 if (narg > 0) {
136 do {
137 sfree(argnam[--narg]);
138 } while (narg > 0);
139 }
140 skipeol();
141}
142
143isarg(s) char *s;
144{
145 int i;
146
147 if (narg > 0) {
148 for (i = narg - 1; i >= 0; i--)
149 if (strcmp(s, argnam[i]) == 0)
150 break;
151 }
152 else
153 i = -1;
154 return i;
155}
156
157/*
158interactive()
159{
160 NODE *p, *q;
161 CELL *u;
162
163 for (lex(); sym; lex()) {
164 p = stat();
165 if (p->n_type != PRINT && !iscntl(p->n_type)) {
166 q = (NODE *) emalloc(sizeof(NODE) + sizeof(NODE *) * 4);
167 q->n_type = PRINT;
168 q->n_arg[0] = q->n_arg[1] = q->n_arg[3] = NULL;
169 q->n_arg[2] = p;
170 q->n_next = NULL;
171 p = q;
172 }
173 u = execute(p);
174 printf("[%g(%s)]\n", u->c_fval, u->c_sval);
175 c_free(u);
176 }
177 closeall();
178 exit(0);
179}
180*/
181
182static
183iscntl(t)
184{
185 static int tab[] = {
186 IF, DO, WHILE, FOR, JUMP, GETLINE, 0
187 };
188 int i;
189
190 for (i = 0; tab[i]; i++)
191 if (t == tab[i])
192 break;
193 return tab[i];
194}
195
196static NODE *
197pastat()
198{
199 NODE *p, *q, *r;
200
201 if (sym == '{') /* action only */
202 p = stat();
203 else { /* exp [, expr] [{ .. }] */
204 p = expr();
205 if (sym == ',') {
206 lex();
207 q = expr();
208 }
209 else
210 q = NULL;
211 if (sym && sym != EOL)
212 r = stat();
213 else
214 r = node0(PRINT0);
215 if (q)
216 p = node3(P2STAT, p, q, r);
217 else
218 p = node2(P1STAT, p, r);
219 }
220 return p;
221}
222
223static NODE *
224stat()
225{
226 NODE *p, *q, *r;
227 CELL *u, *v;
228 int op;
229
230/*printf("@stat(%d)(%s)\n", sym, text);*/
231 while (sym == EOL)
232 lex();
233 switch(sym) {
234 case PRINT:
235 p = doprint(0);
236 break;
237 case PRINTF:
238 p = doprint(FORMAT);
239 break;
240 case IF:
241 p = doif();
242 break;
243 case WHILE:
244 p = dowhile();
245 break;
246 case DO:
247 p = dodo();
248 break;
249 case FOR:
250 p = dofor();
251 break;
252 case RETURN:
253 p = doreturn();
254 break;
255 case EXIT:
256 p = node2(JUMP, (NODE *)sym, (NODE *)NULL);
257 lex();
258 if (sym == IDENT || sym == NUMBER || sym == ARG)
259 p->n_arg[1] = expr();
260 break;
261 case BREAK: case CONTIN: case NEXT:
262 p = node1(JUMP, (NODE *)sym);
263 lex();
264 break;
265 case DELETE:
266 lex();
267 u = getvar(text, hashtab, ARR);
268 if (Getc() != '[')
269 synerr("'[' expected");
270 p = doarray(u);
271 p->n_type = DELETE;
272 lex(); /* ']' */
273 break;
274 case '{':
275 lex();
276 skipeol();
277 if (sym == '}')
278 p = node0(NULPROC);
279 else
280 p = q = stat();
281 skipeol();
282 while (sym != '}') {
283 r = stat();
284 q->n_next = r;
285 q = r;
286 skipeol();
287 }
288 lex();
289 break;
290 default:
291 p = expr();
292#if 0
293 if (sym == BINOR) { /* expr | GETLINE */
294 lex();
295 if (sym != GETLINE)
296 synerr("'GETLINE' expected");
297 lex();
298 if (sym == IDENT || sym == STRING || sym == ARG) {
299 q = expr();
300 }
301 else
302 q = NULL;
303 p = node3(GETLINE, q, p, (NODE *)R_PIN);
304 }
305#endif
306 break;
307 }
308 if (p->n_type == VALUE)
309 synerr("statement expected");
310 return p;
311}
312
313static
314skipeol()
315{
316 while (sym == EOL)
317 lex();
318}
319
320static NODE *
321doprint(fmt)
322{
323 NODE *p, *q, *r;
324 CELL *u;
325 int i, op;
326 int n = 0;
327
328 printflg++;
329 lex();
330 if (sym == '(')
331 lex();
332 if (sym != '}' && sym != ')' && sym != EOL && sym != R_OUT && sym != R_APD
333 && sym != R_POUT) {
334 p = q = expr(); n++;
335 while (sym == ',') {
336 lex();
337 skipeol();
338 r = expr(); n++;
339 q->n_next = r;
340 q = r;
341 }
342 }
343 if (sym == ')')
344 lex();
345 if (sym == R_OUT || sym == R_APD || sym == R_POUT) {
346 op = sym;
347 lex();
348/* q = expr10();*/
349 q = expr(); /* 94-04-02 */
350 }
351 else
352 q = (NODE *) (op = 0); /* stdout */
353 printflg = 0;
354 r = (NODE *) emalloc(sizeof(*r) + sizeof(r) * (n + 3));
355 r->n_type = PRINT; /* convert list to arg */
356 r->n_next = NULL;
357 r->n_arg[0] = (NODE *) (op | fmt);
358 r->n_arg[1] = q;
359 if (n == 0) {
360 p = node1(VALUE, (NODE *)field[0]);
361 }
362 for (i = 2; p != NULL; i++) {
363 r->n_arg[i] = p;
364 q = p->n_next;
365 p->n_next = NULL;
366 p = q;
367 }
368 r->n_arg[i] = NULL;
369 return r;
370}
371
372static NODE *
373doif()
374{
375 NODE *p, *q, *r;
376
377 lex();
378 if (sym != '(')
379 synerr("'(' expected");
380 lex();
381 p = expr();
382 if (sym != ')')
383 synerr("')' expected");
384 lex();
385 skipeol();
386 q = stat();
387 skipeol();
388 if (sym == ELSE) {
389 lex();
390 skipeol();
391 r = stat();
392 }
393 else
394 r = NULL;
395 return node3(IF, p, q, r);
396}
397
398static NODE *
399dowhile()
400{
401 NODE *p, *q;
402
403 lex();
404 if (sym != '(')
405 synerr("'(' expected");
406 lex();
407 p = stat();
408 if (sym != ')')
409 synerr("')' expected");
410 q = body();
411 return node2(WHILE, p, q);
412}
413
414static NODE *
415dofor()
416{
417 NODE *p, *q, *r, *s;
418 CELL *u;
419 int i;
420
421 lex();
422 if (sym != '(')
423 synerr("'(' expected");
424 lex();
425 if (sym != EOL) {
426 forflg++; /* inhibit parsing 'expr IN array' */
427 p = expr();
428 forflg = 0;
429 }
430 else
431 p = NULL;
432 if (sym == IN) {
433 lex();
434 if (sym == ARG) {
435/*
436printf("***FOR_IN_ARG(%d)***\n", sym);
437*/
438 u = mkcell(POS, NULL, (double)sym1);
439 q = node1(ARG, u);
440 }
441 else {
442 u = getvar(text, hashtab, ARR);
443 q = node1(VALUE, u);
444 }
445 lex();
446 if (sym != ')')
447 synerr("')' expected");
448 lex();
449 skipeol();
450 s = stat();
451 r = node3(FORIN, p, q, s);
452 }
453 else {
454 if (sym != EOL)
455 synerr("'in' or ';' expected");
456 lex();
457 if (sym != EOL)
458 q = expr();
459 else
460 q = NULL;
461 if (sym != EOL)
462 synerr("';' expected");
463 lex();
464 if (sym != ')')
465 r = expr();
466 else
467 r = NULL;
468 if (sym != ')')
469 synerr("')' expected");
470 s = body();
471 r = node4(FOR, p, q, r, s);
472 }
473 return r;
474}
475
476static NODE *
477body()
478{
479 NODE *r;
480
481 while ((sym = Getc()) == '\n' || sym == ' ' || sym == '\t')
482 ;
483 if (sym == ';') {
484 r = node0(NULPROC);
485 lex();
486 }
487 else {
488 Ungetc(sym);
489 lex();
490 r = stat();
491 }
492 return r;
493}
494
495static NODE *
496dodo()
497{
498 NODE *p, *q;
499
500 lex();
501 skipeol();
502 p = stat();
503 skipeol();
504 if (sym != WHILE)
505 synerr("'while' expected");
506 lex();
507 if (sym != '(')
508 synerr("'(' expected");
509 lex();
510 q = stat();
511 if (sym != ')')
512 synerr("')' expected");
513 lex();
514 return node2(DO, p, q);
515}
516
517static NODE *
518doreturn()
519{
520 NODE *p, *q, *r;
521 int i, n = 0;
522
523 if (lex() != EOL) {
524 p = q = expr(); n++;
525 while (sym == ',') {
526 lex(); skipeol();
527 r = expr(); n++;
528 q ->n_next = r;
529 q = r;
530 }
531 }
532 else
533 p = (NODE *)NULL;
534
535 r = (NODE *) emalloc(sizeof(*r) + sizeof (r) * (n + 1));
536 r->n_type = JUMP;
537 r->n_next = NULL;
538 r->n_arg[0] = (NODE *) RETURN;
539 for (i = 1; p != NULL; i++) {
540 r->n_arg[i] = p;
541 q = p->n_next;
542 p->n_next = NULL;
543 p = q;
544 }
545 r->n_arg[i] = NULL;
546 return r;
547}
548
549static NODE *
550expr()
551{
552 NODE *p;
553
554 p = expr1();
555 if (isassign(sym))
556 p = doassign(sym, p);
557 return p;
558}
559
560static isassign(sym)
561{
562 return (sym == ASSIGN || sym == ADDEQ || sym == SUBEQ || sym == MULTEQ
563 || sym == DIVEQ || sym == MODEQ || sym == POWEQ);
564}
565
566static NODE *
567doassign(op, p) NODE *p;
568{ /* evaluate right to left */
569 NODE *q;
570
571 lex();
572 q = expr();
573 if (isassign(sym))
574 q = doassign(sym, q);
575 return node3(ASSIGN, (NODE *)op, p, q);
576}
577
578static NODE *
579expr1()
580{
581 NODE *p, *q;
582
583/*
584printf("expr1(%d)(%s)\n", sym, text);
585*/
586 p = expr2();
587 if (sym == '?') {
588 lex();
589#if 0
590 q = stat();
591 if (sym != ':')
592 synerr("':' expected");
593 lex();
594 return node3(IF, p, q, stat());
595#else
596 q = expr();
597 if (sym != ':')
598 synerr("':' expected");
599 lex();
600 return node3(IF, p, q, expr());
601#endif
602 }
603 return p; /* 930213 */
604}
605
606static NODE *
607expr2()
608{
609 NODE *p;
610
611/*
612printf("expr2(%d)(%s)\n", sym, text);
613*/
614 p = expr3();
615 while (sym == OR) {
616 lex();
617 skipeol();
618 p = node3(COND, (NODE *)OR, p, expr3());
619 }
620 return p;
621}
622
623static NODE *
624expr3()
625{
626 NODE *p;
627
628/*
629printf("expr3(%d)(%s)\n", sym, text);
630*/
631 p = expr4();
632 while (sym == AND) {
633 lex();
634 skipeol();
635 p = node3(COND, (NODE *)AND, p, expr4());
636 }
637 return p;
638}
639
640static NODE *
641expr4()
642{
643 NODE *p;
644 CELL *q;
645 int op;
646
647/*
648printf("expr4(%d)(%s)\n", sym, text);
649*/
650 p = expr5();
651 if (!forflg && sym == IN) {
652 lex();
653 q = getvar(text, hashtab, ARR);
654 lex();
655 return node2(IN, p, q);
656 }
657 while (sym == EQ || sym == NE || sym == LT || sym == LE || sym == GT
658 || sym == GE || sym == MATCH || sym == NOMATCH) {
659 op = sym;
660 lex();
661 p = node3(COND, (NODE *)op, p, expr5());
662 }
663 return p;
664}
665
666static NODE *
667expr5()
668{
669 NODE *p, *q;
670
671/*
672printf("expr5(%d)(%s)\n", sym, text);
673*/
674 p = expr6();
675 while (iscat(sym)) {
676 q = expr6();
677 p = node2(CAT, p, q);
678 }
679 return p;
680}
681
682static iscat(sym)
683{
684 static int ctab[] = {
685 ADD, SUB, MULT, DIV, MOD, INC, DEC, STRING, NUMBER, IDENT, '(',
686 MATHFUN, STRFUN, SPRINTF, '$', SUBST, ARG, CALL, 0
687 };
688 register int i, j;
689
690 for (i = 0; j = ctab[i]; i++)
691 if (sym == j)
692 break;
693 return j;
694}
695
696static NODE *
697expr6()
698{
699 register int sign = sym;
700 NODE *p, *q;
701
702/*
703printf("expr6(%d)(%s)\n", sym, text);
704*/
705 if (sym == SUB || sym == ADD)
706 lex();
707 p = expr7();
708 if (sign == SUB)
709 p = node2(ARITH, (NODE *)UMINUS, p);
710 while (sym == ADD || sym == SUB) {
711 sign = sym;
712 lex();
713 q = expr7();
714 if (sign == ADD) {
715 p = node3(ARITH, (NODE *)ADD, p, q);
716 }
717 else if (sign == SUB) {
718 p = node3(ARITH, (NODE *)SUB, p, q);
719 }
720 else
721 synerr("'+' or '-' expected");
722 }
723 return p;
724}
725
726static NODE *
727expr7()
728{
729 register int op;
730 NODE *p, *q;
731
732/*
733printf("expr7(%d)(%s)\n", sym, text);
734*/
735 p = expr8();
736 while (sym == MULT || sym == DIV || sym == MOD) {
737 op = sym;
738 lex();
739 q = expr8();
740 switch (op) {
741 case MULT: p = node3(ARITH, (NODE *)MULT, p, q); break;
742 case DIV: p = node3(ARITH, (NODE *)DIV, p, q); break;
743 case MOD: p = node3(ARITH, (NODE *)MOD, p, q); break;
744 default: synerr("'*', '/' or '%' expected"); break;
745 }
746 }
747 return p;
748}
749
750static NODE *
751expr8()
752{
753 NODE *p;
754 int op;
755
756/*
757printf("expr8(%d)(%s)\n", sym, text);
758*/
759 if (sym == NOT) {
760 lex();
761 p = node2(COND, (NODE *)NOT, expr9());
762 }
763 else {
764 p = expr9();
765 if (sym == POWER) {
766 lex();
767 p = node3(ARITH, (NODE *)POWER, p, expr9());
768 }
769 }
770 return p;
771}
772
773static NODE *
774expr9()
775{
776 NODE *p, *q;
777 int op, sym0;
778
779/*
780printf("expr9(%d)(%s)\n", sym, text);
781*/
782 if (op = isincdec(sym)) {
783 lex();
784 if (sym != IDENT && sym != ARG)
785 synerr("illegal '++/--' operator");
786 p = expr10();
787 p = node4(ARITH, (NODE *)INCDEC, p, (NODE *)op, (NODE *)PRE);
788 }
789 else {
790 sym0 = sym;
791 p = expr10();
792 if (op = isincdec(sym)) {
793/*printf("POST(%d)(%d)(%s)\n", sym, sym0, text);*/
794 if (sym0 == IDENT || sym0 == ARG) {
795 p = node4(ARITH, (NODE *)INCDEC, p, (NODE *)op,
796 (NODE *)POST);
797 lex();
798 }
799 }
800 if (sym == BINOR) { /* | getline */
801 lex();
802 if (sym != GETLINE)
803 synerr("'GETLINE' expected");
804 lex();
805 if (sym == IDENT || sym == STRING || sym == ARG) {
806 q = expr();
807 }
808 else
809 q = NULL;
810 p = node3(GETLINE, q, p, (NODE *)R_PIN);
811 }
812 }
813 return p;
814}
815
816static isincdec(sym)
817{
818 return sym == INC ? 1 : (sym == DEC ? -1 : 0);
819}
820
821static NODE *
822expr10()
823{
824 NODE *p, *q;
825 CELL *u, *v;
826 int op;
827 int c;
828int gsave, psave;
829 double atof();
830
831/*
832printf("expr10(%d)(%s)\n", sym, text);
833*/
834 switch (sym) {
835 case STRING:
836 u = mkcell(STR, text, 0.0);
837 goto g1;
838 case NUMBER:
839 u = mkcell(NUM, NULL, atof(text));
840g1:
841 p = node1(VALUE, u);
842 lex();
843 break;
844 case IDENT: case ARG:
845 if ((c = Getc()) == '[') { /* array */
846 /* 940403 */
847 if (sym == ARG) {
848 u = (CELL *)emalloc(sizeof(CELL));
849 u = mkcell(POS, NULL, (double)sym1);
850 p = doarray(u);
851 }
852 else {
853 u = getvar(text, hashtab, ARR);
854 p = doarray(u);
855 }
856 }
857 else {
858 Ungetc(c);
859 if (sym == ARG) {
860 u = mkcell(POS, NULL, (double)sym1);
861 p = node1(ARG, u);
862 }
863 else { /* symple variable */
864 u = getvar(text, hashtab, VAR|STR|NUM);
865 p = node1(VALUE, u);
866 }
867 }
868 lex();
869 break;
870 case '(':
871 /* print >(x ? y : z) needs this */
872gsave = getlineflg; psave = printflg;
873getlineflg = printflg = 0;
874 lex();
875 p = expr();
876 if (sym == ',') /* (expr, expr, .. ) */
877 p = doelement(p);
878 if (sym != ')')
879 synerr("')' expected");
880getlineflg = gsave; printflg = psave;
881 lex();
882 break;
883 case CALL:
884 p = dofuncn(sym, getvar(text, funtab, UDF));
885 break;
886 case MATHFUN: case STRFUN: case SUBST:
887 p = dofuncn(sym, (CELL *)sym1);
888 break;
889 case SPRINTF:
890 p = doprint(FORMAT|STROUT);
891 break;
892 case '$':
893 lex();
894 switch (sym) {
895 case NUMBER:
896 u = mkcell(NUM, NULL, atof(text));
897 p = node1(VALUE, u);
898 p = node1(FIELD, p);
899 lex();
900 break;
901 case IDENT: case ARG: case '(':
902 p = node1(FIELD, expr10());
903 break;
904 default:
905 synerr("number or identifier expected after '$'", (char *)0);
906 }
907 break;
908 case DIV:
909 regexflg++;
910 lex();
911 regexflg = 0;
912 u = mkcell(PAT, NULL, 0.0);
913 u->c_sval = (char *) mkpat(text);
914 p = node1(VALUE, u);
915 lex();
916 break;
917 case GETLINE:
918 getlineflg++;
919 lex();
920 if (sym == IDENT || sym == STRING || sym == ARG)
921 q = expr10(); /* read into var */
922 else
923 q = NULL;
924 getlineflg = 0;
925 if (sym == R_IN) {
926 op = R_IN;
927 lex();
928 p = expr10();
929 }
930 else
931 op = (int) (p = NULL);
932 p = node3(GETLINE, q, p, (NODE *)op);
933 break;
934 default:
935 synerr(
936 "identifier, number, string, argument, regexpr, call or '(' expected");
937 break;
938 }
939 return p;
940}
941
942static NODE *
943dofuncn(fun, op) CELL *op;
944{
945 NODE *p;
946 int i, j;
947 int n = 0;
948 NODE *a[100];
949
950 if (lex() == '(') {
951 prmflg++;
952 for (lex(); sym && (sym != ')'); n++) {
953 if ((int)op == SPLIT && n == 1) {
954/*
955printf("sym(%d)sym1(%d)(%d)\n", sym, sym1, isarg(text));
956*/
957 if (sym != ARG) { /*isarg(text) == -1*/
958 /* make an array if not exist */
959 prmflg = 0;
960 getvar(text, hashtab, ARR);
961 prmflg++;
962 }
963 }
964 a[n] = expr();
965 if (sym == ',')
966 lex();
967 else if (sym != ')')
968 synerr("',' or ')' expected");
969 }
970 prmflg = 0;
971
972 if (sym == ')')
973 lex();
974 else
975 synerr("')' expected");
976 }
977 p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 2));
978 p->n_type = fun;
979 p->n_next = NULL;
980 p->n_arg[0] = (NODE *) op;
981 p->n_arg[1] = (NODE *) n;
982 for (i = 0, j = 2; i < n; )
983 p->n_arg[j++] = a[i++];
984 p->n_arg[j] = NULL;
985 return p;
986}
987
988static NODE *
989doarray(u) CELL *u;
990{
991 NODE *p;
992 int i, j;
993 int n;
994 NODE *a[20];
995
996 for (lex(), n = 0; sym && sym != ']'; n++) {
997 a[n] = expr();
998 if (sym == ',')
999 lex();
1000 }
1001 if (sym != ']')
1002 synerr("']' expected");
1003 /* left ']' for expr10() */
1004 p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 1));
1005 p->n_type = ARRAY;
1006 p->n_next = NULL;
1007 p->n_arg[0] = (NODE *)u;
1008 p->n_arg[1] = (NODE *) n;
1009 for (i = 0, j = 2; i < n; )
1010 p->n_arg[j++] = a[i++];
1011 return p;
1012}
1013
1014static NODE *
1015doelement(q) NODE *q;
1016{
1017 NODE *p;
1018 int i, j;
1019 int n;
1020 NODE *a[20];
1021
1022 a[0] = q;
1023 for (lex(), n = 1; sym && sym != ')'; n++) {
1024 a[n] = expr();
1025 if (sym == ',')
1026 lex();
1027 else if (sym != ')')
1028 synerr("',' or ')' expected");
1029 }
1030 /* left ')' for expr10() */
1031 p = (NODE *) emalloc(sizeof(*p) + sizeof(p) * (n + 1));
1032 p->n_type = ELEMENT;
1033 p->n_next = NULL;
1034 p->n_arg[0] = NULL;
1035 p->n_arg[1] = (NODE *) n;
1036 for (i = 0, j = 2; i < n; )
1037 p->n_arg[j++] = a[i++];
1038 return p;
1039}
1040
1041synerr(s, t) char *s, *t;
1042{
1043 extern int lineno;
1044 extern char line[], *linep;
1045 int c, i;
1046 char *u, *v;
1047
1048 fprintf(stderr, "%s: Syntax error at line %d", cmd, lineno);
1049 if (funflg)
1050 fprintf(stderr, " in function %s", funnam);
1051 fprintf(stderr, ":\n");
1052 if ((v = linep - 1) < line)
1053 v = line + BUFSIZ - 1;
1054 for (i = 0, u = v - 1; ; --u) {
1055 if (u < line) {
1056 if (line[BUFSIZ - 1] == '\0')
1057 break;
1058 u = line + BUFSIZ - 1;
1059 }
1060 if (*u == '\n' && ++i == 2)
1061 break;
1062 }
1063 if (u != v) {
1064 while (u != v) {
1065 fputc(*u, stderr);
1066 if ((++u - line) == BUFSIZ)
1067 u = line;
1068 }
1069 if (*u != '\n')
1070 fputc(*u, stderr);
1071 fprintf(stderr, " <--\n\n");
1072/*
1073 fprintf(stderr, " <-- ");
1074 while ((c = Getc()) != EOF && c != '\n')
1075 fputc(c, stderr);
1076 fprintf(stderr, "\n");
1077 if (c == EOF);
1078 fprintf(stderr, "\n");
1079*/
1080 }
1081 fprintf(stderr, s, t);
1082 fprintf(stderr, "\n");
1083#ifdef DOS
1084 closeall();
1085#endif
1086 exit(1);
1087}
Note: See TracBrowser for help on using the repository browser.