Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libexpr/excc.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* expression library C program generator
26
*/
27
28
#define _EX_CC_PRIVATE_ \
29
char* id; /* prefix + _ */ \
30
int lastop; /* last op */ \
31
int tmp; /* temp var index */ \
32
Exccdisc_t* ccdisc; /* excc() discipline */
33
34
#include "exlib.h"
35
36
#define EX_CC_DUMP 0x8000
37
38
static const char quote[] = "\"";
39
40
static void gen(Excc_t*, Exnode_t*);
41
42
/*
43
* return C name for op
44
*/
45
46
static char*
47
opname(int op)
48
{
49
static char buf[16];
50
51
switch (op)
52
{
53
case '!':
54
return "!";
55
case '%':
56
return "%";
57
case '&':
58
return "&";
59
case '(':
60
return "(";
61
case '*':
62
return "*";
63
case '+':
64
return "+";
65
case ',':
66
return ",";
67
case '-':
68
return "-";
69
case '/':
70
return "/";
71
case ':':
72
return ":";
73
case '<':
74
return "<";
75
case '=':
76
return "=";
77
case '>':
78
return ">";
79
case '?':
80
return "?";
81
case '^':
82
return "^";
83
case '|':
84
return "|";
85
case '~':
86
return "~";
87
case AND:
88
return "&&";
89
case EQ:
90
return "==";
91
case GE:
92
return ">=";
93
case LE:
94
return "<=";
95
case LS:
96
return "<<";
97
case NE:
98
return "!=";
99
case OR:
100
return "||";
101
case RS:
102
return ">>";
103
}
104
sfsprintf(buf, sizeof(buf) - 1, "(OP=%03o)", op);
105
return buf;
106
}
107
108
/*
109
* generate printf()
110
*/
111
112
static void
113
print(Excc_t* cc, Exnode_t* expr)
114
{
115
register Print_t* x;
116
register int i;
117
118
if (x = expr->data.print.args)
119
{
120
sfprintf(cc->ccdisc->text, "sfprintf(%s, \"%s", expr->data.print.descriptor->op == CONSTANT && expr->data.print.descriptor->data.constant.value.integer == 2 ? "sfstderr" : "sfstdout", fmtesq(x->format, quote));
121
while (x = x->next)
122
sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
123
sfprintf(cc->ccdisc->text, "\"");
124
for (x = expr->data.print.args; x; x = x->next)
125
{
126
if (x->arg)
127
{
128
for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
129
{
130
sfprintf(cc->ccdisc->text, ", (");
131
gen(cc, x->param[i]);
132
sfprintf(cc->ccdisc->text, ")");
133
}
134
sfprintf(cc->ccdisc->text, ", (");
135
gen(cc, x->arg);
136
sfprintf(cc->ccdisc->text, ")");
137
}
138
}
139
sfprintf(cc->ccdisc->text, ");\n");
140
}
141
}
142
143
/*
144
* generate scanf()
145
*/
146
147
static void
148
scan(Excc_t* cc, Exnode_t* expr)
149
{
150
register Print_t* x;
151
register int i;
152
153
if (x = expr->data.print.args)
154
{
155
sfprintf(cc->ccdisc->text, "sfscanf(sfstdin, \"%s", fmtesq(x->format, quote));
156
while (x = x->next)
157
sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
158
sfprintf(cc->ccdisc->text, "\"");
159
for (x = expr->data.print.args; x; x = x->next)
160
{
161
if (x->arg)
162
{
163
for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
164
{
165
sfprintf(cc->ccdisc->text, ", &(");
166
gen(cc, x->param[i]);
167
sfprintf(cc->ccdisc->text, ")");
168
}
169
sfprintf(cc->ccdisc->text, ", &(");
170
gen(cc, x->arg);
171
sfprintf(cc->ccdisc->text, ")");
172
}
173
}
174
sfprintf(cc->ccdisc->text, ");\n");
175
}
176
}
177
178
/*
179
* internal excc
180
*/
181
182
static void
183
gen(Excc_t* cc, register Exnode_t* expr)
184
{
185
register Exnode_t* x;
186
register Exnode_t* y;
187
register int n;
188
register int m;
189
register int t;
190
char* s;
191
Extype_t* v;
192
Extype_t** p;
193
194
if (!expr)
195
return;
196
x = expr->data.operand.left;
197
switch (expr->op)
198
{
199
case BREAK:
200
sfprintf(cc->ccdisc->text, "break;\n");
201
return;
202
case CONTINUE:
203
sfprintf(cc->ccdisc->text, "continue;\n");
204
return;
205
case CONSTANT:
206
switch (expr->type)
207
{
208
case FLOATING:
209
sfprintf(cc->ccdisc->text, "%g", expr->data.constant.value.floating);
210
break;
211
case STRING:
212
sfprintf(cc->ccdisc->text, "\"%s\"", fmtesq(expr->data.constant.value.string, quote));
213
break;
214
case UNSIGNED:
215
sfprintf(cc->ccdisc->text, "%I*u", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
216
break;
217
default:
218
sfprintf(cc->ccdisc->text, "%I*d", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
219
break;
220
}
221
return;
222
case DEC:
223
sfprintf(cc->ccdisc->text, "%s--", x->data.variable.symbol->name);
224
return;
225
case DYNAMIC:
226
sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
227
return;
228
case EXIT:
229
sfprintf(cc->ccdisc->text, "exit(");
230
gen(cc, x);
231
sfprintf(cc->ccdisc->text, ");\n");
232
return;
233
case IF:
234
sfprintf(cc->ccdisc->text, "if (");
235
gen(cc, x);
236
sfprintf(cc->ccdisc->text, ") {\n");
237
gen(cc, expr->data.operand.right->data.operand.left);
238
if (expr->data.operand.right->data.operand.right)
239
{
240
sfprintf(cc->ccdisc->text, "} else {\n");
241
gen(cc, expr->data.operand.right->data.operand.right);
242
}
243
sfprintf(cc->ccdisc->text, "}\n");
244
return;
245
case FOR:
246
sfprintf(cc->ccdisc->text, "for (;");
247
gen(cc, x);
248
sfprintf(cc->ccdisc->text, ");");
249
if (expr->data.operand.left)
250
{
251
sfprintf(cc->ccdisc->text, "(");
252
gen(cc, expr->data.operand.left);
253
sfprintf(cc->ccdisc->text, ")");
254
}
255
sfprintf(cc->ccdisc->text, ") {");
256
if (expr->data.operand.right)
257
gen(cc, expr->data.operand.right);
258
sfprintf(cc->ccdisc->text, "}");
259
return;
260
case ID:
261
if (cc->ccdisc->ccf)
262
(*cc->ccdisc->ccf)(cc, expr, expr->data.variable.symbol, expr->data.variable.reference, expr->data.variable.index, cc->ccdisc);
263
else
264
sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
265
return;
266
case INC:
267
sfprintf(cc->ccdisc->text, "%s++", x->data.variable.symbol->name);
268
return;
269
case ITERATE:
270
if (expr->op == DYNAMIC)
271
{
272
sfprintf(cc->ccdisc->text, "{ Exassoc_t* %stmp_%d;", cc->id, ++cc->tmp);
273
sfprintf(cc->ccdisc->text, "for (%stmp_%d = (Exassoc_t*)dtfirst(%s); %stmp_%d && (%s = %stmp_%d->name); %stmp_%d = (Exassoc_t*)dtnext(%s, %stmp_%d)) {", cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp, expr->data.generate.index->name, cc->id, cc->tmp, cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp);
274
gen(cc, expr->data.generate.statement);
275
sfprintf(cc->ccdisc->text, "} }");
276
}
277
return;
278
case PRINTF:
279
print(cc, expr);
280
return;
281
case RETURN:
282
sfprintf(cc->ccdisc->text, "return(");
283
gen(cc, x);
284
sfprintf(cc->ccdisc->text, ");\n");
285
return;
286
case SCANF:
287
scan(cc, expr);
288
return;
289
case SWITCH:
290
t = x->type;
291
sfprintf(cc->ccdisc->text, "{ %s %stmp_%d = ", extype(t), cc->id, ++cc->tmp);
292
gen(cc, x);
293
sfprintf(cc->ccdisc->text, ";");
294
x = expr->data.operand.right;
295
y = x->data.select.statement;
296
n = 0;
297
while (x = x->data.select.next)
298
{
299
if (n)
300
sfprintf(cc->ccdisc->text, "else ");
301
if (!(p = x->data.select.constant))
302
y = x->data.select.statement;
303
else
304
{
305
m = 0;
306
while (v = *p++)
307
{
308
if (m)
309
sfprintf(cc->ccdisc->text, "||");
310
else
311
{
312
m = 1;
313
sfprintf(cc->ccdisc->text, "if (");
314
}
315
if (t == STRING)
316
sfprintf(cc->ccdisc->text, "strmatch(%stmp_%d, \"%s\")", cc->id, cc->tmp, fmtesq(v->string, quote));
317
else
318
{
319
sfprintf(cc->ccdisc->text, "%stmp_%d == ", cc->id, cc->tmp);
320
switch (t)
321
{
322
case INTEGER:
323
case UNSIGNED:
324
sfprintf(cc->ccdisc->text, "%I*u", sizeof(v->integer), v->integer);
325
break;
326
default:
327
sfprintf(cc->ccdisc->text, "%g", v->floating);
328
break;
329
}
330
}
331
}
332
sfprintf(cc->ccdisc->text, ") {");
333
gen(cc, x->data.select.statement);
334
sfprintf(cc->ccdisc->text, "}");
335
}
336
}
337
if (y)
338
{
339
if (n)
340
sfprintf(cc->ccdisc->text, "else ");
341
sfprintf(cc->ccdisc->text, "{");
342
gen(cc, y);
343
sfprintf(cc->ccdisc->text, "}");
344
}
345
sfprintf(cc->ccdisc->text, "}");
346
return;
347
case WHILE:
348
sfprintf(cc->ccdisc->text, "while (");
349
gen(cc, x);
350
sfprintf(cc->ccdisc->text, ") {");
351
if (expr->data.operand.right)
352
gen(cc, expr->data.operand.right);
353
sfprintf(cc->ccdisc->text, "}");
354
return;
355
case '=':
356
sfprintf(cc->ccdisc->text, "(%s%s=", x->data.variable.symbol->name, expr->subop == '=' ? "" : opname(expr->subop));
357
gen(cc, expr->data.operand.right);
358
sfprintf(cc->ccdisc->text, ")");
359
return;
360
case ';':
361
for (;;)
362
{
363
if (!(x = expr->data.operand.right))
364
switch (cc->lastop = expr->data.operand.left->op)
365
{
366
case FOR:
367
case IF:
368
case PRINTF:
369
case RETURN:
370
case WHILE:
371
break;
372
default:
373
sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
374
break;
375
}
376
gen(cc, expr->data.operand.left);
377
sfprintf(cc->ccdisc->text, ";\n");
378
if (!(expr = x))
379
break;
380
switch (cc->lastop = expr->op)
381
{
382
case ';':
383
continue;
384
case FOR:
385
case IF:
386
case PRINTF:
387
case RETURN:
388
case WHILE:
389
break;
390
default:
391
sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
392
break;
393
}
394
gen(cc, expr);
395
sfprintf(cc->ccdisc->text, ";\n");
396
break;
397
}
398
return;
399
case ',':
400
sfprintf(cc->ccdisc->text, "(");
401
gen(cc, x);
402
while ((expr = expr->data.operand.right) && expr->op == ',')
403
{
404
sfprintf(cc->ccdisc->text, "), (");
405
gen(cc, expr->data.operand.left);
406
}
407
if (expr)
408
{
409
sfprintf(cc->ccdisc->text, "), (");
410
gen(cc, expr);
411
}
412
sfprintf(cc->ccdisc->text, ")");
413
return;
414
case '?':
415
sfprintf(cc->ccdisc->text, "(");
416
gen(cc, x);
417
sfprintf(cc->ccdisc->text, ") ? (");
418
gen(cc, expr->data.operand.right->data.operand.left);
419
sfprintf(cc->ccdisc->text, ") : (");
420
gen(cc, expr->data.operand.right->data.operand.right);
421
sfprintf(cc->ccdisc->text, ")");
422
return;
423
case AND:
424
sfprintf(cc->ccdisc->text, "(");
425
gen(cc, x);
426
sfprintf(cc->ccdisc->text, ") && (");
427
gen(cc, expr->data.operand.right);
428
sfprintf(cc->ccdisc->text, ")");
429
return;
430
case OR:
431
sfprintf(cc->ccdisc->text, "(");
432
gen(cc, x);
433
sfprintf(cc->ccdisc->text, ") || (");
434
gen(cc, expr->data.operand.right);
435
sfprintf(cc->ccdisc->text, ")");
436
return;
437
case F2I:
438
sfprintf(cc->ccdisc->text, "(%s)(", extype(INTEGER));
439
gen(cc, x);
440
sfprintf(cc->ccdisc->text, ")");
441
return;
442
case I2F:
443
sfprintf(cc->ccdisc->text, "(%s)(", extype(FLOATING));
444
gen(cc, x);
445
sfprintf(cc->ccdisc->text, ")");
446
return;
447
case S2I:
448
sfprintf(cc->ccdisc->text, "strto%s(", sizeof(intmax_t) > sizeof(long) ? "ll" : "l");
449
gen(cc, x);
450
sfprintf(cc->ccdisc->text, ",(char**)0,0)");
451
return;
452
}
453
y = expr->data.operand.right;
454
if (x->type == STRING)
455
{
456
switch (expr->op)
457
{
458
case S2B:
459
sfprintf(cc->ccdisc->text, "*(");
460
gen(cc, x);
461
sfprintf(cc->ccdisc->text, ")!=0");
462
return;
463
case S2F:
464
sfprintf(cc->ccdisc->text, "strtod(");
465
gen(cc, x);
466
sfprintf(cc->ccdisc->text, ",0)");
467
return;
468
case S2I:
469
sfprintf(cc->ccdisc->text, "strtol(");
470
gen(cc, x);
471
sfprintf(cc->ccdisc->text, ",0,0)");
472
return;
473
case S2X:
474
sfprintf(cc->ccdisc->text, "** cannot convert string value to external **");
475
return;
476
case NE:
477
sfprintf(cc->ccdisc->text, "!");
478
/*FALLTHROUGH*/
479
case EQ:
480
sfprintf(cc->ccdisc->text, "strmatch(");
481
gen(cc, x);
482
sfprintf(cc->ccdisc->text, ",");
483
gen(cc, y);
484
sfprintf(cc->ccdisc->text, ")");
485
return;
486
case '+':
487
case '|':
488
case '&':
489
case '^':
490
case '%':
491
case '*':
492
sfprintf(cc->ccdisc->text, "** string bits not supported **");
493
return;
494
}
495
switch (expr->op)
496
{
497
case '<':
498
s = "<0";
499
break;
500
case LE:
501
s = "<=0";
502
break;
503
case GE:
504
s = ">=0";
505
break;
506
case '>':
507
s = ">0";
508
break;
509
default:
510
s = "** unknown string op **";
511
break;
512
}
513
sfprintf(cc->ccdisc->text, "strcoll(");
514
gen(cc, x);
515
sfprintf(cc->ccdisc->text, ",");
516
gen(cc, y);
517
sfprintf(cc->ccdisc->text, ")%s", s);
518
return;
519
}
520
else
521
{
522
if (!y)
523
sfprintf(cc->ccdisc->text, "%s", opname(expr->op));
524
sfprintf(cc->ccdisc->text, "(");
525
gen(cc, x);
526
if (y)
527
{
528
sfprintf(cc->ccdisc->text, ")%s(", opname(expr->op));
529
gen(cc, y);
530
}
531
sfprintf(cc->ccdisc->text, ")");
532
}
533
return;
534
}
535
536
/*
537
* generate global declarations
538
*/
539
540
static int
541
global(Dt_t* table, void* object, void* handle)
542
{
543
register Excc_t* cc = (Excc_t*)handle;
544
register Exid_t* sym = (Exid_t*)object;
545
546
if (sym->lex == DYNAMIC)
547
sfprintf(cc->ccdisc->text, "static %s %s;\n", extype(sym->type), sym->name);
548
return 0;
549
}
550
551
/*
552
* open C program generator context
553
*/
554
555
Excc_t*
556
exccopen(Expr_t* expr, Exccdisc_t* disc)
557
{
558
register Excc_t* cc;
559
char* id;
560
561
if (!(id = disc->id))
562
id = "";
563
if (!(cc = newof(0, Excc_t, 1, strlen(id) + 2)))
564
return 0;
565
cc->expr = expr;
566
cc->disc = expr->disc;
567
cc->id = (char*)(cc + 1);
568
cc->ccdisc = disc;
569
if (!(disc->flags & EX_CC_DUMP))
570
{
571
sfprintf(disc->text, "/* : : generated by %s : : */\n", exversion);
572
sfprintf(disc->text, "\n#include <ast.h>\n");
573
if (*id)
574
sfsprintf(cc->id, strlen(id) + 2, "%s_", id);
575
sfprintf(disc->text, "\n");
576
dtwalk(expr->symbols, global, cc);
577
}
578
return cc;
579
}
580
581
/*
582
* close C program generator context
583
*/
584
585
int
586
exccclose(Excc_t* cc)
587
{
588
int r = 0;
589
590
if (!cc)
591
r = -1;
592
else
593
{
594
if (!(cc->ccdisc->flags & EX_CC_DUMP))
595
{
596
if (cc->ccdisc->text)
597
sfclose(cc->ccdisc->text);
598
else
599
r = -1;
600
}
601
free(cc);
602
}
603
return r;
604
}
605
606
/*
607
* generate the program for name or sym coerced to type
608
*/
609
610
int
611
excc(Excc_t* cc, const char* name, Exid_t* sym, int type)
612
{
613
register char* t;
614
615
if (!cc)
616
return -1;
617
if (!sym)
618
sym = name ? (Exid_t*)dtmatch(cc->expr->symbols, name) : &cc->expr->main;
619
if (sym && sym->lex == PROCEDURE && sym->value)
620
{
621
t = extype(type);
622
sfprintf(cc->ccdisc->text, "\n%s %s%s(data) char** data; {\n%s _%svalue = 0;\n", t, cc->id, sym->name, t, cc->id);
623
gen(cc, sym->value->data.procedure.body);
624
sfprintf(cc->ccdisc->text, ";\n");
625
if (cc->lastop != RETURN)
626
sfprintf(cc->ccdisc->text, "return _%svalue;\n", cc->id);
627
sfprintf(cc->ccdisc->text, "}\n");
628
return 0;
629
}
630
return -1;
631
}
632
633
/*
634
* dump an expression tree on sp
635
*/
636
637
int
638
exdump(Expr_t* expr, Exnode_t* node, Sfio_t* sp)
639
{
640
Excc_t* cc;
641
Exccdisc_t ccdisc;
642
Exid_t* sym;
643
644
memset(&ccdisc, 0, sizeof(ccdisc));
645
ccdisc.flags = EX_CC_DUMP;
646
ccdisc.text = sp;
647
if (!(cc = exccopen(expr, &ccdisc)))
648
return -1;
649
if (node)
650
gen(cc, node);
651
else
652
for (sym = (Exid_t*)dtfirst(expr->symbols); sym; sym = (Exid_t*)dtnext(expr->symbols, sym))
653
if (sym->lex == PROCEDURE && sym->value)
654
{
655
sfprintf(sp, "%s:\n", sym->name);
656
gen(cc, sym->value->data.procedure.body);
657
}
658
sfprintf(sp, "\n");
659
return exccclose(cc);
660
}
661
662