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

« back to all changes in this revision

Viewing changes to tools/expr/exgram.h

  • 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
/*
 
4
 * grammar support routines
 
5
 * stuffed in a header so exparse.y can work
 
6
 * with both yacc and bison
 
7
 * sometimes free stuff can cost a lot
 
8
 */
 
9
 
 
10
#if defined(MINTOKEN) && !defined(_EXGRAM_H)
 
11
#define _EXGRAM_H
 
12
 
 
13
#if !defined(_EXPARSE_H)
 
14
#define _EXPARSE_H
 
15
#endif
 
16
 
 
17
#include "exlib.h"
 
18
#include <string.h>
 
19
 
 
20
#define exlex()         extoken(expr.program)
 
21
 
 
22
#define ALLOCATE(p,x)   (x*)exalloc(p,sizeof(x))
 
23
#define QUALIFY(r,s)    ((r)&&(expr.program->disc->flags&EX_QUALIFY)?qualify(r,s):(s))
 
24
 
 
25
static int              a2t[] = { 0, FLOATING, INTEGER, STRING };
 
26
static Switch_t         swstate;
 
27
 
 
28
Exstate_t               expr;
 
29
 
 
30
static int 
 
31
T(int t)
 
32
{
 
33
  if (expr.program->disc->types)
 
34
    return expr.program->disc->types[t&TMASK];
 
35
  else
 
36
    return a2t[t&TMASK];
 
37
}
 
38
 
 
39
/*
 
40
 * allocate and initialize a new expression node in the current program
 
41
 */
 
42
 
 
43
Exnode_t*
 
44
exnewnode(Expr_t* p, int op, int binary, int type, Exnode_t* left, Exnode_t* right)
 
45
{
 
46
        register Exnode_t*      x;
 
47
 
 
48
        x = ALLOCATE(p, Exnode_t);
 
49
        x->op = op;
 
50
        x->type = type;
 
51
        x->binary = binary;
 
52
        x->local.number = 0;
 
53
        x->local.pointer = 0;
 
54
        x->data.operand.left = left;
 
55
        x->data.operand.right = right;
 
56
        return x;
 
57
}
 
58
 
 
59
/*
 
60
 * free node x and its children
 
61
 */
 
62
 
 
63
void
 
64
exfreenode(Expr_t* p, register Exnode_t* x)
 
65
{
 
66
        register Print_t*       pr;
 
67
        register Exref_t*       r;
 
68
        Print_t*                pn;
 
69
        Exref_t*                rn;
 
70
        int                     i;
 
71
 
 
72
        switch (x->op)
 
73
        {
 
74
        case CALL:
 
75
                if (x->data.call.args)
 
76
                        exfreenode(p, x->data.call.args);
 
77
                break;
 
78
        case CONSTANT:
 
79
                break;
 
80
        case DEFAULT:
 
81
                if (x->data.select.next)
 
82
                        exfreenode(p, x->data.select.next);
 
83
                break;
 
84
        case DYNAMIC:
 
85
                if (x->data.variable.index)
 
86
                        exfreenode(p, x->data.variable.index);
 
87
                if (x->data.variable.symbol->local.pointer)
 
88
                {
 
89
                        dtclose((Dt_t*)x->data.variable.symbol->local.pointer);
 
90
                        x->data.variable.symbol->local.pointer = 0;
 
91
                }
 
92
                break;
 
93
        case ITERATE:
 
94
                if (x->data.generate.statement)
 
95
                        exfreenode(p, x->data.generate.statement);
 
96
                break;
 
97
        case ID:
 
98
                rn = x->data.variable.reference;
 
99
                while (r = rn)
 
100
                {
 
101
                        rn = r->next;
 
102
                        vmfree(p->vm, r);
 
103
                }
 
104
                if (x->data.variable.index)
 
105
                        exfreenode(p, x->data.variable.index);
 
106
                break;
 
107
        case PRINTF:
 
108
        case SPRINTF:
 
109
                if (x->data.print.descriptor)
 
110
                        exfreenode(p, x->data.print.descriptor);
 
111
                pn = x->data.print.args;
 
112
                while (pr = pn)
 
113
                {
 
114
                        for (i = 0; i < elementsof(pr->param) && pr->param[i]; i++)
 
115
                                exfreenode(p, pr->param[i]);
 
116
                        if (pr->arg)
 
117
                                exfreenode(p, pr->arg);
 
118
                        pn = pr->next;
 
119
                        vmfree(p->vm, pr);
 
120
                }
 
121
                break;
 
122
        default:
 
123
                if (x->data.operand.left)
 
124
                        exfreenode(p, x->data.operand.left);
 
125
                if (x->data.operand.right)
 
126
                        exfreenode(p, x->data.operand.right);
 
127
                break;
 
128
        }
 
129
        vmfree(p->vm, x);
 
130
}
 
