OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [rtems_webserver/] [ejparse.c] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * ejparse.c -- Ejscript(TM) Parser
3
 *
4
 * Copyright (c) Go Ahead Software, Inc., 1995-1999
5
 *
6
 * See the file "license.txt" for usage and redistribution license requirements
7
 */
8
 
9
/******************************** Description *********************************/
10
 
11
/*
12
 *      Ejscript parser. This implementes a subset of the JavaScript language.
13
 *      Multiple Ejscript parsers can be opened at a time.
14
 */
15
 
16
/********************************** Includes **********************************/
17
 
18
#include        "ej.h"
19
 
20
/********************************** Local Data ********************************/
21
 
22
ej_t                    **ejHandles;                                                    /* List of ej handles */
23
int                             ejMax = -1;                                                             /* Maximum size of      */
24
 
25
/****************************** Forward Declarations **************************/
26
 
27
static ej_t             *ejPtr(int eid);
28
static void             clearString(char_t **ptr);
29
static void             setString(char_t **ptr, char_t *s);
30
static void             appendString(char_t **ptr, char_t *s);
31
static void             freeVar(sym_t* sp);
32
static int              parse(ej_t *ep, int state, int flags);
33
static int              parseStmt(ej_t *ep, int state, int flags);
34
static int              parseDeclaration(ej_t *ep, int state, int flags);
35
static int              parseArgs(ej_t *ep, int state, int flags);
36
static int              parseCond(ej_t *ep, int state, int flags);
37
static int              parseExpr(ej_t *ep, int state, int flags);
38
static int              evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
39
static int              evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
40
static int              evalFunction(ej_t *ep);
41
static void             freeFunc(ejfunc_t *func);
42
 
43
/************************************* Code ***********************************/
44
/*
45
 *      Initialize a Ejscript engine
46
 */
47
 
48
int ejOpenEngine(sym_fd_t variables, sym_fd_t functions)
49
{
50
        ej_t    *ep;
51
        int             eid, vid;
52
 
53
        if ((eid = hAllocEntry((void***) &ejHandles, &ejMax, sizeof(ej_t))) < 0) {
54
                return -1;
55
        }
56
        ep = ejHandles[eid];
57
        ep->eid = eid;
58
 
59
/*
60
 *      Create a top level symbol table if one is not provided for variables and
61
 *      functions. Variables may create other symbol tables for block level
62
 *      declarations so we use hAlloc to manage a list of variable tables.
63
 */
64
        if ((vid = hAlloc((void***) &ep->variables)) < 0) {
65
                ejMax = hFree((void***) &ejHandles, ep->eid);
66
                return -1;
67
        }
68
        if (vid >= ep->variableMax) {
69
                ep->variableMax = vid + 1;
70
        }
71
 
72
        if (variables == -1) {
73
                ep->variables[vid] = symOpen(64) + EJ_OFFSET;
74
                ep->flags |= FLAGS_VARIABLES;
75
 
76
        } else {
77
                ep->variables[vid] = variables + EJ_OFFSET;
78
        }
79
 
80
        if (functions == -1) {
81
                ep->functions = symOpen(64);
82
                ep->flags |= FLAGS_FUNCTIONS;
83
        } else {
84
                ep->functions = functions;
85
        }
86
 
87
        ejLexOpen(ep);
88
 
89
/*
90
 *      Define standard constants
91
 */
92
        ejSetGlobalVar(ep->eid, T("null"), NULL);
93
 
94
#if EMF
95
        ejEmfOpen(ep->eid);
96
#endif
97
        return ep->eid;
98
}
99
 
100
/******************************************************************************/
101
/*
102
 *      Close
103
 */
104
 
105
void ejCloseEngine(int eid)
106
{
107
        ej_t    *ep;
108
        int             i;
109
 
110
        if ((ep = ejPtr(eid)) == NULL) {
111
                return;
112
        }
113
 
114
#if EMF
115
        ejEmfClose(eid);
116
#endif
117
 
118
        bfreeSafe(B_L, ep->error);
119
        ep->error = NULL;
120
        bfreeSafe(B_L, ep->result);
121
        ep->result = NULL;
122
 
123
        ejLexClose(ep);
124
 
125
        if (ep->flags & FLAGS_VARIABLES) {
126
                for (i = ep->variableMax - 1; i >= 0; i--) {
127
                        symClose(ep->variables[i] - EJ_OFFSET, freeVar);
128
                        ep->variableMax = hFree((void***) &ep->variables, i);
129
                }
130
        }
131
        if (ep->flags & FLAGS_FUNCTIONS) {
132
                symClose(ep->functions, freeVar);
133
        }
134
 
135
        ejMax = hFree((void***) &ejHandles, ep->eid);
136
        bfree(B_L, ep);
137
}
138
 
139
/******************************************************************************/
140
/*
141
 *      Callback from symClose. Free the variable.
142
 */
143
 
144
static void freeVar(sym_t* sp)
145
{
146
        valueFree(&sp->content);
147
}
148
 
149
/******************************************************************************/
150
/*
151
 *      Evaluate a Ejscript file
152
 */
153
 
154
#if DEV
155
char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
156
{
157
        gstat_t sbuf;
158
        ej_t    *ep;
159
        char_t  *script, *rs;
160
        char    *fileBuf;
161
        int             fd;
162
 
163
        a_assert(path && *path);
164
 
165
        if (emsg) {
166
                *emsg = NULL;
167
        }
168
        if ((ep = ejPtr(eid)) == NULL) {
169
                return NULL;
170
        }
171
 
172
        if ((fd = gopen(path, O_RDONLY | O_BINARY, 0666)) < 0) {
173
                ejError(ep, T("Bad handle %d"), eid);
174
                return NULL;
175
        }
176
        if (gstat(path, &sbuf) < 0) {
177
                close(fd);
178
                ejError(ep, T("Cant stat %s"), path);
179
                return NULL;
180
        }
181
        if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) {
182
                close(fd);
183
                ejError(ep, T("Cant malloc %d"), sbuf.st_size);
184
                return NULL;
185
        }
186
        if (read(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
187
                close(fd);
188
                bfree(B_L, fileBuf);
189
                ejError(ep, T("Error reading %s"), path);
190
                return NULL;
191
        }
192
        fileBuf[sbuf.st_size] = '\0';
193
        close(fd);
194
 
195
        if ((script = ballocAscToUni(fileBuf)) == NULL) {
196
                bfree(B_L, fileBuf);
197
                ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1);
198
                return NULL;
199
        }
