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

« back to all changes in this revision

Viewing changes to lefty/aix_mods/exec.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
/* Lefteris Koutsofios - AT&T Bell Laboratories */
 
3
 
 
4
#include "common.h"
 
5
#include "mem.h"
 
6
#include "code.h"
 
7
#include "tbl.h"
 
8
#include "str.h"
 
9
#include "exec.h"
 
10
#include "internal.h"
 
11
 
 
12
static lvar_t *lvarp;
 
13
static int lvarn, llvari, flvari;
 
14
#define LVARINCR 1000
 
15
#define LVARSIZE sizeof (lvar_t)
 
16
 
 
17
Tobj root, null;
 
18
Tobj rtno;
 
19
int Erun;
 
20
int Eerrlevel, Estackdepth, Eshowbody, Eshowcalls, Eoktorun;
 
21
 
 
22
#define PUSHJMP(op, np, b) op = (volatile jmp_buf *) np, np = (jmp_buf *) &b
 
23
#define POPJMP(op, np) np = (jmp_buf *) op
 
24
 
 
25
/* longjmps for normal program execution */
 
26
typedef enum {
 
27
    PLJ_BREAK, PLJ_CONTINUE, PLJ_RETURN, PLJ_SIZE
 
28
} PLJtype_t;
 
29
static jmp_buf *pljbufp1, *pljbufp2;
 
30
static PLJtype_t pljtype;
 
31
 
 
32
/* longjmp for error handling */
 
33
static jmp_buf *eljbufp;
 
34
 
 
35
/* error levels and types */
 
36
typedef enum {
 
37
    ERR0, ERR1, ERR2, ERR3, ERR4, ERR5
 
38
} errlevel_t;
 
39
typedef enum {
 
40
    ERRNOLHS, ERRNORHS, ERRNOSUCHFUNC, ERRBADARG, ERRARGMIS, ERRNOTATABLE,
 
41
    ERRIFUNCERR, ERRRECRUN, ERRTABLECHANGED
 
42
} errnum_t;
 
43
static char *errnam[] = {
 
44
    "no variable",
 
45
    "no value",
 
46
    "no such function",
 
47
    "bad argument",
 
48
    "argument number mismatch",
 
49
    "not a table",
 
50
    "internal function call error",
 
51
    "recursive run attempt",
 
52
    "table changed during a forin loop",
 
53
};
 
54
 
 
55
static int errdo;
 
56
 
 
57
/* stack information */
 
58
typedef struct sinfo_t {
 
59
    Tobj co, fco;
 
60
    int ci, fci;
 
61
    int flvari, llvari;
 
62
} sinfo_t;
 
63
#define SINFOSIZE sizeof (sinfo_t)
 
64
#define SINFOINCR 100
 
65
static sinfo_t *sinfop;
 
66
static int sinfoi, sinfon;
 
67
 
 
68
typedef enum {
 
69
    TNK_LI, TNK_O, TNK_S
 
70
} tnktype_t;
 
71
typedef struct tnk_t {
 
72
    tnktype_t type;
 
73
    union {
 
74
        int li;
 
75
        struct {
 
76
            Tobj to, ko;
 
77
        } tnko;
 
78
        struct {
 
79
            Ctype_t kt;
 
80
            Tobj to, co;
 
81
            int vi;
 
82
        } tnks;
 
83
    } u;
 
84
} tnk_t;
 
85
 
 
86
typedef struct num_tt {
 
87
    Ctype_t type;
 
88
    union {
 
89
        long i;
 
90
        double d;
 
91
        Tobj no;
 
92
    } u;
 
93
} num_tt;
 
94
 
 
95
static long rootm;
 
96
static int running;
 
97
 
 
98
static Tobj eeval (Tobj, int);
 
99
static Tobj efcall (Tobj, int);
 
100
static void ewhilest (Tobj, int);
 
101
static void eforst (Tobj, int);
 
102
static void eforinst (Tobj, int);
 
103
 
 
104
static Tobj getval (Tobj, int);
 
105
static int getvar (Tobj, int, tnk_t *);
 
106
static void setvar (tnk_t, Tobj);
 
107
static int boolop (Tobj);
 
108
static int orderop (Tobj, Ctype_t, Tobj);
 
109
static Tobj arithop (num_tt *, Ctype_t, num_tt *);
 
110
static void err (int, int, Tobj, int);
 
111
static void printbody (char *, int);
 
112
 
 
113
void Einit (void) {
 
114
    root = Ttable (100);
 
115
    rootm = Mpushmark (root);
 
116
    Tinss (root, "null", (null = Ttable (2)));
 
117
    rtno = NULL;
 
118
    pljbufp1 = pljbufp2 = NULL, pljtype = 0;
 
119
    eljbufp = NULL;
 
120
    lvarp = Marrayalloc ((long) LVARINCR * LVARSIZE);
 
121
    lvarn = LVARINCR;
 
122
    llvari = 0;
 
123
    flvari = 0;
 
124
    sinfop = Marrayalloc ((long) SINFOINCR * SINFOSIZE);
 
125
    sinfon = SINFOINCR;
 
126
    sinfoi = 0;
 
127
    Erun = FALSE;
 
128
    running = 0;
 
129
    Eoktorun = FALSE;
 
130
}
 
131
 
 
132
void Eterm (void) {
 
133
    Marrayfree (sinfop), sinfop = NULL, sinfon = 0, sinfoi = 0;
 
134
    Marrayfree (lvarp), lvarp = NULL, lvarn = 0, llvari = 0, flvari = 0;
 
135
    rtno = NULL;
 
136
    null = NULL;
 
137
    Mpopmark (rootm);
 
138
}
 