131
 
 
132
/* makeVar:
 
133
 *
 
134
 * Create variable from s[idx].refs 
 
135
 * If s is DYNAMIC, refs is non-empty and dyna represents s[idx].
 
136
 * The rightmost element in s[idx].refs becomes the dominant symbol,
 
137
 * and the prefix gets stored in refs. (This format is used to simplify
 
138
 * the yacc parser.)
 
139
 */
 
140
static Exnode_t*
 
141
makeVar (Expr_t* prog, Exid_t* s, Exnode_t* idx, Exnode_t* dyna, Exref_t* refs)
 
142
{
 
143
  Exnode_t* nn;
 
144
  int       kind;
 
145
  Exid_t*   sym;
 
146
 
 
147
    /* parse components */
 
148
  if (refs) {
 
149
    if (refs->next) {
 
150
      sym = refs->next->symbol;
 
151
      refs->next->symbol = refs->symbol;
 
152
    }
 
153
    else sym = refs->symbol;
 
154
    refs->symbol = s;
 
155
    refs->index = idx;
 
156
  } 
 
157
  else sym = s;
 
158
 
 
159
  if (sym->type) kind = sym->type;
 
160
  else kind = STRING;
 
161
 
 
162
  nn = exnewnode(prog, ID, 0, kind, NiL, NiL);
 
163
  nn->data.variable.symbol = sym;
 
164
  nn->data.variable.reference = refs;
 
165
  nn->data.variable.index = 0;
 
166
  nn->data.variable.dyna = dyna;
 
167
  if (!prog->disc->getf)
 
168
    exerror("%s: identifier references not supported", sym->name);
 
169
  else if (expr.program->disc->reff)
 
170
    (*expr.program->disc->reff)(prog, nn, nn->data.variable.symbol, refs, NiL, EX_SCALAR, prog->disc);
 
171
 
 
172
  return nn;
 
173
}
 
174
 
 
175
/*
 
176
 * cast x to type
 
177
 */
 
178
 
 
179
static char*    typename[] =
 
180
{
 
181
        "external", "integer", "unsigned", "float", "string"
 
182
};
 
183
 
 
184
static int      typecast[5][5] =
 
185
{
 
186
        0,      X2I,    X2I,    X2F,    X2S,
 
187
        I2X,    0,      0,      I2F,    I2S,
 
188
        I2X,    0,      0,      I2F,    I2S,
 
189
        F2X,    F2I,    F2I,    0,      F2S,
 
190
        S2X,    S2I,    S2I,    S2F,    0
 
191
};
 
192
 
 
193
#define TYPEINDEX(t)    (((t)>=INTEGER&&(t)<=STRING)?((t)-INTEGER+1):0)
 
194
#define TYPENAME(t)     typename[TYPEINDEX(t)]
 
195
#define TYPECAST(f,t)   typecast[TYPEINDEX(f)][TYPEINDEX(t)]
 
196
 
 
197
#define EXTERNAL(t)     ((t)>=F2X)
 
198
 
 
199
Exnode_t*
 
200
excast(Expr_t* p, register Exnode_t* x, register int type, register Exnode_t* xref, int arg)
 
