Graphviz 13.1.3~dev.20250829.0113
Loading...
Searching...
No Matches
exgram.h
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#ifdef __cplusplus
12extern "C" {
13#endif
14
15
16/*
17 * grammar support routines
18 * stuffed in a header so exparse.y can work
19 * with both yacc and bison
20 */
21
22#if !defined(_EXGRAM_H) && ( defined(MINTOKEN) || defined(YYTOKENTYPE) )
23#define _EXGRAM_H
24
25#include <expr/exlib.h>
26#include <stdbool.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <util/agxbuf.h>
30#include <util/arena.h>
31#include <util/gv_ctype.h>
32
33#define ex_lex() extoken_fn(expr.program)
34
35static int a2t[] = { 0, FLOATING, INTEGER, STRING };
36
38
39static int T(long t) {
40 if (expr.program->disc->types)
41 return expr.program->disc->types[t & TMASK];
42 else
43 return a2t[t & TMASK];
44}
45
46/*
47 * allocate and initialize a new expression node in the current program
48 */
49
50Exnode_t *exnewnode(Expr_t *p, long op, bool binary, long type, Exnode_t *left,
51 Exnode_t *right) {
52 Exnode_t* x;
53
54 x = ARENA_NEW(&p->vm, Exnode_t);
55 x->op = op;
56 x->type = type;
57 x->binary = binary;
58 x->data.operand.left = left;
60 return x;
61}
62
63/*
64 * free node x and its children
65 */
66
67void
69{
70 Print_t* pr;
71 Exref_t* r;
72 Print_t* pn;
73 Exref_t* rn;
74
75 switch (x->op)
76 {
77 case CALL:
78 if (x->data.call.args)
79 exfreenode(p, x->data.call.args);
80 break;
81 case CONSTANT:
82 break;
83 case DEFAULT:
84 if (x->data.select.next)
86 break;
87 case DYNAMIC:
88 if (x->data.variable.index)
90 if (x->data.variable.symbol->local)
91 {
94 }
95 break;
96 case '#':
97 if (x->data.variable.symbol->local) {
100 }
101 break;
102// case IN_OP:
103 case UNSET:
104 if (x->data.variable.index)
106 if (x->data.variable.symbol->local) {
109 }
110 break;
111 case ITERATE:
112 case ITERATOR:
113 if (x->data.generate.statement)
114 exfreenode(p, x->data.generate.statement);
115 break;
116 case ID:
117 rn = x->data.variable.reference;
118 while ((r = rn))
119 {
120 rn = r->next;
121 gv_arena_free(&p->vm, r, sizeof(*r));
122 }
123 if (x->data.variable.index)
125 break;
126 case GSUB:
127 case SUB:
128 case SUBSTR:
129 exfreenode(p, x->data.string.base);
130 exfreenode(p, x->data.string.pat);
131 if (x->data.string.repl)
132 exfreenode(p, x->data.string.repl);
133 break;
134 case TOKENS:
135 case SPLIT:
136 if (x->data.split.seps)
137 exfreenode(p, x->data.split.seps);
138 exfreenode(p, x->data.split.string);
139 if (x->data.split.array->local) {
140 dtclose(x->data.split.array->local);
141 x->data.split.array->local = NULL;
142 }
143 break;
144 case PRINT:
146 break;
147 case PRINTF:
148 case SPRINTF:
149 if (x->data.print.descriptor)
150 exfreenode(p, x->data.print.descriptor);
151 pn = x->data.print.args;
152 while ((pr = pn))
153 {
154 size_t i;
155 for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
156 exfreenode(p, pr->param[i]);
157 if (pr->arg)
158 exfreenode(p, pr->arg);
159 pn = pr->next;
160 gv_arena_free(&p->vm, pr, sizeof(*pr));
161 }
162 break;
163 case PROCEDURE:
164 if (x->data.procedure.args)
165 exfreenode(p, x->data.procedure.args);
166 if (x->data.procedure.body)
167 exfreenode(p, x->data.procedure.body);
168 break;
169 default:
170 if (x->data.operand.left)
172 if (x->data.operand.right)
174 break;
175 }
176 gv_arena_free(&p->vm, x, sizeof(*x));
177}
178
179/* extract:
180 * Given an argument list, extract first argument,
181 * check its type, reset argument list, and
182 * return first argument.
183 * Return 0 on failure.
184 */
185static Exnode_t *extract(Expr_t * p, Exnode_t ** argp, int type) {
186 Exnode_t *args = *argp;
187 Exnode_t *left;
188
189 if (!args || (type != args->data.operand.left->type))
190 return 0;
191 *argp = args->data.operand.right;
192 left = args->data.operand.left;
193 args->data.operand.left = args->data.operand.right = 0;
194 exfreenode(p, args);
195 return left;
196}
197
198/* exnewsplit:
199 * Generate split/tokens node.
200 * Fifth argument is optional.
201 */
202static Exnode_t *exnewsplit(Expr_t *p, long op, Exid_t *dyn, Exnode_t *s,
203 Exnode_t *seps) {
204 Exnode_t *ss = 0;
205
206 if (dyn->local == NULL)
207 exerror("cannot use non-array %s in %s", dyn->name, exopname(op));
208 if ((dyn->index_type > 0) && (dyn->index_type != INTEGER))
209 exerror("in %s, array %s must have integer index type, not %s",
210 exopname(op), dyn->name, extypename(p, s->type));
211 if (dyn->type != STRING)
212 exerror("in %s, array %s entries must have string type, not %s",
213 exopname(op), dyn->name, extypename(p, s->type));
214 if (s->type != STRING)
215 exerror("first argument to %s must have string type, not %s",
216 exopname(op), extypename(p, s->type));
217 if (seps && (seps->type != STRING))
218 exerror("third argument to %s must have string type, not %s",
219 exopname(op), extypename(p, seps->type));
220 ss = exnewnode(p, op, false, INTEGER, NULL, NULL);
221 ss->data.split.array = dyn;
222 ss->data.split.string = s;
223 ss->data.split.seps = seps;
224 return ss;
225}
226
227/* exnewsub:
228 * Generate sub node.
229 * Third argument is optional.
230 */
231static Exnode_t *exnewsub(Expr_t * p, Exnode_t * args, int op) {
232 Exnode_t *base;
233 Exnode_t *pat;
234 Exnode_t *repl;
235 Exnode_t *ss = 0;
236
237 base = extract(p, &args, STRING);
238 if (!base)
239 exerror("invalid first argument to sub operator");
240 pat = extract(p, &args, STRING);
241 if (!pat)
242 exerror("invalid second argument to sub operator");
243 if (args) {
244 repl = extract(p, &args, STRING);
245 if (!repl)
246 exerror("invalid third argument to sub operator");
247 } else
248 repl = 0;
249 if (args)
250 exerror("too many arguments to sub operator");
251 ss = exnewnode(p, op, false, STRING, NULL, NULL);
252 ss->data.string.base = base;
253 ss->data.string.pat = pat;
254 ss->data.string.repl = repl;
255 return ss;
256}
257
258/* exnewsubstr:
259 * Generate substr node.
260 */
261static Exnode_t *exnewsubstr(Expr_t * p, Exnode_t * args) {
262 Exnode_t *base;
263 Exnode_t *pat;
264 Exnode_t *repl;
265 Exnode_t *ss = 0;
266
267 base = extract(p, &args, STRING);
268 if (!base)
269 exerror("invalid first argument to substr operator");
270 pat = extract(p, &args, INTEGER);
271 if (!pat)
272 exerror("invalid second argument to substr operator");
273 if (args) {
274 repl = extract(p, &args, INTEGER);
275 if (!repl)
276 exerror("invalid third argument to substr operator");
277 } else
278 repl = 0;
279 if (args)
280 exerror("too many arguments to substr operator");
281 ss = exnewnode(p, SUBSTR, false, STRING, NULL, NULL);
282 ss->data.string.base = base;
283 ss->data.string.pat = pat;
284 ss->data.string.repl = repl;
285 return ss;
286}
287
288/*
289 * cast x to type
290 */
291
292static char* typename[] =
293{
294 "external", "integer", "unsigned", "char", "float", "string"
295};
296
297static int typecast[6][6] =
298{
299 {X2X, X2I, X2I, X2I, X2F, X2S},
300 {I2X, 0, 0, 0, I2F, I2S},
301 {I2X, 0, 0, 0, I2F, I2S},
302 {I2X, 0, 0, 0, I2F, I2S},
303 {F2X, F2I, F2I, F2I, 0, F2S},
304 {S2X, S2I, S2I, S2I, S2F, 0},
305};
306
307#define TYPEINDEX(t) (((t)>=INTEGER&&(t)<=STRING)?((t)-INTEGER+1):0)
308#define TYPENAME(t) typename[TYPEINDEX(t)]
309#define TYPECAST(f,t) typecast[TYPEINDEX(f)][TYPEINDEX(t)]
310
311#define EXTERNAL(t) ((t)>=F2X)
312
313char *extypename(Expr_t *p, long type) {
314 if (BUILTIN(type))
315 return TYPENAME(type);
316 return p->disc->typename(type);
317}
318
319/* exstringOf:
320 * Cast x to type STRING
321 * Assume x->type != STRING
322 */
323static Exnode_t *exstringOf(Expr_t * p, Exnode_t * x) {
324 const long type = x->type;
325 int cvt = 0;
326
327 if (!type) {
328 x->type = STRING;
329 return x;
330 }
331 if (!BUILTIN(type) && !p->disc->stringof)
332 exerror("cannot convert %s to STRING", extypename(p, type));
333 if (x->op != CONSTANT) {
334 if (!BUILTIN(type)) {
335 if (p->disc->stringof(p, x, 1) < 0) {
336 exerror("cannot convert %s to STRING",
337 extypename(p, type));
338 }
339 cvt = XPRINT;
340 } else if (TYPEINDEX(type) != 0) {
341 cvt = TYPECAST(type, STRING);
342 }
343 x = exnewnode(p, cvt, false, STRING, x, 0);
344 } else if (!BUILTIN(type)) {
345 if (p->disc->stringof(p, x, 0) < 0)
346 exerror("cannot convert constant %s to STRING",
347 extypename(p, x->type));
348 } else
349 switch (type) {
350 case FLOATING:
352 exprintf(&p->vm, "%g", x->data.constant.value.floating);
353 break;
354 case INTEGER:
356 exprintf(&p->vm, "%lld", x->data.constant.value.integer);
357 break;
358 default:
359 exerror("internal error: %ld: unknown type", type);
360 break;
361 }
362 x->type = STRING;
363 return x;
364}
365
366/* exprint:
367 * Generate argument list of strings.
368 */
369static Exnode_t *exprint(Expr_t * p, Exid_t * ex, Exnode_t * args) {
370 Exnode_t *arg = args;
371 Exnode_t *pr;
372
373 while (arg) {
374 if (arg->data.operand.left->type != STRING)
375 arg->data.operand.left =
376 exstringOf(p, arg->data.operand.left);
377 arg = arg->data.operand.right;
378 }
379 pr = exnewnode(p, ex->index, true, ex->type, args, NULL);
380 return pr;
381}
382
383/* makeVar:
384 *
385 * Create variable from s[idx].refs
386 * If s is DYNAMIC, refs is non-empty and dyna represents s[idx].
387 * The rightmost element in s[idx].refs becomes the dominant symbol,
388 * and the prefix gets stored in refs. (This format is used to simplify
389 * the yacc parser.)
390 */
391static Exnode_t *makeVar(Expr_t * prog, Exid_t * s, Exnode_t * idx,
392 Exnode_t * dyna, Exref_t * refs) {
393 Exnode_t *nn;
394 Exid_t *sym;
395
396 /* parse components */
397 if (refs) {
398 if (refs->next) {
399 sym = refs->next->symbol;
400 refs->next->symbol = refs->symbol;
401 } else
402 sym = refs->symbol;
403 refs->symbol = s;
404 refs->index = idx;
405 } else
406 sym = s;
407
408 const long kind = sym->type ? sym->type : STRING;
409
410 nn = exnewnode(prog, ID, false, kind, NULL, NULL);
411 nn->data.variable.symbol = sym;
412 nn->data.variable.reference = refs;
413 nn->data.variable.index = 0;
414 nn->data.variable.dyna = dyna;
415 if (!prog->disc->getf)
416 exerror("%s: identifier references not supported", sym->name);
417 else if (expr.program->disc->reff)
418 expr.program->disc->reff(prog, nn, nn->data.variable.symbol, refs);
419
420 return nn;
421}
422
423/* exnoncast:
424 * Return first non-cast node.
425 */
427 while (x && (x->op >= F2I) && (x->op <= X2X))
428 x = x->data.operand.left;
429 return x;
430}
431
432Exnode_t *excast(Expr_t *p, Exnode_t *x, long type, Exnode_t *xref, int arg) {
433 int t2t;
434 char* s;
435 char* e;
436
437 if (x && x->type != type && type && type != VOIDTYPE)
438 {
439 if (!x->type)
440 {
441 x->type = type;
442 return x;
443 }
444 if (!(t2t = TYPECAST(x->type, type)))
445 return x;
446 if (EXTERNAL(t2t) && !p->disc->convertf)
447 exerror("cannot convert %s to %s", extypename(p, x->type), extypename(p, type));
448 if (x->op != CONSTANT) {
449 Exid_t *sym = (xref ? xref->data.variable.symbol : NULL);
450 if (EXTERNAL(t2t)) {
451 if (p->disc->convertf(x, type, 1) < 0) {
452 if (xref) {
453 if ((sym->lex == FUNCTION) && arg)
454 exerror ("%s: cannot use value of type %s as argument %d in function %s",
455 sym->name, extypename(p, x->type),
456 arg, sym->name);
457 else
458 exerror("%s: cannot convert %s to %s",
459 xref->data.variable.symbol->name,
460 extypename(p, x->type),
461 extypename(p, type));
462 } else {
463 exerror("cannot convert %s to %s",
464 extypename(p, x->type), extypename(p, type));
465 }
466 }
467 }
468 x = exnewnode(p, t2t, false, type, x, xref);
469 }
470 else switch (t2t)
471 {
472 case F2X:
473 case I2X:
474 case S2X:
475 case X2F:
476 case X2I:
477 case X2S:
478 case X2X:
479 if (xref && xref->op == ID)
480 {
481 if (p->disc->convertf(x, type, arg) < 0)
482 exerror("%s: cannot cast constant %s to %s", xref->data.variable.symbol->name, extypename(p, x->type), extypename(p, type));
483 }
484 else if (p->disc->convertf(x, type, arg) < 0)
485 exerror("cannot cast constant %s to %s", extypename(p, x->type), extypename(p, type));
486 break;
487 case F2I:
489 break;
490 case F2S:
492 exprintf(&p->vm, "%g", x->data.constant.value.floating);
493 break;
494 case I2F:
496 break;
497 case I2S:
499 exprintf(&p->vm, "%lld", x->data.constant.value.integer);
500 break;
501 case S2F:
503 x->data.constant.value.floating = strtod(s, &e);
504 if (*e)
505 x->data.constant.value.floating = (*s != 0);
506 break;
507 case S2I:
509 x->data.constant.value.integer = strtoll(s, &e, 0);
510 if (*e)
511 x->data.constant.value.integer = (*s != 0);
512 break;
513 default:
514 exerror("internal error: %d: unknown cast op", t2t);
515 break;
516 }
517 x->type = type;
518 }
519 return x;
520}
521
522/*
523 * check function call arg types and count
524 * return function identifier node
525 */
526
527static Exnode_t*
528call(Exref_t* ref, Exid_t* fun, Exnode_t* args)
529{
530 int type;
531 Exnode_t* x;
532 int num;
533
534 x = exnewnode(expr.program, ID, false, 0, NULL, NULL);
535 long t = fun->type;
536 x->data.variable.symbol = fun;
538 num = 0;
539 N(t);
540 while ((type = T(t)))
541 {
542 if (!args)
543 {
544 exerror("%s: not enough args", fun->name);
545 return args;
546 }
547 num++;
548 if (type != args->data.operand.left->type)
549 args->data.operand.left = excast(expr.program, args->data.operand.left, type, NULL, num);
550 args = args->data.operand.right;
551 N(t);
552 }
553 if (args)
554 exerror("%s: too many args", fun->name);
555 return x;
556}
557
558/*
559 * precompile a printf/scanf call
560 */
561
562static Print_t*
563preprint(Exnode_t* args)
564{
565 Print_t* x;
566 char* s;
567 char c;
568 int t;
569 int i;
570 int n;
571 char* e;
572 char* f;
573 Print_t* p = 0;
574 Print_t* q;
575
576 if (!args || args->data.operand.left->type != STRING)
577 exerror("format string argument expected");
578 if (args->data.operand.left->op != CONSTANT)
579 {
581 x->arg = args;
582 return x;
583 }
585 args = args->data.operand.right;
586 for (s = f; *s; s++)
587 {
588 agxbputc(&expr.program->tmp, *s);
589 if (*s == '%')
590 {
591 if (!*++s)
592 exerror("%s: trailing %% in format", f);
593 if (*s != '%')
594 break;
595 if (args)
596 agxbputc(&expr.program->tmp, '%');
597 }
598 }
599 x = 0;
600 for (;;)
601 {
603 if (x)
604 x->next = q;
605 else
606 p = q;
607 x = q;
608 *x = (Print_t){0};
609 if (*s)
610 {
611 i = 0;
612 t = INTEGER;
613 for (;;)
614 {
615 switch (c = *s++)
616 {
617 case 0:
618 exerror("unterminated %%... in format");
619 goto done;
620 case '*':
621 if (i >= (int)elementsof(x->param))
622 {
623 *s = 0;
624 exerror("format %s has too many * arguments", f);
625 goto done;
626 }
627 if (!args)
628 {
629 *s = 0;
630 exerror("format %s * argument expected", f);
631 goto done;
632 }
633 x->param[i++] = args->data.operand.left;
634 args = args->data.operand.right;
635 break;
636 case '(':
637 n = 1;
638 for (;;)
639 {
640 agxbputc(&expr.program->tmp, c);
641 switch (c = *s++)
642 {
643 case 0:
644 s--;
645 break;
646 case '(':
647 n++;
648 continue;
649 case ')':
650 if (--n <= 0)
651 break;
652 continue;
653 default:
654 continue;
655 }
656 break;
657 }
658 break;
659 case 'c':
660 case 'd':
661 goto specified;
662 case 'e':
663 case 'f':
664 case 'g':
665 t = FLOATING;
666 goto specified;
667 case 'h':
668 exerror("short formats not supported");
669 goto done;
670 case 'l':
671 t = INTEGER;
672 break;
673 case 'o':
674 case 'u':
675 case 'x':
676 case 'T':
677 t = UNSIGNED;
678 goto specified;
679 case 's':
680 case 'S':
681 t = STRING;
682 goto specified;
683 default:
684 if (gv_isalpha(c))
685 goto specified;
686 break;
687 }
688 agxbputc(&expr.program->tmp, c);
689 }
690 specified:
691 agxbputc(&expr.program->tmp, c);
692 for (e = s; *s; s++)
693 {
694 if (*s == '%')
695 {
696 if (!*++s)
697 {
698 *e = 0;
699 exerror("%s: trailing %% in format", f);
700 goto done;
701 }
702 if (*s != '%')
703 {
704 s--;
705 break;
706 }
707 }
708 agxbputc(&expr.program->tmp, *s);
709 }
710 if (!args)
711 {
712 *e = 0;
713 exerror("%s format argument expected", f);
714 goto done;
715 }
716 x->arg = args->data.operand.left;
717 switch (t)
718 {
719 case FLOATING:
720 if (x->arg->type != FLOATING)
722 x->arg->type == STRING ? S2F : INTEGRAL(x->arg->type) ? I2F : X2F,
723 false, FLOATING, x->arg,
724 x->arg->op == ID ? x->arg : NULL);
725 break;
726 case INTEGER:
727 case UNSIGNED:
728 if (!INTEGRAL(x->arg->type))
730 x->arg->type == STRING ? S2I : x->arg->type == FLOATING ? F2I : X2I,
731 false, INTEGER, x->arg,
732 x->arg->op == ID ? x->arg : NULL);
733 x->arg->type = t;
734 break;
735 case STRING:
736 if (x->arg->type != STRING)
737 {
738 if (x->arg->op == CONSTANT && x->arg->data.constant.reference && expr.program->disc->convertf)
739 {
740 if (expr.program->disc->convertf(x->arg, STRING, 0) < 0)
741 exerror("cannot convert string format argument");
743 }
744 else if (!expr.program->disc->convertf || (x->arg->op != ID && x->arg->op != DYNAMIC && x->arg->op != F2X && x->arg->op != I2X && x->arg->op != S2X))
745 exerror("string format argument expected");
746 else
748 x->arg->type == FLOATING ? F2S : INTEGRAL(x->arg->type) ? I2S : X2S,
749 false, STRING, x->arg,
750 x->arg->op == ID ? x->arg : NULL);
751 }
752 break;
753 }
754 args = args->data.operand.right;
755 }
757 if (!*s)
758 break;
759 f = s;
760 }
761 if (args)
762 exerror("too many format arguments");
763 done:
764 agxbclear(&expr.program->tmp);
765 return p;
766}
767
768/*
769 * push a new input stream and program
770 */
771
772int expush(Expr_t *p, const char *name, int line, FILE *fp) {
773 Exinput_t* in;
774
775 if (!(in = calloc(1, sizeof(Exinput_t))))
776 {
777 exnospace();
778 return -1;
779 }
780 if (!p->input)
781 p->input = &expr.null;
782 if ((in->fp = fp))
783 in->close = 0;
784 else if (name)
785 {
786 if (!(in->fp = fopen(name, "r")))
787 {
788 exerror("%s: file not found", name);
789 }
790 else
791 {
792 name = gv_arena_strdup(&p->vm, name);
793 in->close = 1;
794 }
795 }
796 if (!(in->next = p->input)->next)
797 {
798 p->errors = 0;
799 if (line >= 0)
800 error_info.line = line;
801 }
802 else if (line >= 0)
803 error_info.line = line;
804 setcontext(p);
805 p->eof = 0;
806 p->input = in;
808 if (line >= 0)
809 error_info.file = (char*)name;
810 in->line = error_info.line;
811 in->nesting = 0;
812 in->unit = !name && !line;
813 p->program = expr.program;
814 expr.program = p;
815 return 0;
816}
817
818/*
819 * pop the current input stream
820 */
821
822int
823expop(Expr_t* p)
824{
825 int c;
826 Exinput_t* in;
827
828 if (!(in = p->input) || !in->next || in->unit)
829 return -1;
830 if (in->nesting)
831 exerror("unbalanced quote or nesting construct");
832 error_info.file = in->file;
833 if (in->next->next)
834 error_info.line = in->line;
835 else
836 {
837 if (p->errors && in->fp && p->linep != p->line)
838 while ((c = getc(in->fp)) != EOF)
839 if (c == '\n')
840 {
842 break;
843 }
844 error_info.line = in->line;
845 }
846 if (in->fp && in->close)
847 fclose(in->fp);
848 free(in->pushback);
849 p->input = in->next;
850 free(in);
851 setcontext(p);
852 if (p->program)
853 expr.program = p->program;
854 return 0;
855}
856
857/*
858 * clear global state of stale pointers
859 */
860
861void exinit(void) { expr = (Exstate_t){0}; }
862
863int excomp(Expr_t *p, const char *name, int line, FILE *fp, char *prefix) {
864 int eof;
865
866 eof = p->eof;
867 if (expush(p, name, line, fp))
868 return -1;
869 p->input->unit = line >= 0;
870 // insert prefix as pre-loaded pushback
871 p->input->pushback = p->input->pp = prefix;
872 ex_parse();
873 p->input->unit = 0;
874 expop(p);
875 p->eof = eof;
876 return 0;
877}
878
879/*
880 * free the program p
881 */
882
883void exclose(Expr_t *p) {
884 Exinput_t* in;
885
886 if (p)
887 {
888 size_t i;
889 for (i = 3; i < elementsof(p->file); i++)
890 if (p->file[i])
891 fclose(p->file[i]);
892 if (p->symbols)
893 dtclose(p->symbols);
894 gv_arena_reset(&p->vm);
895 gv_arena_reset(&p->ve);
896 agxbfree(&p->tmp);
897 while ((in = p->input))
898 {
899 free(in->pushback);
900 if (in->fp && in->close)
901 fclose(in->fp);
902 if ((p->input = in->next))
903 free(in);
904 }
905 free(p);
906 }
907}
908
909/* checkBinary:
910 * See if application wants to allow the given expression
911 * combination. l and r give the operands; the operator
912 * is given by ex. r may be NULL.
913 */
914static void
915checkBinary(Expr_t * p, Exnode_t * l, Exnode_t * ex, Exnode_t * r)
916{
917 if (p->disc->binaryf(l, ex, r, 1) < 0) {
918 if (r)
919 exerror
920 ("cannot apply operator %s to expressions of types %s and %s",
921 exopname(ex->op), extypename(p, l->type),
922 extypename(p, r->type));
923 else
924 exerror
925 ("cannot apply operator %s to expression of type %s",
926 exopname(ex->op), extypename(p, l->type));
927 }
928}
929
930/* checkName:
931 * We allow parser to accept any name in a declaration, in
932 * order to check that the name is undeclared and give a better
933 * error message if it isn't.
934 */
935static void checkName(const Exid_t *id) {
936 switch (id->lex) {
937 case DYNAMIC:
938 exerror("Variable \"%s\" already declared", id->name);
939 break;
940 case FUNCTION:
941 exerror("Name \"%s\" already used as a function", id->name);
942 break;
943 case ID:
944 exerror("Name \"%s\" already used as a keyword", id->name);
945 break;
946 case NAME:
947 break;
948 default:
950 "Unexpected token \"%s\" as name in dcl_item", id->name);
951 break;
952 }
953}
954
955static int cmpKey(void *k1, void *k2) {
956 const Extype_t *key1 = k1;
957 const Extype_t *key2 = k2;
958 if (key1->integer < key2->integer)
959 return -1;
960 else if (key1->integer > key2->integer)
961 return 1;
962 else
963 return 0;
964}
965
966int
968{
969 return n->op == '=' && n->subop == '=';
970}
971
972#endif
973
974#ifdef __cplusplus
975}
976#endif
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static void agxbclear(agxbuf *xb)
resets pointer to data
Definition agxbuf.h:293
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:306
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Definition agxbuf.h:276
void gv_arena_reset(arena_t *arena)
Definition arena.c:162
char * gv_arena_strdup(arena_t *arena, const char *s)
Definition arena.c:134
void gv_arena_free(arena_t *arena, void *ptr, size_t size)
Definition arena.c:147
Region-based memory allocator.
#define ARENA_NEW(arena, type)
Definition arena.h:55
#define elementsof(x)
Definition ast.h:33
#define N(n)
Definition bcomps.c:58
CDT_API int dtclose(Dt_t *)
Definition dtclose.c:8
#define right(i)
Definition closest.c:80
@ EXTERNAL
Definition ccomps.c:61
static int binary(Exnode_t *l, Exnode_t *ex, Exnode_t *r, int arg)
Definition compile.c:1829
static int a2t[]
Definition compile.c:2150
static int in(Extype_t lhs, Exid_t *rhs, Exdisc_t *disc)
Definition compile.c:1632
#define left
Definition dthdr.h:12
Error_info_t error_info
Definition error.c:22
#define ERROR_PANIC
Definition error.h:38
char * exopname(long op)
Definition excc.c:41
void exerror(const char *format,...)
Definition exerror.c:62
struct Print_s Print_t
Exstate_t expr
int ex_parse(void)
#define setcontext(p)
Definition exlib.h:128
char * exnospace(void)
Definition exnospace.c:25
#define UNSIGNED
Definition exparse.h:153
#define DYNAMIC
Definition exparse.h:167
#define F2S
Definition exparse.h:201
#define DEFAULT
Definition exparse.h:166
#define X2F
Definition exparse.h:210
#define S2X
Definition exparse.h:209
#define ITERATE
Definition exparse.h:173
#define S2I
Definition exparse.h:206
#define SUB
Definition exparse.h:194
#define FLOATING
Definition exparse.h:155
#define I2X
Definition exparse.h:208
#define SUBSTR
Definition exparse.h:195
#define TOKENS
Definition exparse.h:197
#define ITERATOR
Definition exparse.h:174
#define VOIDTYPE
Definition exparse.h:157
#define PRINT
Definition exparse.h:183
#define I2F
Definition exparse.h:202
#define SPRINTF
Definition exparse.h:191
#define I2S
Definition exparse.h:203
#define CONSTANT
Definition exparse.h:163
#define CALL
Definition exparse.h:161
#define GSUB
Definition exparse.h:172
#define UNSET
Definition exparse.h:198
#define XPRINT
Definition exparse.h:214
#define F2I
Definition exparse.h:200
#define X2S
Definition exparse.h:212
#define SPLIT
Definition exparse.h:190
#define S2F
Definition exparse.h:205
#define PROCEDURE
Definition exparse.h:185
#define X2X
Definition exparse.h:213
#define F2X
Definition exparse.h:207
#define X2I
Definition exparse.h:211
#define PRINTF
Definition exparse.h:184
#define FUNCTION
Definition exparse.h:171
expr procedure type
Definition exparse.y:208
int exisAssign(Exnode_t *)
Exnode_t * exnoncast(Exnode_t *)
Exnode_t * excast(Expr_t *, Exnode_t *, long, Exnode_t *, int)
int expop(Expr_t *)
#define BUILTIN(t)
Definition expr.h:58
static char * exprintf(arena_t *vm, const char *fmt,...)
Definition expr.h:287
void exinit(void)
Exnode_t * exnewnode(Expr_t *, long, bool, long, Exnode_t *, Exnode_t *)
void exfreenode(Expr_t *, Exnode_t *)
void exclose(Expr_t *)
char * extypename(Expr_t *p, long)
#define INTEGRAL(t)
Definition expr.h:57
int expush(Expr_t *, const char *, int, FILE *)
int excomp(Expr_t *p, const char *name, int line, FILE *fp, char *prefix)
#define TMASK
Definition expr.h:75
void free(void *)
#define NAME
Definition gmlparse.h:135
#define ID
Definition gmlparse.h:134
#define STRING
Definition gmlparse.h:133
#define INTEGER
Definition gmlparse.h:131
require define api prefix
Definition gmlparse.y:17
node NULL
Definition grammar.y:181
static uint64_t id
Definition gv2gml.c:40
replacements for ctype.h functions
static bool gv_isalpha(int c)
Definition gv_ctype.h:29
table Syntax error
Definition htmlparse.y:288
void ref(Site *v)
Definition site.c:59
char * file
Definition error.h:30
int line
Definition error.h:27
Definition expr.h:91
long index_type
Definition expr.h:96
long type
Definition expr.h:95
long lex
Definition expr.h:93
char name[EX_NAMELEN]
Definition expr.h:99
long index
Definition expr.h:94
void * local
user defined local stuff
Definition expr.h:98
int close
Definition exlib.h:35
long op
operator
Definition expr.h:148
long type
value type
Definition expr.h:147
bool binary
data.operand.{left,right} ok
Definition expr.h:149
Exdata_t data
Definition expr.h:156
Definition expr.h:218
arena_t vm
Definition expr.h:222
Dt_t * symbols
Definition expr.h:220
FILE * file[10]
Definition expr.h:221
Exid_t * symbol
Definition expr.h:105
Exref_t * next
Definition expr.h:104
Exnode_t * index
Definition expr.h:106
Expr_t * program
Definition exlib.h:157
Exinput_t null
Definition exlib.h:156
struct Exnode_s * param[3]
Definition exlib.h:50
char * format
Definition exlib.h:49
struct Exnode_s * arg
Definition exlib.h:51
struct Print_s * next
Definition exlib.h:48
static mytime_t T
Definition timing.c:41
long long integer
Definition exparse.h:240
double floating
Definition exparse.h:237
char * string
Definition exparse.h:242
Exnode_t * left
Definition expr.h:120
Exnode_t * right
Definition expr.h:121
Exid_t * reference
Definition expr.h:115
Exnode_t * next
Definition expr.h:127
struct Exdata_u::@94 select
struct Exdata_u::@93 operand
Exnode_t * statement
Definition expr.h:126
Exid_t * symbol
Definition expr.h:133
struct Exdata_u::@95 variable
Exnode_t * dyna
Definition expr.h:136
struct Exdata_u::@92 constant
Extype_t value
Definition expr.h:114
Exnode_t * index
Definition expr.h:135
Definition grammar.c:90