139
 
 
140
Tobj Eunit (Tobj co) {
 
141
    volatile jmp_buf *oeljbufp;
 
142
    volatile int ownsinfoi;
 
143
    volatile long m;
 
144
    volatile Tobj lrtno;
 
145
 
 
146
    jmp_buf eljbuf;
 
147
 
 
148
#if 0
 
149
    if (running && !Eoktorun) {
 
150
        err (ERRRECRUN, ERR2, NULL, 0);
 
151
        return NULL;
 
152
    }
 
153
#endif
 
154
    Eoktorun = FALSE;
 
155
 
 
156
    if (!co)
 
157
        return NULL;
 
158
 
 
159
    if (Tgettype (co) != T_CODE)
 
160
        panic (POS, "Eunit", "argument type is not T_CODE");
 
161
 
 
162
    m = Mpushmark (co);
 
163
    PUSHJMP (oeljbufp, eljbufp, eljbuf);
 
164
    ownsinfoi = sinfoi++;
 
165
    if (sinfoi == sinfon) {
 
166
        sinfop = Marraygrow (sinfop, (long) (sinfon + SINFOINCR) * SINFOSIZE);
 
167
        sinfon += SINFOINCR;
 
168
    }
 
169
    sinfop[ownsinfoi].co = co;
 
170
    sinfop[ownsinfoi].ci = TCgetfp (co, 0);
 
171
    sinfop[ownsinfoi].fco = NULL;
 
172
    sinfop[ownsinfoi].flvari = flvari;
 
173
    sinfop[ownsinfoi].llvari = llvari;
 
174
    running++;
 
175
    if (setjmp (*eljbufp))
 
176
        lrtno = NULL;
 
177
    else
 
178
        lrtno = eeval (co, TCgetfp (co, 0));
 
179
    running--;
 
180
    rtno = NULL;
 
181
    flvari = sinfop[ownsinfoi].flvari;
 
182
    llvari = sinfop[ownsinfoi].llvari;
 
183
    sinfoi = ownsinfoi;
 
184
    POPJMP (oeljbufp, eljbufp);
 
185
    Mpopmark (m);
 
186
    Erun = TRUE;
 
187
    return lrtno;
 
188
}
 
189
 
 
190
/* shortcut: this function executes a piece of code that corresponds to
 
191
   <internal func name> = function () internal "<internal func name>";
 
192
*/
 
193
Tobj Efunction (Tobj co, char *ifnam) {
 
194
    Tobj v1o;
 
195
    int fi;
 
196
 
 
197
    fi = TCgetnext (co, TCgetfp (co, TCgetfp (co, 0)));
 
198
    v1o = Tcode (TCgetaddr (co, fi), fi,
 
199
            (int) TCgetinteger (co, TCgetfp (co, fi)));
 
200
    Tinss (root, ifnam, v1o);
 
201
    return v1o;
 
202
}
 