200
        bfree(B_L, fileBuf);
201
 
202
        rs = ejEvalBlock(eid, script, emsg);
203
 
204
        bfree(B_L, script);
205
        return rs;
206
}
207
#endif
208
 
209
/******************************************************************************/
210
/*
211
 *      Create a new variable scope block so that consecutive ejEval calls may
212
 *      be made with the same varible scope. This space MUST be closed with
213
 *      ejCloseBlock when the evaluations are complete.
214
 */
215
 
216
int ejOpenBlock(int eid)
217
{
218
        ej_t    *ep;
219
        int             vid;
220
 
221
        if((ep = ejPtr(eid)) == NULL) {
222
                return -1;
223
        }
224
        if ((vid = hAlloc((void***) &ep->variables)) < 0) {
225
                return -1;
226
        }
227
        if (vid >= ep->variableMax) {
228
                ep->variableMax = vid + 1;
229
        }
230
        ep->variables[vid] = symOpen(64) + EJ_OFFSET;
231
        return vid;
232
 
233
}
234
 
235
/******************************************************************************/
236
/*
237
 *      Close a variable scope block. The vid parameter is the return value from
238
 *      the call to ejOpenBlock
239
 */
240
 
241
int ejCloseBlock(int eid, int vid)
242
{
243
        ej_t    *ep;
244
 
245
        if((ep = ejPtr(eid)) == NULL) {
246
                return -1;
247
        }
248
        symClose(ep->variables[vid] - EJ_OFFSET, freeVar);
249
        ep->variableMax = hFree((void***) &ep->variables, vid);
250
        return 0;
251
 
252
}
253
/******************************************************************************/
254
/*
255
 *      Create a new variable scope block and evaluate a script. All variables
256
 *      created during this context will be automatically deleted when complete.
257
 */
258
 
259
char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg)
260
{
261
        char_t* returnVal;
262
        int             vid;
263
 
264
        a_assert(script);
265
 
266
        vid = ejOpenBlock(eid);
267
        returnVal = ejEval(eid, script, emsg);
268
        ejCloseBlock(eid, vid);
269
 
270
        return returnVal;
271
}
272
 
273
/******************************************************************************/
274
/*
275
 *      Parse and evaluate a Ejscript. The caller may provide a symbol table to
276
 *      use for variables and function definitions. Return char_t pointer on
277
 *      success otherwise NULL pointer is returned.
278
 */
279
 
280
char_t *ejEval(int eid, char_t *script, char_t **emsg)
281
{
282
        ej_t    *ep;
283
        ejinput_t       *oldBlock;
284
        int             state;
285
 
286
        a_assert(script);
287
 
288
        if (emsg) {
289
                *emsg = NULL;
290
        }
291
        if ((ep = ejPtr(eid)) == NULL) {
292
                return NULL;
293
        }
294
 
295
        setString(&ep->result, T(""));
296
 
297
/*
298
 *      Allocate a new evaluation block, and save the old one
299
 */
300
        oldBlock = ep->input;
301
        ejLexOpenScript(ep, script);
302
 
303
/*
304
 *      Do the actual parsing and evaluation
305
 */
306
        do {
307
                state = parse(ep, STATE_BEGIN, FLAGS_EXE);
308
        } while (state != STATE_EOF && state != STATE_ERR);
309
 
310
        ejLexCloseScript(ep);
311
 
312
/*
313
 *      Return any error string to the user
314
 */
315
        if (state == STATE_ERR && emsg) {
316
                *emsg = bstrdup(B_L, ep->error);
317
        }
318
 
319
/*
320
 *      Restore the old evaluation block
321
 */
322
        ep->input = oldBlock;
323
 
324
        if (state == STATE_EOF) {
325
                return ep->result;
326
        }
327
        if (state == STATE_ERR) {
328
                return NULL;
329
        }
330
        return ep->result;
331
}
332
 
333
/******************************************************************************/
334
/*
335
 *      Recursive descent parser for Ejscript
336
 */
337
 
338
static int parse(ej_t *ep, int state, int flags)
339
{
340
        a_assert(ep);
341
 
342
        switch (state) {
343
/*
344
 *      Any statement, function arguments or conditional expressions
345
 */
346
        case STATE_STMT:
347
        case STATE_DEC:
348
                state = parseStmt(ep, state, flags);
349
                break;
350
 
351
        case STATE_EXPR:
352
                state = parseStmt(ep, state, flags);
353
                break;
354
 
355
/*
356
 *      Variable declaration list
357
 */
358
        case STATE_DEC_LIST:
359
                state = parseDeclaration(ep, state, flags);
360
                break;
361
 
362
/*
363
 *      Function argument string
364
 */
365
        case STATE_ARG_LIST:
366
                state = parseArgs(ep, state, flags);
367
                break;
368
 
369
/*
370
 *      Logical condition list (relational operations separated by &&, ||)
371
 */
372
        case STATE_COND:
373
                state = parseCond(ep, state, flags);
374
                break;
375
 
376
/*
377
 *      Expression list
378
 */
379
        case STATE_RELEXP:
380
                state = parseExpr(ep, state, flags);
381
                break;
382
        }
383
 
384
        if (state == STATE_ERR && ep->error == NULL) {
385
                ejError(ep, T("Syntax error"));
386
        }
387
        return state;
388
}
389
 
390
/******************************************************************************/
391
/*
392
 *      Parse any statement including functions and simple relational operations
393
 */
394
 