201
{
 
202
        register int    t2t;
 
203
        char*           s;
 
204
        char*           e;
 
205
 
 
206
        if (x && x->type != type && type && type != VOID)
 
207
        {
 
208
                if (!x->type)
 
209
                {
 
210
                        x->type = type;
 
211
                        return x;
 
212
                }
 
213
                if (!(t2t = TYPECAST(x->type, type)))
 
214
                        return x;
 
215
                if (EXTERNAL(t2t) && !p->disc->convertf)
 
216
                        exerror("cannot cast %s to %s", TYPENAME(x->type), TYPENAME(type));
 
217
                if (x->op != CONSTANT)
 
218
                        x = exnewnode(p, t2t, 0, type, x, xref);
 
219
                else switch (t2t)
 
220
                {
 
221
                case F2X:
 
222
                case I2X:
 
223
                case S2X:
 
224
                case X2F:
 
225
                case X2I:
 
226
                case X2S:
 
227
                        if (xref && xref->op == ID)
 
228
                        {
 
229
                                if ((*p->disc->convertf)(p, x, type, xref->data.variable.symbol, arg, p->disc) < 0)
 
230
                                        exerror("%s: cannot cast constant %s to %s", xref->data.variable.symbol->name, TYPENAME(x->type), TYPENAME(type));
 
231
                        }
 
232
                        else if ((*p->disc->convertf)(p, x, type, NiL, arg, p->disc) < 0)
 
233
                                exerror("cannot cast constant %s to %s", TYPENAME(x->type), TYPENAME(type));
 
234
                        break;
 
235
                case F2I:
 
236
                        x->data.constant.value.integer = x->data.constant.value.floating;
 
237
                        break;
 
238
                case F2S:
 
239
                        sfprintf(p->tmp, "%g", x->data.constant.value.floating);
 
240
                        x->data.constant.value.string = vmstrdup(p->vm, sfstruse(p->tmp));
 
241
                        break;
 
242
                case I2F:
 
243
                        x->data.constant.value.floating = x->data.constant.value.integer;
 
244
                        break;
 
245
                case I2S:
 
246
                        sfprintf(p->tmp, "%I*d", sizeof(x->data.constant.value.integer), x->data.constant.value.integer);
 
247
                        x->data.constant.value.string = vmstrdup(p->vm, sfstruse(p->tmp));
 
248
                        break;
 
249
                case S2F:
 
250
                        x->data.constant.value.integer = strtod(x->data.constant.value.string, &e);
 
251
                        if (*e)
 
252
                                x->data.constant.value.floating = *x->data.constant.value.string != 0;
 
253
                        break;
 
254
                case S2I:
 
255
                        s = x->data.constant.value.string;
 
256
                        x->data.constant.value.integer = strtoll(s, &e, 0);
 
257
                        if (*e)
 
258
                                x->data.constant.value.integer = *s != 0;
 
259
                        break;
 
260
                default:
 
261
                        exerror("internal error: %d: unknown cast op", t2t);
 
262
                        break;
 
263
                }
 
264
                x->type = type;
 
265
        }
 
266
        return x;
 
267
}
 
268
 
 
269
/*
 
270
 * force ref . sym qualification
 
271
 */
 
272
 
 
273
static Exid_t*
 
274
qualify(register Exref_t* ref, register Exid_t* sym)
 
275
{
 
276
        register Exid_t*        x;
 
277
        char*                   s;
 
278
 
 
279
        while (ref->next)
 
280
                ref = ref->next;
 
281
        sfprintf(expr.program->tmp, "%s.%s", ref->symbol->name, sym->name);
 
282
        s = sfstruse(expr.program->tmp);
 
283
        if (!(x = (Exid_t*)dtmatch(expr.program->symbols, s)))
 
284
        {
 
285
                if (x = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1))
 
286
                {
 
287
                        memcpy(x, sym, sizeof(Exid_t) - EX_NAMELEN);
 
288
                        strcpy(x->name, s);
 
289
                        dtinsert(expr.program->symbols, x);
 
290
                }
 
291
                else
 
292
                {
 
293
                        exerror("out of space [qualify]");
 
294
                        x = sym;
 
295
                }
 
296
        }
 
297
        return x;
 
298
}
 
299
 
 
300
/*
 
301
 * check function call arg types and count
 
302
 * return function identifier node
 
303
 */
 
304
 
 
305
static Exnode_t*
 
306
call(Exref_t* ref, register Exid_t* fun, register Exnode_t* args)
 
307
{
 
308
        register int    t;
 
309
        register int    type;
 
310
        Exnode_t*       x;
 
311
        int             num;
 
312
 
 
313
        x = exnewnode(expr.program, ID, 0, 0, NiL, NiL);
 
314
        t = fun->type;
 
315
        x->data.variable.symbol = fun = QUALIFY(ref, fun);
 
316
        x->data.variable.reference = ref;
 
317
        num = 0;
 
318
        N(t);
 
319
        while (type = T(t))
 
320
        {
 
321
                if (!args)
 
322
                {
 
323
                        exerror("%s: not enough args", fun->name);
 
324
                        return args;
 
325
                }
 
326
                num++;
 
327
                if (type != args->data.operand.left->type)
 
328
                        args->data.operand.left = excast(expr.program, args->data.operand.left, type, x, num);
 
329
                args = args->data.operand.right;
 
330
                N(t);
 
331
        }
 
332
        if (args)
 
333
                exerror("%s: too many args", fun->name);
 
334
        return x;
 
335
}
 