203
 
 
204
static Tobj eeval (Tobj co, int ci) {
 
205
    Tobj v1o, v2o, v3o;
 
206
    Ttype_t ttype;
 
207
    Ctype_t ctype;
 
208
    tnk_t tnk;
 
209
    num_tt lnum, rnum;
 
210
    long m1, m2;
 
211
    int i1, i2, res;
 
212
 
 
213
tailrec:
 
214
    errdo = TRUE;
 
215
    v1o = NULL;
 
216
    ctype = TCgettype (co, ci);
 
217
    switch (ctype) {
 
218
    case C_ASSIGN:
 
219
        i1 = TCgetfp (co, ci);
 
220
        if ((v1o = eeval (co, TCgetnext (co, i1))) == NULL) {
 
221
            err (ERRNORHS, ERR4, co, TCgetnext (co, i1));
 
222
            return NULL;
 
223
        }
 
224
        m1 = Mpushmark (v1o);
 
225
        res = getvar (co, i1, &tnk);
 
226
        Mpopmark (m1);
 
227
        if (res == -1) {
 
228
            err (ERRNOLHS, ERR3, co, i1);
 
229
            return NULL;
 
230
        }
 
231
        setvar (tnk, v1o);
 
232
        return v1o;
 
233
    case C_OR:
 
234
    case C_AND:
 
235
    case C_NOT:
 
236
        i1 = TCgetfp (co, ci);
 
237
        if ((v1o = eeval (co, i1)) == NULL)
 
238
            err (ERRNORHS, ERR4, co, i1);
 
239
        switch (ctype) {
 
240
        case C_OR:
 
241
            if (boolop (v1o) == TRUE)
 
242
                return Ttrue;
 
243
            if ((v1o = eeval (co, TCgetnext (co, i1))) == NULL)
 
244
                err (ERRNORHS, ERR4, co, TCgetnext (co, i1));
 
245
            return (boolop (v1o) == TRUE) ? Ttrue: Tfalse;
 
246
        case C_AND:
 
247
            if (boolop (v1o) == FALSE)
 
248
                return Tfalse;
 
249
            if ((v1o = eeval (co, TCgetnext (co, i1))) == NULL)
 
250
                err (ERRNORHS, ERR4, co, TCgetnext (co, i1));
 
251
            return (boolop (v1o) == FALSE) ? Tfalse: Ttrue;
 
252
        case C_NOT:
 
253
            return (boolop (v1o) == TRUE) ? Tfalse: Ttrue;
 
254
        }
 
255
        /* NOT REACHED */
 
256
        return Tfalse;
 
257
    case C_EQ:
 
258
    case C_NE:
 
259
    case C_LT:
 
260
    case C_LE:
 
261
    case C_GT:
 
262
    case C_GE:
 
263
        i1 = TCgetfp (co, ci);
 
264
        if ((v1o = eeval (co, i1)) == NULL)
 
265
            err (ERRNORHS, ERR4, co, i1);
 
266
        else
 
267
            m1 = Mpushmark (v1o);
 
268
        if ((v2o = eeval (co, TCgetnext (co, i1))) == NULL)
 
269
            err (ERRNORHS, ERR4, co, TCgetnext (co, i1));
 
270
        if (v1o)
 
271
            Mpopmark (m1);
 
272
        return (orderop (v1o, ctype, v2o) == TRUE) ? Ttrue: Tfalse;
 
273
    case C_PLUS:
 
274
    case C_MINUS:
 
275
    case C_MUL:
 
276
    case C_DIV:
 
277
    case C_MOD:
 
278
    case C_UMINUS:
 
279
        i1 = TCgetfp (co, ci);
 
280
        if ((lnum.type = TCgettype (co, i1)) == C_INTEGER)
 
281
            lnum.u.i = TCgetinteger (co, i1);
 
282
        else if (lnum.type == C_REAL)
 
283
            lnum.u.d = TCgetreal (co, i1);
 
284
        else if ((lnum.u.no = eeval (co, i1)) == NULL) {
 
285
            err (ERRNORHS, ERR4, co, i1);
 
286
            return NULL;
 
287
        }
 
288
        if (ctype == C_UMINUS) {
 
289
            if (!(v1o = arithop (&lnum, ctype, NULL)))
 
290
                err (ERRNORHS, ERR4, co, ci);
 
291
            return v1o;
 
292
        }
 
293
        if (lnum.type != C_INTEGER && lnum.type != C_REAL)
 
294
            m1 = Mpushmark (lnum.u.no);
 
295
        i1 = TCgetnext (co, i1);
 
296
        if ((rnum.type = TCgettype (co, i1)) == C_INTEGER)
 
297
            rnum.u.i = TCgetinteger (co, i1);
 
298
        else if (rnum.type == C_REAL)
 
299
            rnum.u.d = TCgetreal (co, i1);
 
300
        else if ((rnum.u.no = eeval (co, i1)) == NULL)
 
301
            err (ERRNORHS, ERR4, co, i1);
 
302
        if (lnum.type != C_INTEGER && lnum.type != C_REAL)
 
303
            Mpopmark (m1);
 
304
        if (!(v1o = arithop (&lnum, ctype, &rnum)))
 
305
            err (ERRNORHS, ERR4, co, ci);
 
306
        return v1o;
 
307
    case C_PEXPR:
 
308
        ci = TCgetfp (co, ci);
 
309
        goto tailrec;
 
310
    case C_FCALL:
 
311
        return efcall (co, ci);
 
312
    case C_INTEGER:
 
313
        return Tinteger (TCgetinteger (co, ci));
 
314
    case C_REAL:
 
315
        return Treal (TCgetreal (co, ci));
 
316
    case C_STRING:
 
317
        return Tstring (TCgetstring (co, ci));
 
318
    case C_GVAR:
 
319
    case C_LVAR:
 
320
    case C_PVAR:
 
321
        return getval (co, ci);
 
322
    case C_FUNCTION:
 
323
        return Tcode (TCgetaddr (co, ci), ci,
 
324
                (int) TCgetinteger (co, TCgetfp (co, ci)));
 
325
    case C_TCONS:
 
326
        v1o = Ttable (0);
 
327
        m1 = Mpushmark (v1o);
 
328
        for (i1 = TCgetfp (co, ci); i1 != C_NULL;
 
329
                i1 = TCgetnext (co, TCgetnext (co, i1))) {
 
330
            if (!(v3o = eeval (co, TCgetnext (co, i1)))) {
 
331
                err (ERRNORHS, ERR4, co, TCgetnext (co, i1));
 
332
                continue;
 
333
            }
 
334
            m2 = Mpushmark (v3o);
 
335
            if (!(v2o = eeval (co, i1))) {
 
336
                err (ERRNOLHS, ERR3, co, i1);
 
337
                Mpopmark (m2);
 
338
                continue;
 
339
            }
 
340
            ttype = Tgettype (v2o);
 
341
            if (ttype == T_INTEGER || ttype == T_REAL || ttype == T_STRING)
 
342
                Tinso (v1o, v2o, v3o);
 
343
            else
 
344
                err (ERRNOLHS, ERR1, co, i1);
 
345
        }
 
346
        Mpopmark (m1);
 
347
        return v1o;
 
348
    case C_STMT:
 
349
        for (i1 = TCgetfp (co, ci); i1 != C_NULL; )
 
350
            if ((i2 = TCgetnext (co, i1)) != C_NULL) {
 
351
                eeval (co, i1);
 
352
                i1 = i2;
 
353
            } else {
 
354
                ci = i1;
 
355
                goto tailrec;
 
356
            }
 
357
        /* NOT REACHED */
 
358
        break;
 
359
    case C_IF:
 
360
        i1 = TCgetfp (co, ci);
 
361
        if (!(v1o = eeval (co, i1)))
 
362
            err (ERRNORHS, ERR5, co, i1);
 
363
        if (boolop (v1o) == TRUE) {
 
364
            ci = TCgetnext (co, i1);
 
365
            goto tailrec;
 
366
        } else if ((ci = TCgetnext (co, TCgetnext (co, i1))) != C_NULL)
 
367
            goto tailrec;
 
368
        break;
 
369
    case C_WHILE:
 
370
        ewhilest (co, ci);
 
371
        break;
 
372
    case C_FOR:
 
373
        eforst (co, ci);
 
374
        break;
 
375
    case C_FORIN:
 
376
        eforinst (co, ci);
 
377
        break;
 
378
    case C_BREAK:
 
379
        pljtype = PLJ_BREAK;
 
380
        longjmp (*pljbufp1, 1);
 
381
        /* NOT REACHED */
 
382
        break;
 
383
    case C_CONTINUE:
 
384
        pljtype = PLJ_CONTINUE;
 
385
        longjmp (*pljbufp1, 1);
 
386
        /* NOT REACHED */
 
387
        break;
 
388
    case C_RETURN:
 
389
        if ((i1 = TCgetfp (co, ci)) != C_NULL)
 
390
            rtno = eeval (co, i1);
 
391
        pljtype = PLJ_RETURN;
 
392
        longjmp (*pljbufp2, 1);
 
393
        /* NOT REACHED */
 
394
        break;
 
395
    default:
 
396
        panic (POS, "eeval", "unknown program token type %d", ctype);
 
397
    }
 
398
    return v1o;
 
399
}
 