395
static int parseStmt(ej_t *ep, int state, int flags)
396
{
397
        ejfunc_t        func;
398
        ejfunc_t        *saveFunc;
399
        ejinput_t       condScript, endScript, bodyScript, incrScript;
400
        char_t          *value;
401
        char_t          *identifier;
402
        int                     done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags;
403
 
404
        a_assert(ep);
405
 
406
/*
407
 *      Set these to NULL, else we try to free them if an error occurs.
408
 */
409
        endScript.putBackToken = NULL;
410
        bodyScript.putBackToken = NULL;
411
        incrScript.putBackToken = NULL;
412
        condScript.putBackToken = NULL;
413
 
414
        expectSemi = 0;
415
        saveFunc = NULL;
416
 
417
        for (done = 0; !done; ) {
418
                tid = ejLexGetToken(ep, state);
419
 
420
                switch (tid) {
421
                default:
422
                        ejLexPutbackToken(ep, TOK_EXPR, ep->token);
423
                        done++;
424
                        break;
425
 
426
                case TOK_ERR:
427
                        state = STATE_ERR;
428
                        done++;
429
                        break;
430
 
431
                case TOK_EOF:
432
                        state = STATE_EOF;
433
                        done++;
434
                        break;
435
 
436
                case TOK_NEWLINE:
437
                        break;
438
 
439
                case TOK_SEMI:
440
/*
441
 *                      This case is when we discover no statement and just a lone ';'
442
 */
443
                        if (state != STATE_STMT) {
444
                                ejLexPutbackToken(ep, tid, ep->token);
445
                        }
446
                        done++;
447
                        break;
448
 
449
                case TOK_ID:
450
/*
451
 *                      This could either be a reference to a variable or an assignment
452
 */
453
                        identifier = NULL;
454
                        setString(&identifier, ep->token);
455
/*
456
 *                      Peek ahead to see if this is an assignment
457
 */
458
                        tid = ejLexGetToken(ep, state);
459
                        if (tid == TOK_ASSIGNMENT) {
460
                                if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
461
                                        goto error;
462
                                }
463
                                if (flags & FLAGS_EXE) {
464
                                        if ( state == STATE_DEC ) {
465
                                                ejSetLocalVar(ep->eid, identifier, ep->result);
466
                                        }
467
                                        else {
468
                                                if (ejGetVar(ep->eid, identifier, &value) > 0) {
469
                                                        ejSetLocalVar(ep->eid, identifier, ep->result);
470
                                                } else {
471
                                                        ejSetGlobalVar(ep->eid, identifier, ep->result);
472
                                                }
473
                                        }
474
                                }
475
 
476
                        } else if (tid == TOK_INC_DEC ) {
477
                                value = NULL;
478
                                if ( flags & FLAGS_EXE ) {
479
                                        if (ejGetVar(ep->eid, identifier, &value) < 0) {
480
                                                ejError(ep, T("Undefined variable %s\n"), identifier);
481
                                                goto error;
482
                                        }
483
                                        setString(&ep->result, value);
484
                                        if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) {
485
                                                state = STATE_ERR;
486
                                                break;
487
                                        }
488
                                        ejSetGlobalVar(ep->eid, identifier, ep->result);
489
                                }
490
 
491
                        } else {
492
/*
493
 *                              If we are processing a declaration, allow undefined vars
494
 */
495
                                value = NULL;
496
                                if (state == STATE_DEC) {
497
                                        if (ejGetVar(ep->eid, identifier, &value) > 0) {
498
                                                ejError(ep, T("Variable already declared"),
499
                                                        identifier);
500
                                                clearString(&identifier);
501
                                                goto error;
502
                                        }
503
                                        ejSetLocalVar(ep->eid, identifier, NULL);
504
                                } else {
505
                                        if ( flags & FLAGS_EXE ) {
506
                                                if (ejGetVar(ep->eid, identifier, &value) < 0) {
507
                                                        ejError(ep, T("Undefined variable %s\n"),
508
                                                                identifier);
509
                                                        clearString(&identifier);
510
                                                        goto error;
511
                                                }
512
                                        }
513
                                }
514
                                setString(&ep->result, value);
515
                                ejLexPutbackToken(ep, tid, ep->token);
516
                        }
517
                        clearString(&identifier);
518
 
519
                        if (state == STATE_STMT) {
520
                                expectSemi++;
521
                        }
522
                        done++;
523
                        break;
524
 
525
                case TOK_LITERAL:
526
/*
527
 *                      Set the result to the literal (number or string constant)
528
 */
529
                        setString(&ep->result, ep->token);
530
                        if (state == STATE_STMT) {
531
                                expectSemi++;
532
                        }
533
                        done++;
534
                        break;
535
 
536
                case TOK_FUNCTION:
537
/*
538
 *                      We must save any current ep->func value for the current stack frame
539
 */
540
                        if (ep->func) {
541
                                saveFunc = ep->func;
542
                        }
543
                        memset(&func, 0, sizeof(ejfunc_t));
544
                        setString(&func.fname, ep->token);
545
                        ep->func = &func;
546
 
547
                        setString(&ep->result, T(""));
548
                        if (ejLexGetToken(ep, state) != TOK_LPAREN) {
549
                                freeFunc(&func);
550
                                goto error;
551
                        }
552
 
553
                        if (parse(ep, STATE_ARG_LIST, flags) != STATE_ARG_LIST_DONE) {
554
                                freeFunc(&func);
555
                                ep->func = saveFunc;
556
                                goto error;
557
                        }
558
/*
559
 *                      Evaluate the function if required
560
 */
561
                        if (flags & FLAGS_EXE && evalFunction(ep) < 0) {
562
                                freeFunc(&func);
563
                                ep->func = saveFunc;
564
                                goto error;
565
                        }
566
 
567
                        freeFunc(&func);
568
                        ep->func = saveFunc;
569
 
570
                        if (ejLexGetToken(ep, state) != TOK_RPAREN) {
571
                                goto error;
572
                        }
573
                        if (state == STATE_STMT) {
574
                                expectSemi++;
575
                        }
576
                        done++;
577
                        break;
578
 
579
                case TOK_IF:
580
                        if (state != STATE_STMT) {
581
                                goto error;
582
                        }
583
                        if (ejLexGetToken(ep, state) != TOK_LPAREN) {
584
                                goto error;
585
                        }
586
/*
587
 *                      Evaluate the entire condition list "(condition)"
588
 */
589
                        if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {
590
                                goto error;
591
                        }
592
                        if (ejLexGetToken(ep, state) != TOK_RPAREN) {
593
                                goto error;
594
                        }
595
/*
596
 *                      This is the "then" case. We need to always parse both cases and
597
 *                      execute only the relevant case.
598
 */
599
                        if (*ep->result == '1') {
600
                                thenFlags = flags;
601
                                elseFlags = flags & ~FLAGS_EXE;
602
                        } else {
603
                                thenFlags = flags & ~FLAGS_EXE;
604
                                elseFlags = flags;
605
                        }
606
/*
607
 *                      Process the "then" case
608
 */
609
                        if (parse(ep, STATE_STMT, thenFlags) != STATE_STMT_DONE) {
610
                                goto error;
611
                        }
612
                        tid = ejLexGetToken(ep, state);
613
                        if (tid != TOK_ELSE) {
614
                                ejLexPutbackToken(ep, tid, ep->token);
615
                                done++;
616
                                break;
617
                        }
618
/*
619
 *                      Process the "else" case
620
 */
621
                        if (parse(ep, STATE_STMT, elseFlags) != STATE_STMT_DONE) {
622
                                goto error;
623
                        }
624
                        done++;
625
                        break;
626
 
627
                case TOK_FOR:
628
/*
629
 *                      Format for the expression is:
630
 *
631
 *                              for (initial; condition; incr) {
632
 *                                      body;
633
 *                              }
634
 */
635
                        if (state != STATE_STMT) {
636
                                goto error;
637
                        }
638
                        if (ejLexGetToken(ep, state) != TOK_LPAREN) {
639
                                goto error;
640
                        }
641
 
642
/*
643
 *                      Evaluate the for loop initialization statement
644
 */
645
                        if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) {
646
                                goto error;
647
                        }
