~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to tools/expr/excc.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

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