400
 
 
401
static Tobj efcall (Tobj co, int ci) {
 
402
    volatile jmp_buf *opljbufp1, *opljbufp2;
 
403
    volatile long m;
 
404
    volatile int bi, ownsinfoi, li, ln;
 
405
 
 
406
    jmp_buf pljbuf;
 
407
    Tobj fdo, vo, lrtno;
 
408
    int i, fci, ai, di, di1, fid;
 
409
 
 
410
    ownsinfoi = sinfoi++;
 
411
    if (sinfoi == sinfon) {
 
412
        sinfop = Marraygrow (sinfop, (long) (sinfon + SINFOINCR) * SINFOSIZE);
 
413
        sinfon += SINFOINCR;
 
414
    }
 
415
    sinfop[ownsinfoi].co = co;
 
416
    sinfop[ownsinfoi].ci = ci;
 
417
    sinfop[ownsinfoi].fco = NULL;
 
418
    sinfop[ownsinfoi].flvari = flvari;
 
419
    sinfop[ownsinfoi].llvari = llvari;
 
420
    fci = TCgetfp (co, ci);
 
421
    if (!(fdo = getval (co, fci)) || Tgettype (fdo) != T_CODE) {
 
422
        err (ERRNOSUCHFUNC, ERR2, co, fci);
 
423
        sinfoi = ownsinfoi;
 
424
        return NULL;
 
425
    }
 
426
 
 
427
    m = Mpushmark ((Tobj) fdo);
 
428
    ai = TCgetfp (co, TCgetnext (co, fci));
 
429
    ln = (int) TCgetinteger (fdo, (li = TCgetnext (fdo, TCgetfp (fdo, 0))));
 
430
    di = TCgetnext (fdo, li);
 
431
    bi = TCgetnext (fdo, di);
 
432
    if (bi != C_NULL && TCgettype (fdo, bi) == C_INTERNAL) {
 
433
        for (i = 0; ai != C_NULL; ai = TCgetnext (co, ai), i++) {
 
434
            if (!(vo = eeval (co, ai))) {
 
435
                err (ERRBADARG, ERR2, co, ai);
 
436
                Mpopmark (m);
 
437
                llvari = sinfop[ownsinfoi].llvari;
 
438
                sinfoi = ownsinfoi;
 
439
                return NULL;
 
440
            }
 
441
            if (llvari + 1 > lvarn) {
 
442
                lvarp = Marraygrow (lvarp, (long) (llvari + 1) * LVARSIZE);
 
443
                lvarn = llvari + 1;
 
444
            }
 
445
            lvarp[llvari].m = Mpushmark ((lvarp[llvari].o = vo));
 
446
            llvari++;
 
447
        }
 
448
        fid = (int) TCgetinteger (fdo, TCgetfp (fdo, bi));
 
449
        if (Ifuncs[fid].min > i || Ifuncs[fid].max < i) {
 
450
            err (ERRARGMIS, ERR2, co, ci);
 
451
            Mpopmark (m);
 
452
            llvari = sinfop[ownsinfoi].llvari;
 
453
            sinfoi = ownsinfoi;
 
454
            return NULL;
 
455
        }
 
456
        flvari = sinfop[ownsinfoi].llvari;
 
457
        sinfop[ownsinfoi].fco = fdo;
 
458
        sinfop[ownsinfoi].fci = bi;
 
459
        if (fid < 0 || fid >= Ifuncn)
 
460
            panic (POS, "efcall", "no such internal function: %d", fid);
 
461
        rtno = Ttrue;
 
462
        if ((*Ifuncs[fid].func) (i, &lvarp[flvari]) == L_FAILURE) {
 
463
            rtno = NULL;
 
464
            err (ERRIFUNCERR, ERR2, co, ci);
 
465
        }
 
466
    } else {
 
467
        if (llvari + ln > lvarn) {
 
468
            lvarp = Marraygrow (lvarp, (long) (llvari + ln) * LVARSIZE);
 
469
            lvarn = llvari + ln;
 
470
        }
 
471
        di1 = TCgetfp (fdo, di);
 
472
        for (i = 0; i < ln && di1 != C_NULL && ai != C_NULL;
 
473
                i++, ai = TCgetnext (co, ai)) {
 
474
            if (!(vo = eeval (co, ai))) {
 
475
                err (ERRBADARG, ERR2, co, ai);
 
476
                Mpopmark (m);
 
477
                llvari = sinfop[ownsinfoi].llvari;
 
478
                sinfoi = ownsinfoi;
 
479
                return NULL;
 
480
            }
 
481
            lvarp[llvari].m = Mpushmark ((lvarp[llvari].o = vo));
 
482
            llvari++;
 
483
            di1 = TCgetnext (fdo, di1);
 
484
        }
 
485
        if (di1 != C_NULL || ai != C_NULL) {
 
486
            err (ERRARGMIS, ERR2, co, ci);
 
487
            Mpopmark (m);
 
488
            llvari = sinfop[ownsinfoi].llvari;
 
489
            sinfoi = ownsinfoi;
 
490
            return NULL;
 
491
        }
 
492
        for (; i < ln; i++, llvari++)
 
493
            lvarp[llvari].m = Mpushmark ((lvarp[llvari].o = NULL));
 
494
        flvari = sinfop[ownsinfoi].llvari;
 
495
        PUSHJMP (opljbufp2, pljbufp2, pljbuf);
 
496
        opljbufp1 = (volatile jmp_buf *) pljbufp1;
 
497
        if (setjmp (*pljbufp2)) {
 
498
            ;
 
499
        } else {
 
500
            sinfop[ownsinfoi].fco = fdo;
 
501
            for (; bi != C_NULL; bi = TCgetnext (fdo, bi)) {
 
502
                sinfop[ownsinfoi].fci = bi;
 
503
                if (TCgettype (fdo, bi) != C_DECL)
 
504
                    eeval ((Tobj) fdo, bi);
 
505
            }
 
506
        }
 
507
        POPJMP (opljbufp2, pljbufp2);
 
508
        pljbufp1 = (jmp_buf *) opljbufp1;
 
509
    }
 
510
    flvari = sinfop[ownsinfoi].flvari;
 
511
    llvari = sinfop[ownsinfoi].llvari;
 
512
    sinfoi = ownsinfoi;
 
513
    Mpopmark (m);
 
514
    lrtno = rtno, rtno = NULL;
 
515
    errdo = TRUE;
 
516
    return lrtno;
 
517
}
 