648
                        if (ejLexGetToken(ep, state) != TOK_SEMI) {
649
                                goto error;
650
                        }
651
 
652
/*
653
 *                      The first time through, we save the current input context just
654
 *                      to each step: prior to the conditional, the loop increment and the
655
 *                      loop body.
656
 */
657
                        ejLexSaveInputState(ep, &condScript);
658
                        if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {
659
                                goto error;
660
                        }
661
                        cond = (*ep->result != '0');
662
 
663
                        if (ejLexGetToken(ep, state) != TOK_SEMI) {
664
                                goto error;
665
                        }
666
 
667
/*
668
 *                      Don't execute the loop increment statement or the body first time
669
 */
670
                        forFlags = flags & ~FLAGS_EXE;
671
                        ejLexSaveInputState(ep, &incrScript);
672
                        if (parse(ep, STATE_EXPR, forFlags) != STATE_EXPR_DONE) {
673
                                goto error;
674
                        }
675
                        if (ejLexGetToken(ep, state) != TOK_RPAREN) {
676
                                goto error;
677
                        }
678
 
679
/*
680
 *                      Parse the body and remember the end of the body script
681
 */
682
                        ejLexSaveInputState(ep, &bodyScript);
683
                        if (parse(ep, STATE_STMT, forFlags) != STATE_STMT_DONE) {
684
                                goto error;
685
                        }
686
                        ejLexSaveInputState(ep, &endScript);
687
 
688
/*
689
 *                      Now actually do the for loop. Note loop has been rotated
690
 */
691
                        while (cond && (flags & FLAGS_EXE) ) {
692
/*
693
 *                              Evaluate the body
694
 */
695
                                ejLexRestoreInputState(ep, &bodyScript);
696
                                if (parse(ep, STATE_STMT, flags) != STATE_STMT_DONE) {
697
                                        goto error;
698
                                }
699
/*
700
 *                              Evaluate the increment script
701
 */
702
                                ejLexRestoreInputState(ep, &incrScript);
703
                                if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) {
704
                                        goto error;
705
                                }
706
/*
707
 *                              Evaluate the condition
708
 */
709
                                ejLexRestoreInputState(ep, &condScript);
710
                                if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {
711
                                        goto error;
712
                                }
713
                                cond = (*ep->result != '0');
714
                        }
715
                        ejLexRestoreInputState(ep, &endScript);
716
                        done++;
717
                        break;
718
 
719
                case TOK_VAR:
720
                        if (parse(ep, STATE_DEC_LIST, flags) != STATE_DEC_LIST_DONE) {
721
                                goto error;
722
                        }
723
                        done++;
724
                        break;
725
 
726
                case TOK_COMMA:
727
                        ejLexPutbackToken(ep, TOK_EXPR, ep->token);
728
                        done++;
729
                        break;
730
 
731
                case TOK_LPAREN:
732
                        if (state == STATE_EXPR) {
733
                                if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
734
                                        goto error;
735
                                }
736
                                if (ejLexGetToken(ep, state) != TOK_RPAREN) {
737
                                        goto error;
738
                                }
739
                                return STATE_EXPR_DONE;
740
                        }
741
                        done++;
742
                        break;
743
 
744
                case TOK_RPAREN:
745
                        ejLexPutbackToken(ep, tid, ep->token);
746
                        return STATE_EXPR_DONE;
747
 
748
                case TOK_LBRACE:
749
/*
750
 *                      This handles any code in braces except "if () {} else {}"
751
 */
752
                        if (state != STATE_STMT) {
753
                                goto error;
754
                        }
755
 
756
/*
757
 *                      Parse will return STATE_STMT_BLOCK_DONE when the RBRACE is seen
758
 */
759
                        do {
760
                                state = parse(ep, STATE_STMT, flags);
761
                        } while (state == STATE_STMT_DONE);
762
 
763
                        if (ejLexGetToken(ep, state) != TOK_RBRACE) {
764
                                goto error;
765
                        }
766
                        return STATE_STMT_DONE;
767
 
768
                case TOK_RBRACE:
769
                        if (state == STATE_STMT) {
770
                                ejLexPutbackToken(ep, tid, ep->token);
771
                                return STATE_STMT_BLOCK_DONE;
772
                        }
773
                        goto error;
774
 
775
                case TOK_RETURN:
776
                        if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
777
                                goto error;
778
                        }
779
                        if (flags & FLAGS_EXE) {
780
                                while ( ejLexGetToken(ep, state) != TOK_EOF );
781
                                done++;
782
                                return STATE_EOF;
783
                        }
784
                        break;
785
                }
786
        }
787
 
788
        if (expectSemi) {
789
                tid = ejLexGetToken(ep, state);
790
                if (tid != TOK_SEMI && tid != TOK_NEWLINE) {
791
                        goto error;
792
                }
793
 
794
/*
795
 *              Skip newline after semi-colon
796
 */
797
                tid = ejLexGetToken(ep, state);
798
                if (tid != TOK_NEWLINE) {
799
                        ejLexPutbackToken(ep, tid, ep->token);
800
                }
801
        }
802
 
803
/*
804
 *      Free resources and return the correct status
805
 */
806
doneParse:
807
        if (tid == TOK_FOR) {
808
                ejLexFreeInputState(ep, &condScript);
809
                ejLexFreeInputState(ep, &incrScript);
810
                ejLexFreeInputState(ep, &endScript);
811
                ejLexFreeInputState(ep, &bodyScript);
812
        }
813
        if (state == STATE_STMT) {
814
                return STATE_STMT_DONE;
815
        } else if (state == STATE_DEC) {
816
                return STATE_DEC_DONE;
817
        } else if (state == STATE_EXPR) {
818
                return STATE_EXPR_DONE;
819
        } else if (state == STATE_EOF) {
820
                return state;
821
        } else {
822
                return STATE_ERR;
823
        }
