Graphviz 14.1.5~dev.20260409.0840
Loading...
Searching...
No Matches
excc.c
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 v2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11/*
12 * Glenn Fowler
13 * AT&T Research
14 *
15 * expression library C program generator
16 */
17
18#include "config.h"
19
20#include <expr/exlib.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <util/agxbuf.h>
25#include <util/exit.h>
26
28typedef struct {
29 Expr_t* expr; /* exopen() state */
30 Exdisc_t* disc; /* exopen() discipline */
31 int tmp; /* temp var index */
33} Excc_t;
34
35static const char quote[] = "\"";
36
37static void gen(Excc_t*, Exnode_t*);
38
39/*
40 * return C name for op
41 */
42
43char *exopname(long op) {
44 static char buf[16];
45
46 switch (op)
47 {
48 case '!':
49 return "!";
50 case '%':
51 return "%";
52 case '&':
53 return "&";
54 case '(':
55 return "(";
56 case '*':
57 return "*";
58 case '+':
59 return "+";
60 case ',':
61 return ",";
62 case '-':
63 return "-";
64 case '/':
65 return "/";
66 case ':':
67 return ":";
68 case '<':
69 return "<";
70 case '=':
71 return "=";
72 case '>':
73 return ">";
74 case '?':
75 return "?";
76 case '^':
77 return "^";
78 case '|':
79 return "|";
80 case '~':
81 return "~";
82 case AND:
83 return "&&";
84 case EQ:
85 return "==";
86 case GE:
87 return ">=";
88 case LE:
89 return "<=";
90 case LSH:
91 return "<<";
92 case NE:
93 return "!=";
94 case OR:
95 return "||";
96 case RSH:
97 return ">>";
98 default:
99 break;
100 }
101 snprintf(buf, sizeof(buf) - 1, "(OP=%03lo)", op);
102 return buf;
103}
104
105/*
106 * generate printf()
107 */
108
109static void print(Excc_t *cc, Exnode_t *exnode) {
110 Print_t* x;
111
112 if ((x = exnode->data.print.args))
113 {
114 char *quoted = fmtesq(x->format, quote);
115 agxbprint(cc->text, "sfprintf(%s, \"%s", exnode->data.print.descriptor->op == CONSTANT && exnode->data.print.descriptor->data.constant.value.integer == 2 ? "sfstderr" : "sfstdout", quoted);
116 free(quoted);
117 while ((x = x->next)) {
118 quoted = fmtesq(x->format, quote);
119 agxbput(cc->text, quoted);
120 free(quoted);
121 }
122 agxbputc(cc->text, '"');
123 for (x = exnode->data.print.args; x; x = x->next)
124 {
125 if (x->arg)
126 {
127 for (size_t i = 0; i < elementsof(x->param) && x->param[i]; i++)
128 {
129 agxbput(cc->text, ", (");
130 gen(cc, x->param[i]);
131 agxbputc(cc->text, ')');
132 }
133 agxbput(cc->text, ", (");
134 gen(cc, x->arg);
135 agxbputc(cc->text, ')');
136 }
137 }
138 agxbput(cc->text, ");\n");
139 }
140}
141
142/*
143 * generate scanf()
144 */
145
146static void scan(Excc_t *cc, Exnode_t *exnode) {
147 Print_t* x;
148
149 if ((x = exnode->data.print.args))
150 {
151 char *quoted = fmtesq(x->format, quote);
152 agxbprint(cc->text, "sfscanf(sfstdin, \"%s", quoted);
153 free(quoted);
154 while ((x = x->next)) {
155 quoted = fmtesq(x->format, quote);
156 agxbput(cc->text, quoted);
157 free(quoted);
158 }
159 agxbputc(cc->text, '"');
160 for (x = exnode->data.print.args; x; x = x->next)
161 {
162 if (x->arg)
163 {
164 for (size_t i = 0; i < elementsof(x->param) && x->param[i]; i++)
165 {
166 agxbput(cc->text, ", &(");
167 gen(cc, x->param[i]);
168 agxbputc(cc->text, ')');
169 }
170 agxbput(cc->text, ", &(");
171 gen(cc, x->arg);
172 agxbputc(cc->text, ')');
173 }
174 }
175 agxbput(cc->text, ");\n");
176 }
177}
178
179/*
180 * internal excc
181 */
182
183static void gen(Excc_t *cc, Exnode_t *exnode) {
184 Exnode_t* x;
185 Exnode_t* y;
186 char* s;
187 Extype_t* v;
188 Extype_t** p;
189
190 if (!exnode)
191 return;
192 if (exnode->op == CALL) {
193 agxbprint(cc->text, "%s(", exnode->data.call.procedure->name);
194 if (exnode->data.call.args)
195 gen(cc, exnode->data.call.args);
196 agxbputc(cc->text, ')');
197 return;
198 }
199 x = exnode->data.operand.left;
200 switch (exnode->op)
201 {
202 case BREAK:
203 agxbput(cc->text, "break;\n");
204 return;
205 case CONTINUE:
206 agxbput(cc->text, "continue;\n");
207 return;
208 case CONSTANT:
209 switch (exnode->type)
210 {
211 case FLOATING:
212 agxbprint(cc->text, "%g", exnode->data.constant.value.floating);
213 break;
214 case STRING: {
215 char *quoted = fmtesq(exnode->data.constant.value.string, quote);
216 agxbprint(cc->text, "\"%s\"", quoted);
217 free(quoted);
218 break;
219 }
220 case UNSIGNED:
221 agxbprint(cc->text, "%llu",
222 (long long unsigned)exnode->data.constant.value.integer);
223 break;
224 default:
225 agxbprint(cc->text, "%lld", exnode->data.constant.value.integer);
226 break;
227 }
228 return;
229 case DEC:
230 agxbprint(cc->text, "%s--", x->data.variable.symbol->name);
231 return;
232 case DYNAMIC:
233 agxbput(cc->text, exnode->data.variable.symbol->name);
234 return;
235 case EXIT:
236 agxbput(cc->text, "exit(");
237 gen(cc, x);
238 agxbput(cc->text, ");\n");
239 return;
240 case FUNCTION:
241 gen(cc, x);
242 agxbputc(cc->text, '(');
243 if ((y = exnode->data.operand.right)) {
244 gen(cc, y);
245 }
246 agxbputc(cc->text, ')');
247 return;
248 case RAND:
249 agxbput(cc->text, "rand();\n");
250 return;
251 case SRAND:
252 if (exnode->binary) {
253 agxbput(cc->text, "srand(");
254 gen(cc, x);
255 agxbput(cc->text, ");\n");
256 } else
257 agxbput(cc->text, "srand();\n");
258 return;
259 case GSUB:
260 case SUB:
261 case SUBSTR:
262 s = (exnode->op == GSUB ? "gsub(" : exnode->op == SUB ? "sub(" : "substr(");
263 agxbput(cc->text, s);
264 gen(cc, exnode->data.string.base);
265 agxbput(cc->text, ", ");
266 gen(cc, exnode->data.string.pat);
267 if (exnode->data.string.repl) {
268 agxbput(cc->text, ", ");
269 gen(cc, exnode->data.string.repl);
270 }
271 agxbputc(cc->text, ')');
272 return;
273 case IN_OP:
274 gen(cc, exnode->data.variable.index);
275 agxbprint(cc->text, " in %s", exnode->data.variable.symbol->name);
276 return;
277 case IF:
278 agxbput(cc->text, "if (");
279 gen(cc, x);
280 agxbput(cc->text, ") {\n");
281 gen(cc, exnode->data.operand.right->data.operand.left);
282 if (exnode->data.operand.right->data.operand.right)
283 {
284 agxbput(cc->text, "} else {\n");
285 gen(cc, exnode->data.operand.right->data.operand.right);
286 }
287 agxbput(cc->text, "}\n");
288 return;
289 case FOR:
290 agxbput(cc->text, "for (;");
291 gen(cc, x);
292 agxbput(cc->text, ");");
293 if (exnode->data.operand.left)
294 {
295 agxbputc(cc->text, '(');
296 gen(cc, exnode->data.operand.left);
297 agxbputc(cc->text, ')');
298 }
299 agxbput(cc->text, ") {");
300 if (exnode->data.operand.right)
301 gen(cc, exnode->data.operand.right);
302 agxbputc(cc->text, '}');
303 return;
304 case ID:
305 agxbput(cc->text, exnode->data.variable.symbol->name);
306 return;
307 case INC:
308 agxbprint(cc->text, "%s++", x->data.variable.symbol->name);
309 return;
310 case ITERATE:
311 case ITERATOR:
312 if (exnode->op == DYNAMIC)
313 {
314 agxbprint(cc->text, "{ Exassoc_t* tmp_%d;", ++cc->tmp);
315 agxbprint(cc->text, "for (tmp_%d = (Exassoc_t*)dtfirst(%s); tmp_%d && (%s = tmp_%d->name); tmp_%d = (Exassoc_t*)dtnext(%s, tmp_%d)) {", cc->tmp, exnode->data.generate.array->data.variable.symbol->name, cc->tmp, exnode->data.generate.index->name, cc->tmp, cc->tmp, exnode->data.generate.array->data.variable.symbol->name, cc->tmp);
316 gen(cc, exnode->data.generate.statement);
317 agxbput(cc->text, "} }");
318 }
319 return;
320 case PRINT:
321 agxbput(cc->text, "print");
322 if (x)
323 gen(cc, x);
324 else
325 agxbput(cc->text, "()");
326 return;
327 case PRINTF:
328 print(cc, exnode);
329 return;
330 case RETURN:
331 agxbput(cc->text, "return(");
332 gen(cc, x);
333 agxbput(cc->text, ");\n");
334 return;
335 case SCANF:
336 scan(cc, exnode);
337 return;
338 case SPLIT:
339 case TOKENS:
340 if (exnode->op == SPLIT)
341 agxbput(cc->text, "split (");
342 else
343 agxbput(cc->text, "tokens (");
344 gen(cc, exnode->data.split.string);
345 agxbprint(cc->text, ", %s", exnode->data.split.array->name);
346 if (exnode->data.split.seps) {
347 agxbputc(cc->text, ',');
348 gen(cc, exnode->data.split.seps);
349 }
350 agxbputc(cc->text, ')');
351 return;
352 case SWITCH: {
353 long t = x->type;
354 agxbput(cc->text, "switch (");
355 gen(cc, x);
356 agxbput(cc->text, ") {");
357 x = exnode->data.operand.right;
358 y = x->data.select.statement;
359 while ((x = x->data.select.next))
360 {
361 if (!(p = x->data.select.constant))
362 y = x->data.select.statement;
363 else
364 {
365 while ((v = *p++))
366 {
367 agxbput(cc->text, "case ");
368 if (t == STRING) {
369 char *quoted = fmtesq(v->string, quote);
370 agxbprint(cc->text, "\"%s\":", quoted);
371 free(quoted);
372 } else {
373 switch (t)
374 {
375 case INTEGER:
376 case UNSIGNED:
377 agxbprint(cc->text, "%llu",
378 (unsigned long long)v->integer);
379 break;
380 default:
381 agxbprint(cc->text, "%g", v->floating);
382 break;
383 }
384 }
385 agxbputc(cc->text, ':');
386 }
387 agxbputc(cc->text, '{');
388 gen(cc, x->data.select.statement);
389 agxbput(cc->text, ";}");
390 }
391 }
392 if (y)
393 {
394 agxbput(cc->text, "default:{");
395 gen(cc, y);
396 agxbput(cc->text, ";}");
397 }
398 agxbputc(cc->text, '}');
399 return;
400 }
401 case UNSET:
402 agxbprint(cc->text, "unset(%s", exnode->data.variable.symbol->name);
403 if (exnode->data.variable.index) {
404 agxbputc(cc->text, ',');
405 gen(cc, exnode->data.variable.index);
406 }
407 agxbputc(cc->text, ')');
408 return;
409 case WHILE:
410 agxbput(cc->text, "while (");
411 gen(cc, x);
412 agxbput(cc->text, ") {");
413 if (exnode->data.operand.right)
414 gen(cc, exnode->data.operand.right);
415 agxbputc(cc->text, '}');
416 return;
417 case '#':
418 agxbprint(cc->text, "# %s", exnode->data.variable.symbol->name);
419 return;
420 case '=':
421 agxbprint(cc->text, "(%s%s=", x->data.variable.symbol->name, exnode->subop == '=' ? "" : exopname(exnode->subop));
422 gen(cc, exnode->data.operand.right);
423 agxbputc(cc->text, ')');
424 return;
425 case ';':
426 for (;;)
427 {
428 if (!(x = exnode->data.operand.right))
429 switch (exnode->data.operand.left->op)
430 {
431 case FOR:
432 case IF:
433 case PRINTF:
434 case PRINT:
435 case RETURN:
436 case WHILE:
437 break;
438 default:
439 agxbput(cc->text, "_value=");
440 break;
441 }
442 gen(cc, exnode->data.operand.left);
443 agxbput(cc->text, ";\n");
444 if (!(exnode = x))
445 break;
446 switch (exnode->op)
447 {
448 case ';':
449 continue;
450 case FOR:
451 case IF:
452 case PRINTF:
453 case PRINT:
454 case RETURN:
455 case WHILE:
456 break;
457 default:
458 agxbput(cc->text, "_%svalue=");
459 break;
460 }
461 gen(cc, exnode);
462 agxbput(cc->text, ";\n");
463 break;
464 }
465 return;
466 case ',':
467 agxbputc(cc->text, '(');
468 gen(cc, x);
469 while ((exnode = exnode->data.operand.right) && exnode->op == ',')
470 {
471 agxbput(cc->text, "), (");
472 gen(cc, exnode->data.operand.left);
473 }
474 if (exnode)
475 {
476 agxbput(cc->text, "), (");
477 gen(cc, exnode);
478 }
479 agxbputc(cc->text, ')');
480 return;
481 case '?':
482 agxbputc(cc->text, '(');
483 gen(cc, x);
484 agxbput(cc->text, ") ? (");
485 gen(cc, exnode->data.operand.right->data.operand.left);
486 agxbput(cc->text, ") : (");
487 gen(cc, exnode->data.operand.right->data.operand.right);
488 agxbputc(cc->text, ')');
489 return;
490 case AND:
491 agxbputc(cc->text, '(');
492 gen(cc, x);
493 agxbput(cc->text, ") && (");
494 gen(cc, exnode->data.operand.right);
495 agxbputc(cc->text, ')');
496 return;
497 case OR:
498 agxbputc(cc->text, '(');
499 gen(cc, x);
500 agxbput(cc->text, ") || (");
501 gen(cc, exnode->data.operand.right);
502 agxbputc(cc->text, ')');
503 return;
504 case F2I:
505 agxbprint(cc->text, "(%s)(", extype(INTEGER));
506 gen(cc, x);
507 agxbputc(cc->text, ')');
508 return;
509 case I2F:
510 agxbprint(cc->text, "(%s)(", extype(FLOATING));
511 gen(cc, x);
512 agxbputc(cc->text, ')');
513 return;
514 case S2I:
515 agxbput(cc->text, "strtoll(");
516 gen(cc, x);
517 agxbput(cc->text, ",(char**)0,0)");
518 return;
519 case X2I:
520 agxbput(cc->text, "X2I(");
521 gen(cc, x);
522 agxbputc(cc->text, ')');
523 return;
524 case X2X:
525 agxbput(cc->text, "X2X(");
526 gen(cc, x);
527 agxbputc(cc->text, ')');
528 return;
529 }
530 y = exnode->data.operand.right;
531 if (x->type == STRING)
532 {
533 switch (exnode->op)
534 {
535 case S2B:
536 agxbput(cc->text, "*(");
537 gen(cc, x);
538 agxbput(cc->text, ")!=0");
539 return;
540 case S2F:
541 agxbput(cc->text, "strtod(");
542 gen(cc, x);
543 agxbput(cc->text, ",0)");
544 return;
545 case S2I:
546 agxbput(cc->text, "strtol(");
547 gen(cc, x);
548 agxbput(cc->text, ",0,0)");
549 return;
550 case S2X:
551 agxbput(cc->text, "** cannot convert string value to external **");
552 return;
553 case NE:
554 agxbputc(cc->text, '!');
555 /*FALLTHROUGH*/
556 case EQ:
557 agxbput(cc->text, "strmatch(");
558 gen(cc, x);
559 agxbputc(cc->text, ',');
560 gen(cc, y);
561 agxbputc(cc->text, ')');
562 return;
563 case '+':
564 case '|':
565 case '&':
566 case '^':
567 case '%':
568 case '*':
569 agxbput(cc->text, "** string bits not supported **");
570 return;
571 }
572 switch (exnode->op)
573 {
574 case '<':
575 s = "<0";
576 break;
577 case LE:
578 s = "<=0";
579 break;
580 case GE:
581 s = ">=0";
582 break;
583 case '>':
584 s = ">0";
585 break;
586 default:
587 s = "** unknown string op **";
588 break;
589 }
590 agxbput(cc->text, "strcoll(");
591 gen(cc, x);
592 agxbputc(cc->text, ',');
593 gen(cc, y);
594 agxbprint(cc->text, ")%s", s);
595 return;
596 }
597 else
598 {
599 if (!y)
600 agxbput(cc->text, exopname(exnode->op));
601 agxbputc(cc->text, '(');
602 gen(cc, x);
603 if (y)
604 {
605 agxbprint(cc->text, ")%s(", exopname(exnode->op));
606 gen(cc, y);
607 }
608 agxbputc(cc->text, ')');
609 }
610 return;
611}
612
613/*
614 * dump an expression tree to a buffer
615 */
616
617void exdump(Expr_t *ex, Exnode_t *node, agxbuf *xb) {
618 Excc_t cc = {.expr = ex, .disc = ex->disc, .text = xb};
619 if (node)
620 gen(&cc, node);
621 else
622 for (Exid_t *sym = dtfirst(ex->symbols); sym; sym = dtnext(ex->symbols, sym))
623 if (sym->lex == PROCEDURE && sym->value)
624 {
625 agxbprint(xb, "%s:\n", sym->name);
626 gen(&cc, sym->value->data.procedure.body);
627 }
628 agxbputc(xb, '\n');
629}
Dynamically expanding string buffers.
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:252
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Definition agxbuf.h:295
char * fmtesq(const char *, const char *)
Definition fmtesc.c:125
#define elementsof(x)
Definition ast.h:33
#define dtnext(d, o)
Definition cdt.h:181
#define dtfirst(d)
Definition cdt.h:180
char * exopname(long op)
Definition excc.c:43
static void scan(Excc_t *cc, Exnode_t *exnode)
Definition excc.c:146
static void print(Excc_t *cc, Exnode_t *exnode)
Definition excc.c:109
static const char quote[]
Definition excc.c:35
static void gen(Excc_t *, Exnode_t *)
Definition excc.c:183
void exdump(Expr_t *ex, Exnode_t *node, agxbuf *xb)
Definition excc.c:617
#define UNSIGNED
Definition exparse.h:153
#define DYNAMIC
Definition exparse.h:167
#define SCANF
Definition exparse.h:189
#define RSH
Definition exparse.h:222
#define OR
Definition exparse.h:215
#define GE
Definition exparse.h:220
#define S2X
Definition exparse.h:209
#define WHILE
Definition exparse.h:199
#define ITERATE
Definition exparse.h:173
#define NE
Definition exparse.h:218
#define SRAND
Definition exparse.h:192
#define S2I
Definition exparse.h:206
#define SUB
Definition exparse.h:194
#define LSH
Definition exparse.h:221
#define FLOATING
Definition exparse.h:155
#define FOR
Definition exparse.h:170
#define IN_OP
Definition exparse.h:223
#define SUBSTR
Definition exparse.h:195
#define TOKENS
Definition exparse.h:197
#define ITERATOR
Definition exparse.h:174
#define RAND
Definition exparse.h:187
#define PRINT
Definition exparse.h:183
#define I2F
Definition exparse.h:202
#define CONSTANT
Definition exparse.h:163
#define LE
Definition exparse.h:219
#define S2B
Definition exparse.h:204
#define CALL
Definition exparse.h:161
#define GSUB
Definition exparse.h:172
#define UNSET
Definition exparse.h:198
#define CONTINUE
Definition exparse.h:164
#define F2I
Definition exparse.h:200
#define SPLIT
Definition exparse.h:190
#define EQ
Definition exparse.h:217
#define BREAK
Definition exparse.h:160
#define S2F
Definition exparse.h:205
#define IF
Definition exparse.h:176
#define PROCEDURE
Definition exparse.h:185
#define SWITCH
Definition exparse.h:196
#define AND
Definition exparse.h:216
#define X2X
Definition exparse.h:213
#define EXIT
Definition exparse.h:169
#define X2I
Definition exparse.h:211
#define PRINTF
Definition exparse.h:184
#define FUNCTION
Definition exparse.h:171
#define INC
Definition exparse.h:225
#define DEC
Definition exparse.h:226
char * extype(long int)
Definition extype.c:26
void free(void *)
#define ID
Definition gmlparse.h:134
#define STRING
Definition gmlparse.h:133
#define INTEGER
Definition gmlparse.h:131
agxbput(xb, staging)
#define RETURN(v)
Definition strmatch.c:146
excc() state
Definition excc.c:28
Exdisc_t * disc
Definition excc.c:30
agxbuf * text
result of dumping
Definition excc.c:32
int tmp
Definition excc.c:31
Expr_t * expr
Definition excc.c:29
Definition expr.h:91
char name[EX_NAMELEN]
Definition expr.h:99
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:150
Definition expr.h:212
Dt_t * symbols
Definition expr.h:214
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
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
struct Exdata_u::@63 select
Exnode_t * next
Definition expr.h:127
Exnode_t * statement
Definition expr.h:126
Exid_t * symbol
Definition expr.h:133
struct Exdata_u::@61 constant
struct Exdata_u::@62 operand
struct Exdata_u::@64 variable
Extype_t value
Definition expr.h:114
Exnode_t * index
Definition expr.h:135
Definition grammar.c:90