518
 
 
519
static void ewhilest (Tobj co, int ci) {
 
520
    volatile jmp_buf *opljbufp;
 
521
    volatile jmp_buf pljbuf;
 
522
    volatile Tobj c1o;
 
523
    volatile int ei, si;
 
524
 
 
525
    Tobj v1o;
 
526
 
 
527
    c1o = (volatile Tobj) co; /* protect argument from longjmp */
 
528
    ei = TCgetfp (c1o, ci);
 
529
    si = TCgetnext (c1o, ei);
 
530
    PUSHJMP (opljbufp, pljbufp1, pljbuf);
 
531
    for (;;) {
 
532
        if (!(v1o = eeval ((Tobj) c1o, ei)))
 
533
            err (ERRNORHS, ERR5, c1o, ei);
 
534
        if (boolop (v1o) == FALSE)
 
535
            break;
 
536
        if (setjmp (*pljbufp1)) {
 
537
            if (pljtype == PLJ_CONTINUE)
 
538
                continue;
 
539
            else if (pljtype == PLJ_BREAK)
 
540
                break;
 
541
        }
 
542
        eeval ((Tobj) c1o, si);
 
543
    }
 
544
    POPJMP (opljbufp, pljbufp1);
 
545
}
 
546
 
 
547
static void eforst (Tobj co, int ci) {
 
548
    volatile jmp_buf *opljbufp;
 
549
    volatile jmp_buf pljbuf;
 
550
    volatile Tobj c1o;
 
551
    volatile int ei1, ei2, ei3, si, eisnop1, eisnop2, eisnop3;
 
552
 
 
553
    Tobj v1o;
 
554
 
 
555
    c1o = (volatile Tobj) co; /* protect argument from longjmp */
 
556
    ei1 = TCgetfp (c1o, ci);
 
557
    ei2 = TCgetnext (c1o, ei1);
 
558
    ei3 = TCgetnext (c1o, ei2);
 
559
    si = TCgetnext (c1o, ei3);
 
560
    eisnop1 = (TCgettype (c1o, ei1) == C_NOP);
 
561
    eisnop2 = (TCgettype (c1o, ei2) == C_NOP);
 
562
    eisnop3 = (TCgettype (c1o, ei3) == C_NOP);
 
563
    PUSHJMP (opljbufp, pljbufp1, pljbuf);
 
564
    if (!eisnop1)
 
565
        eeval ((Tobj) c1o, ei1);
 
566
    for (;;) {
 
567
        if (!eisnop2) {
 
568
            if (!(v1o = eeval ((Tobj) c1o, ei2)))
 
569
                err (ERRNORHS, ERR5, c1o, ei2);
 
570
            if (boolop (v1o) == FALSE)
 
571
                break;
 
572
        }
 
573
        if (setjmp (*pljbufp1) != 0) {
 
574
            if (pljtype == PLJ_CONTINUE)
 
575
                ;
 
576
            else if (pljtype == PLJ_BREAK)
 
577
                break;
 
578
        } else {
 
579
            eeval ((Tobj) c1o, si);
 
580
        }
 
581
        if (!eisnop3)
 
582
            eeval ((Tobj) c1o, ei3);
 
583
    }
 
584
    POPJMP (opljbufp, pljbufp1);
 
585
}
 