824
 
825
/*
826
 *      Common error exit
827
 */
828
error:
829
        state = STATE_ERR;
830
        goto doneParse;
831
}
832
 
833
/******************************************************************************/
834
/*
835
 *      Parse variable declaration list
836
 */
837
 
838
static int parseDeclaration(ej_t *ep, int state, int flags)
839
{
840
        int             tid;
841
 
842
        a_assert(ep);
843
 
844
/*
845
 *      Declarations can be of the following forms:
846
 *                      var x;
847
 *                      var x, y, z;
848
 *                      var x = 1 + 2 / 3, y = 2 + 4;
849
 *
850
 *      We set the variable to NULL if there is no associated assignment.
851
 */
852
 
853
        do {
854
                if ((tid = ejLexGetToken(ep, state)) != TOK_ID) {
855
                        return STATE_ERR;
856
                }
857
                ejLexPutbackToken(ep, tid, ep->token);
858
 
859
/*
860
 *              Parse the entire assignment or simple identifier declaration
861
 */
862
                if (parse(ep, STATE_DEC, flags) != STATE_DEC_DONE) {
863
                        return STATE_ERR;
864
                }
865
 
866
/*
867
 *              Peek at the next token, continue if comma seen
868
 */
869
                tid = ejLexGetToken(ep, state);
870
                if (tid == TOK_SEMI) {
871
                        return STATE_DEC_LIST_DONE;
872
                } else if (tid != TOK_COMMA) {
873
                        return STATE_ERR;
874
                }
875
        } while (tid == TOK_COMMA);
876
 
877
        if (tid != TOK_SEMI) {
878
                return STATE_ERR;
879
        }
880
        return STATE_DEC_LIST_DONE;
881
}
882
 
883
/******************************************************************************/
884
/*
885
 *      Parse function arguments
886
 */
887
 
888
static int parseArgs(ej_t *ep, int state, int flags)
889
{
890
        int             tid, aid;
891
 
892
        a_assert(ep);
893
 
894
        do {
895
                state = parse(ep, STATE_RELEXP, flags);
896
                if (state == STATE_EOF || state == STATE_ERR) {
897
                        return state;
898
                }
899
                if (state == STATE_RELEXP_DONE) {
900
                        aid = hAlloc((void***) &ep->func->args);
901
                        ep->func->args[aid] = bstrdup(B_L, ep->result);
902
                        ep->func->nArgs++;
903
                }
904
/*
905
 *              Peek at the next token, continue if more args (ie. comma seen)
906
 */
907
                tid = ejLexGetToken(ep, state);
908
                if (tid != TOK_COMMA) {
909
                        ejLexPutbackToken(ep, tid, ep->token);
910
                }
911
        } while (tid == TOK_COMMA);
912
 
913
        if (tid != TOK_RPAREN && state != STATE_RELEXP_DONE) {
914
                return STATE_ERR;
915
        }
916
        return STATE_ARG_LIST_DONE;
917
}
918
 
919
/******************************************************************************/
920
/*
921
 *      Parse conditional expression (relational ops separated by ||, &&)
922
 */
923
 
924
static int parseCond(ej_t *ep, int state, int flags)
925
{
926
        char_t  *lhs, *rhs;
927
        int             tid, operator;
928
 
929
        a_assert(ep);
930
 
931
        setString(&ep->result, T(""));
932
        rhs = lhs = NULL;
933
        operator = 0;
934
 
935
        do {
936
/*
937
 *      Recurse to handle one side of a conditional. Accumulate the
938
 *      left hand side and the final result in ep->result.
939
 */
940
                state = parse(ep, STATE_RELEXP, flags);
941
                if (state != STATE_RELEXP_DONE) {
942
                        state = STATE_ERR;
943
                        break;
944
                }
945
                if (operator > 0) {
946
                        setString(&rhs, ep->result);
947
                        if (evalCond(ep, lhs, operator, rhs) < 0) {
948
                                state = STATE_ERR;
949
                                break;
950
                        }
951
                }
952
                setString(&lhs, ep->result);
953
 
954
                tid = ejLexGetToken(ep, state);
955
                if (tid == TOK_LOGICAL) {
956
                        operator = (int) *ep->token;
957
 
958
                } else if (tid == TOK_RPAREN || tid == TOK_SEMI) {
959
                        ejLexPutbackToken(ep, tid, ep->token);
960
                        state = STATE_COND_DONE;
961
                        break;
962
 
963
                } else {
964
                        ejLexPutbackToken(ep, tid, ep->token);
965
                }
966
 
967
        } while (state == STATE_RELEXP_DONE);
968
 
969
        if (lhs) {
970
                bfree(B_L, lhs);
971
        }
972
        if (rhs) {
973
                bfree(B_L, rhs);
974
        }
975
        return state;
976
}
977
 
978
/******************************************************************************/
979
/*
980
 *      Parse expression (leftHandSide operator rightHandSide)
981
 */
982
 
983
static int parseExpr(ej_t *ep, int state, int flags)
984
{
985
        char_t  *lhs, *rhs;
986
        int             rel, tid;
987
 
988
        a_assert(ep);
989
 
990
        setString(&ep->result, T(""));
991
        rhs = lhs = NULL;
992
        rel = 0;
993
 
994
        do {
995
/*
996
 *      This loop will handle an entire expression list. We call parse
997
 *      to evalutate each term which returns the result in ep->result.
998
 */
999
                state = parse(ep, STATE_EXPR, flags);
1000
                if (state != STATE_EXPR_DONE) {
1001
                        state = STATE_ERR;
1002
                        break;
1003
                }
1004
                if (rel > 0) {
1005
                        setString(&rhs, ep->result);
1006
                        if (evalExpr(ep, lhs, rel, rhs) < 0) {
1007
                                state = STATE_ERR;
1008
                                break;
1009
                        }
1010
                }
1011
                setString(&lhs, ep->result);
1012
 
1013
                if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR) {
1014
                        rel = (int) *ep->token;
1015
 
1016
                } else if (tid == TOK_INC_DEC) {
1017
                        rel = (int) *ep->token;
1018
 
1019
                } else {
1020
                        ejLexPutbackToken(ep, tid, ep->token);
1021
                        state = STATE_RELEXP_DONE;
1022
                }
1023
 
1024
        } while (state == STATE_EXPR_DONE);
1025
 
1026
        if (rhs)
1027
                bfree(B_L, rhs);
1028
        if (lhs)
1029
                bfree(B_L, lhs);
