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