586
 
 
587
static void eforinst (Tobj co, int ci) {
 
588
    volatile jmp_buf *opljbufp;
 
589
    volatile jmp_buf pljbuf;
 
590
    volatile Tobj tblo, c1o;
 
591
    volatile Tkvindex_t tkvi;
 
592
    volatile tnk_t tnk;
 
593
    volatile long km, t;
 
594
    volatile int ei1, ei2, si;
 
595
 
 
596
    c1o = (volatile Tobj) co; /* protect argument from longjmp */
 
597
    ei1 = TCgetfp (c1o, ci);
 
598
    ei2 = TCgetnext (c1o, ei1);
 
599
    si = TCgetnext (c1o, ei2);
 
600
    if (getvar ((Tobj) c1o, ei1, (tnk_t *) &tnk) == -1) {
 
601
        err (ERRNOLHS, ERR3, c1o, ei1);
 
602
        return;
 
603
    }
 
604
    if (tnk.type == TNK_O)
 
605
        km = Mpushmark (tnk.u.tnko.ko);
 
606
    if (!(tblo = (volatile Tobj) eeval ((Tobj) c1o, ei2))) {
 
607
        if (tnk.type == TNK_O)
 
608
            Mpopmark (km);
 
609
        err (ERRNORHS, ERR4, c1o, ei2);
 
610
        return;
 
611
    }
 
612
    if (Tgettype (tblo) != T_TABLE) {
 
613
        err (ERRNOTATABLE, ERR1, c1o, ei2);
 
614
        return;
 
615
    }
 
616
    PUSHJMP (opljbufp, pljbufp1, pljbuf);
 
617
    t = Tgettime (tblo);
 
618
    for (Tgetfirst ((Tobj) tblo, (Tkvindex_t *) &tkvi); tkvi.kvp;
 
619
            Tgetnext ((Tkvindex_t *) &tkvi)) {
 
620
        setvar (tnk, tkvi.kvp->ko);
 
621
        if (setjmp (*pljbufp1) != 0) {
 
622
            if (pljtype == PLJ_CONTINUE)
 
623
                continue;
 
624
            else if (pljtype == PLJ_BREAK)
 
625
                break;
 
626
        }
 
627
        eeval ((Tobj) c1o, si);
 
628
        if (t != Tgettime (tblo)) {
 
629
            err (ERRTABLECHANGED, ERR1, c1o, ei2);
 
630
            break;
 
631
        }
 
632
    }
 
633
    POPJMP (opljbufp, pljbufp1);
 
634
    if (tnk.type == TNK_O)
 
635
        Mpopmark (km);
 
636
}
 
637
 
 
638
static Tobj getval (Tobj co, int ci) {
 
639
    Tobj cvo, cko, cto;
 
640
    Ctype_t ct, vt;
 
641
    int vi, ni, nn;
 
642
 
 
643
    if ((ct = TCgettype (co, ci)) == C_LVAR) {
 
644
        nn = (int) TCgetinteger (co, (ni = TCgetnext (co, TCgetfp (co, ci))));
 
645
        cto = cvo = lvarp[flvari + nn].o;
 
646
        if (!cto)
 
647
            return NULL;
 
648
        vi = TCgetnext (co, ni);
 
649
    } else if (ct == C_GVAR) {
 
650
        cto = root;
 
651
        vi = TCgetfp (co, ci);
 
652
    } else if (ct == C_PVAR)
 
653
        return TCgetobject (co, ci);
 
654
    else
 
655
        return NULL;
 
656
 
 
657
    while (vi != C_NULL) {
 
658
        if (Tgettype (cto) != T_TABLE)
 
659
            return NULL;
 
660
        if ((vt = TCgettype (co, vi)) == C_STRING) {
 
661
            if (!(cvo = Tfinds (cto, TCgetstring (co, vi))))
 
662
                return NULL;
 
663
        } else if (vt == C_INTEGER) {
 
664
            if (!(cvo = Tfindi (cto, TCgetinteger (co, vi))))
 
665
                return NULL;
 
666
        } else if (vt == C_REAL) {
 
667
            if (!(cvo = Tfindr (cto, TCgetreal (co, vi))))
 
668
                return NULL;
 
669
        } else {
 
670
            if (!(cko = eeval (co, vi)) || !(cvo = Tfindo (cto, cko)))
 
671
                return NULL;
 
672
        }
 
673
        cto = cvo;
 
674
        vi = TCgetnext (co, vi);
 
675
    }
 
676
    return cvo;
 
677
}
 