336
 
 
337
/*
 
338
 * precompile a printf call
 
339
 */
 
340
 
 
341
static Print_t*
 
342
preprint(register Exnode_t* args)
 
343
{
 
344
        register Print_t*       x;
 
345
        register char*          s;
 
346
        register int            c;
 
347
        int                     t;
 
348
        int                     i;
 
349
        int                     n;
 
350
        char*                   e;
 
351
        char*                   f;
 
352
        Print_t*                p;
 
353
        Print_t*                q;
 
354
 
 
355
        if (!args || args->data.operand.left->type != STRING)
 
356
                exerror("format string argument expected");
 
357
        if (args->data.operand.left->op != CONSTANT)
 
358
        {
 
359
                x = ALLOCATE(expr.program, Print_t);
 
360
                memzero(x, sizeof(*x));
 
361
                x->arg = args;
 
362
                return x;
 
363
        }
 
364
        f = args->data.operand.left->data.constant.value.string;
 
365
        args = args->data.operand.right;
 
366
        for (s = f; *s; s++)
 
367
        {
 
368
                sfputc(expr.program->tmp, *s);
 
369
                if (*s == '%')
 
370
                {
 
371
                        if (!*++s)
 
372
                                exerror("%s: trailing %% in printf format", f);
 
373
                        if (*s != '%')
 
374
                                break;
 
375
                }
 
376
        }
 
377
        x = 0;
 
378
        for (;;)
 
379
        {
 
380
                q = ALLOCATE(expr.program, Print_t);
 
381
                if (x)
 
382
                        x->next = q;
 
383
                else
 
384
                        p = q;
 
385
                x = q;
 
386
                memzero(x, sizeof(*x));
 
387
                if (*s)
 
388
                {
 
389
                        i = 0;
 
390
                        t = INTEGER;
 
391
                        for (;;)
 
392
                        {
 
393
                                switch (c = *s++)
 
394
                                {
 
395
                                case 0:
 
396
                                        exerror("unterminated %%... in printf format");
 
397
                                        goto done;
 
398
                                case '*':
 
399
                                        if (i >= elementsof(x->param))
 
400
                                        {
 
401
                                                *s = 0;
 
402
                                                exerror("printf format %s has too many * arguments", f);
 
403
                                                goto done;
 
404
                                        }
 
405
                                        if (!args)
 
406
                                        {
 
407
                                                *s = 0;
 
408
                                                exerror("printf format %s * argument expected", f);
 
409
                                                goto done;
 
410
                                        }
 
411
                                        x->param[i++] = args->data.operand.left;
 
412
                                        args = args->data.operand.right;
 
413
                                        break;
 
414
                                case '(':
 
415
                                        n = 1;
 
416
                                        for (;;)
 
417
                                        {
 
418
                                                sfputc(expr.program->tmp, c);
 
419
                                                switch (c = *s++)
 
420
                                                {
 
421
                                                case 0:
 
422
                                                        s--;
 
423
                                                        break;
 
424
                                                case '(':
 
425
                                                        n++;
 
426
                                                        continue;
 
427
                                                case ')':
 
428
                                                        if (--n <= 0)
 
429
                                                                break;
 
430
                                                        continue;
 
431
                                                default:
 
432
                                                        continue;
 
433
                                                }
 
434
                                                break;
 
435
                                        }
 
436
                                        break;
 
437
                                case 'c':
 
438
                                case 'd':
 
439
                                        goto specified;
 
440
                                case 'e':
 
441
                                case 'f':
 
442
                                case 'g':
 
443
                                        t = FLOATING;
 
444
                                        goto specified;
 
445
                                case 'h':
 
446
                                        exerror("short printf formats not supported");
 
447
                                        goto done;
 
448
                                case 'l':
 
449
                                        t = INTEGER;
 
450
                                        break;
 
451
                                case 'o':
 
452
                                case 'u':
 
453
                                case 'x':
 
454
                                case 'T':
 
455
                                        t = UNSIGNED;
 
456
                                        goto specified;
 
457
                                case 's':
 
458
                                case 'S':
 
459
                                        t = STRING;
 
460
                                        goto specified;
 
461
                                default:
 
462
                                        if (isalpha(c))
 
463
                                                goto specified;
 
464
                                        break;
 
465
                                }
 
466
                                sfputc(expr.program->tmp, c);
 
467
                        }
 
468
                specified:
 
469
                        sfputc(expr.program->tmp, c);
 
470
                        for (e = s; *s; s++)
 
471
                        {
 
472
                                if (*s == '%')
 
473
                                {
 
474
                                        if (!*++s)
 
475
                                        {
 
476
                                                *e = 0;
 
477
                                                exerror("%s: trailing %% in printf format", f);
 
478
                                                goto done;
 
479
                                        }
 
480
                                        if (*s != '%')
 
481
                                        {
 
482
                                                s--;
 
483
                                                break;
 
484
                                        }
 
485
                                }
 
486
                                sfputc(expr.program->tmp, *s);
 
487
                        }
 
488
                        if (!args)
 
489
                        {
 
490
                                *e = 0;
 
491
                                exerror("%s printf argument expected", f);
 
492
                                goto done;
 
493
                        }
 
494
                        x->arg = args->data.operand.left;
 
495
                        switch (t)
 
496
                        {
 
497
                        case FLOATING:
 
498
                                if (x->arg->type != FLOATING)
 
499
                                        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 : (Exnode_t*)0);
 
500
                                break;
 
501
                        case INTEGER:
 
502
                        case UNSIGNED:
 
503
                                if (!INTEGRAL(x->arg->type))
 
504
                                        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 : (Exnode_t*)0);
 
505
                                x->arg->type = t;
 
506
                                break;
 
507
                        case STRING:
 
508
                                if (x->arg->type != STRING)
 
509
                                {
 
510
                                        if (x->arg->op == CONSTANT && x->arg->data.constant.reference && expr.program->disc->convertf)
 
511
                                        {
 
512
                                                if ((*expr.program->disc->convertf)(expr.program, x->arg, STRING, x->arg->data.constant.reference, 0, expr.program->disc) < 0)
 
513
                                                        exerror("cannot convert string printf argument");
 
514
                                                else x->arg->data.constant.value.string = vmstrdup(expr.program->vm, x->arg->data.constant.value.string);
 
515
                                        }
 
516
                                        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)
 
517
                                                exerror("string printf argument expected");
 
518
                                        else
 
519
                                                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 : (Exnode_t*)0);
 
520
                                }
 
