1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
32
33 #include "interpret.h"
34 #include "textBuf.h"
35 #include "nedit.h"
36 #include "menu.h"
37 #include "text.h"
38 #include "../util/rbTree.h"
39 #include "../util/nedit_malloc.h"
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <math.h>
45 #include <limits.h>
46 #include <ctype.h>
47 #include <errno.h>
48
49 #ifndef __MVS__
50 #include <sys/param.h>
51 #endif
52
53
54 #include <X11/Intrinsic.h>
55 #include <Xm/Xm.h>
56
57 #include "window.h"
58
59 #ifdef HAVE_DEBUG_H
60 #include "../debug.h"
61 #endif
62
63 #define PROGRAM_SIZE 4096
64 #define MAX_ERR_MSG_LEN 256
65 #define LOOP_STACK_SIZE 200
66
67 #define INSTRUCTION_LIMIT 100
68
69
70
71
72
73 #define NEEDS_BREAK 1
74 #define NEEDS_CONTINUE 2
75
76 #define N_ARGS_ARG_SYM -
1
77
78 enum opStatusCodes {
STAT_OK=
2,
STAT_DONE,
STAT_ERROR,
STAT_PREEMPT};
79
80 static void addLoopAddr(Inst *addr);
81 static void saveContext(RestartData *context);
82 static void restoreContext(RestartData *context);
83 static int returnNoVal(
void);
84 static int returnVal(
void);
85 static int returnValOrNone(
int valOnStack);
86 static int pushSymVal(
void);
87 static int pushArgVal(
void);
88 static int pushArgCount(
void);
89 static int pushArgArray(
void);
90 static int pushArraySymVal(
void);
91 static int dupStack(
void);
92 static int add(
void);
93 static int subtract(
void);
94 static int multiply(
void);
95 static int divide(
void);
96 static int modulo(
void);
97 static int negate(
void);
98 static int increment(
void);
99 static int decrement(
void);
100 static int gt(
void);
101 static int lt(
void);
102 static int ge(
void);
103 static int le(
void);
104 static int eq(
void);
105 static int ne(
void);
106 static int bitAnd(
void);
107 static int bitOr(
void);
108 static int and(
void);
109 static int or(
void);
110 static int not(
void);
111 static int power(
void);
112 static int concat(
void);
113 static int assign(
void);
114 static int callSubroutine(
void);
115 static int fetchRetVal(
void);
116 static int branch(
void);
117 static int branchTrue(
void);
118 static int branchFalse(
void);
119 static int branchNever(
void);
120 static int arrayRef(
void);
121 static int arrayAssign(
void);
122 static int arrayRefAndAssignSetup(
void);
123 static int beginArrayIter(
void);
124 static int arrayIter(
void);
125 static int inArray(
void);
126 static int deleteArrayElement(
void);
127 static void freeSymbolTable(Symbol *symTab);
128 static int errCheck(
const char *s);
129 static int execError(
const char *s1,
const char *s2);
130 static rbTreeNode *arrayEmptyAllocator(
void);
131 static rbTreeNode *arrayAllocateNode(rbTreeNode *src);
132 static int arrayEntryCopyToNode(rbTreeNode *dst, rbTreeNode *src);
133 static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right);
134 static void arrayDisposeNode(rbTreeNode *src);
135 static SparseArrayEntry *allocateSparseArrayEntry(
void);
136
137
138
139
140 #if defined(
DEBUG_ASSEMBLY) || defined(
DEBUG_STACK)
141 #define DEBUG_DISASSEMBLER
142 static void disasm(Inst *inst,
int nInstr);
143 #endif
144
145 #ifdef DEBUG_ASSEMBLY
146 #define DISASM(i, n) disasm(i, n)
147 #else
148 #define DISASM(i, n)
149 #endif
150
151 #ifdef DEBUG_STACK
152 static void stackdump(
int n,
int extra);
153 #define STACKDUMP(n, x) stackdump(n, x)
154 #define DISASM_RT(i, n) disasm(i, n)
155 #else
156 #define STACKDUMP(n, x)
157 #define DISASM_RT(i, n)
158 #endif
159
160
161 static Symbol *GlobalSymList =
NULL;
162
163
164 static char *AllocatedStrings =
NULL;
165
166 typedef struct SparseArrayEntryWrapperTag {
167 SparseArrayEntry data;
168 int inUse;
169 struct SparseArrayEntryWrapperTag *next;
170 } SparseArrayEntryWrapper;
171
172 static SparseArrayEntryWrapper *AllocatedSparseArrayEntries =
NULL;
173
174
175
176 static const char *StackOverflowMsg =
"macro stack overflow";
177 static const char *StackUnderflowMsg =
"macro stack underflow";
178 static const char *StringToNumberMsg =
"string could not be converted to number";
179
180
181 static Symbol *LocalSymList =
NULL;
182 static Inst Prog[
PROGRAM_SIZE];
183 static Inst *ProgP;
184 static Inst *LoopStack[
LOOP_STACK_SIZE];
185 static Inst **LoopStackPtr = LoopStack;
186
187
188 static DataValue *TheStack;
189 static DataValue *StackP;
190 static DataValue *FrameP;
191
192 static Inst *
PC;
193 static char *ErrMsg;
194
195 static WindowInfo
196 *InitiatingWindow =
NULL;
197 static WindowInfo *FocusWindow;
198 static int PreemptRequest;
199
200
201
202
203 static int (*OpFns[
N_OPS])() = {returnNoVal, returnVal, pushSymVal, dupStack,
204 add, subtract, multiply, divide, modulo, negate, increment, decrement,
205 gt, lt, ge, le, eq, ne, bitAnd, bitOr, and, or, not, power, concat,
206 assign, callSubroutine, fetchRetVal, branch, branchTrue, branchFalse,
207 branchNever, arrayRef, arrayAssign, beginArrayIter, arrayIter, inArray,
208 deleteArrayElement, pushArraySymVal,
209 arrayRefAndAssignSetup, pushArgVal, pushArgCount, pushArgArray};
210
211
212 #define FP_ARG_ARRAY_CACHE_INDEX (-
1)
213 #define FP_ARG_COUNT_INDEX (-
2)
214 #define FP_OLD_FP_INDEX (-
3)
215 #define FP_RET_PC_INDEX (-
4)
216 #define FP_TO_ARGS_DIST (
4)
217 #define FP_GET_ITEM(xFrameP,xIndex) (*(xFrameP + xIndex))
218 #define FP_GET_ARG_ARRAY_CACHE(xFrameP) (
FP_GET_ITEM(xFrameP,
FP_ARG_ARRAY_CACHE_INDEX))
219 #define FP_GET_ARG_COUNT(xFrameP) (
FP_GET_ITEM(xFrameP,
FP_ARG_COUNT_INDEX).val.n)
220 #define FP_GET_OLD_FP(xFrameP) ((
FP_GET_ITEM(xFrameP,
FP_OLD_FP_INDEX)).val.dataval)
221 #define FP_GET_RET_PC(xFrameP) ((
FP_GET_ITEM(xFrameP,
FP_RET_PC_INDEX)).val.inst)
222 #define FP_ARG_START_INDEX(xFrameP) (-(
FP_GET_ARG_COUNT(xFrameP) +
FP_TO_ARGS_DIST))
223 #define FP_GET_ARG_N(xFrameP,xN) (
FP_GET_ITEM(xFrameP, xN +
FP_ARG_START_INDEX(xFrameP)))
224 #define FP_GET_SYM_N(xFrameP,xN) (
FP_GET_ITEM(xFrameP, xN))
225 #define FP_GET_SYM_VAL(xFrameP,xSym) (
FP_GET_SYM_N(xFrameP, xSym->value.val.n))
226
227
228
229
230
231
232 void InitMacroGlobals(
void)
233 {
234 XtActionsRec *actions;
235 int i, nActions;
236 static char argName[
3] =
"$x";
237 static DataValue dv = {
NO_TAG, {
0}};
238
239
240 actions = GetMenuActions(&nActions);
241 for (i=
0; i<nActions; i++) {
242 dv.val.xtproc = actions[i].proc;
243 InstallSymbol(actions[i].string,
ACTION_ROUTINE_SYM, dv);
244 }
245 actions = TextGetActions(&nActions);
246 for (i=
0; i<nActions; i++) {
247 dv.val.xtproc = actions[i].proc;
248 InstallSymbol(actions[i].string,
ACTION_ROUTINE_SYM, dv);
249 }
250
251
252 for (i=
0; i<
9; i++) {
253 argName[
1] =
'1' + i;
254 dv.val.n = i;
255 InstallSymbol(argName,
ARG_SYM, dv);
256 }
257
258
259 dv.val.n =
N_ARGS_ARG_SYM;
260 InstallSymbol(
"$n_args",
ARG_SYM, dv);
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275 void BeginCreatingProgram(
void)
276 {
277 LocalSymList =
NULL;
278 ProgP = Prog;
279 LoopStackPtr = LoopStack;
280 }
281
282
283
284
285
286
287 Program *FinishCreatingProgram(
void)
288 {
289 Program *newProg;
290 int progLen, fpOffset =
0;
291 Symbol *s;
292
293 newProg = (Program *)NEditMalloc(
sizeof(Program));
294 progLen = ((
char *)ProgP) - ((
char *)Prog);
295 newProg->code = (Inst *)NEditMalloc(progLen);
296 memcpy(newProg->code, Prog, progLen);
297 newProg->localSymList = LocalSymList;
298 LocalSymList =
NULL;
299
300
301
302 for (s = newProg->localSymList; s !=
NULL; s = s->next)
303 s->value.val.n = fpOffset++;
304
305 DISASM(newProg->code, ProgP - Prog);
306
307 return newProg;
308 }
309
310 void FreeProgram(Program *prog)
311 {
312 freeSymbolTable(prog->localSymList);
313 NEditFree(prog->code);
314 NEditFree(prog);
315 }
316
317
318
319
320 int AddOp(
int op,
char **msg)
321 {
322 if (ProgP >= &Prog[
PROGRAM_SIZE]) {
323 *msg =
"macro too large";
324 return 0;
325 }
326 ProgP->func = OpFns[op];
327 ProgP++;
328 return 1;
329 }
330
331
332
333
334 int AddSym(Symbol *sym,
char **msg)
335 {
336 if (ProgP >= &Prog[
PROGRAM_SIZE]) {
337 *msg =
"macro too large";
338 return 0;
339 }
340 ProgP->sym = sym;
341 ProgP++;
342 return 1;
343 }
344
345
346
347
348 int AddImmediate(
int value,
char **msg)
349 {
350 if (ProgP >= &Prog[
PROGRAM_SIZE]) {
351 *msg =
"macro too large";
352 return 0;
353 }
354 ProgP->value = value;
355 ProgP++;
356 return 1;
357 }
358
359
360
361
362 int AddBranchOffset(Inst *to,
char **msg)
363 {
364 if (ProgP >= &Prog[
PROGRAM_SIZE]) {
365 *msg =
"macro too large";
366 return 0;
367 }
368
369 ProgP->value = to - ProgP;
370 ProgP++;
371
372 return 1;
373 }
374
375
376
377
378 Inst *GetPC(
void)
379 {
380 return ProgP;
381 }
382
383
384
385
386
387
388 void SwapCode(Inst *start, Inst *boundary, Inst *end)
389 {
390 #define reverseCode(
L,
H) \
391 do {
register Inst t, *l =
L, *h =
H -
1; \
392 while (l < h) { t = *h; *h-- = *l; *l++ = t; } }
while (
0)
393
394
395 reverseCode(start, boundary);
396 reverseCode(boundary, end);
397 reverseCode(start, end);
398 }
399
400
401
402
403
404
405
406
407
408
409
410 void StartLoopAddrList(
void)
411 {
412 addLoopAddr(
NULL);
413 }
414
415 int AddBreakAddr(Inst *addr)
416 {
417 if (LoopStackPtr == LoopStack)
return 1;
418 addLoopAddr(addr);
419 addr->value =
NEEDS_BREAK;
420 return 0;
421 }
422
423 int AddContinueAddr(Inst *addr)
424 {
425 if (LoopStackPtr == LoopStack)
return 1;
426 addLoopAddr(addr);
427 addr->value =
NEEDS_CONTINUE;
428 return 0;
429 }
430
431 static void addLoopAddr(Inst *addr)
432 {
433 if (LoopStackPtr > &LoopStack[
LOOP_STACK_SIZE-
1]) {
434 fprintf(stderr,
"NEdit: loop stack overflow in macro parser");
435 return;
436 }
437 *LoopStackPtr++ = addr;
438 }
439
440 void FillLoopAddrs(Inst *breakAddr, Inst *continueAddr)
441 {
442 while (True) {
443 LoopStackPtr--;
444 if (LoopStackPtr < LoopStack) {
445 fprintf(stderr,
"NEdit: internal error (lsu) in macro parser\n");
446 return;
447 }
448 if (*LoopStackPtr ==
NULL)
449 break;
450 if ((*LoopStackPtr)->value ==
NEEDS_BREAK)
451 (*LoopStackPtr)->value = breakAddr - *LoopStackPtr;
452 else if ((*LoopStackPtr)->value ==
NEEDS_CONTINUE)
453 (*LoopStackPtr)->value = continueAddr - *LoopStackPtr;
454 else
455 fprintf(stderr,
"NEdit: internal error (uat) in macro parser\n");
456 }
457 }
458
459
460
461
462
463
464
465
466 int ExecuteMacro(WindowInfo *window, Program *prog,
int nArgs, DataValue *args,
467 DataValue *result, RestartData **continuation,
char **msg)
468 {
469 RestartData *context;
470 static DataValue noValue = {
NO_TAG, {
0}};
471 Symbol *s;
472 int i;
473
474
475
476
477 context = (RestartData *)NEditMalloc(
sizeof(RestartData));
478 context->stack = (DataValue *)NEditMalloc(
sizeof(DataValue) *
STACK_SIZE);
479 *continuation = context;
480 context->stackP = context->stack;
481 context->pc = prog->code;
482 context->runWindow = window;
483 context->focusWindow = window;
484
485
486 for (i=
0; i<nArgs; i++)
487 *(context->stackP++) = args[i];
488
489 context->stackP->val.subr =
NULL;
490 context->stackP->tag =
NO_TAG;
491 context->stackP++;
492
493 *(context->stackP++) = noValue;
494
495 context->stackP->tag =
NO_TAG;
496 context->stackP->val.n = nArgs;
497 context->stackP++;
498
499 *(context->stackP++) = noValue;
500
501 context->frameP = context->stackP;
502
503
504 for (s = prog->localSymList; s !=
NULL; s = s->next) {
505 FP_GET_SYM_VAL(context->frameP, s) = noValue;
506 context->stackP++;
507 }
508
509
510 return ContinueMacro(context, result, msg);
511 }
512
513
514
515
516
517 int ContinueMacro(RestartData *continuation, DataValue *result,
char **msg)
518 {
519 register int status, instCount =
0;
520 register Inst *inst;
521 RestartData oldContext;
522
523
524
525
526 saveContext(&oldContext);
527
528
529
530
531
532 restoreContext(continuation);
533 ErrMsg =
NULL;
534 for (;;) {
535
536
537 inst =
PC++;
538 status = (inst->func)();
539
540
541 if (status !=
STAT_OK) {
542 if (status ==
STAT_PREEMPT) {
543 saveContext(continuation);
544 restoreContext(&oldContext);
545 return MACRO_PREEMPT;
546 }
else if (status ==
STAT_ERROR) {
547 *msg = ErrMsg;
548 FreeRestartData(continuation);
549 restoreContext(&oldContext);
550 return MACRO_ERROR;
551 }
else if (status ==
STAT_DONE) {
552 *msg =
"";
553 *result = *--StackP;
554 FreeRestartData(continuation);
555 restoreContext(&oldContext);
556 return MACRO_DONE;
557 }
558 }
559
560
561
562
563 instCount++;
564 if (instCount >=
INSTRUCTION_LIMIT) {
565 saveContext(continuation);
566 restoreContext(&oldContext);
567 return MACRO_TIME_LIMIT;
568 }
569 }
570 }
571
572
573
574
575
576
577
578
579 void RunMacroAsSubrCall(Program *prog)
580 {
581 Symbol *s;
582 static DataValue noValue = {
NO_TAG, {
0}};
583
584
585
586 StackP->tag =
NO_TAG;
587 StackP->val.inst =
PC;
588 StackP++;
589
590 StackP->tag =
NO_TAG;
591 StackP->val.dataval = FrameP;
592 StackP++;
593
594 StackP->tag =
NO_TAG;
595 StackP->val.n =
0;
596 StackP++;
597
598 *(StackP++) = noValue;
599
600 FrameP = StackP;
601 PC = prog->code;
602 for (s = prog->localSymList; s !=
NULL; s = s->next) {
603 FP_GET_SYM_VAL(FrameP, s) = noValue;
604 StackP++;
605 }
606 }
607
608 void FreeRestartData(RestartData *context)
609 {
610 NEditFree(context->stack);
611 NEditFree(context);
612 }
613
614
615
616
617
618
619 void PreemptMacro(
void)
620 {
621 PreemptRequest = True;
622 }
623
624
625
626
627
628
629 void ModifyReturnedValue(RestartData *context, DataValue dv)
630 {
631 if ((context->pc-
1)->func == fetchRetVal)
632 *(context->stackP-
1) = dv;
633 }
634
635
636
637
638
639 WindowInfo *MacroRunWindow(
void)
640 {
641 return InitiatingWindow;
642 }
643
644
645
646
647
648
649 WindowInfo *MacroFocusWindow(
void)
650 {
651 return FocusWindow;
652 }
653
654
655
656
657
658 void SetMacroFocusWindow(WindowInfo *window)
659 {
660 FocusWindow = window;
661 }
662
663
664
665
666
667 #define ARRAY_ITER_SYM_PREFIX "aryiter "
668 Symbol *InstallIteratorSymbol(
void)
669 {
670 char symbolName[
sizeof(
ARRAY_ITER_SYM_PREFIX) +
TYPE_INT_STR_SIZE(
int)];
671 DataValue value;
672 static int interatorNameIndex =
0;
673
674 sprintf(symbolName,
ARRAY_ITER_SYM_PREFIX "#%d", interatorNameIndex);
675 ++interatorNameIndex;
676 value.tag =
INT_TAG;
677 value.val.arrayPtr =
NULL;
678 return(InstallSymbol(symbolName,
LOCAL_SYM, value));
679 }
680
681
682
683
684
685 Symbol *LookupStringConstSymbol(
const char *value)
686 {
687 Symbol *s;
688
689 for (s = GlobalSymList; s !=
NULL; s = s->next) {
690 if (s->type ==
CONST_SYM &&
691 s->value.tag ==
STRING_TAG &&
692 !strcmp(s->value.val.str.rep, value)) {
693 return(s);
694 }
695 }
696 return(
NULL);
697 }
698
699
700
701
702 Symbol *InstallStringConstSymbol(
const char *str)
703 {
704 static int stringConstIndex =
0;
705 char stringName[
35];
706 DataValue value;
707 Symbol *sym = LookupStringConstSymbol(str);
708 if (sym) {
709 return sym;
710 }
711
712 sprintf(stringName,
"string #%d", stringConstIndex++);
713 value.tag =
STRING_TAG;
714 AllocNStringCpy(&value.val.str, str);
715 return(InstallSymbol(stringName,
CONST_SYM, value));
716 }
717
718
719
720
721 Symbol *LookupSymbol(
const char *name)
722 {
723 Symbol *s;
724
725 for (s = LocalSymList; s !=
NULL; s = s->next)
726 if (strcmp(s->name, name) ==
0)
727 return s;
728 for (s = GlobalSymList; s !=
NULL; s = s->next)
729 if (strcmp(s->name, name) ==
0)
730 return s;
731 return NULL;
732 }
733
734
735
736
737 Symbol *InstallSymbol(
const char *name,
enum symTypes type, DataValue value)
738 {
739 Symbol *s;
740
741 s = (Symbol *)NEditMalloc(
sizeof(Symbol));
742 s->name = NEditStrdup(name);
743 s->type = type;
744 s->value = value;
745 if (type ==
LOCAL_SYM) {
746 s->next = LocalSymList;
747 LocalSymList = s;
748 }
else {
749 s->next = GlobalSymList;
750 GlobalSymList = s;
751 }
752 return s;
753 }
754
755
756
757
758
759
760
761
762
763
764
765 Symbol *PromoteToGlobal(Symbol *sym)
766 {
767 Symbol *s;
768
769 if (sym->type !=
LOCAL_SYM)
770 return sym;
771
772
773 if (sym == LocalSymList)
774 LocalSymList = sym->next;
775 else {
776 for (s = LocalSymList; s !=
NULL; s = s->next) {
777 if (s->next == sym) {
778 s->next = sym->next;
779 break;
780 }
781 }
782 }
783
784
785
786
787
788
789
790 s = LookupSymbol(sym->name);
791 if (sym == s) {
792
793
794 fprintf(stderr,
795 "xnedit: To boldly go where no local sym has gone before: %s\n",
796 sym->name);
797 sym->type =
GLOBAL_SYM;
798 return sym;
799 }
else if (
NULL != s) {
800
801
802 fprintf(stderr,
803 "xnedit: duplicate symbol in LocalSymList and GlobalSymList: %s\n",
804 sym->name);
805 }
806
807
808
809
810
811
812
813 sym->type =
GLOBAL_SYM;
814 sym->next = GlobalSymList;
815 GlobalSymList = sym;
816
817 return sym;
818 }
819
820
821
822
823
824
825
826
827
828
829
830 #ifdef TRACK_GARBAGE_LEAKS
831 static int numAllocatedStrings =
0;
832 static int numAllocatedSparseArrayElements =
0;
833 #endif
834
835
836 char *AllocString(
int length)
837 {
838 char *mem;
839
840 mem = (
char*)NEditMalloc(length +
sizeof(
char *) +
1);
841 *((
char **)mem) = AllocatedStrings;
842 AllocatedStrings = mem;
843 #ifdef TRACK_GARBAGE_LEAKS
844 ++numAllocatedStrings;
845 #endif
846 return mem +
sizeof(
char *) +
1;
847 }
848
849
850
851
852
853
854 int AllocNString(NString *string,
int length)
855 {
856 char *mem;
857
858 mem = (
char*)NEditMalloc(length +
sizeof(
char *) +
1);
859 if (!mem) {
860 string->rep =
0;
861 string->len =
0;
862 return False;
863 }
864
865 *((
char **)mem) = AllocatedStrings;
866 AllocatedStrings = mem;
867 #ifdef TRACK_GARBAGE_LEAKS
868 ++numAllocatedStrings;
869 #endif
870 string->rep = mem +
sizeof(
char *) +
1;
871 string->rep[length-
1] =
'\0';
872 string->len = length-
1;
873 return True;
874 }
875
876
877 char *AllocStringNCpy(
const char *s,
int length)
878 {
879 char *p = AllocString(length +
1);
880 if (!p)
881 return p;
882 if (!s)
883 s =
"";
884 p[length] =
'\0';
885 return strncpy(p, s, length);
886 }
887
888
889
890
891
892
893
894 int AllocNStringNCpy(NString *string,
const char *s,
int length)
895 {
896 if (!AllocNString(string, length +
1))
897 return False;
898 if (!s)
899 s =
"";
900 strncpy(string->rep, s, length);
901 string->len = strlen(string->rep);
902 return True;
903 }
904
905
906 char *AllocStringCpy(
const char *s)
907 {
908 return AllocStringNCpy(s, s ? strlen(s) :
0);
909 }
910
911
912
913
914
915
916 int AllocNStringCpy(NString *string,
const char *s)
917 {
918 size_t length = s ? strlen(s) :
0;
919 if (!AllocNString(string, length +
1))
920 return False;
921 if (s)
922 strncpy(string->rep, s, length);
923 return True;
924 }
925
926 static SparseArrayEntry *allocateSparseArrayEntry(
void)
927 {
928 SparseArrayEntryWrapper *mem;
929
930 mem = (SparseArrayEntryWrapper *)NEditMalloc(
sizeof(SparseArrayEntryWrapper));
931 mem->next = AllocatedSparseArrayEntries;
932 AllocatedSparseArrayEntries = mem;
933 #ifdef TRACK_GARBAGE_LEAKS
934 ++numAllocatedSparseArrayElements;
935 #endif
936 return(&(mem->data));
937 }
938
939 static void MarkArrayContentsAsUsed(SparseArrayEntry *arrayPtr)
940 {
941 SparseArrayEntry *globalSEUse;
942
943 if (arrayPtr) {
944 ((SparseArrayEntryWrapper *)arrayPtr)->inUse =
1;
945 for (globalSEUse = (SparseArrayEntry *)rbTreeBegin((rbTreeNode *)arrayPtr);
946 globalSEUse !=
NULL;
947 globalSEUse = (SparseArrayEntry *)rbTreeNext((rbTreeNode *)globalSEUse)) {
948
949 ((SparseArrayEntryWrapper *)globalSEUse)->inUse =
1;
950
951 if (!(*(globalSEUse->key -
1))) {
952 *(globalSEUse->key -
1) =
1;
953 }
954 if (globalSEUse->value.tag ==
STRING_TAG) {
955
956 if (!(*(globalSEUse->value.val.str.rep -
1))) {
957 *(globalSEUse->value.val.str.rep -
1) =
1;
958 }
959 }
960 else if (globalSEUse->value.tag ==
ARRAY_TAG) {
961 MarkArrayContentsAsUsed(globalSEUse->value.val.arrayPtr);
962 }
963 }
964 }
965 }
966
967
968
969
970
971
972
973 void GarbageCollectStrings(
void)
974 {
975 SparseArrayEntryWrapper *nextAP, *thisAP;
976 char *p, *next;
977 Symbol *s;
978
979
980 for (p = AllocatedStrings; p !=
NULL; p = *((
char **)p)) {
981 *(p +
sizeof(
char *)) =
0;
982 }
983
984 for (thisAP = AllocatedSparseArrayEntries;
985 thisAP !=
NULL; thisAP = thisAP->next) {
986 thisAP->inUse =
0;
987 }
988
989
990
991 for (s = GlobalSymList; s !=
NULL; s = s->next) {
992 if (s->value.tag ==
STRING_TAG) {
993
994 if (!(*(s->value.val.str.rep -
1))) {
995 *(s->value.val.str.rep -
1) =
1;
996 }
997 }
998 else if (s->value.tag ==
ARRAY_TAG) {
999 MarkArrayContentsAsUsed(s->value.val.arrayPtr);
1000 }
1001 }
1002
1003
1004 next = AllocatedStrings;
1005 AllocatedStrings =
NULL;
1006 while (next !=
NULL) {
1007 p = next;
1008 next = *((
char **)p);
1009 if (*(p +
sizeof(
char *)) !=
0) {
1010 *((
char **)p) = AllocatedStrings;
1011 AllocatedStrings = p;
1012 }
1013 else {
1014 #ifdef TRACK_GARBAGE_LEAKS
1015 --numAllocatedStrings;
1016 #endif
1017 NEditFree(p);
1018 }
1019 }
1020
1021 nextAP = AllocatedSparseArrayEntries;
1022 AllocatedSparseArrayEntries =
NULL;
1023 while (nextAP !=
NULL) {
1024 thisAP = nextAP;
1025 nextAP = nextAP->next;
1026 if (thisAP->inUse !=
0) {
1027 thisAP->next = AllocatedSparseArrayEntries;
1028 AllocatedSparseArrayEntries = thisAP;
1029 }
1030 else {
1031 #ifdef TRACK_GARBAGE_LEAKS
1032 --numAllocatedSparseArrayElements;
1033 #endif
1034 NEditFree(thisAP);
1035 }
1036 }
1037
1038 #ifdef TRACK_GARBAGE_LEAKS
1039 printf(
"str count = %d\nary count = %d\n", numAllocatedStrings, numAllocatedSparseArrayElements);
1040 #endif
1041 }
1042
1043
1044
1045
1046 static void saveContext(RestartData *context)
1047 {
1048 context->stack = TheStack;
1049 context->stackP = StackP;
1050 context->frameP = FrameP;
1051 context->pc =
PC;
1052 context->runWindow = InitiatingWindow;
1053 context->focusWindow = FocusWindow;
1054 }
1055
1056 static void restoreContext(RestartData *context)
1057 {
1058 TheStack = context->stack;
1059 StackP = context->stackP;
1060 FrameP = context->frameP;
1061 PC = context->pc;
1062 InitiatingWindow = context->runWindow;
1063 FocusWindow = context->focusWindow;
1064 }
1065
1066 static void freeSymbolTable(Symbol *symTab)
1067 {
1068 Symbol *s;
1069
1070 while(symTab !=
NULL) {
1071 s = symTab;
1072 free(s->name);
1073 symTab = s->next;
1074 NEditFree(s);
1075 }
1076 }
1077
1078 #define POP(dataVal) \
1079 if (StackP == TheStack) \
1080 return execError(StackUnderflowMsg,
""); \
1081 dataVal = *--StackP;
1082
1083 #define PUSH(dataVal) \
1084 if (StackP >= &TheStack[
STACK_SIZE]) \
1085 return execError(StackOverflowMsg,
""); \
1086 *StackP++ = dataVal;
1087
1088 #define PEEK(dataVal, peekIndex) \
1089 dataVal = *(StackP - peekIndex -
1);
1090
1091 #define POP_INT(number) \
1092 if (StackP == TheStack) \
1093 return execError(StackUnderflowMsg,
""); \
1094 --StackP; \
1095 if (StackP->tag ==
STRING_TAG) { \
1096 if (!StringToNum(StackP->val.str.rep, &number)) \
1097 return execError(StringToNumberMsg,
""); \
1098 }
else if (StackP->tag ==
INT_TAG) \
1099 number = StackP->val.n; \
1100 else \
1101 return(execError(
"can''t convert array to integer",
NULL));
1102
1103 #define POP_STRING(string) \
1104 if (StackP == TheStack) \
1105 return execError(StackUnderflowMsg,
""); \
1106 --StackP; \
1107 if (StackP->tag ==
INT_TAG) { \
1108 string = AllocString(
TYPE_INT_STR_SIZE(
int)); \
1109 sprintf(string,
"%d", StackP->val.n); \
1110 }
else if (StackP->tag ==
STRING_TAG) \
1111 string = StackP->val.str.rep; \
1112 else \
1113 return(execError(
"can''t convert array to string",
NULL));
1114
1115 #define PEEK_STRING(string, peekIndex) \
1116 if ((StackP - peekIndex -
1)->tag ==
INT_TAG) { \
1117 string = AllocString(
TYPE_INT_STR_SIZE(
int)); \
1118 sprintf(string,
"%d", (StackP - peekIndex -
1)->val.n); \
1119 } \
1120 else if ((StackP - peekIndex -
1)->tag ==
STRING_TAG) { \
1121 string = (StackP - peekIndex -
1)->val.str.rep; \
1122 } \
1123 else { \
1124 return(execError(
"can''t convert array to string",
NULL)); \
1125 }
1126
1127 #define PEEK_INT(number, peekIndex) \
1128 if ((StackP - peekIndex -
1)->tag ==
STRING_TAG) { \
1129 if (!StringToNum((StackP - peekIndex -
1)->val.str.rep, &number)) { \
1130 return execError(StringToNumberMsg,
""); \
1131 } \
1132 }
else if ((StackP - peekIndex -
1)->tag ==
INT_TAG) { \
1133 number = (StackP - peekIndex -
1)->val.n; \
1134 } \
1135 else { \
1136 return(execError(
"can''t convert array to string",
NULL)); \
1137 }
1138
1139 #define PUSH_INT(number) \
1140 if (StackP >= &TheStack[
STACK_SIZE]) \
1141 return execError(StackOverflowMsg,
""); \
1142 StackP->tag =
INT_TAG; \
1143 StackP->val.n = number; \
1144 StackP++;
1145
1146 #define PUSH_STRING(string, length) \
1147 if (StackP >= &TheStack[
STACK_SIZE]) \
1148 return execError(StackOverflowMsg,
""); \
1149 StackP->tag =
STRING_TAG; \
1150 StackP->val.str.rep = string; \
1151 StackP->val.str.len = length; \
1152 StackP++;
1153
1154 #define BINARY_NUMERIC_OPERATION(operator) \
1155 int n1, n2; \
1156 DISASM_RT(
PC-
1,
1); \
1157 STACKDUMP(
2,
3); \
1158 POP_INT(n2) \
1159 POP_INT(n1) \
1160 PUSH_INT(n1 operator n2) \
1161 return STAT_OK;
1162
1163 #define UNARY_NUMERIC_OPERATION(operator) \
1164 int n; \
1165 DISASM_RT(
PC-
1,
1); \
1166 STACKDUMP(
1,
3); \
1167 POP_INT(n) \
1168 PUSH_INT(operator n) \
1169 return STAT_OK;
1170
1171
1172
1173
1174
1175
1176
1177
1178 static int pushSymVal(
void)
1179 {
1180 Symbol *s;
1181 int nArgs, argNum;
1182 DataValue symVal;
1183
1184 DISASM_RT(
PC-
1,
2);
1185 STACKDUMP(
0,
3);
1186
1187 s =
PC->sym;
1188 PC++;
1189
1190 if (s->type ==
LOCAL_SYM) {
1191 symVal =
FP_GET_SYM_VAL(FrameP, s);
1192 }
else if (s->type ==
GLOBAL_SYM || s->type ==
CONST_SYM) {
1193 symVal = s->value;
1194 }
else if (s->type ==
ARG_SYM) {
1195 nArgs =
FP_GET_ARG_COUNT(FrameP);
1196 argNum = s->value.val.n;
1197 if (argNum >= nArgs) {
1198 return execError(
"referenced undefined argument: %s", s->name);
1199 }
1200 if (argNum ==
N_ARGS_ARG_SYM) {
1201 symVal.tag =
INT_TAG;
1202 symVal.val.n = nArgs;
1203 }
1204 else {
1205 symVal =
FP_GET_ARG_N(FrameP, argNum);
1206 }
1207 }
else if (s->type ==
PROC_VALUE_SYM) {
1208 char *errMsg;
1209 if (!(s->value.val.subr)(FocusWindow,
NULL,
0,
1210 &symVal, &errMsg)) {
1211 return execError(errMsg, s->name);
1212 }
1213 }
else
1214 return execError(
"reading non-variable: %s", s->name);
1215 if (symVal.tag ==
NO_TAG) {
1216 return execError(
"variable not set: %s", s->name);
1217 }
1218
1219 PUSH(symVal)
1220
1221 return STAT_OK;
1222 }
1223
1224 static int pushArgVal(
void)
1225 {
1226 int nArgs, argNum;
1227
1228 DISASM_RT(
PC-
1,
1);
1229 STACKDUMP(
1,
3);
1230
1231 POP_INT(argNum)
1232 --argNum;
1233 nArgs =
FP_GET_ARG_COUNT(FrameP);
1234 if (argNum >= nArgs || argNum <
0) {
1235 char argStr[
TYPE_INT_STR_SIZE(argNum)];
1236 sprintf(argStr,
"%d", argNum +
1);
1237 return execError(
"referenced undefined argument: $args[%s]", argStr);
1238 }
1239 PUSH(
FP_GET_ARG_N(FrameP, argNum));
1240 return STAT_OK;
1241 }
1242
1243 static int pushArgCount(
void)
1244 {
1245 DISASM_RT(
PC-
1,
1);
1246 STACKDUMP(
0,
3);
1247
1248 PUSH_INT(
FP_GET_ARG_COUNT(FrameP));
1249 return STAT_OK;
1250 }
1251
1252 static int pushArgArray(
void)
1253 {
1254 int nArgs, argNum;
1255 DataValue argVal, *resultArray;
1256
1257 DISASM_RT(
PC-
1,
1);
1258 STACKDUMP(
0,
3);
1259
1260 nArgs =
FP_GET_ARG_COUNT(FrameP);
1261 resultArray = &
FP_GET_ARG_ARRAY_CACHE(FrameP);
1262 if (resultArray->tag !=
ARRAY_TAG) {
1263 resultArray->tag =
ARRAY_TAG;
1264 resultArray->val.arrayPtr = ArrayNew();
1265
1266 for (argNum =
0; argNum < nArgs; ++argNum) {
1267 char intStr[
TYPE_INT_STR_SIZE(argNum)];
1268
1269 sprintf(intStr,
"%d", argNum +
1);
1270 argVal =
FP_GET_ARG_N(FrameP, argNum);
1271 if (!ArrayInsert(resultArray, AllocStringCpy(intStr), &argVal)) {
1272 return(execError(
"array insertion failure",
NULL));
1273 }
1274 }
1275 }
1276 PUSH(*resultArray);
1277 return STAT_OK;
1278 }
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289 static int pushArraySymVal(
void)
1290 {
1291 Symbol *sym;
1292 DataValue *dataPtr;
1293 int initEmpty;
1294
1295 DISASM_RT(
PC-
1,
3);
1296 STACKDUMP(
0,
3);
1297
1298 sym =
PC->sym;
1299 PC++;
1300 initEmpty =
PC->value;
1301 PC++;
1302
1303 if (sym->type ==
LOCAL_SYM) {
1304 dataPtr = &
FP_GET_SYM_VAL(FrameP, sym);
1305 }
1306 else if (sym->type ==
GLOBAL_SYM) {
1307 dataPtr = &sym->value;
1308 }
1309 else {
1310 return execError(
"assigning to non-lvalue array or non-array: %s", sym->name);
1311 }
1312
1313 if (initEmpty && dataPtr->tag ==
NO_TAG) {
1314 dataPtr->tag =
ARRAY_TAG;
1315 dataPtr->val.arrayPtr = ArrayNew();
1316 }
1317
1318 if (dataPtr->tag ==
NO_TAG) {
1319 return execError(
"variable not set: %s", sym->name);
1320 }
1321
1322 PUSH(*dataPtr)
1323
1324 return STAT_OK;
1325 }
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335 static int assign(
void)
1336 {
1337 Symbol *sym;
1338 DataValue *dataPtr;
1339 DataValue value;
1340
1341 DISASM_RT(
PC-
1,
2);
1342 STACKDUMP(
1,
3);
1343
1344 sym =
PC->sym;
1345 PC++;
1346
1347 if (sym->type !=
GLOBAL_SYM && sym->type !=
LOCAL_SYM) {
1348 if (sym->type ==
ARG_SYM) {
1349 return execError(
"assignment to function argument: %s", sym->name);
1350 }
1351 else if (sym->type ==
PROC_VALUE_SYM) {
1352 return execError(
"assignment to read-only variable: %s", sym->name);
1353 }
1354 else {
1355 return execError(
"assignment to non-variable: %s", sym->name);
1356 }
1357 }
1358
1359 if (sym->type ==
LOCAL_SYM) {
1360 dataPtr = &
FP_GET_SYM_VAL(FrameP, sym);
1361 }
1362 else {
1363 dataPtr = &sym->value;
1364 }
1365
1366 POP(value)
1367
1368 if (value.tag ==
ARRAY_TAG) {
1369 return ArrayCopy(dataPtr, &value);
1370 }
1371
1372 *dataPtr = value;
1373 return STAT_OK;
1374 }
1375
1376
1377
1378
1379
1380
1381 static int dupStack(
void)
1382 {
1383 DataValue value;
1384
1385 DISASM_RT(
PC-
1,
1);
1386 STACKDUMP(
1,
3);
1387
1388 PEEK(value,
0)
1389 PUSH(value)
1390
1391 return STAT_OK;
1392 }
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402 static int add(
void)
1403 {
1404 DataValue leftVal, rightVal, resultArray;
1405 int n1, n2;
1406
1407 DISASM_RT(
PC-
1,
1);
1408 STACKDUMP(
2,
3);
1409
1410 PEEK(rightVal,
0)
1411 if (rightVal.tag ==
ARRAY_TAG) {
1412 PEEK(leftVal,
1)
1413 if (leftVal.tag ==
ARRAY_TAG) {
1414 SparseArrayEntry *leftIter, *rightIter;
1415 resultArray.tag =
ARRAY_TAG;
1416 resultArray.val.arrayPtr = ArrayNew();
1417
1418 POP(rightVal)
1419 POP(leftVal)
1420 leftIter = arrayIterateFirst(&leftVal);
1421 rightIter = arrayIterateFirst(&rightVal);
1422 while (leftIter || rightIter) {
1423 Boolean insertResult = True;
1424
1425 if (leftIter && rightIter) {
1426 int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);
1427 if (compareResult <
0) {
1428 insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);
1429 leftIter = arrayIterateNext(leftIter);
1430 }
1431 else if (compareResult >
0) {
1432 insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);
1433 rightIter = arrayIterateNext(rightIter);
1434 }
1435 else {
1436 insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);
1437 leftIter = arrayIterateNext(leftIter);
1438 rightIter = arrayIterateNext(rightIter);
1439 }
1440 }
1441 else if (leftIter) {
1442 insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);
1443 leftIter = arrayIterateNext(leftIter);
1444 }
1445 else {
1446 insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);
1447 rightIter = arrayIterateNext(rightIter);
1448 }
1449 if (!insertResult) {
1450 return(execError(
"array insertion failure",
NULL));
1451 }
1452 }
1453 PUSH(resultArray)
1454 }
1455 else {
1456 return(execError(
"can''t mix math with arrays and non-arrays",
NULL));
1457 }
1458 }
1459 else {
1460 POP_INT(n2)
1461 POP_INT(n1)
1462 PUSH_INT(n1 + n2)
1463 }
1464 return(
STAT_OK);
1465 }
1466
1467
1468
1469
1470
1471
1472
1473
1474 static int subtract(
void)
1475 {
1476 DataValue leftVal, rightVal, resultArray;
1477 int n1, n2;
1478
1479 DISASM_RT(
PC-
1,
1);
1480 STACKDUMP(
2,
3);
1481
1482 PEEK(rightVal,
0)
1483 if (rightVal.tag ==
ARRAY_TAG) {
1484 PEEK(leftVal,
1)
1485 if (leftVal.tag ==
ARRAY_TAG) {
1486 SparseArrayEntry *leftIter, *rightIter;
1487 resultArray.tag =
ARRAY_TAG;
1488 resultArray.val.arrayPtr = ArrayNew();
1489
1490 POP(rightVal)
1491 POP(leftVal)
1492 leftIter = arrayIterateFirst(&leftVal);
1493 rightIter = arrayIterateFirst(&rightVal);
1494 while (leftIter) {
1495 Boolean insertResult = True;
1496
1497 if (rightIter) {
1498 int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);
1499 if (compareResult <
0) {
1500 insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);
1501 leftIter = arrayIterateNext(leftIter);
1502 }
1503 else if (compareResult >
0) {
1504 rightIter = arrayIterateNext(rightIter);
1505 }
1506 else {
1507 leftIter = arrayIterateNext(leftIter);
1508 rightIter = arrayIterateNext(rightIter);
1509 }
1510 }
1511 else {
1512 insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);
1513 leftIter = arrayIterateNext(leftIter);
1514 }
1515 if (!insertResult) {
1516 return(execError(
"array insertion failure",
NULL));
1517 }
1518 }
1519 PUSH(resultArray)
1520 }
1521 else {
1522 return(execError(
"can''t mix math with arrays and non-arrays",
NULL));
1523 }
1524 }
1525 else {
1526 POP_INT(n2)
1527 POP_INT(n1)
1528 PUSH_INT(n1 - n2)
1529 }
1530 return(
STAT_OK);
1531 }
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542 static int multiply(
void)
1543 {
1544 BINARY_NUMERIC_OPERATION(*)
1545 }
1546
1547 static int divide(
void)
1548 {
1549 int n1, n2;
1550
1551 DISASM_RT(
PC-
1,
1);
1552 STACKDUMP(
2,
3);
1553
1554 POP_INT(n2)
1555 POP_INT(n1)
1556 if (n2 ==
0) {
1557 return execError(
"division by zero",
"");
1558 }
1559 PUSH_INT(n1 / n2)
1560 return STAT_OK;
1561 }
1562
1563 static int modulo(
void)
1564 {
1565 int n1, n2;
1566
1567 DISASM_RT(
PC-
1,
1);
1568 STACKDUMP(
2,
3);
1569
1570 POP_INT(n2)
1571 POP_INT(n1)
1572 if (n2 ==
0) {
1573 return execError(
"modulo by zero",
"");
1574 }
1575 PUSH_INT(n1 % n2)
1576 return STAT_OK;
1577 }
1578
1579 static int negate(
void)
1580 {
1581 UNARY_NUMERIC_OPERATION(-)
1582 }
1583
1584 static int increment(
void)
1585 {
1586 UNARY_NUMERIC_OPERATION(++)
1587 }
1588
1589 static int decrement(
void)
1590 {
1591 UNARY_NUMERIC_OPERATION(--)
1592 }
1593
1594 static int gt(
void)
1595 {
1596 BINARY_NUMERIC_OPERATION(>)
1597 }
1598
1599 static int lt(
void)
1600 {
1601 BINARY_NUMERIC_OPERATION(<)
1602 }
1603
1604 static int ge(
void)
1605 {
1606 BINARY_NUMERIC_OPERATION(>=)
1607 }
1608
1609 static int le(
void)
1610 {
1611 BINARY_NUMERIC_OPERATION(<=)
1612 }
1613
1614
1615
1616
1617
1618
1619
1620 static int eq(
void)
1621 {
1622 DataValue v1, v2;
1623
1624 DISASM_RT(
PC-
1,
1);
1625 STACKDUMP(
2,
3);
1626
1627 POP(v1)
1628 POP(v2)
1629 if (v1.tag ==
INT_TAG && v2.tag ==
INT_TAG) {
1630 v1.val.n = v1.val.n == v2.val.n;
1631 }
1632 else if (v1.tag ==
STRING_TAG && v2.tag ==
STRING_TAG) {
1633 v1.val.n = !strcmp(v1.val.str.rep, v2.val.str.rep);
1634 }
1635 else if (v1.tag ==
STRING_TAG && v2.tag ==
INT_TAG) {
1636 int number;
1637 if (!StringToNum(v1.val.str.rep, &number)) {
1638 v1.val.n =
0;
1639 }
1640 else {
1641 v1.val.n = number == v2.val.n;
1642 }
1643 }
1644 else if (v2.tag ==
STRING_TAG && v1.tag ==
INT_TAG) {
1645 int number;
1646 if (!StringToNum(v2.val.str.rep, &number)) {
1647 v1.val.n =
0;
1648 }
1649 else {
1650 v1.val.n = number == v1.val.n;
1651 }
1652 }
1653 else {
1654 return(execError(
"incompatible types to compare",
NULL));
1655 }
1656 v1.tag =
INT_TAG;
1657 PUSH(v1)
1658 return(
STAT_OK);
1659 }
1660
1661
1662 static int ne(
void)
1663 {
1664 eq();
1665 return not();
1666 }
1667
1668
1669
1670
1671
1672
1673
1674
1675 static int bitAnd(
void)
1676 {
1677 DataValue leftVal, rightVal, resultArray;
1678 int n1, n2;
1679
1680 DISASM_RT(
PC-
1,
1);
1681 STACKDUMP(
2,
3);
1682
1683 PEEK(rightVal,
0)
1684 if (rightVal.tag ==
ARRAY_TAG) {
1685 PEEK(leftVal,
1)
1686 if (leftVal.tag ==
ARRAY_TAG) {
1687 SparseArrayEntry *leftIter, *rightIter;
1688 resultArray.tag =
ARRAY_TAG;
1689 resultArray.val.arrayPtr = ArrayNew();
1690
1691 POP(rightVal)
1692 POP(leftVal)
1693 leftIter = arrayIterateFirst(&leftVal);
1694 rightIter = arrayIterateFirst(&rightVal);
1695 while (leftIter && rightIter) {
1696 Boolean insertResult = True;
1697 int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);
1698
1699 if (compareResult <
0) {
1700 leftIter = arrayIterateNext(leftIter);
1701 }
1702 else if (compareResult >
0) {
1703 rightIter = arrayIterateNext(rightIter);
1704 }
1705 else {
1706 insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);
1707 leftIter = arrayIterateNext(leftIter);
1708 rightIter = arrayIterateNext(rightIter);
1709 }
1710 if (!insertResult) {
1711 return(execError(
"array insertion failure",
NULL));
1712 }
1713 }
1714 PUSH(resultArray)
1715 }
1716 else {
1717 return(execError(
"can''t mix math with arrays and non-arrays",
NULL));
1718 }
1719 }
1720 else {
1721 POP_INT(n2)
1722 POP_INT(n1)
1723 PUSH_INT(n1 & n2)
1724 }
1725 return(
STAT_OK);
1726 }
1727
1728
1729
1730
1731
1732
1733
1734
1735 static int bitOr(
void)
1736 {
1737 DataValue leftVal, rightVal, resultArray;
1738 int n1, n2;
1739
1740 DISASM_RT(
PC-
1,
1);
1741 STACKDUMP(
2,
3);
1742
1743 PEEK(rightVal,
0)
1744 if (rightVal.tag ==
ARRAY_TAG) {
1745 PEEK(leftVal,
1)
1746 if (leftVal.tag ==
ARRAY_TAG) {
1747 SparseArrayEntry *leftIter, *rightIter;
1748 resultArray.tag =
ARRAY_TAG;
1749 resultArray.val.arrayPtr = ArrayNew();
1750
1751 POP(rightVal)
1752 POP(leftVal)
1753 leftIter = arrayIterateFirst(&leftVal);
1754 rightIter = arrayIterateFirst(&rightVal);
1755 while (leftIter || rightIter) {
1756 Boolean insertResult = True;
1757
1758 if (leftIter && rightIter) {
1759 int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter);
1760 if (compareResult <
0) {
1761 insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);
1762 leftIter = arrayIterateNext(leftIter);
1763 }
1764 else if (compareResult >
0) {
1765 insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);
1766 rightIter = arrayIterateNext(rightIter);
1767 }
1768 else {
1769 leftIter = arrayIterateNext(leftIter);
1770 rightIter = arrayIterateNext(rightIter);
1771 }
1772 }
1773 else if (leftIter) {
1774 insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value);
1775 leftIter = arrayIterateNext(leftIter);
1776 }
1777 else {
1778 insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value);
1779 rightIter = arrayIterateNext(rightIter);
1780 }
1781 if (!insertResult) {
1782 return(execError(
"array insertion failure",
NULL));
1783 }
1784 }
1785 PUSH(resultArray)
1786 }
1787 else {
1788 return(execError(
"can''t mix math with arrays and non-arrays",
NULL));
1789 }
1790 }
1791 else {
1792 POP_INT(n2)
1793 POP_INT(n1)
1794 PUSH_INT(n1 | n2)
1795 }
1796 return(
STAT_OK);
1797 }
1798
1799 static int and(
void)
1800 {
1801 BINARY_NUMERIC_OPERATION(&&)
1802 }
1803
1804 static int or(
void)
1805 {
1806 BINARY_NUMERIC_OPERATION(||)
1807 }
1808
1809 static int not(
void)
1810 {
1811 UNARY_NUMERIC_OPERATION(!)
1812 }
1813
1814
1815
1816
1817
1818
1819 static int power(
void)
1820 {
1821 int n1, n2, n3;
1822
1823 DISASM_RT(
PC-
1,
1);
1824 STACKDUMP(
2,
3);
1825
1826 POP_INT(n2)
1827 POP_INT(n1)
1828
1829
1830
1831
1832
1833
1834
1835 if (n2 <
0 && n1 !=
1 && n1 != -
1) {
1836 if (n1 !=
0) {
1837
1838 n3 =
0;
1839 }
1840 else {
1841
1842 n3 = (
int)pow((
double)n1, (
double)n2);
1843 }
1844 }
1845 else {
1846 if ((n1 <
0) && (n2 &
1)) {
1847
1848 n3 = (
int)(pow((
double)n1, (
double)n2) - (
double)
0.
5);
1849 }
1850 else {
1851
1852 n3 = (
int)(pow((
double)n1, (
double)n2) + (
double)
0.
5);
1853 }
1854 }
1855 PUSH_INT(n3)
1856 return errCheck(
"exponentiation");
1857 }
1858
1859
1860
1861
1862
1863
1864 static int concat(
void)
1865 {
1866 char *s1, *s2, *out;
1867 int len1, len2;
1868
1869 DISASM_RT(
PC-
1,
1);
1870 STACKDUMP(
2,
3);
1871
1872 POP_STRING(s2)
1873 POP_STRING(s1)
1874 len1 = strlen(s1);
1875 len2 = strlen(s2);
1876 out = AllocString(len1 + len2 +
1);
1877 strncpy(out, s1, len1);
1878 strcpy(&out[len1], s2);
1879 PUSH_STRING(out, len1 + len2)
1880 return STAT_OK;
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900 static int callSubroutine(
void)
1901 {
1902 Symbol *sym, *s;
1903 int i, nArgs;
1904 static DataValue noValue = {
NO_TAG, {
0}};
1905 Program *prog;
1906 char *errMsg;
1907
1908 sym =
PC->sym;
1909 PC++;
1910 nArgs =
PC->value;
1911 PC++;
1912
1913 DISASM_RT(
PC-
3,
3);
1914 STACKDUMP(nArgs,
3);
1915
1916
1917
1918
1919 if (sym->type ==
C_FUNCTION_SYM) {
1920 DataValue result;
1921
1922
1923 StackP -= nArgs;
1924
1925
1926 PreemptRequest = False;
1927 if (!sym->value.val.subr(FocusWindow, StackP,
1928 nArgs, &result, &errMsg))
1929 return execError(errMsg, sym->name);
1930 if (
PC->func == fetchRetVal) {
1931 if (result.tag ==
NO_TAG) {
1932 return execError(
"%s does not return a value", sym->name);
1933 }
1934 PUSH(result);
1935 PC++;
1936 }
1937 return PreemptRequest ?
STAT_PREEMPT :
STAT_OK;
1938 }
1939
1940
1941
1942
1943
1944
1945
1946
1947 if (sym->type ==
MACRO_FUNCTION_SYM) {
1948 StackP->tag =
NO_TAG;
1949 StackP->val.inst =
PC;
1950 StackP++;
1951
1952 StackP->tag =
NO_TAG;
1953 StackP->val.dataval = FrameP;
1954 StackP++;
1955
1956 StackP->tag =
NO_TAG;
1957 StackP->val.n = nArgs;
1958 StackP++;
1959
1960 *(StackP++) = noValue;
1961
1962 FrameP = StackP;
1963 prog = sym->value.val.prog;
1964 PC = prog->code;
1965 for (s = prog->localSymList; s !=
NULL; s = s->next) {
1966 FP_GET_SYM_VAL(FrameP, s) = noValue;
1967 StackP++;
1968 }
1969 return STAT_OK;
1970 }
1971
1972
1973
1974
1975 if (sym->type ==
ACTION_ROUTINE_SYM) {
1976 String *argList;
1977 Cardinal numArgs = nArgs;
1978 XKeyEvent key_event;
1979 Display *disp;
1980 Window win;
1981
1982
1983
1984
1985 disp=XtDisplay(InitiatingWindow->shell);
1986 win=XtWindow(InitiatingWindow->shell);
1987
1988 key_event.type = KeyPress;
1989 key_event.send_event =
MACRO_EVENT_MARKER;
1990 key_event.time=XtLastTimestampProcessed(XtDisplay(InitiatingWindow->shell));
1991
1992
1993
1994
1995 key_event.display=disp;
1996 key_event.window=key_event.root=key_event.subwindow=win;
1997
1998 argList = (String *)NEditCalloc(nArgs,
sizeof(*argList));
1999
2000 for (i=nArgs-
1; i>=
0; i--) {
2001 POP_STRING(argList[i])
2002 }
2003
2004
2005 PreemptRequest = False;
2006 sym->value.val.xtproc(FocusWindow->lastFocus,
2007 (XEvent *)&key_event, argList, &numArgs);
2008 NEditFree(argList);
2009 if (
PC->func == fetchRetVal) {
2010 return execError(
"%s does not return a value", sym->name);
2011 }
2012 return PreemptRequest ?
STAT_PREEMPT :
STAT_OK;
2013 }
2014
2015
2016 return execError(
"%s is not a function or subroutine", sym->name);
2017 }
2018
2019
2020
2021
2022
2023
2024 static int fetchRetVal(
void)
2025 {
2026 return execError(
"internal error: frv",
NULL);
2027 }
2028
2029
2030 static int returnNoVal(
void)
2031 {
2032 return returnValOrNone(False);
2033 }
2034 static int returnVal(
void)
2035 {
2036 return returnValOrNone(True);
2037 }
2038
2039
2040
2041
2042
2043
2044
2045
2046 static int returnValOrNone(
int valOnStack)
2047 {
2048 DataValue retVal;
2049 static DataValue noValue = {
NO_TAG, {
0}};
2050 DataValue *newFrameP;
2051 int nArgs;
2052
2053 DISASM_RT(
PC-
1,
1);
2054 STACKDUMP(StackP - FrameP +
FP_GET_ARG_COUNT(FrameP) +
FP_TO_ARGS_DIST,
3);
2055
2056
2057 if (valOnStack) {
2058 POP(retVal);
2059 }
2060
2061
2062 nArgs =
FP_GET_ARG_COUNT(FrameP);
2063 newFrameP =
FP_GET_OLD_FP(FrameP);
2064 PC =
FP_GET_RET_PC(FrameP);
2065
2066
2067 StackP = FrameP;
2068
2069 StackP -= (
FP_TO_ARGS_DIST + nArgs);
2070 FrameP = newFrameP;
2071
2072
2073 if (
PC ==
NULL) {
2074 if (valOnStack) {
2075 PUSH(retVal);
2076 }
else {
2077 PUSH(noValue);
2078 }
2079 }
else if (
PC->func == fetchRetVal) {
2080 if (valOnStack) {
2081 PUSH(retVal);
2082 PC++;
2083 }
else {
2084 return execError(
2085 "using return value of %s which does not return a value",
2086 ((
PC-
2)->sym->name));
2087 }
2088 }
2089
2090
2091 return PC ==
NULL ?
STAT_DONE :
STAT_OK;
2092 }
2093
2094
2095
2096
2097
2098
2099
2100 static int branch(
void)
2101 {
2102 DISASM_RT(
PC-
1,
2);
2103 STACKDUMP(
0,
3);
2104
2105 PC +=
PC->value;
2106 return STAT_OK;
2107 }
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117 static int branchTrue(
void)
2118 {
2119 int value;
2120 Inst *addr;
2121
2122 DISASM_RT(
PC-
1,
2);
2123 STACKDUMP(
1,
3);
2124
2125 POP_INT(value)
2126 addr =
PC +
PC->value;
2127 PC++;
2128
2129 if (value)
2130 PC = addr;
2131 return STAT_OK;
2132 }
2133 static int branchFalse(
void)
2134 {
2135 int value;
2136 Inst *addr;
2137
2138 DISASM_RT(
PC-
1,
2);
2139 STACKDUMP(
1,
3);
2140
2141 POP_INT(value)
2142 addr =
PC +
PC->value;
2143 PC++;
2144
2145 if (!value)
2146 PC = addr;
2147 return STAT_OK;
2148 }
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158 static int branchNever(
void)
2159 {
2160 DISASM_RT(
PC-
1,
2);
2161 STACKDUMP(
0,
3);
2162
2163 PC++;
2164 return STAT_OK;
2165 }
2166
2167
2168
2169
2170
2171
2172 int ArrayCopy(DataValue *dstArray, DataValue *srcArray)
2173 {
2174 SparseArrayEntry *srcIter;
2175
2176 dstArray->tag =
ARRAY_TAG;
2177 dstArray->val.arrayPtr = ArrayNew();
2178
2179 srcIter = arrayIterateFirst(srcArray);
2180 while (srcIter) {
2181 if (srcIter->value.tag ==
ARRAY_TAG) {
2182 int errNum;
2183 DataValue tmpArray;
2184
2185 errNum = ArrayCopy(&tmpArray, &srcIter->value);
2186 if (errNum !=
STAT_OK) {
2187 return(errNum);
2188 }
2189 if (!ArrayInsert(dstArray, srcIter->key, &tmpArray)) {
2190 return(execError(
"array copy failed",
NULL));
2191 }
2192 }
2193 else {
2194 if (!ArrayInsert(dstArray, srcIter->key, &srcIter->value)) {
2195 return(execError(
"array copy failed",
NULL));
2196 }
2197 }
2198 srcIter = arrayIterateNext(srcIter);
2199 }
2200 return(
STAT_OK);
2201 }
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211 static int makeArrayKeyFromArgs(
int nArgs,
char **keyString,
int leaveParams)
2212 {
2213 DataValue tmpVal;
2214 int sepLen = strlen(
ARRAY_DIM_SEP);
2215 int keyLength =
0;
2216 int i;
2217
2218 keyLength = sepLen * (nArgs -
1);
2219 for (i = nArgs -
1; i >=
0; --i) {
2220 PEEK(tmpVal, i)
2221 if (tmpVal.tag ==
INT_TAG) {
2222 keyLength +=
TYPE_INT_STR_SIZE(tmpVal.val.n);
2223 }
2224 else if (tmpVal.tag ==
STRING_TAG) {
2225 keyLength += tmpVal.val.str.len;
2226 }
2227 else {
2228 return(execError(
"can only index array with string or int.",
NULL));
2229 }
2230 }
2231 *keyString = AllocString(keyLength +
1);
2232 (*keyString)[
0] =
0;
2233 for (i = nArgs -
1; i >=
0; --i) {
2234 if (i != nArgs -
1) {
2235 strcat(*keyString,
ARRAY_DIM_SEP);
2236 }
2237 PEEK(tmpVal, i)
2238 if (tmpVal.tag ==
INT_TAG) {
2239 sprintf(&((*keyString)[strlen(*keyString)]),
"%d", tmpVal.val.n);
2240 }
2241 else if (tmpVal.tag ==
STRING_TAG) {
2242 strcat(*keyString, tmpVal.val.str.rep);
2243 }
2244 else {
2245 return(execError(
"can only index array with string or int.",
NULL));
2246 }
2247 }
2248 if (!leaveParams) {
2249 for (i = nArgs -
1; i >=
0; --i) {
2250 POP(tmpVal)
2251 }
2252 }
2253 return(
STAT_OK);
2254 }
2255
2256
2257
2258
2259
2260 static rbTreeNode *arrayEmptyAllocator(
void)
2261 {
2262 SparseArrayEntry *newNode = allocateSparseArrayEntry();
2263 if (newNode) {
2264 newNode->key =
NULL;
2265 newNode->value.tag =
NO_TAG;
2266 }
2267 return((rbTreeNode *)newNode);
2268 }
2269
2270
2271
2272
2273
2274 static rbTreeNode *arrayAllocateNode(rbTreeNode *src)
2275 {
2276 SparseArrayEntry *newNode = allocateSparseArrayEntry();
2277 if (newNode) {
2278 newNode->key = ((SparseArrayEntry *)src)->key;
2279 newNode->value = ((SparseArrayEntry *)src)->value;
2280 }
2281 return((rbTreeNode *)newNode);
2282 }
2283
2284
2285
2286
2287
2288 static int arrayEntryCopyToNode(rbTreeNode *dst, rbTreeNode *src)
2289 {
2290 ((SparseArrayEntry *)dst)->key = ((SparseArrayEntry *)src)->key;
2291 ((SparseArrayEntry *)dst)->value = ((SparseArrayEntry *)src)->value;
2292 return(
1);
2293 }
2294
2295
2296
2297
2298 static int arrayEntryCompare(rbTreeNode *left, rbTreeNode *right)
2299 {
2300 return(strcmp(((SparseArrayEntry *)left)->key, ((SparseArrayEntry *)right)->key));
2301 }
2302
2303
2304
2305
2306
2307 static void arrayDisposeNode(rbTreeNode *src)
2308 {
2309
2310 src->left =
NULL;
2311 src->right =
NULL;
2312 src->parent =
NULL;
2313 src->color = -
1;
2314 }
2315
2316 SparseArrayEntry *ArrayNew(
void)
2317 {
2318 return((SparseArrayEntry *)rbTreeNew(arrayEmptyAllocator));
2319 }
2320
2321
2322
2323
2324
2325 Boolean ArrayInsert(DataValue* theArray,
char* keyStr, DataValue* theValue)
2326 {
2327 SparseArrayEntry tmpEntry;
2328 rbTreeNode *insertedNode;
2329
2330 tmpEntry.key = keyStr;
2331 tmpEntry.value = *theValue;
2332
2333 if (theArray->val.arrayPtr ==
NULL) {
2334 theArray->val.arrayPtr = ArrayNew();
2335 }
2336
2337 if (theArray->val.arrayPtr !=
NULL) {
2338 insertedNode = rbTreeInsert((rbTreeNode*) (theArray->val.arrayPtr),
2339 (rbTreeNode *)&tmpEntry, arrayEntryCompare, arrayAllocateNode,
2340 arrayEntryCopyToNode);
2341
2342 if (insertedNode) {
2343 return True;
2344 }
else {
2345 return False;
2346 }
2347 }
2348
2349 return False;
2350 }
2351
2352
2353
2354
2355 void ArrayDelete(DataValue *theArray,
char *keyStr)
2356 {
2357 SparseArrayEntry searchEntry;
2358
2359 if (theArray->val.arrayPtr) {
2360 searchEntry.key = keyStr;
2361 rbTreeDelete((rbTreeNode *)theArray->val.arrayPtr, (rbTreeNode *)&searchEntry,
2362 arrayEntryCompare, arrayDisposeNode);
2363 }
2364 }
2365
2366
2367
2368
2369 void ArrayDeleteAll(DataValue *theArray)
2370 {
2371 if (theArray->val.arrayPtr) {
2372 rbTreeNode *iter = rbTreeBegin((rbTreeNode *)theArray->val.arrayPtr);
2373 while (iter) {
2374 rbTreeNode *nextIter = rbTreeNext(iter);
2375 rbTreeDeleteNode((rbTreeNode *)theArray->val.arrayPtr,
2376 iter, arrayDisposeNode);
2377
2378 iter = nextIter;
2379 }
2380 }
2381 }
2382
2383
2384
2385
2386 unsigned ArraySize(DataValue* theArray)
2387 {
2388 if (theArray->val.arrayPtr) {
2389 return rbTreeSize((rbTreeNode *)theArray->val.arrayPtr);
2390 }
else {
2391 return 0;
2392 }
2393 }
2394
2395
2396
2397
2398
2399 Boolean ArrayGet(DataValue* theArray,
char* keyStr, DataValue* theValue)
2400 {
2401 SparseArrayEntry searchEntry;
2402 rbTreeNode *foundNode;
2403
2404 if (theArray->val.arrayPtr) {
2405 searchEntry.key = keyStr;
2406 foundNode = rbTreeFind((rbTreeNode*) theArray->val.arrayPtr,
2407 (rbTreeNode*) &searchEntry, arrayEntryCompare);
2408 if (foundNode) {
2409 *theValue = ((SparseArrayEntry*) foundNode)->value;
2410 return True;
2411 }
2412 }
2413
2414 return False;
2415 }
2416
2417
2418
2419
2420 SparseArrayEntry *arrayIterateFirst(DataValue *theArray)
2421 {
2422 SparseArrayEntry *startPos;
2423 if (theArray->val.arrayPtr) {
2424 startPos = (SparseArrayEntry *)rbTreeBegin((rbTreeNode *)theArray->val.arrayPtr);
2425 }
2426 else {
2427 startPos =
NULL;
2428 }
2429 return(startPos);
2430 }
2431
2432
2433
2434
2435 SparseArrayEntry *arrayIterateNext(SparseArrayEntry *iterator)
2436 {
2437 SparseArrayEntry *nextPos;
2438 if (iterator) {
2439 nextPos = (SparseArrayEntry *)rbTreeNext((rbTreeNode *)iterator);
2440 }
2441 else {
2442 nextPos =
NULL;
2443 }
2444 return(nextPos);
2445 }
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455 static int arrayRef(
void)
2456 {
2457 int errNum;
2458 DataValue srcArray, valueItem;
2459 char *keyString =
NULL;
2460 int nDim;
2461
2462 nDim =
PC->value;
2463 PC++;
2464
2465 DISASM_RT(
PC-
2,
2);
2466 STACKDUMP(nDim,
3);
2467
2468 if (nDim >
0) {
2469 errNum = makeArrayKeyFromArgs(nDim, &keyString,
0);
2470 if (errNum !=
STAT_OK) {
2471 return(errNum);
2472 }
2473
2474 POP(srcArray)
2475 if (srcArray.tag ==
ARRAY_TAG) {
2476 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
2477 return(execError(
"referenced array value not in array: %s", keyString));
2478 }
2479 PUSH(valueItem)
2480 return(
STAT_OK);
2481 }
2482 else {
2483 return(execError(
"operator [] on non-array",
NULL));
2484 }
2485 }
2486 else {
2487 POP(srcArray)
2488 if (srcArray.tag ==
ARRAY_TAG) {
2489 PUSH_INT(ArraySize(&srcArray))
2490 return(
STAT_OK);
2491 }
2492 else {
2493 return(execError(
"operator [] on non-array",
NULL));
2494 }
2495 }
2496 }
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506 static int arrayAssign(
void)
2507 {
2508 char *keyString =
NULL;
2509 DataValue srcValue, dstArray;
2510 int errNum;
2511 int nDim;
2512
2513 nDim =
PC->value;
2514 PC++;
2515
2516 DISASM_RT(
PC-
2,
1);
2517 STACKDUMP(nDim,
3);
2518
2519 if (nDim >
0) {
2520 POP(srcValue)
2521
2522 errNum = makeArrayKeyFromArgs(nDim, &keyString,
0);
2523 if (errNum !=
STAT_OK) {
2524 return(errNum);
2525 }
2526
2527 POP(dstArray)
2528
2529 if (dstArray.tag !=
ARRAY_TAG && dstArray.tag !=
NO_TAG) {
2530 return(execError(
"cannot assign array element of non-array",
NULL));
2531 }
2532 if (srcValue.tag ==
ARRAY_TAG) {
2533 DataValue arrayCopyValue;
2534
2535 errNum = ArrayCopy(&arrayCopyValue, &srcValue);
2536 srcValue = arrayCopyValue;
2537 if (errNum !=
STAT_OK) {
2538 return(errNum);
2539 }
2540 }
2541 if (ArrayInsert(&dstArray, keyString, &srcValue)) {
2542 return(
STAT_OK);
2543 }
2544 else {
2545 return(execError(
"array member allocation failure",
NULL));
2546 }
2547 }
2548 return(execError(
"empty operator []",
NULL));
2549 }
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559 static int arrayRefAndAssignSetup(
void)
2560 {
2561 int errNum;
2562 DataValue srcArray, valueItem, moveExpr;
2563 char *keyString =
NULL;
2564 int binaryOp, nDim;
2565
2566 binaryOp =
PC->value;
2567 PC++;
2568 nDim =
PC->value;
2569 PC++;
2570
2571 DISASM_RT(
PC-
3,
3);
2572 STACKDUMP(nDim +
1,
3);
2573
2574 if (binaryOp) {
2575 POP(moveExpr)
2576 }
2577
2578 if (nDim >
0) {
2579 errNum = makeArrayKeyFromArgs(nDim, &keyString,
1);
2580 if (errNum !=
STAT_OK) {
2581 return(errNum);
2582 }
2583
2584 PEEK(srcArray, nDim)
2585 if (srcArray.tag ==
ARRAY_TAG) {
2586 if (!ArrayGet(&srcArray, keyString, &valueItem)) {
2587 return(execError(
"referenced array value not in array: %s", keyString));
2588 }
2589 PUSH(valueItem)
2590 if (binaryOp) {
2591 PUSH(moveExpr)
2592 }
2593 return(
STAT_OK);
2594 }
2595 else {
2596 return(execError(
"operator [] on non-array",
NULL));
2597 }
2598 }
2599 else {
2600 return(execError(
"array[] not an lvalue",
NULL));
2601 }
2602 }
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616 static int beginArrayIter(
void)
2617 {
2618 Symbol *iterator;
2619 DataValue *iteratorValPtr;
2620 DataValue arrayVal;
2621
2622 DISASM_RT(
PC-
1,
2);
2623 STACKDUMP(
1,
3);
2624
2625 iterator =
PC->sym;
2626 PC++;
2627
2628 POP(arrayVal)
2629
2630 if (iterator->type ==
LOCAL_SYM) {
2631 iteratorValPtr = &
FP_GET_SYM_VAL(FrameP, iterator);
2632 }
2633 else {
2634 return(execError(
"bad temporary iterator: %s", iterator->name));
2635 }
2636
2637 iteratorValPtr->tag =
INT_TAG;
2638 if (arrayVal.tag !=
ARRAY_TAG) {
2639 return(execError(
"can''t iterate non-array",
NULL));
2640 }
2641
2642 iteratorValPtr->val.arrayPtr = arrayIterateFirst(&arrayVal);
2643 return(
STAT_OK);
2644 }
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668 static int arrayIter(
void)
2669 {
2670 Symbol *iterator;
2671 Symbol *item;
2672 DataValue *iteratorValPtr;
2673 DataValue *itemValPtr;
2674 SparseArrayEntry *thisEntry;
2675 Inst *branchAddr;
2676
2677 DISASM_RT(
PC-
1,
4);
2678 STACKDUMP(
0,
3);
2679
2680 item =
PC->sym;
2681 PC++;
2682 iterator =
PC->sym;
2683 PC++;
2684 branchAddr =
PC +
PC->value;
2685 PC++;
2686
2687 if (item->type ==
LOCAL_SYM) {
2688 itemValPtr = &
FP_GET_SYM_VAL(FrameP, item);
2689 }
2690 else if (item->type ==
GLOBAL_SYM) {
2691 itemValPtr = &(item->value);
2692 }
2693 else {
2694 return(execError(
"can''t assign to: %s", item->name));
2695 }
2696 itemValPtr->tag =
NO_TAG;
2697
2698 if (iterator->type ==
LOCAL_SYM) {
2699 iteratorValPtr = &
FP_GET_SYM_VAL(FrameP, iterator);
2700 }
2701 else {
2702 return(execError(
"bad temporary iterator: %s", iterator->name));
2703 }
2704
2705 thisEntry = iteratorValPtr->val.arrayPtr;
2706 if (thisEntry && thisEntry->nodePtrs.color != -
1) {
2707 itemValPtr->tag =
STRING_TAG;
2708 itemValPtr->val.str.rep = thisEntry->key;
2709 itemValPtr->val.str.len = strlen(thisEntry->key);
2710
2711 iteratorValPtr->val.arrayPtr = arrayIterateNext(thisEntry);
2712 }
2713 else {
2714 PC = branchAddr;
2715 }
2716 return(
STAT_OK);
2717 }
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731 static int inArray(
void)
2732 {
2733 DataValue theArray, leftArray, theValue;
2734 char *keyStr;
2735 int inResult =
0;
2736
2737 DISASM_RT(
PC-
1,
1);
2738 STACKDUMP(
2,
3);
2739
2740 POP(theArray)
2741 if (theArray.tag !=
ARRAY_TAG) {
2742 return(execError(
"operator in on non-array",
NULL));
2743 }
2744 PEEK(leftArray,
0)
2745 if (leftArray.tag ==
ARRAY_TAG) {
2746 SparseArrayEntry *iter;
2747
2748 POP(leftArray)
2749 inResult =
1;
2750 iter = arrayIterateFirst(&leftArray);
2751 while (inResult && iter) {
2752 inResult = inResult && ArrayGet(&theArray, iter->key, &theValue);
2753 iter = arrayIterateNext(iter);
2754 }
2755 }
2756 else {
2757 POP_STRING(keyStr)
2758 if (ArrayGet(&theArray, keyStr, &theValue)) {
2759 inResult =
1;
2760 }
2761 }
2762 PUSH_INT(inResult)
2763 return(
STAT_OK);
2764 }
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775 static int deleteArrayElement(
void)
2776 {
2777 DataValue theArray;
2778 char *keyString =
NULL;
2779 int nDim;
2780
2781 nDim =
PC->value;
2782 PC++;
2783
2784 DISASM_RT(
PC-
2,
2);
2785 STACKDUMP(nDim +
1,
3);
2786
2787 if (nDim >
0) {
2788 int errNum;
2789
2790 errNum = makeArrayKeyFromArgs(nDim, &keyString,
0);
2791 if (errNum !=
STAT_OK) {
2792 return(errNum);
2793 }
2794 }
2795
2796 POP(theArray)
2797 if (theArray.tag ==
ARRAY_TAG) {
2798 if (nDim >
0) {
2799 ArrayDelete(&theArray, keyString);
2800 }
2801 else {
2802 ArrayDeleteAll(&theArray);
2803 }
2804 }
2805 else {
2806 return(execError(
"attempt to delete from non-array",
NULL));
2807 }
2808 return(
STAT_OK);
2809 }
2810
2811
2812
2813
2814
2815 static int errCheck(
const char *s)
2816 {
2817 if (errno ==
EDOM)
2818 return execError(
"%s argument out of domain", s);
2819 else if (errno ==
ERANGE)
2820 return execError(
"%s result out of range", s);
2821 else
2822 return STAT_OK;
2823 }
2824
2825
2826
2827
2828
2829
2830 static int execError(
const char *s1,
const char *s2)
2831 {
2832 static char msg[
MAX_ERR_MSG_LEN];
2833
2834 sprintf(msg, s1, s2);
2835 ErrMsg = msg;
2836 return STAT_ERROR;
2837 }
2838
2839 int StringToNum(
const char *string,
int *number)
2840 {
2841 const char *c = string;
2842
2843 while (*c ==
' ' || *c ==
'\t') {
2844 ++c;
2845 }
2846 if (*c ==
'+' || *c ==
'-') {
2847 ++c;
2848 }
2849 while (isdigit((
unsigned char)*c)) {
2850 ++c;
2851 }
2852 while (*c ==
' ' || *c ==
'\t') {
2853 ++c;
2854 }
2855 if (*c) {
2856
2857 return False;
2858 }
2859 if (number) {
2860 if (sscanf(string,
"%d", number) !=
1) {
2861
2862 *number =
0;
2863 }
2864 }
2865 return True;
2866 }
2867
2868 #ifdef DEBUG_DISASSEMBLER
2869 static void dumpVal(DataValue dv)
2870 {
2871 switch (dv.tag) {
2872 case INT_TAG:
2873 printf(
"i=%d", dv.val.n);
2874 break;
2875 case STRING_TAG:
2876 {
2877 int k;
2878 char s[
21];
2879 char *src = dv.val.str.rep;
2880 if (!src) {
2881 printf(
"s=<NULL>");
2882 }
2883 else {
2884 for (k =
0; src[k] && k <
sizeof s -
1; k++) {
2885 s[k] = isprint(src[k]) ? src[k] :
'?';
2886 }
2887 s[k] =
0;
2888 printf(
"s=\"%s\"%s[%d]", s,
2889 src[k] ?
"..." :
"", strlen(src));
2890 }
2891 }
2892 break;
2893 case ARRAY_TAG:
2894 printf(
"<array>");
2895 break;
2896 case NO_TAG:
2897 if (!dv.val.inst) {
2898 printf(
"<no value>");
2899 }
2900 else {
2901 printf(
"?%8p", dv.val.inst);
2902 }
2903 break;
2904 default:
2905 printf(
"UNKNOWN DATA TAG %d ?%8p", dv.tag, dv.val.inst);
2906 break;
2907 }
2908 }
2909 #endif
2910
2911 #ifdef DEBUG_DISASSEMBLER
2912 static void disasm(Inst *inst,
int nInstr)
2913 {
2914 static const char *opNames[
N_OPS] = {
2915 "RETURN_NO_VAL",
2916 "RETURN",
2917 "PUSH_SYM",
2918 "DUP",
2919 "ADD",
2920 "SUB",
2921 "MUL",
2922 "DIV",
2923 "MOD",
2924 "NEGATE",
2925 "INCR",
2926 "DECR",
2927 "GT",
2928 "LT",
2929 "GE",
2930 "LE",
2931 "EQ",
2932 "NE",
2933 "BIT_AND",
2934 "BIT_OR",
2935 "AND",
2936 "OR",
2937 "NOT",
2938 "POWER",
2939 "CONCAT",
2940 "ASSIGN",
2941 "SUBR_CALL",
2942 "FETCH_RET_VAL",
2943 "BRANCH",
2944 "BRANCH_TRUE",
2945 "BRANCH_FALSE",
2946 "BRANCH_NEVER",
2947 "ARRAY_REF",
2948 "ARRAY_ASSIGN",
2949 "BEGIN_ARRAY_ITER",
2950 "ARRAY_ITER",
2951 "IN_ARRAY",
2952 "ARRAY_DELETE",
2953 "PUSH_ARRAY_SYM",
2954 "ARRAY_REF_ASSIGN_SETUP",
2955 "PUSH_ARG",
2956 "PUSH_ARG_COUNT",
2957 "PUSH_ARG_ARRAY"
2958 };
2959 int i, j;
2960
2961 printf(
"\n");
2962 for (i =
0; i < nInstr; ++i) {
2963 printf(
"Prog %8p ", &inst[i]);
2964 for (j =
0; j <
N_OPS; ++j) {
2965 if (inst[i].func == OpFns[j]) {
2966 printf(
"%22s ", opNames[j]);
2967 if (j ==
OP_PUSH_SYM || j ==
OP_ASSIGN) {
2968 Symbol *sym = inst[i+
1].sym;
2969 printf(
"%s", sym->name);
2970 if (sym->value.tag ==
STRING_TAG &&
2971 strncmp(sym->name,
"string #",
8) ==
0) {
2972 dumpVal(sym->value);
2973 }
2974 ++i;
2975 }
2976 else if (j ==
OP_BRANCH || j ==
OP_BRANCH_FALSE ||
2977 j ==
OP_BRANCH_NEVER || j ==
OP_BRANCH_TRUE) {
2978 printf(
"to=(%d) %p", inst[i+
1].value,
2979 &inst[i+
1] + inst[i+
1].value);
2980 ++i;
2981 }
2982 else if (j ==
OP_SUBR_CALL) {
2983 printf(
"%s (%d arg)", inst[i+
1].sym->name, inst[i+
2].value);
2984 i +=
2;
2985 }
2986 else if (j ==
OP_BEGIN_ARRAY_ITER) {
2987 printf(
"%s in", inst[i+
1].sym->name);
2988 ++i;
2989 }
2990 else if (j ==
OP_ARRAY_ITER) {
2991 printf(
"%s = %s++ end-loop=(%d) %p",
2992 inst[i+
1].sym->name,
2993 inst[i+
2].sym->name,
2994 inst[i+
3].value, &inst[i+
3] + inst[i+
3].value);
2995 i +=
3;
2996 }
2997 else if (j ==
OP_ARRAY_REF || j ==
OP_ARRAY_DELETE ||
2998 j ==
OP_ARRAY_ASSIGN) {
2999 printf(
"nDim=%d", inst[i+
1].value);
3000 ++i;
3001 }
3002 else if (j ==
OP_ARRAY_REF_ASSIGN_SETUP) {
3003 printf(
"binOp=%s ", inst[i+
1].value ?
"true" :
"false");
3004 printf(
"nDim=%d", inst[i+
2].value);
3005 i +=
2;
3006 }
3007 else if (j ==
OP_PUSH_ARRAY_SYM) {
3008 printf(
"%s", inst[++i].sym->name);
3009 printf(
" %s", inst[i+
1].value ?
"createAndRef" :
"refOnly");
3010 ++i;
3011 }
3012
3013 printf(
"\n");
3014 break;
3015 }
3016 }
3017 if (j ==
N_OPS) {
3018 printf(
"%x\n", inst[i].value);
3019 }
3020 }
3021 }
3022 #endif
3023
3024 #ifdef DEBUG_STACK
3025 #define STACK_DUMP_ARG_PREFIX "Arg"
3026 static void stackdump(
int n,
int extra)
3027 {
3028
3029 int nArgs =
FP_GET_ARG_COUNT(FrameP);
3030 int i, offset;
3031 char buffer[
sizeof(
STACK_DUMP_ARG_PREFIX) +
TYPE_INT_STR_SIZE(
int)];
3032 printf(
"Stack ----->\n");
3033 for (i =
0; i < n + extra; i++) {
3034 char *pos =
"";
3035 DataValue *dv = &StackP[-i -
1];
3036 if (dv < TheStack) {
3037 printf(
"--------------Stack base--------------\n");
3038 break;
3039 }
3040 offset = dv - FrameP;
3041
3042 printf(
"%4.4s", i < n ?
">>>>" :
"");
3043 printf(
"%8p ", dv);
3044 switch (offset) {
3045 case 0: pos =
"FrameP";
break;
3046 case FP_ARG_ARRAY_CACHE_INDEX: pos =
"args";
break;
3047 case FP_ARG_COUNT_INDEX: pos =
"NArgs";
break;
3048 case FP_OLD_FP_INDEX: pos =
"OldFP";
break;
3049 case FP_RET_PC_INDEX: pos =
"RetPC";
break;
3050 default:
3051 if (offset < -
FP_TO_ARGS_DIST && offset >= -
FP_TO_ARGS_DIST - nArgs) {
3052 sprintf(pos = buffer,
STACK_DUMP_ARG_PREFIX "%d",
3053 offset +
FP_TO_ARGS_DIST + nArgs +
1);
3054 }
3055 break;
3056 }
3057 printf(
"%-6s ", pos);
3058 dumpVal(*dv);
3059 printf(
"\n");
3060 }
3061 }
3062 #endif
3063