678
 
 
679
static int getvar (Tobj co, int ci, tnk_t *tnkp) {
 
680
    Tobj cvo, cko, cto;
 
681
    Ctype_t ct, vt;
 
682
    long m;
 
683
    int vi, ovi, nn, ni;
 
684
 
 
685
    if ((ct = TCgettype (co, ci)) == C_LVAR) {
 
686
        nn = (int) TCgetinteger (co, (ni = TCgetnext (co, TCgetfp (co, ci))));
 
687
        cvo = cto = lvarp[flvari + nn].o;
 
688
        vi = TCgetnext (co, ni);
 
689
        if (vi != C_NULL && (!cvo || Tgettype (cvo) != T_TABLE))
 
690
            Mresetmark (lvarp[flvari + nn].m,
 
691
                    (lvarp[flvari + nn].o = cvo = cto = Ttable (0)));
 
692
    } else if (ct == C_GVAR) { /* else it's a global variable */
 
693
        cvo = root;
 
694
        vi = TCgetfp (co, ci);
 
695
    } else {
 
696
        return -1;
 
697
    }
 
698
 
 
699
    ovi = -1;
 
700
    while (vi != C_NULL) {
 
701
        cto = cvo;
 
702
        if ((vt = TCgettype (co, vi)) == C_STRING) {
 
703
            cvo = Tfinds (cto, TCgetstring (co, vi));
 
704
        } else if (vt == C_INTEGER) {
 
705
            cvo = Tfindi (cto, TCgetinteger (co, vi));
 
706
        } else if (vt == C_REAL) {
 
707
            cvo = Tfindr (cto, TCgetreal (co, vi));
 
708
        } else {
 
709
            if (!(cko = eeval (co, vi)) || !(T_ISSTRING (cko) ||
 
710
                    T_ISNUMBER (cko)))
 
711
                return -1;
 
712
            cvo = Tfindo (cto, cko);
 
713
        }
 
714
        ovi = vi, vi = TCgetnext (co, vi);
 
715
        if (vi != C_NULL && (!cvo || Tgettype (cvo) != T_TABLE)) {
 
716
            if (vt == C_STRING)
 
717
                Tinss (cto, TCgetstring (co, ovi), (cvo = Ttable (0)));
 
718
            else if (vt == C_INTEGER)
 
719
                Tinsi (cto, TCgetinteger (co, ovi), (cvo = Ttable (0)));
 
720
            else if (vt == C_REAL)
 
721
                Tinsr (cto, TCgetreal (co, ovi), (cvo = Ttable (0)));
 
722
            else
 
723
                m = Mpushmark (cko), Tinso (cto, cko, (cvo = Ttable (0))),
 
724
                        Mpopmark (m);
 
725
        }
 
726
    }
 
727
    if (ct == C_LVAR && ovi == -1) {
 
728
        tnkp->type = TNK_LI;
 
729
        tnkp->u.li = nn;
 
730
    } else {
 
731
        switch (vt) {
 
732
        case C_STRING:
 
733
        case C_INTEGER:
 
734
        case C_REAL:
 
735
            tnkp->type = TNK_S;
 
736
            tnkp->u.tnks.kt = vt;
 
737
            tnkp->u.tnks.to = cto;
 
738
            tnkp->u.tnks.co = co;
 
739
            tnkp->u.tnks.vi = ovi;
 
740
            break;
 
741
        default:
 
742
            tnkp->type = TNK_O;
 
743
            tnkp->u.tnko.to = cto;
 
744
            tnkp->u.tnko.ko = cko;
 
745
            break;
 
746
        }
 
747
    }
 
748
    return 0;
 
749
}
 
750
 
 
751
static void setvar (tnk_t tnk, Tobj vo) {
 
752
    switch (tnk.type) {
 
753
    case TNK_LI:
 
754
        Mresetmark (lvarp[flvari + tnk.u.li].m,
 
755
                (lvarp[flvari + tnk.u.li].o = vo));
 
756
        break;
 
757
    case TNK_O:
 
758
        Tinso (tnk.u.tnko.to, tnk.u.tnko.ko, vo);
 
759
        break;
 
760
    default:
 
761
        switch (tnk.u.tnks.kt) {
 
762
        case C_STRING:
 
763
            Tinss (tnk.u.tnks.to,
 
764
                    TCgetstring (tnk.u.tnks.co, tnk.u.tnks.vi), vo);
 
765
            break;
 
766
        case C_INTEGER:
 
767
            Tinsi (tnk.u.tnks.to,
 
768
                    TCgetinteger (tnk.u.tnks.co, tnk.u.tnks.vi), vo);
 
769
            break;
 
770
        case C_REAL:
 
771
            Tinsr (tnk.u.tnks.to, TCgetreal (tnk.u.tnks.co, tnk.u.tnks.vi), vo);
 
772
            break;
 
773
        }
 
774
        break;
 
775
    }
 
776
}
 
777
 
 
778
static int boolop (Tobj vo) {
 
779
    long i;
 
780
    double d;
 
781
 
 
782
    if (!vo)
 
783
        return FALSE;
 
784
 
 
785
    switch (Tgettype (vo)) {
 
786
    case T_INTEGER:
 
787
        i = Tgetinteger (vo);
 
788
        return (i == 0) ? FALSE : TRUE;
 
789
    case T_REAL:
 
790
        d = Tgetreal (vo);
 
791
        return (d == 0.0) ? FALSE : TRUE;
 
792
    case T_TABLE:
 
793
        if (vo == null)
 
794
            return FALSE;
 
795
        return TRUE;
 
796
    default:
 
797
        return TRUE;
 
798
    }
 
799
}
 