1030
        return state;
1031
}
1032
 
1033
/******************************************************************************/
1034
/*
1035
 *      Evaluate a condition. Implements &&, ||, !
1036
 */
1037
 
1038
static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
1039
{
1040
        char_t  buf[16];
1041
        int             l, r, lval;
1042
 
1043
        a_assert(lhs);
1044
        a_assert(rhs);
1045
        a_assert(rel > 0);
1046
 
1047
        lval = 0;
1048
        if (gisdigit(*lhs) && gisdigit(*rhs)) {
1049
                l = gatoi(lhs);
1050
                r = gatoi(rhs);
1051
                switch (rel) {
1052
                case COND_AND:
1053
                        lval = l && r;
1054
                        break;
1055
                case COND_OR:
1056
                        lval = l || r;
1057
                        break;
1058
                default:
1059
                        ejError(ep, T("Bad operator %d"), rel);
1060
                        return -1;
1061
                }
1062
        } else {
1063
                if (!gisdigit(*lhs)) {
1064
                        ejError(ep, T("Conditional must be numeric"), lhs);
1065
                } else {
1066
                        ejError(ep, T("Conditional must be numeric"), rhs);
1067
                }
1068
        }
1069
 
1070
        stritoa(lval, buf, sizeof(buf));
1071
        setString(&ep->result, buf);
1072
        return 0;
1073
}
1074
 
1075
/******************************************************************************/
1076
/*
1077
 *      Evaluate an operation
1078
 */
1079
 
1080
static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
1081
{
1082
        char_t  *cp, buf[16];
1083
        int             numeric, l, r, lval;
1084
 
1085
        a_assert(lhs);
1086
        a_assert(rhs);
1087
        a_assert(rel > 0);
1088
 
1089
/*
1090
 *      All of the characters in the lhs and rhs must be numeric
1091
 */
1092
        numeric = 1;
1093
        for (cp = lhs; *cp; cp++) {
1094
                if (!gisdigit(*cp)) {
1095
                        numeric = 0;
1096
                        break;
1097
                }
1098
        }
1099
        if (numeric) {
1100
                for (cp = rhs; *cp; cp++) {
1101
                        if (!gisdigit(*cp)) {
1102
                                numeric = 0;
1103
                                break;
1104
                        }
1105
                }
1106
        }
1107
        if (numeric) {
1108
                l = gatoi(lhs);
1109
                r = gatoi(rhs);
1110
                switch (rel) {
1111
                case EXPR_PLUS:
1112
                        lval = l + r;
1113
                        break;
1114
                case EXPR_INC:
1115
                        lval = l + 1;
1116
                        break;
1117
                case EXPR_MINUS:
1118
                        lval = l - r;
1119
                        break;
1120
                case EXPR_DEC:
1121
                        lval = l - 1;
1122
                        break;
1123
                case EXPR_MUL:
1124
                        lval = l * r;
1125
                        break;
1126
                case EXPR_DIV:
1127
                        if (r != 0) {
1128
                                lval = l / r;
1129
                        } else {
1130
                                lval = 0;
1131
                        }
1132
                        break;
1133
                case EXPR_MOD:
1134
                        if (r != 0) {
1135
                                lval = l % r;
1136
                        } else {
1137
                                lval = 0;
1138
                        }
1139
                        break;
1140
                case EXPR_LSHIFT:
1141
                        lval = l << r;
1142
                        break;
1143
                case EXPR_RSHIFT:
1144
                        lval = l >> r;
1145
                        break;
1146
                case EXPR_EQ:
1147
                        lval = l == r;
1148
                        break;
1149
                case EXPR_NOTEQ:
1150
                        lval = l != r;
1151
                        break;
1152
                case EXPR_LESS:
1153
                        lval = (l < r) ? 1 : 0;
1154
                        break;
1155
                case EXPR_LESSEQ:
1156
                        lval = (l <= r) ? 1 : 0;
1157
                        break;
1158
                case EXPR_GREATER:
1159
                        lval = (l > r) ? 1 : 0;
1160
                        break;
1161
                case EXPR_GREATEREQ:
1162
                        lval = (l >= r) ? 1 : 0;
1163
                        break;
1164
                default:
1165
                        ejError(ep, T("Bad operator %d"), rel);
1166
                        return -1;
1167
                }
1168
 
1169
        } else {
1170
                switch (rel) {
1171
                case EXPR_PLUS:
1172
                        clearString(&ep->result);
1173
                        appendString(&ep->result, lhs);
1174
                        appendString(&ep->result, rhs);
1175
                        return 0;
1176
                case EXPR_LESS:
1177
                        lval = gstrcmp(lhs, rhs) < 0;
1178
                        break;
1179
                case EXPR_LESSEQ:
1180
                        lval = gstrcmp(lhs, rhs) <= 0;
1181
                        break;
1182
                case EXPR_GREATER:
1183
                        lval = gstrcmp(lhs, rhs) > 0;
1184
                        break;
1185
                case EXPR_GREATEREQ:
1186
                        lval = gstrcmp(lhs, rhs) >= 0;
1187
                        break;
1188
                case EXPR_EQ:
1189
                        lval = gstrcmp(lhs, rhs) == 0;
1190
                        break;
1191
                case EXPR_NOTEQ:
1192
                        lval = gstrcmp(lhs, rhs) != 0;
1193
                        break;
1194
                case EXPR_INC:
1195
                case EXPR_DEC:
1196
                case EXPR_MINUS:
1197
                case EXPR_DIV:
1198
                case EXPR_MOD:
1199
                case EXPR_LSHIFT:
1200
                case EXPR_RSHIFT:
1201
                default:
1202
                        ejError(ep, T("Bad operator"));
1203
                        return -1;
1204
                }
1205
        }
1206
 
1207
        stritoa(lval, buf, sizeof(buf));
1208
        setString(&ep->result, buf);
1209
        return 0;
1210
}
1211
 
1212
/******************************************************************************/
1213
/*
1214
 *      Evaluate a function
1215
 */
1216
 
1217
static int evalFunction(ej_t *ep)
1218
{
1219
        sym_t   *sp;
1220
        int             (*fn)(int eid, void *handle, int argc, char_t **argv);
1221
 
1222
        if ((sp = symLookup(ep->functions, ep->func->fname)) == NULL) {
1223
                ejError(ep, T("Undefined procedure %s"), ep->func->fname);
1224
                return -1;
1225
        }
1226
        fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
1227
        if (fn == NULL) {
1228
                ejError(ep, T("Undefined procedure %s"), ep->func->fname);
1229
                return -1;
1230
        }
1231
 
1232
        return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
1233
                ep->func->args);