521
                                break;
 
522
                        }
 
523
                        args = args->data.operand.right;
 
524
                }
 
525
                x->format = vmstrdup(expr.program->vm, sfstruse(expr.program->tmp));
 
526
                if (!*s)
 
527
                        break;
 
528
                f = s;
 
529
        }
 
530
        if (args)
 
531
                exerror("too many printf arguments");
 
532
 done:
 
533
        sfstrset(expr.program->tmp, 0);
 
534
        return p;
 
535
}
 
536
 
 
537
/*
 
538
 * push a new input stream and program
 
539
 */
 
540
 
 
541
int
 
542
expush(Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
 
543
{
 
544
        register Exinput_t*     in;
 
545
        register char*          s;
 
546
        char                    buf[PATH_MAX];
 
547
 
 
548
        if (!(in = newof(0, Exinput_t, 1, 0)))
 
549
        {
 
550
                exerror("out of space [push]");
 
551
                return -1;
 
552
        }
 
553
        if (!p->input)
 
554
                p->input = &expr.null;
 
555
        if (!(in->bp = in->sp = (char*)sp))
 
556
        {
 
557
                if (in->fp = fp)
 
558
                        in->close = 0;
 
559
                else if (name)
 
560
                {
 
561
                        if (!(s = pathfind(name, p->disc->lib, p->disc->type, buf, sizeof(buf))) || !(in->fp = sfopen(NiL, s, "r")))
 
562
                        {
 
563
                                exerror("%s: file not found", name);
 
564
                                in->bp = in->sp = "";
 
565
                        }
 
566
                        else
 
567
                        {
 
568
                                name = (const char*)vmstrdup(p->vm, s);
 
569
                                in->close = 1;
 
570
                        }
 
571
                }
 
572
        }
 
573
        else in->fp = 0;
 
574
        if (!(in->next = p->input)->next)
 
575
        {
 
576
                p->errors = 0;
 
577
                if (!(p->disc->flags & EX_INTERACTIVE))
 
578
                {
 
579
                        if (line >= 0)
 
580
                                error_info.line = line;
 
581
                }
 
582
                else if (!error_info.line)
 
583
                        error_info.line = 1;
 
584
        }
 
585
        else if (line >= 0)
 
586
                error_info.line = line;
 
587
        setcontext(p);
 
588
        p->eof = 0;
 
589
        p->input = in;
 
590
        in->file = error_info.file;
 
591
        if (line >= 0)
 
592
                error_info.file = (char*)name;
 
593
        in->line = error_info.line;
 
594
        in->nesting = 0;
 
595
        in->unit = !name && !line;
 
596
        p->program = expr.program;
 
597
        expr.program = p;
 
598
        return 0;
 
599
}
 
600
 
 
601
/*
 
602
 * pop the current input stream
 
603
 */
 
604
 
 
605
int
 
606
expop(register Expr_t* p)
 
607
{
 
608
        register int            c;
 
609
        register Exinput_t*     in;
 
610
 
 
611
        if (!(in = p->input) || !in->next || in->unit)
 
612
                return -1;
 
613
        if (in->nesting)
 
614
                exerror("unbalanced quote or nesting construct");
 
615
        error_info.file = in->file;
 
616
        if (in->next->next)
 
617
                error_info.line = in->line;
 
618
        else
 
619
        {
 
620
                if (p->errors && in->fp && p->linep != p->line)
 
621
                        while ((c = sfgetc(in->fp)) != EOF)
 
622
                                if (c == '\n')
 
623
                                {
 
624
                                        error_info.line++;
 
625
                                        break;
 
626
                                }
 
627
                if (!(p->disc->flags & EX_INTERACTIVE))
 
628
                        error_info.line = in->line;
 
629
        }
 
630
        if (in->fp && in->close)
 
631
                sfclose(in->fp);
 
632
        if (in->pushback)
 
633
                free(in->pushback);
 
634
        p->input = in->next;
 
635
        free(in);
 
636
        setcontext(p);
 
637
        if (p->program)
 
638
                expr.program = p->program;
 
639
        return 0;
 
640
}
 
641
 
 
642
/*
 
643
 * compile the expression in [sf]p
 
644
 */
 
645
 
 
646
int
 
647
excomp(register Expr_t* p, const char* name, int line, const char* sp, Sfio_t* fp)
 
648
{
 
649
        int     eof;
 
650
 
 
651
        p->more = 0;
 
652
        eof = p->eof;
 
653
        if (!sp && !fp)
 
654
        {
 
655
                if (!p->input)
 
656
                        return -1;
 
657
        }
 
658
        else if (expush(p, name, line, sp, fp))
 
659
                return -1;
 
660
        else p->input->unit = line >= 0;
 
661
        exparse();
 
662
        p->input->unit = 0;
 
663
        expop(p);
 
664
        p->eof = eof;
 
665
        return 0;
 
666
}
 
667
 
 
668
/*
 
669
 * free the program p
 
670
 */
 
671
 
 
672
void
 
673
exclose(register Expr_t* p, int all)
 
674
{
 
675
        register int            i;
 
676
        register Exinput_t*     in;
 
677
 
 
678
        if (p)
 
679
        {
 
680
                if (all)
 
681
                {
 
682
                        for (i = 3; i < elementsof(p->file); i++)
 
683
                                if (p->file[i])
 
684
                                        sfclose(p->file[i]);
 
685
                        if (p->vm)
 
686
                                vmclose(p->vm);
 
687
                        if (p->ve)
 
688
                                vmclose(p->ve);
 
689
                        if (p->symbols)
 
690
                                dtclose(p->symbols);
 
691
                        if (p->tmp)
 
692
                                sfclose(p->tmp);
 
693
                        while (in = p->input)
 
694
                        {
 
695
                                if (in->pushback)
 
696
                                        free(in->pushback);
 
697
                                if (in->fp && in->close)
 
698
                                        sfclose(in->fp);
 
699
                                if (p->input = in->next)
 
700
                                        free(in);
 
701
                        }
 
702
                        free(p);
 
703
                }
 
704
                else
 
705
                {
 
706
                        vmclear(p->ve);
 
707
                        p->main.value = 0;
 
708
                }
 
709
        }
 
710
}
 
711
 
 
712
#endif