800
 
 
801
static int orderop (Tobj v1o, Ctype_t op, Tobj v2o) {
 
802
    Ctype_t t1, t2;
 
803
    long i1, i2;
 
804
    int r;
 
805
    double d1, d2;
 
806
 
 
807
    if (!v1o || !v2o) {
 
808
        if ((v1o || v2o) && op == C_NE)
 
809
            return TRUE;
 
810
        return FALSE;
 
811
    }
 
812
    t1 = Tgettype (v1o), t2 = Tgettype (v2o);
 
813
    if (t1 == T_STRING && t2 == T_STRING) {
 
814
        r = Strcmp (Tgetstring (v1o), Tgetstring (v2o));
 
815
    } else if (t1 == T_INTEGER && t2 == T_INTEGER) {
 
816
        i1 = Tgetinteger (v1o), i2 = Tgetinteger (v2o);
 
817
        r = (i1 == i2) ? 0 : ((i1 < i2) ? -1 : 1);
 
818
    } else if (t1 == T_INTEGER && t2 == T_REAL) {
 
819
        i1 = Tgetinteger (v1o), d2 = Tgetreal (v2o);
 
820
        r = (i1 == d2) ? 0 : ((i1 < d2) ? -1 : 1);
 
821
    } else if (t1 == T_REAL && t2 == T_INTEGER) {
 
822
        d1 = Tgetreal (v1o), i2 = Tgetinteger (v2o);
 
823
        r = (d1 == i2) ? 0 : ((d1 < i2) ? -1 : 1);
 
824
    } else if (t1 == T_REAL && t2 == T_REAL) {
 
825
        d1 = Tgetreal (v1o), d2 = Tgetreal (v2o);
 
826
        r = (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
 
827
    } else if (t1 == t2) {
 
828
        if (op != C_EQ && op != C_NE)
 
829
            return FALSE;
 
830
        r = (v1o == v2o) ? 0 : 1;
 
831
    } else {
 
832
        return FALSE;
 
833
    }
 
834
    switch (op) {
 
835
    case C_EQ: return (r == 0) ? TRUE : FALSE;
 
836
    case C_NE: return (r != 0) ? TRUE : FALSE;
 
837
    case C_LT: return (r <  0) ? TRUE : FALSE;
 
838
    case C_LE: return (r <= 0) ? TRUE : FALSE;
 
839
    case C_GT: return (r >  0) ? TRUE : FALSE;
 
840
    case C_GE: return (r >= 0) ? TRUE : FALSE;
 
841
    }
 
842
    panic (POS, "orderop", "bad op code");
 
843
    return FALSE; /* NOT REACHED */
 
844
}
 
845
 
 
846
static Tobj arithop (num_tt *lnum, Ctype_t op, num_tt *rnum) {
 
847
    double d1, d2, d3;
 
848
 
 
849
    if (!rnum && op != C_UMINUS)
 
850
        return NULL;
 
851
    if (lnum->type == C_INTEGER)
 
852
        d1 = lnum->u.i;
 
853
    else if (lnum->type == C_REAL)
 
854
        d1 = lnum->u.d;
 
855
    else if (!lnum->u.no)
 
856
        return NULL;
 
857
    else if (Tgettype (lnum->u.no) == T_INTEGER)
 
858
        d1 = Tgetinteger (lnum->u.no);
 
859
    else if (Tgettype (lnum->u.no) == T_REAL)
 
860
        d1 = Tgetreal (lnum->u.no);
 
861
    else
 
862
        return NULL;
 
863
    if (op == C_UMINUS) {
 
864
        d3 = -d1;
 
865
        goto result;
 
866
    }
 
867
    if (rnum->type == C_INTEGER)
 
868
        d2 = rnum->u.i;
 
869
    else if (rnum->type == C_REAL)
 
870
        d2 = rnum->u.d;
 
871
    else if (!rnum->u.no)
 
872
        return NULL;
 
873
    else if (Tgettype (rnum->u.no) == T_INTEGER)
 
874
        d2 = Tgetinteger (rnum->u.no);
 
875
    else if (Tgettype (rnum->u.no) == T_REAL)
 
876
        d2 = Tgetreal (rnum->u.no);
 
877
    else
 
878
        return NULL;
 
879
    switch (op) {
 
880
    case C_PLUS:  d3 = d1 + d2;               break;
 
881
    case C_MINUS: d3 = d1 - d2;               break;
 
882
    case C_MUL:   d3 = d1 * d2;               break;
 
883
    case C_DIV:   d3 = d1 / d2;               break;
 
884
    case C_MOD:   d3 = (long) d1 % (long) d2; break;
 
885
    }
 
886
result:
 
887
    if (d3 == (double) (long) d3)
 
888
        return Tinteger ((long) d3);
 
889
    return Treal (d3);
 
890
}
 
891
 
 
892
static void err (int errnum, int level, Tobj co, int ci) {
 
893
    char *s;
 
894
    int si, i;
 
895
 
 
896
    if (level > Eerrlevel || !errdo)
 
897
        return;
 
898
    s = "";
 
899
    fprintf (stderr, "runtime error: %s\n", errnam[errnum]);
 
900
    if (!co)
 
901
        return;
 
902
    if (Estackdepth < 1)
 
903
        return;
 
904
    if (!sinfop[(si = sinfoi - 1)].fco && si > 0)
 
905
        si--;
 
906
    if (Eshowbody > 0) {
 
907
        if (co == sinfop[si].fco)
 
908
            s = Scfull (co, 0, ci);
 
909
        else if (co == sinfop[si].co)
 
910
            s = Scfull (co, TCgetfp (co, 0), ci);
 
911
        printbody (s, Eshowbody), free (s);
 
912
        if (Estackdepth == 1) {
 
913
            fprintf (stderr, "\n");
 
914
            errdo = FALSE;
 
915
        }
 
916
        for (i = si; i >= 0; i--) {
 
917
            if (sinfop[i].fco) {
 
918
                s = Scfull (sinfop[i].fco, 0, sinfop[i].fci);
 
919
                printbody (s, Eshowbody), free (s);
 
920
            }
 
921
        }
 
922
        s = Scfull (sinfop[0].co, TCgetfp (sinfop[0].co, 0), sinfop[0].ci);
 
923
        printbody (s, Eshowbody), free (s);
 
924
    }
 
925
    fprintf (stderr, "\n");
 
926
    errdo = FALSE;
 
927
}
 
928
 
 
929
static void printbody (char *s, int mode) {
 
930
    char *s1, *s2;
 
931
    char c;
 
932
 
 
933
    if (mode == 2) {
 
934
        fprintf (stderr, "%s\n", s);
 
935
        return;
 
936
    }
 
937
    c = '\000';
 
938
    for (s1 = s; *s1; s1++)
 
939
        if (*s1 == '>' && *(s1 + 1) && *(s1 + 1) == '>')
 
940
            break;
 
941
    if (!*s1)
 
942
        return;
 
943
    for (; s1 != s; s1--)
 
944
        if (*(s1 - 1) == '\n')
 
945
            break;
 
946
    for (s2 = s1; *s2; s2++)
 
947
        if (*s2 == '\n')
 
948
            break;
 
949
    if (*s2)
 
950
        c = *s2, *s2 = '\000';
 
951
    fprintf (stderr, "%s\n", s1);
 
952
    if (c)
 
953
        *s2 = c;
 
954
}