1234
}
1235
 
1236
/******************************************************************************/
1237
/*
1238
 *      Output a parse ej_error message
1239
 */
1240
 
1241
void ejError(ej_t* ep, char_t* fmt, ...)
1242
{
1243
        va_list         args;
1244
        ejinput_t       *ip;
1245
        char_t          *errbuf, *msgbuf;
1246
 
1247
        a_assert(ep);
1248
        a_assert(fmt);
1249
        ip = ep->input;
1250
 
1251
        va_start(args, fmt);
1252
        msgbuf = NULL;
1253
        gvsnprintf(&msgbuf, E_MAX_ERROR, fmt, args);
1254
        va_end(args);
1255
 
1256
        if (ep && ip) {
1257
                errbuf = NULL;
1258
                gsnprintf(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
1259
                        msgbuf, ip->lineNumber, ip->line);
1260
                bfreeSafe(B_L, ep->error);
1261
                ep->error = errbuf;
1262
        }
1263
        bfreeSafe(B_L, msgbuf);
1264
}
1265
 
1266
/******************************************************************************/
1267
/*
1268
 *      Clear a string value
1269
 */
1270
 
1271
static void clearString(char_t **ptr)
1272
{
1273
        a_assert(ptr);
1274
 
1275
        if (*ptr) {
1276
                bfree(B_L, *ptr);
1277
        }
1278
        *ptr = NULL;
1279
}
1280
 
1281
/******************************************************************************/
1282
/*
1283
 *      Set a string value
1284
 */
1285
 
1286
static void setString(char_t **ptr, char_t *s)
1287
{
1288
        a_assert(ptr);
1289
 
1290
        if (*ptr) {
1291
                bfree(B_L, *ptr);
1292
        }
1293
        *ptr = bstrdup(B_L, s);
1294
}
1295
 
1296
/******************************************************************************/
1297
/*
1298
 *      Append to the pointer value
1299
 */
1300
 
1301
static void appendString(char_t **ptr, char_t *s)
1302
{
1303
        int     len, oldlen;
1304
 
1305
        a_assert(ptr);
1306
 
1307
        if (*ptr) {
1308
                len = gstrlen(s);
1309
                oldlen = gstrlen(*ptr);
1310
                *ptr = brealloc(B_L, *ptr, (len + oldlen + 1) * sizeof(char_t));
1311
                gstrcpy(&(*ptr)[oldlen], s);
1312
        } else {
1313
                *ptr = bstrdup(B_L, s);
1314
        }
1315
}
1316
 
1317
/******************************************************************************/
1318
/*
1319
 *      Define a function
1320
 */
1321
 
1322
int ejSetGlobalFunction(int eid, char_t *name,
1323
        int (*fn)(int eid, void *handle, int argc, char_t **argv))
1324
{
1325
        ej_t    *ep;
1326
 
1327
        if ((ep = ejPtr(eid)) == NULL) {
1328
                return -1;
1329
        }
1330
        return ejSetGlobalFunctionDirect(ep->functions, name, fn);
1331
}
1332
 
1333
/******************************************************************************/
1334
/*
1335
 *      Define a function directly into the function symbol table.
1336
 */
1337
 
1338
int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
1339
        int (*fn)(int eid, void *handle, int argc, char_t **argv))
1340
{
1341
        if (symEnter(functions, name, valueInteger((long) fn), 0) == NULL) {
1342
                return -1;
1343
        }
1344
        return 0;
1345
}
1346
 
1347
/******************************************************************************/
1348
/*
1349
 *      Get a function definition
1350
 */
1351
 
1352
void *ejGetGlobalFunction(int eid, char_t *name)
1353
{
1354
        ej_t    *ep;
1355
        sym_t   *sp;
1356
        int             (*fn)(int eid, void *handle, int argc, char_t **argv);
1357
 
1358
        if ((ep = ejPtr(eid)) == NULL) {
1359
                return NULL;
1360
        }
1361
        if ((sp = symLookup(ep->functions, name)) != NULL) {
1362
                fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
1363
                return (void*) fn;
1364
        }
1365
        return NULL;
1366
}
1367
 
1368
/******************************************************************************/
1369
/*
1370
 *      Utility routine to crack Ejscript arguments. Return the number of args
1371
 *      seen. This routine only supports %s and %d type args.
1372
 *
1373
 *      Typical usage:
1374
 *
1375
 *              if (ejArgs(argc, argv, "%s %d", &name, &age) < 2) {
1376
 *                      error("Insufficient args\n");
1377
 *                      return -1;
1378
 *              }
1379
 */
1380
 
1381
int ejArgs(int argc, char_t **argv, char_t *fmt, ...)
1382
{
1383
        va_list vargs;
1384
        char_t  *cp, **sp;
1385
        int             *ip;
1386
        int             argn;
1387
 
1388
        va_start(vargs, fmt);
1389
 
1390
        if (argv == NULL) {
1391
                return 0;
1392
        }
1393
 
1394
        for (argn = 0, cp = fmt; cp && *cp && argv[argn]; ) {
1395
                if (*cp++ != '%') {
1396
                        continue;
1397
                }
1398
 
1399
                switch (*cp) {
1400
                case 'd':
1401
                        ip = va_arg(vargs, int*);
1402
                        *ip = gatoi(argv[argn]);
1403
                        break;
1404
 
1405
                case 's':
1406
                        sp = va_arg(vargs, char_t**);
1407
                        *sp = argv[argn];
1408
                        break;
1409
 
1410
                default:
1411
/*
1412
 *                      Unsupported
1413
 */
1414
                        a_assert(0);
1415
                }
1416
                argn++;
1417
        }
1418
 
1419
        va_end(vargs);
1420
        return argn;
1421
}
1422
 
1423
/******************************************************************************/
1424
/*
1425
 *      Define the user handle
1426
 */
1427
 
1428
void ejSetUserHandle(int eid, int handle)
1429
{
1430
        ej_t    *ep;
1431
 
1432
        if ((ep = ejPtr(eid)) == NULL) {
1433
                return;
1434
        }
1435
        ep->userHandle = handle;
1436
}
1437
 
1438
/******************************************************************************/
1439
/*
1440
 *      Get the user handle
1441
 */
1442
 
1443
int ejGetUserHandle(int eid)
1444
{
1445
        ej_t    *ep;
1446
 
1447
        if ((ep = ejPtr(eid)) == NULL) {
1448
                return -1;
1449
        }
1450
        return ep->userHandle;
1451
}
1452
 
1453
/******************************************************************************/
1454
/*
1455
 *      Get the current line number
1456
 */
1457
 
1458
int ejGetLineNumber(int eid)
1459
{
1460
        ej_t    *ep;
1461
 
1462
        if ((ep = ejPtr(eid)) == NULL) {
1463
                return -1;
1464
        }
1465
        return ep->input->lineNumber;
1466
}
1467
 
1468
/******************************************************************************/
1469
/*
1470
 *      Set the result
1471
 */
1472
 
1473
void ejSetResult(int eid, char_t *s)
1474
{
1475
        ej_t    *ep;
1476
 
1477
        if ((ep = ejPtr(eid)) == NULL) {
1478
                return;
1479
        }
1480
        setString(&ep->result, s);
1481
}
1482
 
1483
/******************************************************************************/
1484
/*
1485
 *      Get the result
1486
 */
1487
 
1488
char_t *ejGetResult(int eid)
1489
{
1490
        ej_t    *ep;
1491
 
1492
        if ((ep = ejPtr(eid)) == NULL) {
1493
                return NULL;
1494
        }
1495
        return ep->result;
1496
}
1497
 
1498
/******************************************************************************/
1499
/*
1500
 *      Set a variable. Note: a variable with a value of NULL means declared but
1501
 *      undefined. The value is defined in the top-most variable frame.
1502
 */
1503
 
1504
void ejSetVar(int eid, char_t *var, char_t *value)
1505
{
1506
        ej_t    *ep;
1507
        value_t v;
1508
 
1509
        a_assert(var && *var);
1510
 
1511
        if ((ep = ejPtr(eid)) == NULL) {
1512
                return;
1513
        }
1514
        if (value == NULL) {
1515
                v = valueString(value, 0);
1516
        } else {
1517
                v = valueString(value, VALUE_ALLOCATE);
1518
        }
1519
        symEnter(ep->variables[ep->variableMax - 1] - EJ_OFFSET, var, v, 0);
1520
}
1521
 
1522
/******************************************************************************/
1523
/*
1524
 *      Set a local variable. Note: a variable with a value of NULL means
1525
 *      declared but undefined. The value is defined in the top-most variable frame.
1526
 */
1527
 
1528
void ejSetLocalVar(int eid, char_t *var, char_t *value)
1529
{
1530
        ej_t    *ep;
1531
        value_t v;
1532
 
1533
        a_assert(var && *var);
1534
 
1535
        if ((ep = ejPtr(eid)) == NULL) {
1536
                return;
1537
        }
1538
        if (value == NULL) {
1539
                v = valueString(value, 0);
1540
        } else {
1541
                v = valueString(value, VALUE_ALLOCATE);
1542
        }
1543
        symEnter(ep->variables[ep->variableMax - 1] - EJ_OFFSET, var, v, 0);
1544
}
1545
 
1546
/******************************************************************************/
1547
/*
1548
 *      Set a global variable. Note: a variable with a value of NULL means
1549
 *      declared but undefined. The value is defined in the global variable frame.
1550
 */
1551
 
1552
void ejSetGlobalVar(int eid, char_t *var, char_t *value)
1553
{
1554
        ej_t    *ep;
1555
        value_t v;
1556
 
1557
        a_assert(var && *var);
1558
 
1559
        if ((ep = ejPtr(eid)) == NULL) {
1560
                return;
1561
        }
1562
        if (value == NULL) {
1563
                v = valueString(value, 0);
1564
        } else {
1565
                v = valueString(value, VALUE_ALLOCATE);
1566
        }
1567
        symEnter(ep->variables[0] - EJ_OFFSET, var, v, 0);
1568
}
1569
 
1570
/******************************************************************************/
1571
/*
1572
 *      Get a variable
1573
 */
1574
 
1575
int ejGetVar(int eid, char_t *var, char_t **value)
1576
{
1577
        ej_t    *ep;
1578
        sym_t   *sp;
1579
        int             i;
1580
 
1581
        a_assert(var && *var);
1582
        a_assert(value);
1583
 
1584
        if ((ep = ejPtr(eid)) == NULL) {
1585
                return -1;
1586
        }
1587
 
1588
        for (i = ep->variableMax - 1; i >= 0; i--) {
1589
                if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
1590
                        continue;
1591
                }
1592
                a_assert(sp->content.type == string);
1593
                *value = sp->content.value.string;
1594
                return i;
1595
        }
1596
        return -1;
1597
}
1598
 
1599
/******************************************************************************/
1600
#if UNUSED
1601
/*
1602
 *      Get the variable symbol table
1603
 */
1604
 
1605
sym_fd_t ejGetVariableTable(int eid)
1606
{
1607
        ej_t    *ep;
1608
 
1609
        if ((ep = ejPtr(eid)) == NULL) {
1610
                return -1;
1611
        }
1612
        return ep->variables;
1613
}
1614
#endif
1615
/******************************************************************************/
1616
/*
1617
 *      Get the functions symbol table
1618
 */
1619
 
1620
sym_fd_t ejGetFunctionTable(int eid)
1621
{
1622
        ej_t    *ep;
1623
 
1624
        if ((ep = ejPtr(eid)) == NULL) {
1625
                return -1;
1626
        }
1627
        return ep->functions;
1628
}
1629
 
1630
/******************************************************************************/
1631
/*
1632
 *      Free an argument list
1633
 */
1634
 
1635
static void freeFunc(ejfunc_t *func)
1636
{
1637
        int     i;
1638
 
1639
        for (i = func->nArgs - 1; i >= 0; i--) {
1640
                bfree(B_L, func->args[i]);
1641
                func->nArgs = hFree((void***) &func->args, i);
1642
        }
1643
        if (func->fname) {
1644
                bfree(B_L, func->fname);
1645
                func->fname = NULL;
1646
        }
1647
}
1648
 
1649
/******************************************************************************/
1650
/*
1651
 *      Get Ejscript pointer
1652
 */
1653
 
1654
static ej_t *ejPtr(int eid)
1655
{
1656
        a_assert(0 <= eid && eid < ejMax);
1657
 
1658
        if (eid < 0 || eid >= ejMax || ejHandles[eid] == NULL) {
1659
                ejError(NULL, T("Bad handle %d"), eid);
1660
                return NULL;
1661
        }
1662
        return ejHandles[eid];
1663
}
1664
 
1665
/******************************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.