Rev 7141 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7141 | Rev 7845 | ||
---|---|---|---|
1 | /* Tiny Basic Intermediate Language Interpreter -- 2004 July 19 */ |
1 | /* Tiny Basic Intermediate Language Interpreter -- 2004 July 19 */ |
2 | 2 | ||
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | - | ||
7 | #if defined(__TINYC__) |
6 | |
8 | #include |
- | |
9 | #define printf con_printf /* siemargl for smaller @tinyC */ |
7 | #include |
10 | #endif |
8 | |
11 | char *ExplainErr(int code); |
9 | char *ExplainErr(int code); |
12 | 10 | ||
13 | 11 | ||
14 | /* Default input/output file names, if defined (omit otherwise)... */ |
12 | /* Default input/output file names, if defined (omit otherwise)... */ |
15 | #define DefaultInputFile "TBasm.txt" |
13 | #define DefaultInputFile "TBasm.txt" |
16 | #define DefaultOutputFile "TBout.txt" |
14 | #define DefaultOutputFile "TBout.txt" |
17 | 15 | ||
18 | /* File input/output function macros (adjust for C++ framework) */ |
16 | /* File input/output function macros (adjust for C++ framework) */ |
19 | #define FileType FILE* |
17 | #define FileType FILE* |
20 | #define IoFileClose(fi) fclose(fi) |
18 | #define IoFileClose(fi) fclose(fi) |
21 | #define InFileChar(fi) CfileRead(fi) |
19 | #define InFileChar(fi) CfileRead(fi) |
22 | #define OutFileChar(fi,ch) fputc(ch,fi) |
20 | #define OutFileChar(fi,ch) fputc(ch,fi) |
23 | #define ScreenChar(ch) printf("%c",ch) |
21 | #define ScreenChar(ch) con_printf("%c",ch) |
24 | #define KeyInChar (char)getchar() |
22 | #define KeyInChar (char)getchar() |
25 | #define NeedsEcho true |
23 | #define NeedsEcho true |
26 | #define BreakTest Broken |
24 | #define BreakTest Broken |
27 | 25 | ||
28 | /* File input/output function macros (Qt examples:) */ |
26 | /* File input/output function macros (Qt examples:) */ |
29 | /* #define FileType QFile* */ |
27 | /* #define FileType QFile* */ |
30 | /* #define IoFileClose(fi) fi->close() */ |
28 | /* #define IoFileClose(fi) fi->close() */ |
31 | /* #define InFileChar(fi) (fi->atEnd()?'\0':fi->getch()) */ |
29 | /* #define InFileChar(fi) (fi->atEnd()?'\0':fi->getch()) */ |
32 | /* #define OutFileChar(fi,ch) fi->putch(ch) */ |
30 | /* #define OutFileChar(fi,ch) fi->putch(ch) */ |
33 | 31 | ||
34 | char CfileRead(FileType fi) { /* C file reader, returns '\0' on eof */ |
32 | char CfileRead(FileType fi) { /* C file reader, returns '\0' on eof */ |
35 | int chn = fgetc(fi); |
33 | int chn = fgetc(fi); |
36 | if (chn == EOF) return '\0'; |
34 | if (chn == EOF) return '\0'; |
37 | return (char)chn;} /* ~CfileRead */ |
35 | return (char)chn;} /* ~CfileRead */ |
38 | 36 | ||
39 | /* Constants: */ |
37 | /* Constants: */ |
40 | 38 | ||
41 | #define aByte unsigned char |
39 | #define aByte unsigned char |
42 | #define CoreTop 65536 /* Core size */ |
40 | #define CoreTop 65536 /* Core size */ |
43 | #define UserProg 32 /* Core address of front of Basic program */ |
41 | #define UserProg 32 /* Core address of front of Basic program */ |
44 | #define EndUser 34 /* Core address of end of stack/user space */ |
42 | #define EndUser 34 /* Core address of end of stack/user space */ |
45 | #define EndProg 36 /* Core address of end of Basic program */ |
43 | #define EndProg 36 /* Core address of end of Basic program */ |
46 | #define GoStkTop 38 /* Core address of Gosub stack top */ |
44 | #define GoStkTop 38 /* Core address of Gosub stack top */ |
47 | #define LinoCore 40 /* Core address of "Current BASIC line number" */ |
45 | #define LinoCore 40 /* Core address of "Current BASIC line number" */ |
48 | #define ILPCcore 42 /* Core address of "IL Program Counter" */ |
46 | #define ILPCcore 42 /* Core address of "IL Program Counter" */ |
49 | #define BPcore 44 /* Core address of "Basic Pointer" */ |
47 | #define BPcore 44 /* Core address of "Basic Pointer" */ |
50 | #define SvPtCore 46 /* Core address of "Saved Pointer" */ |
48 | #define SvPtCore 46 /* Core address of "Saved Pointer" */ |
51 | #define InLine 48 /* Core address of input line */ |
49 | #define InLine 48 /* Core address of input line */ |
52 | #define ExpnStk 128 /* Core address of expression stack (empty) */ |
50 | #define ExpnStk 128 /* Core address of expression stack (empty) */ |
53 | #define TabHere 191 /* Core address of output line size, for tabs */ |
51 | #define TabHere 191 /* Core address of output line size, for tabs */ |
54 | #define WachPoint 255 /* Core address of debug watchpoint USR */ |
52 | #define WachPoint 255 /* Core address of debug watchpoint USR */ |
55 | #define ColdGo 256 /* Core address of nominal restart USR */ |
53 | #define ColdGo 256 /* Core address of nominal restart USR */ |
56 | #define WarmGo 259 /* Core address of nominal warm start USR */ |
54 | #define WarmGo 259 /* Core address of nominal warm start USR */ |
57 | #define InchSub 262 /* Core address of nominal char input USR */ |
55 | #define InchSub 262 /* Core address of nominal char input USR */ |
58 | #define OutchSub 265 /* Core address of nominal char output USR */ |
56 | #define OutchSub 265 /* Core address of nominal char output USR */ |
59 | #define BreakSub 268 /* Core address of nominal break test USR */ |
57 | #define BreakSub 268 /* Core address of nominal break test USR */ |
60 | #define DumpSub 273 /* Core address of debug core dump USR */ |
58 | #define DumpSub 273 /* Core address of debug core dump USR */ |
61 | #define PeekSub 276 /* Core address of nominal byte peek USR */ |
59 | #define PeekSub 276 /* Core address of nominal byte peek USR */ |
62 | #define Peek2Sub 277 /* Core address of nominal 2-byte peek USR */ |
60 | #define Peek2Sub 277 /* Core address of nominal 2-byte peek USR */ |
63 | #define PokeSub 280 /* Core address of nominal byte poke USR */ |
61 | #define PokeSub 280 /* Core address of nominal byte poke USR */ |
64 | #define TrLogSub 283 /* Core address of debug trace log USR */ |
62 | #define TrLogSub 283 /* Core address of debug trace log USR */ |
65 | #define BScode 271 /* Core address of backspace code */ |
63 | #define BScode 271 /* Core address of backspace code */ |
66 | #define CanCode 272 /* Core address of line cancel code */ |
64 | #define CanCode 272 /* Core address of line cancel code */ |
67 | #define ILfront 286 /* Core address of IL code address */ |
65 | #define ILfront 286 /* Core address of IL code address */ |
68 | #define BadOp 15 /* illegal op, default IL code */ |
66 | #define BadOp 15 /* illegal op, default IL code */ |
69 | /* Pascal habits die hard.. */ |
67 | /* Pascal habits die hard.. */ |
70 | #define true 1 |
68 | #define true 1 |
71 | #define false 0 |
69 | #define false 0 |
72 | 70 | ||
73 | /* debugging stuff... */ |
71 | /* debugging stuff... */ |
74 | #define DEBUGON 1 /* 1 enables \t Debugging toggle, 0 disables */ |
72 | #define DEBUGON 1 /* 1 enables \t Debugging toggle, 0 disables */ |
75 | #define LOGSIZE 4096 /* how much to log */ |
73 | #define LOGSIZE 4096 /* how much to log */ |
76 | static int Debugging = 0; /* >0 enables debug code */ |
74 | static int Debugging = 0; /* >0 enables debug code */ |
77 | int DebugLog[LOGSIZE]; /* quietly logs recent activity */ |
75 | int DebugLog[LOGSIZE]; /* quietly logs recent activity */ |
78 | int LogHere = 0; /* current index in DebugLog */ |
76 | int LogHere = 0; /* current index in DebugLog */ |
79 | int Watcher = 0, Watchee; /* memory watchpoint */ |
77 | int Watcher = 0, Watchee; /* memory watchpoint */ |
80 | 78 | ||
81 | /* Static/global data: */ |
79 | /* Static/global data: */ |
82 | aByte Core[CoreTop]; /* everything goes in here */ |
80 | aByte Core[CoreTop]; /* everything goes in here */ |
83 | aByte DeCaps[128]; /* capitalization table */ |
81 | aByte DeCaps[128]; /* capitalization table */ |
84 | int Lino, ILPC; /* current line #, IL program counter */ |
82 | int Lino, ILPC; /* current line #, IL program counter */ |
85 | int BP, SvPt; /* current, saved TB parse pointer */ |
83 | int BP, SvPt; /* current, saved TB parse pointer */ |
86 | int SubStk, ExpnTop; /* stack pointers */ |
84 | int SubStk, ExpnTop; /* stack pointers */ |
87 | int InLend, SrcEnd; /* current input line & TB source end */ |
85 | int InLend, SrcEnd; /* current input line & TB source end */ |
88 | int UserEnd; |
86 | int UserEnd; |
89 | int ILend, XQhere; /* end of IL code, start of execute loop */ |
87 | int ILend, XQhere; /* end of IL code, start of execute loop */ |
90 | int Broken = false; /* =true to stop execution or listing */ |
88 | int Broken = false; /* =true to stop execution or listing */ |
91 | FileType inFile = NULL; /* from option '-i' or user menu/button */ |
89 | FileType inFile = NULL; /* from option '-i' or user menu/button */ |
92 | FileType oFile = NULL; /* from option '-o' or user menu/button */ |
90 | FileType oFile = NULL; /* from option '-o' or user menu/button */ |
93 | 91 | ||
94 | /************************* Memory Utilities.. *************************/ |
92 | /************************* Memory Utilities.. *************************/ |
95 | 93 | ||
96 | void Poke2(int loc, int valu) { /* store integer as two bytes */ |
94 | void Poke2(int loc, int valu) { /* store integer as two bytes */ |
97 | Core[loc] = (aByte)((valu>>8)&255); /* nominally Big-Endian */ |
95 | Core[loc] = (aByte)((valu>>8)&255); /* nominally Big-Endian */ |
98 | Core[loc+1] = (aByte)(valu&255);} /* ~Poke2 */ |
96 | Core[loc+1] = (aByte)(valu&255);} /* ~Poke2 */ |
99 | 97 | ||
100 | int Peek2(int loc) { /* fetch integer from two bytes */ |
98 | int Peek2(int loc) { /* fetch integer from two bytes */ |
101 | return ((int)Core[loc])*256 + ((int)Core[loc+1]);} /* ~Peek2 */ |
99 | return ((int)Core[loc])*256 + ((int)Core[loc+1]);} /* ~Peek2 */ |
102 | 100 | ||
103 | /************************** I/O Utilities... **************************/ |
101 | /************************** I/O Utilities... **************************/ |
104 | 102 | ||
105 | void Ouch(char ch) { /* output char to stdout */ |
103 | void Ouch(char ch) { /* output char to stdout */ |
106 | if (oFile != NULL) { /* there is an output file.. */ |
104 | if (oFile != NULL) { /* there is an output file.. */ |
107 | if (ch>=' ') OutFileChar(oFile,ch); |
105 | if (ch>=' ') OutFileChar(oFile,ch); |
108 | else if (ch == '\r') OutFileChar(oFile,'\n');} |
106 | else if (ch == '\r') OutFileChar(oFile,'\n');} |
109 | if (ch=='\r') { |
107 | if (ch=='\r') { |
110 | Core[TabHere] = 0; /* keep count of how long this line is */ |
108 | Core[TabHere] = 0; /* keep count of how long this line is */ |
111 | ScreenChar('\n');} |
109 | ScreenChar('\n');} |
112 | else if (ch>=' ') if (ch<='~') { /* ignore non-print control chars */ |
110 | else if (ch>=' ') if (ch<='~') { /* ignore non-print control chars */ |
113 | Core[TabHere]++; |
111 | Core[TabHere]++; |
114 | ScreenChar(ch);}} /* ~Ouch */ |
112 | ScreenChar(ch);}} /* ~Ouch */ |
115 | 113 | ||
116 | char Inch(void) { /* read input character from stdin or file */ |
114 | char Inch(void) { /* read input character from stdin or file */ |
117 | char ch; |
115 | char ch; |
118 | if (inFile != NULL) { /* there is a file to get input from.. */ |
116 | if (inFile != NULL) { /* there is a file to get input from.. */ |
119 | ch = InFileChar(inFile); |
117 | ch = InFileChar(inFile); |
120 | if (ch == '\n') ch = '\r'; |
118 | if (ch == '\n') ch = '\r'; |
121 | if (ch == '\0') { /* switch over to console input at eof */ |
119 | if (ch == '\0') { /* switch over to console input at eof */ |
122 | IoFileClose(inFile); |
120 | IoFileClose(inFile); |
123 | inFile = NULL;} |
121 | inFile = NULL;} |
124 | else { |
122 | else { |
125 | Ouch(ch); /* echo input to screen (but not output file) */ |
123 | Ouch(ch); /* echo input to screen (but not output file) */ |
126 | return ch;}} |
124 | return ch;}} |
127 | ch = KeyInChar; /* get input from stdin */ |
125 | ch = KeyInChar; /* get input from stdin */ |
128 | if (ch == 0) exit(0); /* Kolibri specific - our window was killed */ |
- | |
- | 126 | ||
- | 127 | // ---Leency |
|
- | 128 | // int __stdcall con_getch(void); |
|
- | 129 | // For normal characters function returns ASCII-code. |
|
- | 130 | // For extended characters (eg, Fx, and arrows), first function call |
|
- | 131 | // returns 0 and second call returns the extended code (similar to the |
|
- | 132 | // DOS-function input). Starting from version 7, after closing the |
|
- | 133 | // console window, this function returns 0. |
|
- | 134 | if (ch == 0) { |
|
- | 135 | ch = (char)con_getch(); |
|
- | 136 | if (ch == 0) exit(0); /* Kolibri specific - user closed window */ |
|
- | 137 | return 0; /* Do not show anything on press extchar */ |
|
- | 138 | } |
|
129 | 139 | ||
130 | if (ch==13) printf ("\n"); |
140 | if (ch==13) con_printf ("\n"); |
131 | if (ch==8) printf ("\b "); |
141 | if (ch==8) con_printf ("\b "); |
132 | if (NeedsEcho) ScreenChar(ch); /* alternative input may need this */ |
142 | if (NeedsEcho) ScreenChar(ch); /* alternative input may need this */ |
133 | if (oFile != NULL) OutFileChar(oFile,ch); /* echo it to output file */ |
143 | if (oFile != NULL) OutFileChar(oFile,ch); /* echo it to output file */ |
134 | if (ch == '\n') { |
144 | if (ch == '\n') { |
135 | ch = '\r'; /* convert line end to TB standard */ |
145 | ch = '\r'; /* convert line end to TB standard */ |
136 | Core[TabHere] = 0;} /* reset tab counter */ |
146 | Core[TabHere] = 0;} /* reset tab counter */ |
137 | return ch;} /* ~Inch */ |
147 | return ch;} /* ~Inch */ |
138 | 148 | ||
139 | int StopIt(void) {return BreakTest;} /* ~StopIt, .. not implemented */ |
149 | int StopIt(void) {return BreakTest;} /* ~StopIt, .. not implemented */ |
140 | 150 | ||
141 | void OutStr(char* theMsg) { /* output a string to the console */ |
151 | void OutStr(char* theMsg) { /* output a string to the console */ |
142 | while (*theMsg != '\0') Ouch(*theMsg++);} /* ~OutStr */ |
152 | while (*theMsg != '\0') Ouch(*theMsg++);} /* ~OutStr */ |
143 | 153 | ||
144 | void OutLn(void) { /* terminate output line to the console */ |
154 | void OutLn(void) { /* terminate output line to the console */ |
145 | OutStr("\r");} /* ~OutLn */ |
155 | OutStr("\r");} /* ~OutLn */ |
146 | 156 | ||
147 | void OutInt(int theNum) { /* output a number to the console */ |
157 | void OutInt(int theNum) { /* output a number to the console */ |
148 | if (theNum<0) { |
158 | if (theNum<0) { |
149 | Ouch('-'); |
159 | Ouch('-'); |
150 | theNum = -theNum;} |
160 | theNum = -theNum;} |
151 | if (theNum>9) OutInt(theNum/10); |
161 | if (theNum>9) OutInt(theNum/10); |
152 | Ouch((char)(theNum%10+48));} /* ~OutInt */ |
162 | Ouch((char)(theNum%10+48));} /* ~OutInt */ |
153 | 163 | ||
154 | /*********************** Debugging Utilities... ***********************/ |
164 | /*********************** Debugging Utilities... ***********************/ |
155 | 165 | ||
156 | void OutHex(int num, int nd) { /* output a hex number to the console */ |
166 | void OutHex(int num, int nd) { /* output a hex number to the console */ |
157 | if (nd>1) OutHex(num>>4, nd-1); |
167 | if (nd>1) OutHex(num>>4, nd-1); |
158 | num = num&15; |
168 | num = num&15; |
159 | if (num>9) Ouch((char)(num+55)); |
169 | if (num>9) Ouch((char)(num+55)); |
160 | else Ouch((char)(num+48));} /* ~OutHex */ |
170 | else Ouch((char)(num+48));} /* ~OutHex */ |
161 | 171 | ||
162 | void ShowSubs(void) { /* display subroutine stack for debugging */ |
172 | void ShowSubs(void) { /* display subroutine stack for debugging */ |
163 | int ix; |
173 | int ix; |
164 | OutLn(); OutStr(" [Stk "); OutHex(SubStk,5); |
174 | OutLn(); OutStr(" [Stk "); OutHex(SubStk,5); |
165 | for (ix=SubStk; ix |
175 | for (ix=SubStk; ix |
166 | OutStr(" "); |
176 | OutStr(" "); |
167 | OutInt(Peek2(ix++));} |
177 | OutInt(Peek2(ix++));} |
168 | OutStr("]");} /* ~ShowSubs */ |
178 | OutStr("]");} /* ~ShowSubs */ |
169 | 179 | ||
170 | void ShowExSt(void) { /* display expression stack for debugging */ |
180 | void ShowExSt(void) { /* display expression stack for debugging */ |
171 | int ix; |
181 | int ix; |
172 | OutLn(); OutStr(" [Exp "); OutHex(ExpnTop,3); |
182 | OutLn(); OutStr(" [Exp "); OutHex(ExpnTop,3); |
173 | if ((ExpnTop&1)==0) for (ix=ExpnTop; ix |
183 | if ((ExpnTop&1)==0) for (ix=ExpnTop; ix |
174 | OutStr(" "); |
184 | OutStr(" "); |
175 | OutInt((int)((short)Peek2(ix++)));} |
185 | OutInt((int)((short)Peek2(ix++)));} |
176 | else for (ix=ExpnTop; ix |
186 | else for (ix=ExpnTop; ix |
177 | OutStr("."); |
187 | OutStr("."); |
178 | OutInt((int)Core[ix]);} |
188 | OutInt((int)Core[ix]);} |
179 | OutStr("]");} /* ~ShowExSt */ |
189 | OutStr("]");} /* ~ShowExSt */ |
180 | 190 | ||
181 | void ShowVars(int whom) { /* display vars for debugging */ |
191 | void ShowVars(int whom) { /* display vars for debugging */ |
182 | int ix, valu = 1, prior = 1; |
192 | int ix, valu = 1, prior = 1; |
183 | if (whom==0) whom = 26; else { |
193 | if (whom==0) whom = 26; else { |
184 | whom = (whom>>1)&31; /* whom is a specified var, or 0 */ |
194 | whom = (whom>>1)&31; /* whom is a specified var, or 0 */ |
185 | valu = whom;} |
195 | valu = whom;} |
186 | OutLn(); OutStr(" [Vars"); |
196 | OutLn(); OutStr(" [Vars"); |
187 | for (ix=valu; ix<=whom; ix++) { /* all non-zero vars, or else whom */ |
197 | for (ix=valu; ix<=whom; ix++) { /* all non-zero vars, or else whom */ |
188 | valu = (int)((short)Peek2(ix*2+ExpnStk)); |
198 | valu = (int)((short)Peek2(ix*2+ExpnStk)); |
189 | if (valu==0) if (prior==0) continue; /* omit multiple 0s */ |
199 | if (valu==0) if (prior==0) continue; /* omit multiple 0s */ |
190 | prior = valu; |
200 | prior = valu; |
191 | OutStr(" "); |
201 | OutStr(" "); |
192 | Ouch((char)(ix+64)); /* show var name */ |
202 | Ouch((char)(ix+64)); /* show var name */ |
193 | OutStr("="); |
203 | OutStr("="); |
194 | OutInt(valu);} |
204 | OutInt(valu);} |
195 | OutStr("]");} /* ~ShowVars */ |
205 | OutStr("]");} /* ~ShowVars */ |
196 | 206 | ||
197 | void ShoMemDump(int here, int nlocs) { /* display hex memory dump */ |
207 | void ShoMemDump(int here, int nlocs) { /* display hex memory dump */ |
198 | int temp, thar = here&-16; |
208 | int temp, thar = here&-16; |
199 | while (nlocs>0) { |
209 | while (nlocs>0) { |
200 | temp = thar; |
210 | temp = thar; |
201 | OutLn(); |
211 | OutLn(); |
202 | OutHex(here,4); |
212 | OutHex(here,4); |
203 | OutStr(": "); |
213 | OutStr(": "); |
204 | while (thar |
214 | while (thar |
205 | do { |
215 | do { |
206 | OutStr(" "); |
216 | OutStr(" "); |
207 | if (nlocs-- >0) OutHex(Core[here],2); |
217 | if (nlocs-- >0) OutHex(Core[here],2); |
208 | else OutStr(" ");} |
218 | else OutStr(" ");} |
209 | while (++here%16 !=0); |
219 | while (++here%16 !=0); |
210 | OutStr(" "); |
220 | OutStr(" "); |
211 | while (temp |
221 | while (temp |
212 | while (thar |
222 | while (thar |
213 | if (nlocs<0) if ((thar&15) >= nlocs+16) break; |
223 | if (nlocs<0) if ((thar&15) >= nlocs+16) break; |
214 | temp = Core[thar++]; |
224 | temp = Core[thar++]; |
215 | if (temp == (int)'\r') Ouch('\\'); |
225 | if (temp == (int)'\r') Ouch('\\'); |
216 | else if (temp<32) Ouch('`'); |
226 | else if (temp<32) Ouch('`'); |
217 | else if (temp>126) Ouch('~'); |
227 | else if (temp>126) Ouch('~'); |
218 | else Ouch((char)temp);}} |
228 | else Ouch((char)temp);}} |
219 | OutLn();} /* ~ShoMemDump */ |
229 | OutLn();} /* ~ShoMemDump */ |
220 | 230 | ||
221 | void ShoLogVal(int item) { /* format & output one activity log item */ |
231 | void ShoLogVal(int item) { /* format & output one activity log item */ |
222 | int valu = DebugLog[item]; |
232 | int valu = DebugLog[item]; |
223 | OutLn(); |
233 | OutLn(); |
224 | if (valu < -65536) { /* store to a variable */ |
234 | if (valu < -65536) { /* store to a variable */ |
225 | Ouch((char)(((valu>>17)&31)+64)); |
235 | Ouch((char)(((valu>>17)&31)+64)); |
226 | OutStr("="); |
236 | OutStr("="); |
227 | OutInt((valu&0x7FFF)-(valu&0x8000));} |
237 | OutInt((valu&0x7FFF)-(valu&0x8000));} |
228 | else if (valu < -32768) { /* error # */ |
238 | else if (valu < -32768) { /* error # */ |
229 | OutStr("Err "); |
239 | OutStr("Err "); |
230 | OutInt(-valu-32768);} |
240 | OutInt(-valu-32768);} |
231 | else if (valu<0) { /* only logs IL sequence changes */ |
241 | else if (valu<0) { /* only logs IL sequence changes */ |
232 | OutStr(" IL+"); |
242 | OutStr(" IL+"); |
233 | OutHex(-Peek2(ILfront)-valu,3);} |
243 | OutHex(-Peek2(ILfront)-valu,3);} |
234 | else if (valu<65536) { /* TinyBasic line # */ |
244 | else if (valu<65536) { /* TinyBasic line # */ |
235 | OutStr("#"); |
245 | OutStr("#"); |
236 | OutInt(valu);} |
246 | OutInt(valu);} |
237 | else { /* poke memory byte */ |
247 | else { /* poke memory byte */ |
238 | OutStr("!"); |
248 | OutStr("!"); |
239 | OutHex(valu,4); |
249 | OutHex(valu,4); |
240 | OutStr("="); |
250 | OutStr("="); |
241 | OutInt(valu>>16);}} /* ~ShoLogVal */ |
251 | OutInt(valu>>16);}} /* ~ShoLogVal */ |
242 | 252 | ||
243 | void ShowLog(void) { /* display activity log for debugging */ |
253 | void ShowLog(void) { /* display activity log for debugging */ |
244 | int ix; |
254 | int ix; |
245 | OutLn(); |
255 | OutLn(); |
246 | OutStr("*** Activity Log @ "); |
256 | OutStr("*** Activity Log @ "); |
247 | OutInt(LogHere); |
257 | OutInt(LogHere); |
248 | OutStr(" ***"); |
258 | OutStr(" ***"); |
249 | if (LogHere >= LOGSIZE) /* circular, show only last 4K activities */ |
259 | if (LogHere >= LOGSIZE) /* circular, show only last 4K activities */ |
250 | for (ix=(LogHere&(LOGSIZE-1)); ix |
260 | for (ix=(LogHere&(LOGSIZE-1)); ix |
251 | for (ix=0; ix<(LogHere&(LOGSIZE-1)); ix++) ShoLogVal(ix); |
261 | for (ix=0; ix<(LogHere&(LOGSIZE-1)); ix++) ShoLogVal(ix); |
252 | OutLn(); |
262 | OutLn(); |
253 | OutStr("*****"); |
263 | OutStr("*****"); |
254 | OutLn();} /* ~ShowLog */ |
264 | OutLn();} /* ~ShowLog */ |
255 | 265 | ||
256 | void LogIt(int valu) { /* insert this valu into activity log */ |
266 | void LogIt(int valu) { /* insert this valu into activity log */ |
257 | DebugLog[(LogHere++)&(LOGSIZE-1)] = valu;} |
267 | DebugLog[(LogHere++)&(LOGSIZE-1)] = valu;} |
258 | 268 | ||
259 | /************************ Utility functions... ************************/ |
269 | /************************ Utility functions... ************************/ |
260 | 270 | ||
261 | void WarmStart(void) { /* initialize existing program */ |
271 | void WarmStart(void) { /* initialize existing program */ |
262 | UserEnd = Peek2(EndUser); |
272 | UserEnd = Peek2(EndUser); |
263 | SubStk = UserEnd; /* empty subroutine, expression stacks */ |
273 | SubStk = UserEnd; /* empty subroutine, expression stacks */ |
264 | Poke2(GoStkTop,SubStk); |
274 | Poke2(GoStkTop,SubStk); |
265 | ExpnTop = ExpnStk; |
275 | ExpnTop = ExpnStk; |
266 | Lino = 0; /* not in any line */ |
276 | Lino = 0; /* not in any line */ |
267 | ILPC = 0; /* start IL at front */ |
277 | ILPC = 0; /* start IL at front */ |
268 | SvPt = InLine; |
278 | SvPt = InLine; |
269 | BP = InLine; |
279 | BP = InLine; |
270 | Core[BP] = 0; |
280 | Core[BP] = 0; |
271 | Core[TabHere] = 0; |
281 | Core[TabHere] = 0; |
272 | InLend = InLine;} /* ~WarmStart */ |
282 | InLend = InLine;} /* ~WarmStart */ |
273 | 283 | ||
274 | void ColdStart(void) { /* initialize program to empty */ |
284 | void ColdStart(void) { /* initialize program to empty */ |
275 | if (Peek2(ILfront) != ILfront+2) ILend = Peek2(ILfront)+0x800; |
285 | if (Peek2(ILfront) != ILfront+2) ILend = Peek2(ILfront)+0x800; |
276 | Poke2(UserProg,(ILend+255)&-256); /* start Basic shortly after IL */ |
286 | Poke2(UserProg,(ILend+255)&-256); /* start Basic shortly after IL */ |
277 | if (CoreTop>65535) { |
287 | if (CoreTop>65535) { |
278 | Poke2(EndUser,65534); |
288 | Poke2(EndUser,65534); |
279 | Poke2(65534,0xDEAD);} |
289 | Poke2(65534,0xDEAD);} |
280 | else Poke2(EndUser,CoreTop); |
290 | else Poke2(EndUser,CoreTop); |
281 | WarmStart(); |
291 | WarmStart(); |
282 | SrcEnd = Peek2(UserProg); |
292 | SrcEnd = Peek2(UserProg); |
283 | Poke2(SrcEnd++,0); |
293 | Poke2(SrcEnd++,0); |
284 | Poke2(EndProg,++SrcEnd);} /* ~ColdStart */ |
294 | Poke2(EndProg,++SrcEnd);} /* ~ColdStart */ |
285 | 295 | ||
286 | void TBerror(void) { /* report interpreter error */ |
296 | void TBerror(void) { /* report interpreter error */ |
287 | if (ILPC == 0) return; /* already reported it */ |
297 | if (ILPC == 0) return; /* already reported it */ |
288 | OutLn(); |
298 | OutLn(); |
289 | LogIt(-ILPC-32768); |
299 | LogIt(-ILPC-32768); |
290 | OutStr("Tiny Basic error #"); /* IL address is the error # */ |
300 | OutStr("Tiny Basic error #"); /* IL address is the error # */ |
291 | OutInt(ILPC-Peek2(ILfront)); |
301 | OutInt(ILPC-Peek2(ILfront)); |
292 | // siemargl - add textual explain |
302 | // siemargl - add textual explain |
293 | OutStr(" - "); |
303 | OutStr(" - "); |
294 | OutStr(ExplainErr(ILPC-Peek2(ILfront))); |
304 | OutStr(ExplainErr(ILPC-Peek2(ILfront))); |
295 | 305 | ||
296 | if (Lino>0) { /* Lino=0 if in command line */ |
306 | if (Lino>0) { /* Lino=0 if in command line */ |
297 | OutStr(" at line "); |
307 | OutStr(" at line "); |
298 | OutInt(Lino);} |
308 | OutInt(Lino);} |
299 | OutLn(); |
309 | OutLn(); |
300 | if (Debugging>0) { /* some extra info if debugging.. */ |
310 | if (Debugging>0) { /* some extra info if debugging.. */ |
301 | ShowSubs(); |
311 | ShowSubs(); |
302 | ShowExSt(); |
312 | ShowExSt(); |
303 | ShowVars(0); |
313 | ShowVars(0); |
304 | OutStr(" [BP="); |
314 | OutStr(" [BP="); |
305 | OutHex(BP,4); |
315 | OutHex(BP,4); |
306 | OutStr(", TB@"); |
316 | OutStr(", TB@"); |
307 | OutHex(Peek2(UserProg),4); |
317 | OutHex(Peek2(UserProg),4); |
308 | OutStr(", IL@"); |
318 | OutStr(", IL@"); |
309 | OutHex(Peek2(ILfront),4); |
319 | OutHex(Peek2(ILfront),4); |
310 | OutStr("]"); |
320 | OutStr("]"); |
311 | ShoMemDump((BP-30)&-16,64);} |
321 | ShoMemDump((BP-30)&-16,64);} |
312 | Lino = 0; /* restart interpreter at front */ |
322 | Lino = 0; /* restart interpreter at front */ |
313 | ExpnTop = ExpnStk; /* with empty expression stack */ |
323 | ExpnTop = ExpnStk; /* with empty expression stack */ |
314 | ILPC = 0; /* cheap error test; interp reloads it from ILfront */ |
324 | ILPC = 0; /* cheap error test; interp reloads it from ILfront */ |
315 | BP = InLine;} /* ~TBerror */ |
325 | BP = InLine;} /* ~TBerror */ |
316 | 326 | ||
317 | void PushSub(int valu) { /* push value onto Gosub stack */ |
327 | void PushSub(int valu) { /* push value onto Gosub stack */ |
318 | if (SubStk<=SrcEnd) TBerror(); /* overflow: bumped into program end */ |
328 | if (SubStk<=SrcEnd) TBerror(); /* overflow: bumped into program end */ |
319 | else { |
329 | else { |
320 | SubStk = SubStk-2; |
330 | SubStk = SubStk-2; |
321 | Poke2(GoStkTop,SubStk); |
331 | Poke2(GoStkTop,SubStk); |
322 | Poke2(SubStk,valu);} |
332 | Poke2(SubStk,valu);} |
323 | if (Debugging>0) ShowSubs();} /* ~PushSub */ |
333 | if (Debugging>0) ShowSubs();} /* ~PushSub */ |
324 | 334 | ||
325 | int PopSub(void) { /* pop value off Gosub stack */ |
335 | int PopSub(void) { /* pop value off Gosub stack */ |
326 | if (SubStk>=Peek2(EndUser)-1) { /* underflow (nothing in stack).. */ |
336 | if (SubStk>=Peek2(EndUser)-1) { /* underflow (nothing in stack).. */ |
327 | TBerror(); |
337 | TBerror(); |
328 | return -1;} |
338 | return -1;} |
329 | else { |
339 | else { |
330 | if (Debugging>1) ShowSubs(); |
340 | if (Debugging>1) ShowSubs(); |
331 | SubStk = SubStk+2; |
341 | SubStk = SubStk+2; |
332 | Poke2(GoStkTop,SubStk); |
342 | Poke2(GoStkTop,SubStk); |
333 | return Peek2(SubStk-2);}} /* ~PopSub */ |
343 | return Peek2(SubStk-2);}} /* ~PopSub */ |
334 | 344 | ||
335 | void PushExBy(int valu) { /* push byte onto expression stack */ |
345 | void PushExBy(int valu) { /* push byte onto expression stack */ |
336 | if (ExpnTop<=InLend) TBerror(); /* overflow: bumped into input line */ |
346 | if (ExpnTop<=InLend) TBerror(); /* overflow: bumped into input line */ |
337 | else Core[--ExpnTop] = (aByte)(valu&255); |
347 | else Core[--ExpnTop] = (aByte)(valu&255); |
338 | if (Debugging>0) ShowExSt();} /* ~PushExBy */ |
348 | if (Debugging>0) ShowExSt();} /* ~PushExBy */ |
339 | 349 | ||
340 | int PopExBy(void) { /* pop byte off expression stack */ |
350 | int PopExBy(void) { /* pop byte off expression stack */ |
341 | if (ExpnTop |
351 | if (ExpnTop |
342 | TBerror(); /* underflow (nothing in stack) */ |
352 | TBerror(); /* underflow (nothing in stack) */ |
343 | return -1;} /* ~PopExBy */ |
353 | return -1;} /* ~PopExBy */ |
344 | 354 | ||
345 | void PushExInt(int valu) { /* push integer onto expression stack */ |
355 | void PushExInt(int valu) { /* push integer onto expression stack */ |
346 | ExpnTop = ExpnTop-2; |
356 | ExpnTop = ExpnTop-2; |
347 | if (ExpnTop |
357 | if (ExpnTop |
348 | else Poke2(ExpnTop,valu); |
358 | else Poke2(ExpnTop,valu); |
349 | if (Debugging>0) ShowExSt();} /* ~PushExInt */ |
359 | if (Debugging>0) ShowExSt();} /* ~PushExInt */ |
350 | 360 | ||
351 | int PopExInt(void) { /* pop integer off expression stack */ |
361 | int PopExInt(void) { /* pop integer off expression stack */ |
352 | if (++ExpnTop |
362 | if (++ExpnTop |
353 | TBerror(); /* underflow (nothing in stack) */ |
363 | TBerror(); /* underflow (nothing in stack) */ |
354 | return -1;} /* ~PopExInt */ |
364 | return -1;} /* ~PopExInt */ |
355 | 365 | ||
356 | int DeHex(char* txt, int ndigs) { /* decode hex -> int */ |
366 | int DeHex(char* txt, int ndigs) { /* decode hex -> int */ |
357 | int num = 0; |
367 | int num = 0; |
358 | char ch = ' '; |
368 | char ch = ' '; |
359 | while (ch<'0') /* first skip to num... */ |
369 | while (ch<'0') /* first skip to num... */ |
360 | if (ch == '\0') return -1; else ch = DeCaps[((int)*txt++)&127]; |
370 | if (ch == '\0') return -1; else ch = DeCaps[((int)*txt++)&127]; |
361 | if (ch>'F' || ch>'9' && ch<'A') return -1; /* not hex */ |
371 | if (ch>'F' || ch>'9' && ch<'A') return -1; /* not hex */ |
362 | while ((ndigs--) >0) { /* only get requested digits */ |
372 | while ((ndigs--) >0) { /* only get requested digits */ |
363 | if (ch<'0' || ch>'F') return num; /* not a hex digit */ |
373 | if (ch<'0' || ch>'F') return num; /* not a hex digit */ |
364 | if (ch>='A') num = num*16-55+((int)ch); /* A-F */ |
374 | if (ch>='A') num = num*16-55+((int)ch); /* A-F */ |
365 | else if (ch<='9') num = num*16-48+((int)ch); /* 0-9 */ |
375 | else if (ch<='9') num = num*16-48+((int)ch); /* 0-9 */ |
366 | else return num; /* something in between, i.e. not hex */ |
376 | else return num; /* something in between, i.e. not hex */ |
367 | ch = DeCaps[((int)*txt++)&127];} |
377 | ch = DeCaps[((int)*txt++)&127];} |
368 | return num;} /* ~DeHex */ |
378 | return num;} /* ~DeHex */ |
369 | 379 | ||
370 | int SkipTo(int here, char fch) { /* search for'd past next marker */ |
380 | int SkipTo(int here, char fch) { /* search for'd past next marker */ |
371 | while (true) { |
381 | while (true) { |
372 | char ch = (char)Core[here++]; /* look at next char */ |
382 | char ch = (char)Core[here++]; /* look at next char */ |
373 | if (ch == fch) return here; /* got it */ |
383 | if (ch == fch) return here; /* got it */ |
374 | if (ch == '\0') return --here;}} /* ~SkipTo */ |
384 | if (ch == '\0') return --here;}} /* ~SkipTo */ |
375 | 385 | ||
376 | int FindLine(int theLine) { /* find theLine in TB source code */ |
386 | int FindLine(int theLine) { /* find theLine in TB source code */ |
377 | int ix; |
387 | int ix; |
378 | int here = Peek2(UserProg); /* start at front */ |
388 | int here = Peek2(UserProg); /* start at front */ |
379 | while (true) { |
389 | while (true) { |
380 | ix = Peek2(here++); |
390 | ix = Peek2(here++); |
381 | if (theLine<=ix || ix==0) return --here; /* found it or overshot */ |
391 | if (theLine<=ix || ix==0) return --here; /* found it or overshot */ |
382 | here = SkipTo(++here, '\r');} /* skip to end of this line */ |
392 | here = SkipTo(++here, '\r');} /* skip to end of this line */ |
383 | } /* ~FindLine */ |
393 | } /* ~FindLine */ |
384 | 394 | ||
385 | void GoToLino(void) { /* find line # Lino and set BP to its front */ |
395 | void GoToLino(void) { /* find line # Lino and set BP to its front */ |
386 | int here; |
396 | int here; |
387 | if (Lino <= 0) { /* Lino=0 is just command line (OK).. */ |
397 | if (Lino <= 0) { /* Lino=0 is just command line (OK).. */ |
388 | BP = InLine; |
398 | BP = InLine; |
389 | if (DEBUGON>0) LogIt(0); |
399 | if (DEBUGON>0) LogIt(0); |
390 | return;} |
400 | return;} |
391 | if (DEBUGON>0) LogIt(Lino); |
401 | if (DEBUGON>0) LogIt(Lino); |
392 | if (Debugging>0) {OutStr(" [#"); OutInt(Lino); OutStr("]");} |
402 | if (Debugging>0) {OutStr(" [#"); OutInt(Lino); OutStr("]");} |
393 | BP = FindLine(Lino); /* otherwise try to find it.. */ |
403 | BP = FindLine(Lino); /* otherwise try to find it.. */ |
394 | here = Peek2(BP++); |
404 | here = Peek2(BP++); |
395 | if (here==0) TBerror(); /* ran off the end, error off */ |
405 | if (here==0) TBerror(); /* ran off the end, error off */ |
396 | else if (Lino != here) TBerror(); /* not there */ |
406 | else if (Lino != here) TBerror(); /* not there */ |
397 | else BP++;} /* ~GoToLino */ /* got it */ |
407 | else BP++;} /* ~GoToLino */ /* got it */ |
398 | 408 | ||
399 | void ListIt(int frm, int too) { /* list the stored program */ |
409 | void ListIt(int frm, int too) { /* list the stored program */ |
400 | char ch; |
410 | char ch; |
401 | int here; |
411 | int here; |
402 | if (frm==0) { /* 0,0 defaults to all; n,0 defaults to n,n */ |
412 | if (frm==0) { /* 0,0 defaults to all; n,0 defaults to n,n */ |
403 | too = 65535; |
413 | too = 65535; |
404 | frm = 1;} |
414 | frm = 1;} |
405 | else if (too==0) too = frm; |
415 | else if (too==0) too = frm; |
406 | here = FindLine(frm); /* try to find first line.. */ |
416 | here = FindLine(frm); /* try to find first line.. */ |
407 | while (!StopIt()) { |
417 | while (!StopIt()) { |
408 | frm = Peek2(here++); /* get this line's # to print it */ |
418 | frm = Peek2(here++); /* get this line's # to print it */ |
409 | if (frm>too || frm==0) break; |
419 | if (frm>too || frm==0) break; |
410 | here++; |
420 | here++; |
411 | OutInt(frm); |
421 | OutInt(frm); |
412 | Ouch(' '); |
422 | Ouch(' '); |
413 | do { /* print the text */ |
423 | do { /* print the text */ |
414 | ch = (char)Core[here++]; |
424 | ch = (char)Core[here++]; |
415 | Ouch(ch);} |
425 | Ouch(ch);} |
416 | while (ch>'\r');}} /* ~ListIt */ |
426 | while (ch>'\r');}} /* ~ListIt */ |
417 | 427 | ||
418 | void ConvtIL(char* txt) { /* convert & load TBIL code */ |
428 | void ConvtIL(char* txt) { /* convert & load TBIL code */ |
419 | int valu; |
429 | int valu; |
420 | ILend = ILfront+2; |
430 | ILend = ILfront+2; |
421 | Poke2(ILfront,ILend); /* initialize pointers as promised in TBEK */ |
431 | Poke2(ILfront,ILend); /* initialize pointers as promised in TBEK */ |
422 | Poke2(ColdGo+1,ILend); |
432 | Poke2(ColdGo+1,ILend); |
423 | Core[ILend] = (aByte)BadOp; /* illegal op, in case nothing loaded */ |
433 | Core[ILend] = (aByte)BadOp; /* illegal op, in case nothing loaded */ |
424 | if (txt == NULL) return; |
434 | if (txt == NULL) return; |
425 | while (*txt != '\0') { /* get the data.. */ |
435 | while (*txt != '\0') { /* get the data.. */ |
426 | while (*txt > '\r') txt++; /* (no code on 1st line) */ |
436 | while (*txt > '\r') txt++; /* (no code on 1st line) */ |
427 | if (*txt++ == '\0') break; /* no code at all */ |
437 | if (*txt++ == '\0') break; /* no code at all */ |
428 | while (*txt > ' ') txt++; /* skip over address */ |
438 | while (*txt > ' ') txt++; /* skip over address */ |
429 | if (*txt++ == '\0') break; |
439 | if (*txt++ == '\0') break; |
430 | while (true) { |
440 | while (true) { |
431 | valu = DeHex(txt++, 2); /* get a byte */ |
441 | valu = DeHex(txt++, 2); /* get a byte */ |
432 | if (valu<0) break; /* no more on this line */ |
442 | if (valu<0) break; /* no more on this line */ |
433 | Core[ILend++] = (aByte)valu; /* insert this byte into code */ |
443 | Core[ILend++] = (aByte)valu; /* insert this byte into code */ |
434 | txt++;}} |
444 | txt++;}} |
435 | XQhere = 0; /* requires new XQ to initialize */ |
445 | XQhere = 0; /* requires new XQ to initialize */ |
436 | Core[ILend] = 0;} /* ~ConvtIL */ |
446 | Core[ILend] = 0;} /* ~ConvtIL */ |
437 | 447 | ||
438 | void LineSwap(int here) { /* swap SvPt/BP if here is not in InLine */ |
448 | void LineSwap(int here) { /* swap SvPt/BP if here is not in InLine */ |
439 | if (here |
449 | if (here |
440 | here = SvPt; |
450 | here = SvPt; |
441 | SvPt = BP; |
451 | SvPt = BP; |
442 | BP = here;} |
452 | BP = here;} |
443 | else SvPt = BP;} /* ~LineSwap */ |
453 | else SvPt = BP;} /* ~LineSwap */ |
444 | 454 | ||
445 | /************************** Main Interpreter **************************/ |
455 | /************************** Main Interpreter **************************/ |
446 | 456 | ||
447 | void Interp(void) { |
457 | void Interp(void) { |
448 | char ch; /* comments from TinyBasic Experimenter's Kit, pp.15-21 */ |
458 | char ch; /* comments from TinyBasic Experimenter's Kit, pp.15-21 */ |
449 | int op, ix, here, chpt; /* temps */ |
459 | int op, ix, here, chpt; /* temps */ |
450 | Broken = false; /* initialize this for possible later test */ |
460 | Broken = false; /* initialize this for possible later test */ |
451 | while (true) { |
461 | while (true) { |
452 | if (StopIt()) { |
462 | if (StopIt()) { |
453 | Broken = false; |
463 | Broken = false; |
454 | OutLn(); |
464 | OutLn(); |
455 | OutStr("*** User Break ***"); |
465 | OutStr("*** User Break ***"); |
456 | TBerror();} |
466 | TBerror();} |
457 | if (ILPC==0) { |
467 | if (ILPC==0) { |
458 | ILPC = Peek2(ILfront); |
468 | ILPC = Peek2(ILfront); |
459 | if (DEBUGON>0) LogIt(-ILPC); |
469 | if (DEBUGON>0) LogIt(-ILPC); |
460 | if (Debugging>0) { |
470 | if (Debugging>0) { |
461 | OutLn(); OutStr("[IL="); OutHex(ILPC,4); OutStr("]");}} |
471 | OutLn(); OutStr("[IL="); OutHex(ILPC,4); OutStr("]");}} |
462 | if (DEBUGON>0) if (Watcher>0) { /* check watchpoint.. */ |
472 | if (DEBUGON>0) if (Watcher>0) { /* check watchpoint.. */ |
463 | if (((Watchee<0) && (Watchee+256+(int)Core[Watcher]) !=0) |
473 | if (((Watchee<0) && (Watchee+256+(int)Core[Watcher]) !=0) |
464 | || ((Watchee >= 0) && (Watchee==(int)Core[Watcher]))) { |
474 | || ((Watchee >= 0) && (Watchee==(int)Core[Watcher]))) { |
465 | OutLn(); |
475 | OutLn(); |
466 | OutStr("*** Watched "); |
476 | OutStr("*** Watched "); |
467 | OutHex(Watcher,4); |
477 | OutHex(Watcher,4); |
468 | OutStr(" = "); |
478 | OutStr(" = "); |
469 | OutInt((int)Core[Watcher]); |
479 | OutInt((int)Core[Watcher]); |
470 | OutStr(" *** "); |
480 | OutStr(" *** "); |
471 | Watcher = 0; |
481 | Watcher = 0; |
472 | TBerror(); |
482 | TBerror(); |
473 | continue;}} |
483 | continue;}} |
474 | op = (int)Core[ILPC++]; |
484 | op = (int)Core[ILPC++]; |
475 | if (Debugging>0) { |
485 | if (Debugging>0) { |
476 | OutLn(); OutStr("[IL+"); OutHex(ILPC-Peek2(ILfront)-1,3); |
486 | OutLn(); OutStr("[IL+"); OutHex(ILPC-Peek2(ILfront)-1,3); |
477 | OutStr("="); OutHex(op,2); OutStr("]");} |
487 | OutStr("="); OutHex(op,2); OutStr("]");} |
478 | switch (op>>5) { |
488 | switch (op>>5) { |
479 | default: switch (op) { |
489 | default: switch (op) { |
480 | case 15: |
490 | case 15: |
481 | TBerror(); |
491 | TBerror(); |
482 | return; |
492 | return; |
483 | 493 | ||
484 | /* SX n 00-07 Stack Exchange. */ |
494 | /* SX n 00-07 Stack Exchange. */ |
485 | /* Exchange the top byte of computational stack with */ |
495 | /* Exchange the top byte of computational stack with */ |
486 | /* that "n" bytes into the stack. The top/left byte of the stack is */ |
496 | /* that "n" bytes into the stack. The top/left byte of the stack is */ |
487 | /* considered to be byte 0, so SX 0 does nothing. */ |
497 | /* considered to be byte 0, so SX 0 does nothing. */ |
488 | case 1: case 2: case 3: case 4: case 5: case 6: case 7: |
498 | case 1: case 2: case 3: case 4: case 5: case 6: case 7: |
489 | if (ExpnTop+op>=ExpnStk) { /* swap is below stack depth */ |
499 | if (ExpnTop+op>=ExpnStk) { /* swap is below stack depth */ |
490 | TBerror(); |
500 | TBerror(); |
491 | return;} |
501 | return;} |
492 | ix = (int)Core[ExpnTop]; |
502 | ix = (int)Core[ExpnTop]; |
493 | Core[ExpnTop] = Core[ExpnTop+op]; |
503 | Core[ExpnTop] = Core[ExpnTop+op]; |
494 | Core[ExpnTop+op] = (aByte)ix; |
504 | Core[ExpnTop+op] = (aByte)ix; |
495 | if (Debugging>0) ShowExSt(); |
505 | if (Debugging>0) ShowExSt(); |
496 | break; |
506 | break; |
497 | 507 | ||
498 | /* LB n 09nn Push Literal Byte onto Stack. */ |
508 | /* LB n 09nn Push Literal Byte onto Stack. */ |
499 | /* This adds one byte to the expression stack, which */ |
509 | /* This adds one byte to the expression stack, which */ |
500 | /* is the second byte of the instruction. An error stop will occur if */ |
510 | /* is the second byte of the instruction. An error stop will occur if */ |
501 | /* the stack overflows. */ |
511 | /* the stack overflows. */ |
502 | case 9: |
512 | case 9: |
503 | PushExBy((int)Core[ILPC++]); /* push IL byte */ |
513 | PushExBy((int)Core[ILPC++]); /* push IL byte */ |
504 | break; |
514 | break; |
505 | 515 | ||
506 | /* LN n 0Annnn Push Literal Number. */ |
516 | /* LN n 0Annnn Push Literal Number. */ |
507 | /* This adds the following two bytes to the */ |
517 | /* This adds the following two bytes to the */ |
508 | /* computational stack, as a 16-bit number. Stack overflow results in */ |
518 | /* computational stack, as a 16-bit number. Stack overflow results in */ |
509 | /* an error stop. Numbers are assumed to be Big-Endian. */ |
519 | /* an error stop. Numbers are assumed to be Big-Endian. */ |
510 | case 10: |
520 | case 10: |
511 | PushExInt(Peek2(ILPC++)); /* get next 2 IL bytes */ |
521 | PushExInt(Peek2(ILPC++)); /* get next 2 IL bytes */ |
512 | ILPC++; |
522 | ILPC++; |
513 | break; |
523 | break; |
514 | 524 | ||
515 | /* DS 0B Duplicate Top Number (two bytes) on Stack. */ |
525 | /* DS 0B Duplicate Top Number (two bytes) on Stack. */ |
516 | /* An error stop will occur if there are less than 2 */ |
526 | /* An error stop will occur if there are less than 2 */ |
517 | /* bytes (1 int) on the expression stack or if the stack overflows. */ |
527 | /* bytes (1 int) on the expression stack or if the stack overflows. */ |
518 | case 11: |
528 | case 11: |
519 | op = ExpnTop; |
529 | op = ExpnTop; |
520 | ix = PopExInt(); |
530 | ix = PopExInt(); |
521 | if (ILPC == 0) break; /* underflow */ |
531 | if (ILPC == 0) break; /* underflow */ |
522 | ExpnTop = op; |
532 | ExpnTop = op; |
523 | PushExInt(ix); |
533 | PushExInt(ix); |
524 | break; |
534 | break; |
525 | 535 | ||
526 | /* SP 0C Stack Pop. */ |
536 | /* SP 0C Stack Pop. */ |
527 | /* The top two bytes are removed from the expression */ |
537 | /* The top two bytes are removed from the expression */ |
528 | /* stack and discarded. Underflow results in an error stop. */ |
538 | /* stack and discarded. Underflow results in an error stop. */ |
529 | case 12: |
539 | case 12: |
530 | ix = PopExInt(); |
540 | ix = PopExInt(); |
531 | if (Debugging>0) ShowExSt(); |
541 | if (Debugging>0) ShowExSt(); |
532 | break; |
542 | break; |
533 | 543 | ||
534 | /* SB 10 Save BASIC Pointer. */ |
544 | /* SB 10 Save BASIC Pointer. */ |
535 | /* If BASIC pointer is pointing into the input line */ |
545 | /* If BASIC pointer is pointing into the input line */ |
536 | /* buffer, it is copied to the Saved Pointer; otherwise the two */ |
546 | /* buffer, it is copied to the Saved Pointer; otherwise the two */ |
537 | /* pointers are exchanged. */ |
547 | /* pointers are exchanged. */ |
538 | case 16: |
548 | case 16: |
539 | LineSwap(BP); |
549 | LineSwap(BP); |
540 | break; |
550 | break; |
541 | 551 | ||
542 | /* RB 11 Restore BASIC Pointer. */ |
552 | /* RB 11 Restore BASIC Pointer. */ |
543 | /* If the Saved Pointer points into the input line */ |
553 | /* If the Saved Pointer points into the input line */ |
544 | /* buffer, it is replaced by the value in the BASIC pointer; */ |
554 | /* buffer, it is replaced by the value in the BASIC pointer; */ |
545 | /* otherwise the two pointers are exchanged. */ |
555 | /* otherwise the two pointers are exchanged. */ |
546 | case 17: |
556 | case 17: |
547 | LineSwap(SvPt); |
557 | LineSwap(SvPt); |
548 | break; |
558 | break; |
549 | 559 | ||
550 | /* FV 12 Fetch Variable. */ |
560 | /* FV 12 Fetch Variable. */ |
551 | /* The top byte of the computational stack is used to */ |
561 | /* The top byte of the computational stack is used to */ |
552 | /* index into Page 00. It is replaced by the two bytes fetched. Error */ |
562 | /* index into Page 00. It is replaced by the two bytes fetched. Error */ |
553 | /* stops occur with stack overflow or underflow. */ |
563 | /* stops occur with stack overflow or underflow. */ |
554 | case 18: |
564 | case 18: |
555 | op = PopExBy(); |
565 | op = PopExBy(); |
556 | if (ILPC != 0) PushExInt(Peek2(op)); |
566 | if (ILPC != 0) PushExInt(Peek2(op)); |
557 | if (Debugging>1) ShowVars(op); |
567 | if (Debugging>1) ShowVars(op); |
558 | break; |
568 | break; |
559 | 569 | ||
560 | /* SV 13 Store Variable. */ |
570 | /* SV 13 Store Variable. */ |
561 | /* The top two bytes of the computational stack are */ |
571 | /* The top two bytes of the computational stack are */ |
562 | /* stored into memory at the Page 00 address specified by the third */ |
572 | /* stored into memory at the Page 00 address specified by the third */ |
563 | /* byte on the stack. All three bytes are deleted from the stack. */ |
573 | /* byte on the stack. All three bytes are deleted from the stack. */ |
564 | /* Underflow results in an error stop. */ |
574 | /* Underflow results in an error stop. */ |
565 | case 19: |
575 | case 19: |
566 | ix = PopExInt(); |
576 | ix = PopExInt(); |
567 | op = PopExBy(); |
577 | op = PopExBy(); |
568 | if (ILPC == 0) break; |
578 | if (ILPC == 0) break; |
569 | Poke2(op,ix); |
579 | Poke2(op,ix); |
570 | if (DEBUGON>0) LogIt((ix&0xFFFF)+((op-256)<<16)); |
580 | if (DEBUGON>0) LogIt((ix&0xFFFF)+((op-256)<<16)); |
571 | if (Debugging>0) {ShowVars(op); if (Debugging>1) ShowExSt();} |
581 | if (Debugging>0) {ShowVars(op); if (Debugging>1) ShowExSt();} |
572 | break; |
582 | break; |
573 | 583 | ||
574 | /* GS 14 GOSUB Save. */ |
584 | /* GS 14 GOSUB Save. */ |
575 | /* The current BASIC line number is pushed */ |
585 | /* The current BASIC line number is pushed */ |
576 | /* onto the BASIC region of the control stack. It is essential that */ |
586 | /* onto the BASIC region of the control stack. It is essential that */ |
577 | /* the IL stack be empty for this to work properly but no check is */ |
587 | /* the IL stack be empty for this to work properly but no check is */ |
578 | /* made for that condition. An error stop occurs on stack overflow. */ |
588 | /* made for that condition. An error stop occurs on stack overflow. */ |
579 | case 20: |
589 | case 20: |
580 | PushSub(Lino); /* push line # (possibly =0) */ |
590 | PushSub(Lino); /* push line # (possibly =0) */ |
581 | break; |
591 | break; |
582 | 592 | ||
583 | /* RS 15 Restore Saved Line. */ |
593 | /* RS 15 Restore Saved Line. */ |
584 | /* Pop the top two bytes off the BASIC region of the */ |
594 | /* Pop the top two bytes off the BASIC region of the */ |
585 | /* control stack, making them the current line number. Set the BASIC */ |
595 | /* control stack, making them the current line number. Set the BASIC */ |
586 | /* pointer at the beginning of that line. Note that this is the line */ |
596 | /* pointer at the beginning of that line. Note that this is the line */ |
587 | /* containing the GOSUB which caused the line number to be saved. As */ |
597 | /* containing the GOSUB which caused the line number to be saved. As */ |
588 | /* with the GS opcode, it is essential that the IL region of the */ |
598 | /* with the GS opcode, it is essential that the IL region of the */ |
589 | /* control stack be empty. If the line number popped off the stack */ |
599 | /* control stack be empty. If the line number popped off the stack */ |
590 | /* does not correspond to a line in the BASIC program an error stop */ |
600 | /* does not correspond to a line in the BASIC program an error stop */ |
591 | /* occurs. An error stop also results from stack underflow. */ |
601 | /* occurs. An error stop also results from stack underflow. */ |
592 | case 21: |
602 | case 21: |
593 | Lino = PopSub(); /* get line # (possibly =0) from pop */ |
603 | Lino = PopSub(); /* get line # (possibly =0) from pop */ |
594 | if (ILPC != 0) GoToLino() ; /* stops run if error */ |
604 | if (ILPC != 0) GoToLino() ; /* stops run if error */ |
595 | break; |
605 | break; |
596 | 606 | ||
597 | /* GO 16 GOTO. */ |
607 | /* GO 16 GOTO. */ |
598 | /* Make current the BASIC line whose line number is */ |
608 | /* Make current the BASIC line whose line number is */ |
599 | /* equal to the value of the top two bytes in the expression stack. */ |
609 | /* equal to the value of the top two bytes in the expression stack. */ |
600 | /* That is, the top two bytes are popped off the computational stack, */ |
610 | /* That is, the top two bytes are popped off the computational stack, */ |
601 | /* and the BASIC program is searched until a matching line number is */ |
611 | /* and the BASIC program is searched until a matching line number is */ |
602 | /* found. The BASIC pointer is then positioned at the beginning of */ |
612 | /* found. The BASIC pointer is then positioned at the beginning of */ |
603 | /* that line and the RUN mode flag is turned on. Stack underflow and */ |
613 | /* that line and the RUN mode flag is turned on. Stack underflow and */ |
604 | /* non-existent BASIC line result in error stops. */ |
614 | /* non-existent BASIC line result in error stops. */ |
605 | case 22: |
615 | case 22: |
606 | ILPC = XQhere; /* the IL assumes an implied NX */ |
616 | ILPC = XQhere; /* the IL assumes an implied NX */ |
607 | if (DEBUGON>0) LogIt(-ILPC); |
617 | if (DEBUGON>0) LogIt(-ILPC); |
608 | Lino = PopExInt(); |
618 | Lino = PopExInt(); |
609 | if (ILPC != 0) GoToLino() ; /* stops run if error */ |
619 | if (ILPC != 0) GoToLino() ; /* stops run if error */ |
610 | break; |
620 | break; |
611 | 621 | ||
612 | /* NE 17 Negate (two's complement). */ |
622 | /* NE 17 Negate (two's complement). */ |
613 | /* The number in the top two bytes of the expression */ |
623 | /* The number in the top two bytes of the expression */ |
614 | /* stack is replaced with its negative. */ |
624 | /* stack is replaced with its negative. */ |
615 | case 23: |
625 | case 23: |
616 | ix = PopExInt(); |
626 | ix = PopExInt(); |
617 | if (ILPC != 0) PushExInt(-ix); |
627 | if (ILPC != 0) PushExInt(-ix); |
618 | break; |
628 | break; |
619 | 629 | ||
620 | /* AD 18 Add. */ |
630 | /* AD 18 Add. */ |
621 | /* Add the two numbers represented by the top four */ |
631 | /* Add the two numbers represented by the top four */ |
622 | /* bytes of the expression stack, and replace them with the two-byte */ |
632 | /* bytes of the expression stack, and replace them with the two-byte */ |
623 | /* sum. Stack underflow results in an error stop. */ |
633 | /* sum. Stack underflow results in an error stop. */ |
624 | case 24: |
634 | case 24: |
625 | ix = PopExInt(); |
635 | ix = PopExInt(); |
626 | op = PopExInt(); |
636 | op = PopExInt(); |
627 | if (ILPC != 0) PushExInt(op+ix); |
637 | if (ILPC != 0) PushExInt(op+ix); |
628 | break; |
638 | break; |
629 | 639 | ||
630 | /* SU 19 Subtract. */ |
640 | /* SU 19 Subtract. */ |
631 | /* Subtract the two-byte number on the top of the */ |
641 | /* Subtract the two-byte number on the top of the */ |
632 | /* expression stack from the next two bytes and replace the 4 bytes */ |
642 | /* expression stack from the next two bytes and replace the 4 bytes */ |
633 | /* with the two-byte difference. */ |
643 | /* with the two-byte difference. */ |
634 | case 25: |
644 | case 25: |
635 | ix = PopExInt(); |
645 | ix = PopExInt(); |
636 | op = PopExInt(); |
646 | op = PopExInt(); |
637 | if (ILPC != 0) PushExInt(op-ix); |
647 | if (ILPC != 0) PushExInt(op-ix); |
638 | break; |
648 | break; |
639 | 649 | ||
640 | /* MP 1A Multiply. */ |
650 | /* MP 1A Multiply. */ |
641 | /* Multiply the two numbers represented by the top 4 */ |
651 | /* Multiply the two numbers represented by the top 4 */ |
642 | /* bytes of the computational stack, and replace them with the least */ |
652 | /* bytes of the computational stack, and replace them with the least */ |
643 | /* significant 16 bits of the product. Stack underflow is possible. */ |
653 | /* significant 16 bits of the product. Stack underflow is possible. */ |
644 | case 26: |
654 | case 26: |
645 | ix = PopExInt(); |
655 | ix = PopExInt(); |
646 | op = PopExInt(); |
656 | op = PopExInt(); |
647 | if (ILPC != 0) PushExInt(op*ix); |
657 | if (ILPC != 0) PushExInt(op*ix); |
648 | break; |
658 | break; |
649 | 659 | ||
650 | /* DV 1B Divide. */ |
660 | /* DV 1B Divide. */ |
651 | /* Divide the number represented by the top two bytes */ |
661 | /* Divide the number represented by the top two bytes */ |
652 | /* of the computational stack into that represented by the next two. */ |
662 | /* of the computational stack into that represented by the next two. */ |
653 | /* Replace the 4 bytes with the quotient and discard the remainder. */ |
663 | /* Replace the 4 bytes with the quotient and discard the remainder. */ |
654 | /* This is a signed (two's complement) integer divide, resulting in a */ |
664 | /* This is a signed (two's complement) integer divide, resulting in a */ |
655 | /* signed integer quotient. Stack underflow or attempted division by */ |
665 | /* signed integer quotient. Stack underflow or attempted division by */ |
656 | /* zero result in an error stop. */ |
666 | /* zero result in an error stop. */ |
657 | case 27: |
667 | case 27: |
658 | ix = PopExInt(); |
668 | ix = PopExInt(); |
659 | op = PopExInt(); |
669 | op = PopExInt(); |
660 | if (ix == 0) TBerror(); /* divide by 0.. */ |
670 | if (ix == 0) TBerror(); /* divide by 0.. */ |
661 | else if (ILPC != 0) PushExInt(op/ix); |
671 | else if (ILPC != 0) PushExInt(op/ix); |
662 | break; |
672 | break; |
663 | 673 | ||
664 | /* CP 1C Compare. */ |
674 | /* CP 1C Compare. */ |
665 | /* The number in the top two bytes of the expression */ |
675 | /* The number in the top two bytes of the expression */ |
666 | /* stack is compared to (subtracted from) the number in the 4th and */ |
676 | /* stack is compared to (subtracted from) the number in the 4th and */ |
667 | /* fifth bytes of the stack, and the result is determined to be */ |
677 | /* fifth bytes of the stack, and the result is determined to be */ |
668 | /* Greater, Equal, or Less. The low three bits of the third byte mask */ |
678 | /* Greater, Equal, or Less. The low three bits of the third byte mask */ |
669 | /* a conditional skip in the IL program to test these conditions; if */ |
679 | /* a conditional skip in the IL program to test these conditions; if */ |
670 | /* the result corresponds to a one bit, the next byte of the IL code */ |
680 | /* the result corresponds to a one bit, the next byte of the IL code */ |
671 | /* is skipped and not executed. The three bits correspond to the */ |
681 | /* is skipped and not executed. The three bits correspond to the */ |
672 | /* conditions as follows: */ |
682 | /* conditions as follows: */ |
673 | /* bit 0 Result is Less */ |
683 | /* bit 0 Result is Less */ |
674 | /* bit 1 Result is Equal */ |
684 | /* bit 1 Result is Equal */ |
675 | /* bit 2 Result is Greater */ |
685 | /* bit 2 Result is Greater */ |
676 | /* Whether the skip is taken or not, all five bytes are deleted from */ |
686 | /* Whether the skip is taken or not, all five bytes are deleted from */ |
677 | /* the stack. This is a signed (two's complement) comparison so that */ |
687 | /* the stack. This is a signed (two's complement) comparison so that */ |
678 | /* any positive number is greater than any negative number. Multiple */ |
688 | /* any positive number is greater than any negative number. Multiple */ |
679 | /* conditions, such as greater-than-or-equal or unequal (i.e.greater- */ |
689 | /* conditions, such as greater-than-or-equal or unequal (i.e.greater- */ |
680 | /* than-or-less-than), may be tested by forming the condition mask */ |
690 | /* than-or-less-than), may be tested by forming the condition mask */ |
681 | /* byte of the sum of the respective bits. In particular, a mask byte */ |
691 | /* byte of the sum of the respective bits. In particular, a mask byte */ |
682 | /* of 7 will force an unconditional skip and a mask byte of 0 will */ |
692 | /* of 7 will force an unconditional skip and a mask byte of 0 will */ |
683 | /* force no skip. The other 5 bits of the control byte are ignored. */ |
693 | /* force no skip. The other 5 bits of the control byte are ignored. */ |
684 | /* Stack underflow results in an error stop. */ |
694 | /* Stack underflow results in an error stop. */ |
685 | case 28: |
695 | case 28: |
686 | ix = PopExInt(); |
696 | ix = PopExInt(); |
687 | op = PopExBy(); |
697 | op = PopExBy(); |
688 | ix = PopExInt()-ix; /* <0 or =0 or >0 */ |
698 | ix = PopExInt()-ix; /* <0 or =0 or >0 */ |
689 | if (ILPC == 0) return; /* underflow.. */ |
699 | if (ILPC == 0) return; /* underflow.. */ |
690 | if (ix<0) ix = 1; |
700 | if (ix<0) ix = 1; |
691 | else if (ix>0) ix = 4; /* choose the bit to test */ |
701 | else if (ix>0) ix = 4; /* choose the bit to test */ |
692 | else ix = 2; |
702 | else ix = 2; |
693 | if ((ix&op)>0) ILPC++; /* skip next IL op if bit =1 */ |
703 | if ((ix&op)>0) ILPC++; /* skip next IL op if bit =1 */ |
694 | if (Debugging>0) ShowExSt(); |
704 | if (Debugging>0) ShowExSt(); |
695 | break; |
705 | break; |
696 | 706 | ||
697 | /* NX 1D Next BASIC Statement. */ |
707 | /* NX 1D Next BASIC Statement. */ |
698 | /* Advance to next line in the BASIC program, if in */ |
708 | /* Advance to next line in the BASIC program, if in */ |
699 | /* RUN mode, or restart the IL program if in the command mode. The */ |
709 | /* RUN mode, or restart the IL program if in the command mode. The */ |
700 | /* remainder of the current line is ignored. In the Run mode if there */ |
710 | /* remainder of the current line is ignored. In the Run mode if there */ |
701 | /* is another line it becomes current with the pointer positioned at */ |
711 | /* is another line it becomes current with the pointer positioned at */ |
702 | /* its beginning. At this time, if the Break condition returns true, */ |
712 | /* its beginning. At this time, if the Break condition returns true, */ |
703 | /* execution is aborted and the IL program is restarted after */ |
713 | /* execution is aborted and the IL program is restarted after */ |
704 | /* printing an error message. Otherwise IL execution proceeds from */ |
714 | /* printing an error message. Otherwise IL execution proceeds from */ |
705 | /* the saved IL address (see the XQ instruction). If there are no */ |
715 | /* the saved IL address (see the XQ instruction). If there are no */ |
706 | /* more BASIC statements in the program an error stop occurs. */ |
716 | /* more BASIC statements in the program an error stop occurs. */ |
707 | case 29: |
717 | case 29: |
708 | if (Lino == 0) ILPC = 0; |
718 | if (Lino == 0) ILPC = 0; |
709 | else { |
719 | else { |
710 | BP = SkipTo(BP, '\r'); /* skip to end of this line */ |
720 | BP = SkipTo(BP, '\r'); /* skip to end of this line */ |
711 | Lino = Peek2(BP++); /* get line # */ |
721 | Lino = Peek2(BP++); /* get line # */ |
712 | if (Lino==0) { /* ran off the end */ |
722 | if (Lino==0) { /* ran off the end */ |
713 | TBerror(); |
723 | TBerror(); |
714 | break;} |
724 | break;} |
715 | else BP++; |
725 | else BP++; |
716 | ILPC = XQhere; /* restart at saved IL address (XQ) */ |
726 | ILPC = XQhere; /* restart at saved IL address (XQ) */ |
717 | if (DEBUGON>0) LogIt(-ILPC);} |
727 | if (DEBUGON>0) LogIt(-ILPC);} |
718 | if (DEBUGON>0) LogIt(Lino); |
728 | if (DEBUGON>0) LogIt(Lino); |
719 | if (Debugging>0) {OutStr(" [#"); OutInt(Lino); OutStr("]");} |
729 | if (Debugging>0) {OutStr(" [#"); OutInt(Lino); OutStr("]");} |
720 | break; |
730 | break; |
721 | 731 | ||
722 | /* LS 1F List The Program. */ |
732 | /* LS 1F List The Program. */ |
723 | /* The expression stack is assumed to have two 2-byte */ |
733 | /* The expression stack is assumed to have two 2-byte */ |
724 | /* numbers. The top number is the line number of the last line to be */ |
734 | /* numbers. The top number is the line number of the last line to be */ |
725 | /* listed, and the next is the line number of the first line to be */ |
735 | /* listed, and the next is the line number of the first line to be */ |
726 | /* listed. If the specified line numbers do not exist in the program, */ |
736 | /* listed. If the specified line numbers do not exist in the program, */ |
727 | /* the next available line (i.e. with the next higher line number) is */ |
737 | /* the next available line (i.e. with the next higher line number) is */ |
728 | /* assumed instead in each case. If the last line to be listed comes */ |
738 | /* assumed instead in each case. If the last line to be listed comes */ |
729 | /* before the first, no lines are listed. If Break condition comes */ |
739 | /* before the first, no lines are listed. If Break condition comes */ |
730 | /* true during a List operation, the remainder of the listing is */ |
740 | /* true during a List operation, the remainder of the listing is */ |
731 | /* aborted. Zero is not a valid line number, and an error stop occurs */ |
741 | /* aborted. Zero is not a valid line number, and an error stop occurs */ |
732 | /* if either line number specification is zero. The line number */ |
742 | /* if either line number specification is zero. The line number */ |
733 | /* specifications are deleted from the stack. */ |
743 | /* specifications are deleted from the stack. */ |
734 | case 31: |
744 | case 31: |
735 | op = 0; |
745 | op = 0; |
736 | ix = 0; /* The IL seems to assume we can handle zero */ |
746 | ix = 0; /* The IL seems to assume we can handle zero */ |
737 | while (ExpnTop |
747 | while (ExpnTop |
738 | op = ix; |
748 | op = ix; |
739 | ix = PopExInt();} /* get final line #, then initial.. */ |
749 | ix = PopExInt();} /* get final line #, then initial.. */ |
740 | if (op<0 || ix<0) TBerror(); |
750 | if (op<0 || ix<0) TBerror(); |
741 | else ListIt(ix,op); |
751 | else ListIt(ix,op); |
742 | break; |
752 | break; |
743 | 753 | ||
744 | /* PN 20 Print Number. */ |
754 | /* PN 20 Print Number. */ |
745 | /* The number represented by the top two bytes of the */ |
755 | /* The number represented by the top two bytes of the */ |
746 | /* expression stack is printed in decimal with leading zero */ |
756 | /* expression stack is printed in decimal with leading zero */ |
747 | /* suppression. If it is negative, it is preceded by a minus sign */ |
757 | /* suppression. If it is negative, it is preceded by a minus sign */ |
748 | /* and the magnitude is printed. Stack underflow is possible. */ |
758 | /* and the magnitude is printed. Stack underflow is possible. */ |
749 | case 32: |
759 | case 32: |
750 | ix = PopExInt(); |
760 | ix = PopExInt(); |
751 | if (ILPC != 0) OutInt(ix); |
761 | if (ILPC != 0) OutInt(ix); |
752 | break; |
762 | break; |
753 | 763 | ||
754 | /* PQ 21 Print BASIC String. */ |
764 | /* PQ 21 Print BASIC String. */ |
755 | /* The ASCII characters beginning with the current */ |
765 | /* The ASCII characters beginning with the current */ |
756 | /* position of BASIC pointer are printed on the console. The string */ |
766 | /* position of BASIC pointer are printed on the console. The string */ |
757 | /* to be printed is terminated by quotation mark ("), and the BASIC */ |
767 | /* to be printed is terminated by quotation mark ("), and the BASIC */ |
758 | /* pointer is left at the character following the terminal quote. An */ |
768 | /* pointer is left at the character following the terminal quote. An */ |
759 | /* error stop occurs if a carriage return is imbedded in the string. */ |
769 | /* error stop occurs if a carriage return is imbedded in the string. */ |
760 | case 33: |
770 | case 33: |
761 | while (true) { |
771 | while (true) { |
762 | ch = (char)Core[BP++]; |
772 | ch = (char)Core[BP++]; |
763 | if (ch=='\"') break; /* done on final quote */ |
773 | if (ch=='\"') break; /* done on final quote */ |
764 | if (ch<' ') { /* error if return or other control char */ |
774 | if (ch<' ') { /* error if return or other control char */ |
765 | TBerror(); |
775 | TBerror(); |
766 | break;} |
776 | break;} |
767 | Ouch(ch);} /* print it */ |
777 | Ouch(ch);} /* print it */ |
768 | break; |
778 | break; |
769 | 779 | ||
770 | /* PT 22 Print Tab. */ |
780 | /* PT 22 Print Tab. */ |
771 | /* Print one or more spaces on the console, ending at */ |
781 | /* Print one or more spaces on the console, ending at */ |
772 | /* the next multiple of eight character positions (from the left */ |
782 | /* the next multiple of eight character positions (from the left */ |
773 | /* margin). */ |
783 | /* margin). */ |
774 | case 34: |
784 | case 34: |
775 | do {Ouch(' ');} while (Core[TabHere]%8>0); |
785 | do {Ouch(' ');} while (Core[TabHere]%8>0); |
776 | break; |
786 | break; |
777 | 787 | ||
778 | /* NL 23 New Line. */ |
788 | /* NL 23 New Line. */ |
779 | /* Output a carriage-return-linefeed sequence to the */ |
789 | /* Output a carriage-return-linefeed sequence to the */ |
780 | /* console. */ |
790 | /* console. */ |
781 | case 35: |
791 | case 35: |
782 | Ouch('\r'); |
792 | Ouch('\r'); |
783 | break; |
793 | break; |
784 | 794 | ||
785 | /* PC "xxxx" 24xxxxxxXx Print Literal String. */ |
795 | /* PC "xxxx" 24xxxxxxXx Print Literal String. */ |
786 | /* The ASCII string follows opcode and its */ |
796 | /* The ASCII string follows opcode and its */ |
787 | /* last byte has the most significant bit set to one. */ |
797 | /* last byte has the most significant bit set to one. */ |
788 | case 36: |
798 | case 36: |
789 | do { |
799 | do { |
790 | ix = (int)Core[ILPC++]; |
800 | ix = (int)Core[ILPC++]; |
791 | Ouch((char)(ix&127)); /* strip high bit for output */ |
801 | Ouch((char)(ix&127)); /* strip high bit for output */ |
792 | } while ((ix&128)==0); |
802 | } while ((ix&128)==0); |
793 | break; |
803 | break; |
794 | 804 | ||
795 | /* GL 27 Get Input Line. */ |
805 | /* GL 27 Get Input Line. */ |
796 | /* ASCII characters are accepted from console input */ |
806 | /* ASCII characters are accepted from console input */ |
797 | /* to fill the line buffer. If the line length exceeds the available */ |
807 | /* to fill the line buffer. If the line length exceeds the available */ |
798 | /* space, the excess characters are ignored and bell characters are */ |
808 | /* space, the excess characters are ignored and bell characters are */ |
799 | /* output. The line is terminated by a carriage return. On completing */ |
809 | /* output. The line is terminated by a carriage return. On completing */ |
800 | /* one line of input, the BASIC pointer is set to point to the first */ |
810 | /* one line of input, the BASIC pointer is set to point to the first */ |
801 | /* character in the input line buffer, and a carriage-return-linefeed */ |
811 | /* character in the input line buffer, and a carriage-return-linefeed */ |
802 | /* sequence is [not] output. */ |
812 | /* sequence is [not] output. */ |
803 | case 39: |
813 | case 39: |
804 | InLend = InLine; |
814 | InLend = InLine; |
805 | while (true) { /* read input line characters... */ |
815 | while (true) { /* read input line characters... */ |
806 | ch = Inch(); |
816 | ch = Inch(); |
- | 817 | if (!ch) continue; |
|
807 | if (ch=='\r') break; /* end of the line */ |
818 | else if (ch=='\r') break; /* end of the line */ |
808 | else if (ch=='\t') { |
819 | else if (ch=='\t') { |
809 | Debugging = (Debugging+DEBUGON)&1; /* maybe toggle debug */ |
820 | Debugging = (Debugging+DEBUGON)&1; /* maybe toggle debug */ |
810 | ch = ' ';} /* convert tabs to space */ |
821 | ch = ' ';} /* convert tabs to space */ |
811 | else if (ch==(char)Core[BScode]) { /* backspace code */ |
822 | else if (ch==(char)Core[BScode]) { /* backspace code */ |
812 | if (InLend>InLine) InLend--; /* assume console already */ |
823 | if (InLend>InLine) InLend--; /* assume console already */ |
813 | else { /* backing up over front of line: just kill it.. */ |
824 | else { /* backing up over front of line: just kill it.. */ |
814 | Ouch('\r'); |
825 | Ouch('\r'); |
815 | break;}} |
826 | break;}} |
816 | else if (ch==(char)Core[CanCode]) { /* cancel this line */ |
827 | else if (ch==(char)Core[CanCode]) { /* cancel this line */ |
817 | InLend = InLine; |
828 | InLend = InLine; |
818 | Ouch('\r'); /* also start a new input line */ |
829 | Ouch('\r'); /* also start a new input line */ |
819 | break;} |
830 | break;} |
820 | else if (ch<' ') continue; /* ignore non-ASCII & controls */ |
831 | else if (ch<' ') continue; /* ignore non-ASCII & controls */ |
821 | else if (ch>'~') continue; |
832 | else if (ch>'~') continue; |
822 | if (InLend>ExpnTop-2) continue; /* discard overrun chars */ |
833 | if (InLend>ExpnTop-2) continue; /* discard overrun chars */ |
823 | /* Siemargl fix for not so smart consoles*/ |
834 | /* Siemargl fix for not so smart consoles*/ |
824 | if (ch != (char)Core[BScode]) |
835 | if (ch != (char)Core[BScode]) |
825 | Core[InLend++] = (aByte)ch; |
836 | Core[InLend++] = (aByte)ch; |
826 | } /* insert this char in buffer */ |
837 | } /* insert this char in buffer */ |
827 | while (InLend>InLine && Core[InLend-1] == ' ') |
838 | while (InLend>InLine && Core[InLend-1] == ' ') |
828 | InLend--; /* delete excess trailing spaces */ |
839 | InLend--; /* delete excess trailing spaces */ |
829 | Core[InLend++] = (aByte) '\r'; /* insert final return & null */ |
840 | Core[InLend++] = (aByte) '\r'; /* insert final return & null */ |
830 | Core[InLend] = 0; |
841 | Core[InLend] = 0; |
831 | BP = InLine; |
842 | BP = InLine; |
832 | break; |
843 | break; |
833 | 844 | ||
834 | /* IL 2A Insert BASIC Line. */ |
845 | /* IL 2A Insert BASIC Line. */ |
835 | /* Beginning with the current position of the BASIC */ |
846 | /* Beginning with the current position of the BASIC */ |
836 | /* pointer and continuing to the [end of it], the line is inserted */ |
847 | /* pointer and continuing to the [end of it], the line is inserted */ |
837 | /* into the BASIC program space; for a line number, the top two bytes */ |
848 | /* into the BASIC program space; for a line number, the top two bytes */ |
838 | /* of the expression stack are used. If this number matches a line */ |
849 | /* of the expression stack are used. If this number matches a line */ |
839 | /* already in the program it is deleted and the new one replaces it. */ |
850 | /* already in the program it is deleted and the new one replaces it. */ |
840 | /* If the new line consists of only a carriage return, it is not */ |
851 | /* If the new line consists of only a carriage return, it is not */ |
841 | /* inserted, though any previous line with the same number will have */ |
852 | /* inserted, though any previous line with the same number will have */ |
842 | /* been deleted. The lines are maintained in the program space sorted */ |
853 | /* been deleted. The lines are maintained in the program space sorted */ |
843 | /* by line number. If the new line to be inserted is a different size */ |
854 | /* by line number. If the new line to be inserted is a different size */ |
844 | /* than the old line being replaced, the remainder of the program is */ |
855 | /* than the old line being replaced, the remainder of the program is */ |
845 | /* shifted over to make room or to close up the gap as necessary. If */ |
856 | /* shifted over to make room or to close up the gap as necessary. If */ |
846 | /* there is insufficient memory to fit in the new line, the program */ |
857 | /* there is insufficient memory to fit in the new line, the program */ |
847 | /* space is unchanged and an error stop occurs (with the IL address */ |
858 | /* space is unchanged and an error stop occurs (with the IL address */ |
848 | /* decremented). A normal error stop occurs on expression stack */ |
859 | /* decremented). A normal error stop occurs on expression stack */ |
849 | /* underflow or if the number is zero, which is not a valid line */ |
860 | /* underflow or if the number is zero, which is not a valid line */ |
850 | /* number. After completing the insertion, the IL program is */ |
861 | /* number. After completing the insertion, the IL program is */ |
851 | /* restarted in the command mode. */ |
862 | /* restarted in the command mode. */ |
852 | case 42: |
863 | case 42: |
853 | Lino = PopExInt(); /* get line # */ |
864 | Lino = PopExInt(); /* get line # */ |
854 | if (Lino <= 0) { /* don't insert line #0 or negative */ |
865 | if (Lino <= 0) { /* don't insert line #0 or negative */ |
855 | if (ILPC != 0) TBerror(); |
866 | if (ILPC != 0) TBerror(); |
856 | else return; |
867 | else return; |
857 | break;} |
868 | break;} |
858 | while (((char)Core[BP]) == ' ') BP++; /* skip leading spaces */ |
869 | while (((char)Core[BP]) == ' ') BP++; /* skip leading spaces */ |
859 | if (((char)Core[BP]) == '\r') ix = 0; /* nothing to add */ |
870 | if (((char)Core[BP]) == '\r') ix = 0; /* nothing to add */ |
860 | else ix = InLend-BP+2; /* the size of the insertion */ |
871 | else ix = InLend-BP+2; /* the size of the insertion */ |
861 | op = 0; /* this will be the number of bytes to delete */ |
872 | op = 0; /* this will be the number of bytes to delete */ |
862 | chpt = FindLine(Lino); /* try to find this line.. */ |
873 | chpt = FindLine(Lino); /* try to find this line.. */ |
863 | if (Peek2(chpt) == Lino) /* there is a line to delete.. */ |
874 | if (Peek2(chpt) == Lino) /* there is a line to delete.. */ |
864 | op = (SkipTo(chpt+2, '\r')-chpt); |
875 | op = (SkipTo(chpt+2, '\r')-chpt); |
865 | if (ix == 0) if (op==0) { /* nothing to add nor delete; done */ |
876 | if (ix == 0) if (op==0) { /* nothing to add nor delete; done */ |
866 | Lino = 0; |
877 | Lino = 0; |
867 | break;} |
878 | break;} |
868 | op = ix-op; /* = how many more bytes to add or (-)delete */ |
879 | op = ix-op; /* = how many more bytes to add or (-)delete */ |
869 | if (SrcEnd+op>=SubStk) { /* too big.. */ |
880 | if (SrcEnd+op>=SubStk) { /* too big.. */ |
870 | TBerror(); |
881 | TBerror(); |
871 | break;} |
882 | break;} |
872 | SrcEnd = SrcEnd+op; /* new size */ |
883 | SrcEnd = SrcEnd+op; /* new size */ |
873 | if (op>0) for (here=SrcEnd; (here--)>chpt+ix; ) |
884 | if (op>0) for (here=SrcEnd; (here--)>chpt+ix; ) |
874 | Core[here] = Core[here-op]; /* shift backend over to right */ |
885 | Core[here] = Core[here-op]; /* shift backend over to right */ |
875 | else if (op<0) for (here=chpt+ix; here |
886 | else if (op<0) for (here=chpt+ix; here |
876 | Core[here] = Core[here-op]; /* shift it left to close gap */ |
887 | Core[here] = Core[here-op]; /* shift it left to close gap */ |
877 | if (ix>0) Poke2(chpt++,Lino); /* insert the new line # */ |
888 | if (ix>0) Poke2(chpt++,Lino); /* insert the new line # */ |
878 | while (ix>2) { /* insert the new line.. */ |
889 | while (ix>2) { /* insert the new line.. */ |
879 | Core[++chpt] = Core[BP++]; |
890 | Core[++chpt] = Core[BP++]; |
880 | ix--;} |
891 | ix--;} |
881 | Poke2(EndProg,SrcEnd); |
892 | Poke2(EndProg,SrcEnd); |
882 | ILPC = 0; |
893 | ILPC = 0; |
883 | Lino = 0; |
894 | Lino = 0; |
884 | if (Debugging>0) ListIt(0,0); |
895 | if (Debugging>0) ListIt(0,0); |
885 | break; |
896 | break; |
886 | 897 | ||
887 | /* MT 2B Mark the BASIC program space Empty. */ |
898 | /* MT 2B Mark the BASIC program space Empty. */ |
888 | /* Also clears the BASIC region of the control stack */ |
899 | /* Also clears the BASIC region of the control stack */ |
889 | /* and restart the IL program in the command mode. The memory bounds */ |
900 | /* and restart the IL program in the command mode. The memory bounds */ |
890 | /* and stack pointers are reset by this instruction to signify empty */ |
901 | /* and stack pointers are reset by this instruction to signify empty */ |
891 | /* program space, and the line number of the first line is set to 0, */ |
902 | /* program space, and the line number of the first line is set to 0, */ |
892 | /* which is the indication of the end of the program. */ |
903 | /* which is the indication of the end of the program. */ |
893 | case 43: |
904 | case 43: |
894 | ColdStart(); |
905 | ColdStart(); |
895 | if (Debugging>0) {ShowSubs(); ShowExSt(); ShowVars(0);} |
906 | if (Debugging>0) {ShowSubs(); ShowExSt(); ShowVars(0);} |
896 | break; |
907 | break; |
897 | 908 | ||
898 | /* XQ 2C Execute. */ |
909 | /* XQ 2C Execute. */ |
899 | /* Turns on RUN mode. This instruction also saves */ |
910 | /* Turns on RUN mode. This instruction also saves */ |
900 | /* the current value of the IL program counter for use of the NX */ |
911 | /* the current value of the IL program counter for use of the NX */ |
901 | /* instruction, and sets the BASIC pointer to the beginning of the */ |
912 | /* instruction, and sets the BASIC pointer to the beginning of the */ |
902 | /* BASIC program space. An error stop occurs if there is no BASIC */ |
913 | /* BASIC program space. An error stop occurs if there is no BASIC */ |
903 | /* program. This instruction must be executed at least once before */ |
914 | /* program. This instruction must be executed at least once before */ |
904 | /* the first execution of a NX instruction. */ |
915 | /* the first execution of a NX instruction. */ |
905 | case 44: |
916 | case 44: |
906 | XQhere = ILPC; |
917 | XQhere = ILPC; |
907 | BP = Peek2(UserProg); |
918 | BP = Peek2(UserProg); |
908 | Lino = Peek2(BP++); |
919 | Lino = Peek2(BP++); |
909 | BP++; |
920 | BP++; |
910 | if (Lino == 0) TBerror(); |
921 | if (Lino == 0) TBerror(); |
911 | else if (Debugging>0) |
922 | else if (Debugging>0) |
912 | {OutStr(" [#"); OutInt(Lino); OutStr("]");} |
923 | {OutStr(" [#"); OutInt(Lino); OutStr("]");} |
913 | break; |
924 | break; |
914 | 925 | ||
915 | /* WS 2D Stop. */ |
926 | /* WS 2D Stop. */ |
916 | /* Stop execution and restart the IL program in the */ |
927 | /* Stop execution and restart the IL program in the */ |
917 | /* command mode. The entire control stack (including BASIC region) */ |
928 | /* command mode. The entire control stack (including BASIC region) */ |
918 | /* is also vacated by this instruction. This instruction effectively */ |
929 | /* is also vacated by this instruction. This instruction effectively */ |
919 | /* jumps to the Warm Start entry of the ML interpreter. */ |
930 | /* jumps to the Warm Start entry of the ML interpreter. */ |
920 | case 45: |
931 | case 45: |
921 | WarmStart(); |
932 | WarmStart(); |
922 | if (Debugging>0) ShowSubs(); |
933 | if (Debugging>0) ShowSubs(); |
923 | break; |
934 | break; |
924 | 935 | ||
925 | /* US 2E Machine Language Subroutine Call. */ |
936 | /* US 2E Machine Language Subroutine Call. */ |
926 | /* The top six bytes of the expression stack contain */ |
937 | /* The top six bytes of the expression stack contain */ |
927 | /* 3 numbers with the following interpretations: The top number is */ |
938 | /* 3 numbers with the following interpretations: The top number is */ |
928 | /* loaded into the A (or A and B) register; the next number is loaded */ |
939 | /* loaded into the A (or A and B) register; the next number is loaded */ |
929 | /* into 16 bits of Index register; the third number is interpreted as */ |
940 | /* into 16 bits of Index register; the third number is interpreted as */ |
930 | /* the address of a machine language subroutine to be called. These */ |
941 | /* the address of a machine language subroutine to be called. These */ |
931 | /* six bytes on the expression stack are replaced with the 16-bit */ |
942 | /* six bytes on the expression stack are replaced with the 16-bit */ |
932 | /* result returned by the subroutine. Stack underflow results in an */ |
943 | /* result returned by the subroutine. Stack underflow results in an */ |
933 | /* error stop. */ |
944 | /* error stop. */ |
934 | case 46: |
945 | case 46: |
935 | Poke2(LinoCore,Lino); /* bring these memory locations up.. */ |
946 | Poke2(LinoCore,Lino); /* bring these memory locations up.. */ |
936 | Poke2(ILPCcore,ILPC); /* ..to date, in case user looks.. */ |
947 | Poke2(ILPCcore,ILPC); /* ..to date, in case user looks.. */ |
937 | Poke2(BPcore,BP); |
948 | Poke2(BPcore,BP); |
938 | Poke2(SvPtCore,SvPt); |
949 | Poke2(SvPtCore,SvPt); |
939 | ix = PopExInt()&0xFFFF; /* datum A */ |
950 | ix = PopExInt()&0xFFFF; /* datum A */ |
940 | here = PopExInt()&0xFFFF; /* datum X */ |
951 | here = PopExInt()&0xFFFF; /* datum X */ |
941 | op = PopExInt()&0xFFFF; /* nominal machine address */ |
952 | op = PopExInt()&0xFFFF; /* nominal machine address */ |
942 | if (ILPC == 0) break; |
953 | if (ILPC == 0) break; |
943 | if (op>=Peek2(ILfront) && op |
954 | if (op>=Peek2(ILfront) && op |
944 | PushExInt(here); |
955 | PushExInt(here); |
945 | PushExInt(ix); |
956 | PushExInt(ix); |
946 | PushSub(ILPC); /* push return location */ |
957 | PushSub(ILPC); /* push return location */ |
947 | ILPC = op; |
958 | ILPC = op; |
948 | if (DEBUGON>0) LogIt(-ILPC); |
959 | if (DEBUGON>0) LogIt(-ILPC); |
949 | break;} |
960 | break;} |
950 | switch (op) { |
961 | switch (op) { |
951 | case WachPoint: /* we only do a few predefined functions.. */ |
962 | case WachPoint: /* we only do a few predefined functions.. */ |
952 | Watcher = here; |
963 | Watcher = here; |
953 | if (ix>32767) ix = -(int)Core[here]-256; |
964 | if (ix>32767) ix = -(int)Core[here]-256; |
954 | Watchee = ix; |
965 | Watchee = ix; |
955 | if (Debugging>0) { |
966 | if (Debugging>0) { |
956 | OutLn(); OutStr("[** Watch "); OutHex(here,4); OutStr("]");} |
967 | OutLn(); OutStr("[** Watch "); OutHex(here,4); OutStr("]");} |
957 | PushExInt((int)Core[here]); |
968 | PushExInt((int)Core[here]); |
958 | break; |
969 | break; |
959 | case ColdGo: |
970 | case ColdGo: |
960 | ColdStart(); |
971 | ColdStart(); |
961 | break; |
972 | break; |
962 | case WarmGo: |
973 | case WarmGo: |
963 | WarmStart(); |
974 | WarmStart(); |
964 | break; |
975 | break; |
965 | case InchSub: |
976 | case InchSub: |
966 | PushExInt((int)Inch()); |
977 | PushExInt((int)Inch()); |
967 | break; |
978 | break; |
968 | case OutchSub: |
979 | case OutchSub: |
969 | Ouch((char)(ix&127)); |
980 | Ouch((char)(ix&127)); |
970 | PushExInt(0); |
981 | PushExInt(0); |
971 | break; |
982 | break; |
972 | case BreakSub: |
983 | case BreakSub: |
973 | PushExInt(StopIt()); |
984 | PushExInt(StopIt()); |
974 | break; |
985 | break; |
975 | case PeekSub: |
986 | case PeekSub: |
976 | PushExInt((int)Core[here]); |
987 | PushExInt((int)Core[here]); |
977 | break; |
988 | break; |
978 | case Peek2Sub: |
989 | case Peek2Sub: |
979 | PushExInt(Peek2(here)); |
990 | PushExInt(Peek2(here)); |
980 | break; |
991 | break; |
981 | case PokeSub: |
992 | case PokeSub: |
982 | ix = ix&0xFF; |
993 | ix = ix&0xFF; |
983 | Core[here] = (aByte)ix; |
994 | Core[here] = (aByte)ix; |
984 | PushExInt(ix); |
995 | PushExInt(ix); |
985 | if (DEBUGON>0) LogIt(((ix+256)<<16)+here); |
996 | if (DEBUGON>0) LogIt(((ix+256)<<16)+here); |
986 | Lino = Peek2(LinoCore); /* restore these pointers.. */ |
997 | Lino = Peek2(LinoCore); /* restore these pointers.. */ |
987 | ILPC = Peek2(ILPCcore); /* ..in case user changed them.. */ |
998 | ILPC = Peek2(ILPCcore); /* ..in case user changed them.. */ |
988 | BP = Peek2(BPcore); |
999 | BP = Peek2(BPcore); |
989 | SvPt = Peek2(SvPtCore); |
1000 | SvPt = Peek2(SvPtCore); |
990 | break; |
1001 | break; |
991 | case DumpSub: |
1002 | case DumpSub: |
992 | ShoMemDump(here,ix); |
1003 | ShoMemDump(here,ix); |
993 | PushExInt(here+ix); |
1004 | PushExInt(here+ix); |
994 | break; |
1005 | break; |
995 | case TrLogSub: |
1006 | case TrLogSub: |
996 | ShowLog(); |
1007 | ShowLog(); |
997 | PushExInt(LogHere); |
1008 | PushExInt(LogHere); |
998 | break; |
1009 | break; |
999 | default: TBerror();} |
1010 | default: TBerror();} |
1000 | break; |
1011 | break; |
1001 | 1012 | ||
1002 | /* RT 2F IL Subroutine Return. */ |
1013 | /* RT 2F IL Subroutine Return. */ |
1003 | /* The IL control stack is popped to give the address */ |
1014 | /* The IL control stack is popped to give the address */ |
1004 | /* of the next IL instruction. An error stop occurs if the entire */ |
1015 | /* of the next IL instruction. An error stop occurs if the entire */ |
1005 | /* control stack (IL and BASIC) is empty. */ |
1016 | /* control stack (IL and BASIC) is empty. */ |
1006 | case 47: |
1017 | case 47: |
1007 | ix = PopSub(); /* get return from pop */ |
1018 | ix = PopSub(); /* get return from pop */ |
1008 | if (ix |
1019 | if (ix |
1009 | else if (ILPC != 0) { |
1020 | else if (ILPC != 0) { |
1010 | ILPC = ix; |
1021 | ILPC = ix; |
1011 | if (DEBUGON>0) LogIt(-ILPC);} |
1022 | if (DEBUGON>0) LogIt(-ILPC);} |
1012 | break; |
1023 | break; |
1013 | 1024 | ||
1014 | /* JS a 3000-37FF IL Subroutine Call. */ |
1025 | /* JS a 3000-37FF IL Subroutine Call. */ |
1015 | /* The least significant eleven bits of this */ |
1026 | /* The least significant eleven bits of this */ |
1016 | /* 2-byte instruction are added to the base address of the IL program */ |
1027 | /* 2-byte instruction are added to the base address of the IL program */ |
1017 | /* to become address of the next instruction. The previous contents */ |
1028 | /* to become address of the next instruction. The previous contents */ |
1018 | /* of the IL program counter are pushed onto the IL region of the */ |
1029 | /* of the IL program counter are pushed onto the IL region of the */ |
1019 | /* control stack. Stack overflow results in an error stop. */ |
1030 | /* control stack. Stack overflow results in an error stop. */ |
1020 | case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: |
1031 | case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: |
1021 | PushSub(ILPC+1); /* push return location there */ |
1032 | PushSub(ILPC+1); /* push return location there */ |
1022 | if (ILPC == 0) break; |
1033 | if (ILPC == 0) break; |
1023 | ILPC = (Peek2(ILPC-1)&0x7FF)+Peek2(ILfront); |
1034 | ILPC = (Peek2(ILPC-1)&0x7FF)+Peek2(ILfront); |
1024 | if (DEBUGON>0) LogIt(-ILPC); |
1035 | if (DEBUGON>0) LogIt(-ILPC); |
1025 | break; |
1036 | break; |
1026 | 1037 | ||
1027 | /* J a 3800-3FFF Jump. */ |
1038 | /* J a 3800-3FFF Jump. */ |
1028 | /* The low eleven bits of this 2-byte */ |
1039 | /* The low eleven bits of this 2-byte */ |
1029 | /* instruction are added to the IL program base address to determine */ |
1040 | /* instruction are added to the IL program base address to determine */ |
1030 | /* the address of the next IL instruction. The previous contents of */ |
1041 | /* the address of the next IL instruction. The previous contents of */ |
1031 | /* the IL program counter is lost. */ |
1042 | /* the IL program counter is lost. */ |
1032 | case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: |
1043 | case 56: case 57: case 58: case 59: case 60: case 61: case 62: case 63: |
1033 | ILPC = (Peek2(ILPC-1)&0x7FF)+Peek2(ILfront); |
1044 | ILPC = (Peek2(ILPC-1)&0x7FF)+Peek2(ILfront); |
1034 | if (DEBUGON>0) LogIt(-ILPC); |
1045 | if (DEBUGON>0) LogIt(-ILPC); |
1035 | break; |
1046 | break; |
1036 | 1047 | ||
1037 | /* NO 08 No Operation. */ |
1048 | /* NO 08 No Operation. */ |
1038 | /* This may be used as a space filler (such as to */ |
1049 | /* This may be used as a space filler (such as to */ |
1039 | /* ignore a skip). */ |
1050 | /* ignore a skip). */ |
1040 | default: break;} /* last of inner switch cases */ |
1051 | default: break;} /* last of inner switch cases */ |
1041 | break; /* end of outer switch cases 0,1 */ |
1052 | break; /* end of outer switch cases 0,1 */ |
1042 | 1053 | ||
1043 | /* BR a 40-7F Relative Branch. */ |
1054 | /* BR a 40-7F Relative Branch. */ |
1044 | /* The low six bits of this instruction opcode are */ |
1055 | /* The low six bits of this instruction opcode are */ |
1045 | /* added algebraically to the current value of the IL program counter */ |
1056 | /* added algebraically to the current value of the IL program counter */ |
1046 | /* to give the address of the next IL instruction. Bit 5 of opcode is */ |
1057 | /* to give the address of the next IL instruction. Bit 5 of opcode is */ |
1047 | /* the sign, with + signified by 1, - by 0. The range of this branch */ |
1058 | /* the sign, with + signified by 1, - by 0. The range of this branch */ |
1048 | /* is +/-31 bytes from address of the byte following the opcode. An */ |
1059 | /* is +/-31 bytes from address of the byte following the opcode. An */ |
1049 | /* offset of zero (i.e. opcode 60) results in an error stop. The */ |
1060 | /* offset of zero (i.e. opcode 60) results in an error stop. The */ |
1050 | /* branch operation is unconditional. */ |
1061 | /* branch operation is unconditional. */ |
1051 | case 2: case 3: |
1062 | case 2: case 3: |
1052 | ILPC = ILPC+op-96; |
1063 | ILPC = ILPC+op-96; |
1053 | if (DEBUGON>0) LogIt(-ILPC); |
1064 | if (DEBUGON>0) LogIt(-ILPC); |
1054 | break; |
1065 | break; |
1055 | 1066 | ||
1056 | /* BC a "xxx" 80xxxxXx-9FxxxxXx String Match Branch. */ |
1067 | /* BC a "xxx" 80xxxxXx-9FxxxxXx String Match Branch. */ |
1057 | /* The ASCII character string in IL */ |
1068 | /* The ASCII character string in IL */ |
1058 | /* following this opcode is compared to the string beginning with the */ |
1069 | /* following this opcode is compared to the string beginning with the */ |
1059 | /* current position of the BASIC pointer, ignoring blanks in BASIC */ |
1070 | /* current position of the BASIC pointer, ignoring blanks in BASIC */ |
1060 | /* program. The comparison continues until either a mismatch, or an */ |
1071 | /* program. The comparison continues until either a mismatch, or an */ |
1061 | /* IL byte is reached with the most significant bit set to one. This */ |
1072 | /* IL byte is reached with the most significant bit set to one. This */ |
1062 | /* is the last byte of the string in the IL, compared as a 7-bit */ |
1073 | /* is the last byte of the string in the IL, compared as a 7-bit */ |
1063 | /* character; if equal, the BASIC pointer is positioned after the */ |
1074 | /* character; if equal, the BASIC pointer is positioned after the */ |
1064 | /* last matching character in the BASIC program and the IL continues */ |
1075 | /* last matching character in the BASIC program and the IL continues */ |
1065 | /* with the next instruction in sequence. Otherwise the BASIC pointer */ |
1076 | /* with the next instruction in sequence. Otherwise the BASIC pointer */ |
1066 | /* is not altered and the low five bits of the Branch opcode are */ |
1077 | /* is not altered and the low five bits of the Branch opcode are */ |
1067 | /* added to the IL program counter to form the address of the next */ |
1078 | /* added to the IL program counter to form the address of the next */ |
1068 | /* IL instruction. If the strings do not match and the branch offset */ |
1079 | /* IL instruction. If the strings do not match and the branch offset */ |
1069 | /* is zero an error stop occurs. */ |
1080 | /* is zero an error stop occurs. */ |
1070 | case 4: |
1081 | case 4: |
1071 | if (op==128) here = 0; /* to error if no match */ |
1082 | if (op==128) here = 0; /* to error if no match */ |
1072 | else here = ILPC+op-128; |
1083 | else here = ILPC+op-128; |
1073 | chpt = BP; |
1084 | chpt = BP; |
1074 | ix = 0; |
1085 | ix = 0; |
1075 | while ((ix&128)==0) { |
1086 | while ((ix&128)==0) { |
1076 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1087 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1077 | ix = (int)Core[ILPC++]; |
1088 | ix = (int)Core[ILPC++]; |
1078 | if (((char)(ix&127)) != DeCaps[((int)Core[BP++])&127]) { |
1089 | if (((char)(ix&127)) != DeCaps[((int)Core[BP++])&127]) { |
1079 | BP = chpt; /* back up to front of string in Basic */ |
1090 | BP = chpt; /* back up to front of string in Basic */ |
1080 | if (here==0) TBerror(); |
1091 | if (here==0) TBerror(); |
1081 | else ILPC = here; /* jump forward in IL */ |
1092 | else ILPC = here; /* jump forward in IL */ |
1082 | break;}} |
1093 | break;}} |
1083 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1094 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1084 | break; |
1095 | break; |
1085 | 1096 | ||
1086 | /* BV a A0-BF Branch if Not Variable. */ |
1097 | /* BV a A0-BF Branch if Not Variable. */ |
1087 | /* If the next non-blank character pointed to by the */ |
1098 | /* If the next non-blank character pointed to by the */ |
1088 | /* BASIC pointer is a capital letter, its ASCII code is [doubled and] */ |
1099 | /* BASIC pointer is a capital letter, its ASCII code is [doubled and] */ |
1089 | /* pushed onto the expression stack and the IL program advances to */ |
1100 | /* pushed onto the expression stack and the IL program advances to */ |
1090 | /* next instruction in sequence, leaving the BASIC pointer positioned */ |
1101 | /* next instruction in sequence, leaving the BASIC pointer positioned */ |
1091 | /* after the letter; if not a letter the branch is taken and BASIC */ |
1102 | /* after the letter; if not a letter the branch is taken and BASIC */ |
1092 | /* pointer is left pointing to that character. An error stop occurs */ |
1103 | /* pointer is left pointing to that character. An error stop occurs */ |
1093 | /* if the next character is not a letter and the offset of the branch */ |
1104 | /* if the next character is not a letter and the offset of the branch */ |
1094 | /* is zero, or on stack overflow. */ |
1105 | /* is zero, or on stack overflow. */ |
1095 | case 5: |
1106 | case 5: |
1096 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1107 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1097 | ch = (char)Core[BP]; |
1108 | ch = (char)Core[BP]; |
1098 | if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') |
1109 | if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') |
1099 | PushExBy((((int)Core[BP++])&0x5F)*2); |
1110 | PushExBy((((int)Core[BP++])&0x5F)*2); |
1100 | else if (op==160) TBerror(); /* error if not letter */ |
1111 | else if (op==160) TBerror(); /* error if not letter */ |
1101 | else ILPC = ILPC+op-160; |
1112 | else ILPC = ILPC+op-160; |
1102 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1113 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1103 | break; |
1114 | break; |
1104 | 1115 | ||
1105 | /* BN a C0-DF Branch if Not a Number. */ |
1116 | /* BN a C0-DF Branch if Not a Number. */ |
1106 | /* If the next non-blank character pointed to by the */ |
1117 | /* If the next non-blank character pointed to by the */ |
1107 | /* BASIC pointer is not a decimal digit, the low five bits of the */ |
1118 | /* BASIC pointer is not a decimal digit, the low five bits of the */ |
1108 | /* opcode are added to the IL program counter, or if zero an error */ |
1119 | /* opcode are added to the IL program counter, or if zero an error */ |
1109 | /* stop occurs. If the next character is a digit, then it and all */ |
1120 | /* stop occurs. If the next character is a digit, then it and all */ |
1110 | /* decimal digits following it (ignoring blanks) are converted to a */ |
1121 | /* decimal digits following it (ignoring blanks) are converted to a */ |
1111 | /* 16-bit binary number which is pushed onto the expression stack. In */ |
1122 | /* 16-bit binary number which is pushed onto the expression stack. In */ |
1112 | /* either case the BASIC pointer is positioned at the next character */ |
1123 | /* either case the BASIC pointer is positioned at the next character */ |
1113 | /* which is neither blank nor digit. Stack overflow will result in an */ |
1124 | /* which is neither blank nor digit. Stack overflow will result in an */ |
1114 | /* error stop. */ |
1125 | /* error stop. */ |
1115 | case 6: |
1126 | case 6: |
1116 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1127 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1117 | ch = (char)Core[BP]; |
1128 | ch = (char)Core[BP]; |
1118 | if (ch >= '0' && ch <= '9') { |
1129 | if (ch >= '0' && ch <= '9') { |
1119 | op = 0; |
1130 | op = 0; |
1120 | while (true) { |
1131 | while (true) { |
1121 | here = (int)Core[BP++]; |
1132 | here = (int)Core[BP++]; |
1122 | if (here==32) continue; /* skip over spaces */ |
1133 | if (here==32) continue; /* skip over spaces */ |
1123 | if (here<48 || here>57) break; /* not a decimal digit */ |
1134 | if (here<48 || here>57) break; /* not a decimal digit */ |
1124 | op = op*10+here-48;} /* insert into value */ |
1135 | op = op*10+here-48;} /* insert into value */ |
1125 | BP--; /* back up over non-digit */ |
1136 | BP--; /* back up over non-digit */ |
1126 | PushExInt(op);} |
1137 | PushExInt(op);} |
1127 | else if (op==192) TBerror(); /* error if no digit */ |
1138 | else if (op==192) TBerror(); /* error if no digit */ |
1128 | else ILPC = ILPC+op-192; |
1139 | else ILPC = ILPC+op-192; |
1129 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1140 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1130 | break; |
1141 | break; |
1131 | 1142 | ||
1132 | /* BE a E0-FF Branch if Not Endline. */ |
1143 | /* BE a E0-FF Branch if Not Endline. */ |
1133 | /* If the next non-blank character pointed to by the */ |
1144 | /* If the next non-blank character pointed to by the */ |
1134 | /* BASIC pointer is a carriage return, the IL program advances to the */ |
1145 | /* BASIC pointer is a carriage return, the IL program advances to the */ |
1135 | /* next instruction in sequence; otherwise the low five bits of the */ |
1146 | /* next instruction in sequence; otherwise the low five bits of the */ |
1136 | /* opcode (if not 0) are added to the IL program counter to form the */ |
1147 | /* opcode (if not 0) are added to the IL program counter to form the */ |
1137 | /* address of next IL instruction. In either case the BASIC pointer */ |
1148 | /* address of next IL instruction. In either case the BASIC pointer */ |
1138 | /* is left pointing to the first non-blank character; this */ |
1149 | /* is left pointing to the first non-blank character; this */ |
1139 | /* instruction will not pass over the carriage return, which must */ |
1150 | /* instruction will not pass over the carriage return, which must */ |
1140 | /* remain for testing by the NX instruction. As with the other */ |
1151 | /* remain for testing by the NX instruction. As with the other */ |
1141 | /* conditional branches, the branch may only advance the IL program */ |
1152 | /* conditional branches, the branch may only advance the IL program */ |
1142 | /* counter from 1 to 31 bytes; an offset of zero results in an error */ |
1153 | /* counter from 1 to 31 bytes; an offset of zero results in an error */ |
1143 | /* stop. */ |
1154 | /* stop. */ |
1144 | case 7: |
1155 | case 7: |
1145 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1156 | while (((char)Core[BP]) == ' ') BP++; /* skip over spaces */ |
1146 | if (((char)Core[BP]) == '\r') ; |
1157 | if (((char)Core[BP]) == '\r') ; |
1147 | else if (op==224) TBerror(); /* error if no offset */ |
1158 | else if (op==224) TBerror(); /* error if no offset */ |
1148 | else ILPC = ILPC+op-224; |
1159 | else ILPC = ILPC+op-224; |
1149 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1160 | if (DEBUGON>0) if (ILPC>0) LogIt(-ILPC); |
1150 | break;}}} /* ~Interp */ |
1161 | break;}}} /* ~Interp */ |
1151 | 1162 | ||
1152 | /***************** Intermediate Interpreter Assembled *****************/ |
1163 | /***************** Intermediate Interpreter Assembled *****************/ |
1153 | 1164 | ||
1154 | char* DefaultIL() { |
1165 | char* DefaultIL() { |
1155 | static char s[9000]; /* be sure to increase size if you add text */ |
1166 | static char s[9000]; /* be sure to increase size if you add text */ |
1156 | strcpy(s,"0000 ; 1 . ORIGINAL TINY BASIC INTERMEDIATE INTERPRETER\n"); |
1167 | strcpy(s,"0000 ; 1 . ORIGINAL TINY BASIC INTERMEDIATE INTERPRETER\n"); |
1157 | strcat(s,"0000 ; 2 .\n"); |
1168 | strcat(s,"0000 ; 2 .\n"); |
1158 | strcat(s,"0000 ; 3 . EXECUTIVE INITIALIZATION\n"); |
1169 | strcat(s,"0000 ; 3 . EXECUTIVE INITIALIZATION\n"); |
1159 | strcat(s,"0000 ; 4 .\n"); |
1170 | strcat(s,"0000 ; 4 .\n"); |
1160 | strcat(s,"0000 ; 5 :STRT PC \":Q^\" COLON, X-ON\n"); |
1171 | strcat(s,"0000 ; 5 :STRT PC \":Q^\" COLON, X-ON\n"); |
1161 | strcat(s,"0000 243A91;\n"); |
1172 | strcat(s,"0000 243A91;\n"); |
1162 | strcat(s,"0003 ; 6 GL\n"); |
1173 | strcat(s,"0003 ; 6 GL\n"); |
1163 | strcat(s,"0003 27; 7 SB\n"); |
1174 | strcat(s,"0003 27; 7 SB\n"); |
1164 | strcat(s,"0004 10; 8 BE L0 BRANCH IF NOT EMPTY\n"); |
1175 | strcat(s,"0004 10; 8 BE L0 BRANCH IF NOT EMPTY\n"); |
1165 | strcat(s,"0005 E1; 9 BR STRT TRY AGAIN IF NULL LINE\n"); |
1176 | strcat(s,"0005 E1; 9 BR STRT TRY AGAIN IF NULL LINE\n"); |
1166 | strcat(s,"0006 59; 10 :L0 BN STMT TEST FOR LINE NUMBER\n"); |
1177 | strcat(s,"0006 59; 10 :L0 BN STMT TEST FOR LINE NUMBER\n"); |
1167 | strcat(s,"0007 C5; 11 IL IF SO, INSERT INTO PROGRAM\n"); |
1178 | strcat(s,"0007 C5; 11 IL IF SO, INSERT INTO PROGRAM\n"); |
1168 | strcat(s,"0008 2A; 12 BR STRT GO GET NEXT\n"); |
1179 | strcat(s,"0008 2A; 12 BR STRT GO GET NEXT\n"); |
1169 | strcat(s,"0009 56; 13 :XEC SB SAVE POINTERS FOR RUN WITH\n"); |
1180 | strcat(s,"0009 56; 13 :XEC SB SAVE POINTERS FOR RUN WITH\n"); |
1170 | strcat(s,"000A 10; 14 RB CONCATENATED INPUT\n"); |
1181 | strcat(s,"000A 10; 14 RB CONCATENATED INPUT\n"); |
1171 | strcat(s,"000B 11; 15 XQ\n"); |
1182 | strcat(s,"000B 11; 15 XQ\n"); |
1172 | strcat(s,"000C 2C; 16 .\n"); |
1183 | strcat(s,"000C 2C; 16 .\n"); |
1173 | strcat(s,"000D ; 17 . STATEMENT EXECUTOR\n"); |
1184 | strcat(s,"000D ; 17 . STATEMENT EXECUTOR\n"); |
1174 | strcat(s,"000D ; 18 .\n"); |
1185 | strcat(s,"000D ; 18 .\n"); |
1175 | strcat(s,"000D ; 19 :STMT BC GOTO \"LET\"\n"); |
1186 | strcat(s,"000D ; 19 :STMT BC GOTO \"LET\"\n"); |
1176 | strcat(s,"000D 8B4C45D4;\n"); |
1187 | strcat(s,"000D 8B4C45D4;\n"); |
1177 | strcat(s,"0011 ; 20 BV * MUST BE A VARIABLE NAME\n"); |
1188 | strcat(s,"0011 ; 20 BV * MUST BE A VARIABLE NAME\n"); |
1178 | strcat(s,"0011 A0; 21 BC * \"=\"\n"); |
1189 | strcat(s,"0011 A0; 21 BC * \"=\"\n"); |
1179 | strcat(s,"0012 80BD; 22 :LET JS EXPR GO GET EXPRESSION\n"); |
1190 | strcat(s,"0012 80BD; 22 :LET JS EXPR GO GET EXPRESSION\n"); |
1180 | strcat(s,"0014 30BC; 23 BE * IF STATEMENT END,\n"); |
1191 | strcat(s,"0014 30BC; 23 BE * IF STATEMENT END,\n"); |
1181 | strcat(s,"0016 E0; 24 SV STORE RESULT\n"); |
1192 | strcat(s,"0016 E0; 24 SV STORE RESULT\n"); |
1182 | strcat(s,"0017 13; 25 NX\n"); |
1193 | strcat(s,"0017 13; 25 NX\n"); |
1183 | strcat(s,"0018 1D; 26 .\n"); |
1194 | strcat(s,"0018 1D; 26 .\n"); |
1184 | strcat(s,"0019 ; 27 :GOTO BC PRNT \"GO\"\n"); |
1195 | strcat(s,"0019 ; 27 :GOTO BC PRNT \"GO\"\n"); |
1185 | strcat(s,"0019 9447CF;\n"); |
1196 | strcat(s,"0019 9447CF;\n"); |
1186 | strcat(s,"001C ; 28 BC GOSB \"TO\"\n"); |
1197 | strcat(s,"001C ; 28 BC GOSB \"TO\"\n"); |
1187 | strcat(s,"001C 8854CF;\n"); |
1198 | strcat(s,"001C 8854CF;\n"); |
1188 | strcat(s,"001F ; 29 JS EXPR GET LINE NUMBER\n"); |
1199 | strcat(s,"001F ; 29 JS EXPR GET LINE NUMBER\n"); |
1189 | strcat(s,"001F 30BC; 30 BE *\n"); |
1200 | strcat(s,"001F 30BC; 30 BE *\n"); |
1190 | strcat(s,"0021 E0; 31 SB (DO THIS FOR STARTING)\n"); |
1201 | strcat(s,"0021 E0; 31 SB (DO THIS FOR STARTING)\n"); |
1191 | strcat(s,"0022 10; 32 RB\n"); |
1202 | strcat(s,"0022 10; 32 RB\n"); |
1192 | strcat(s,"0023 11; 33 GO GO THERE\n"); |
1203 | strcat(s,"0023 11; 33 GO GO THERE\n"); |
1193 | strcat(s,"0024 16; 34 .\n"); |
1204 | strcat(s,"0024 16; 34 .\n"); |
1194 | strcat(s,"0025 ; 35 :GOSB BC * \"SUB\" NO OTHER WORD BEGINS \"GO...\"\n"); |
1205 | strcat(s,"0025 ; 35 :GOSB BC * \"SUB\" NO OTHER WORD BEGINS \"GO...\"\n"); |
1195 | strcat(s,"0025 805355C2;\n"); |
1206 | strcat(s,"0025 805355C2;\n"); |
1196 | strcat(s,"0029 ; 36 JS EXPR\n"); |
1207 | strcat(s,"0029 ; 36 JS EXPR\n"); |
1197 | strcat(s,"0029 30BC; 37 BE *\n"); |
1208 | strcat(s,"0029 30BC; 37 BE *\n"); |
1198 | strcat(s,"002B E0; 38 GS\n"); |
1209 | strcat(s,"002B E0; 38 GS\n"); |
1199 | strcat(s,"002C 14; 39 GO\n"); |
1210 | strcat(s,"002C 14; 39 GO\n"); |
1200 | strcat(s,"002D 16; 40 .\n"); |
1211 | strcat(s,"002D 16; 40 .\n"); |
1201 | strcat(s,"002E ; 41 :PRNT BC SKIP \"PR\"\n"); |
1212 | strcat(s,"002E ; 41 :PRNT BC SKIP \"PR\"\n"); |
1202 | strcat(s,"002E 9050D2;\n"); |
1213 | strcat(s,"002E 9050D2;\n"); |
1203 | strcat(s,"0031 ; 42 BC P0 \"INT\" OPTIONALLY OMIT \"INT\"\n"); |
1214 | strcat(s,"0031 ; 42 BC P0 \"INT\" OPTIONALLY OMIT \"INT\"\n"); |
1204 | strcat(s,"0031 83494ED4;\n"); |
1215 | strcat(s,"0031 83494ED4;\n"); |
1205 | strcat(s,"0035 ; 43 :P0 BE P3\n"); |
1216 | strcat(s,"0035 ; 43 :P0 BE P3\n"); |
1206 | strcat(s,"0035 E5; 44 BR P6 IF DONE, GO TO END\n"); |
1217 | strcat(s,"0035 E5; 44 BR P6 IF DONE, GO TO END\n"); |
1207 | strcat(s,"0036 71; 45 :P1 BC P4 \";\"\n"); |
1218 | strcat(s,"0036 71; 45 :P1 BC P4 \";\"\n"); |
1208 | strcat(s,"0037 88BB; 46 :P2 BE P3\n"); |
1219 | strcat(s,"0037 88BB; 46 :P2 BE P3\n"); |
1209 | strcat(s,"0039 E1; 47 NX NO CRLF IF ENDED BY ; OR ,\n"); |
1220 | strcat(s,"0039 E1; 47 NX NO CRLF IF ENDED BY ; OR ,\n"); |
1210 | strcat(s,"003A 1D; 48 :P3 BC P7 '\"'\n"); |
1221 | strcat(s,"003A 1D; 48 :P3 BC P7 '\"'\n"); |
1211 | strcat(s,"003B 8FA2; 49 PQ QUOTE MARKS STRING\n"); |
1222 | strcat(s,"003B 8FA2; 49 PQ QUOTE MARKS STRING\n"); |
1212 | strcat(s,"003D 21; 50 BR P1 GO CHECK DELIMITER\n"); |
1223 | strcat(s,"003D 21; 50 BR P1 GO CHECK DELIMITER\n"); |
1213 | strcat(s,"003E 58; 51 :SKIP BR IF (ON THE WAY THRU)\n"); |
1224 | strcat(s,"003E 58; 51 :SKIP BR IF (ON THE WAY THRU)\n"); |
1214 | strcat(s,"003F 6F; 52 :P4 BC P5 \",\"\n"); |
1225 | strcat(s,"003F 6F; 52 :P4 BC P5 \",\"\n"); |
1215 | strcat(s,"0040 83AC; 53 PT COMMA SPACING\n"); |
1226 | strcat(s,"0040 83AC; 53 PT COMMA SPACING\n"); |
1216 | strcat(s,"0042 22; 54 BR P2\n"); |
1227 | strcat(s,"0042 22; 54 BR P2\n"); |
1217 | strcat(s,"0043 55; 55 :P5 BC P6 \":\"\n"); |
1228 | strcat(s,"0043 55; 55 :P5 BC P6 \":\"\n"); |
1218 | strcat(s,"0044 83BA; 56 PC \"S^\" OUTPUT X-OFF\n"); |
1229 | strcat(s,"0044 83BA; 56 PC \"S^\" OUTPUT X-OFF\n"); |
1219 | strcat(s,"0046 2493; 57 :P6 BE *\n"); |
1230 | strcat(s,"0046 2493; 57 :P6 BE *\n"); |
1220 | strcat(s,"0048 E0; 58 NL THEN CRLF\n"); |
1231 | strcat(s,"0048 E0; 58 NL THEN CRLF\n"); |
1221 | strcat(s,"0049 23; 59 NX\n"); |
1232 | strcat(s,"0049 23; 59 NX\n"); |
1222 | strcat(s,"004A 1D; 60 :P7 JS EXPR TRY FOR AN EXPRESSION\n"); |
1233 | strcat(s,"004A 1D; 60 :P7 JS EXPR TRY FOR AN EXPRESSION\n"); |
1223 | strcat(s,"004B 30BC; 61 PN\n"); |
1234 | strcat(s,"004B 30BC; 61 PN\n"); |
1224 | strcat(s,"004D 20; 62 BR P1\n"); |
1235 | strcat(s,"004D 20; 62 BR P1\n"); |
1225 | strcat(s,"004E 48; 63 .\n"); |
1236 | strcat(s,"004E 48; 63 .\n"); |
1226 | strcat(s,"004F ; 64 :IF BC INPT \"IF\"\n"); |
1237 | strcat(s,"004F ; 64 :IF BC INPT \"IF\"\n"); |
1227 | strcat(s,"004F 9149C6;\n"); |
1238 | strcat(s,"004F 9149C6;\n"); |
1228 | strcat(s,"0052 ; 65 JS EXPR\n"); |
1239 | strcat(s,"0052 ; 65 JS EXPR\n"); |
1229 | strcat(s,"0052 30BC; 66 JS RELO\n"); |
1240 | strcat(s,"0052 30BC; 66 JS RELO\n"); |
1230 | strcat(s,"0054 3134; 67 JS EXPR\n"); |
1241 | strcat(s,"0054 3134; 67 JS EXPR\n"); |
1231 | strcat(s,"0056 30BC; 68 BC I1 \"THEN\" OPTIONAL NOISEWORD\n"); |
1242 | strcat(s,"0056 30BC; 68 BC I1 \"THEN\" OPTIONAL NOISEWORD\n"); |
1232 | strcat(s,"0058 84544845CE;\n"); |
1243 | strcat(s,"0058 84544845CE;\n"); |
1233 | strcat(s,"005D ; 69 :I1 CP COMPARE SKIPS NEXT IF TRUE\n"); |
1244 | strcat(s,"005D ; 69 :I1 CP COMPARE SKIPS NEXT IF TRUE\n"); |
1234 | strcat(s,"005D 1C; 70 NX FALSE.\n"); |
1245 | strcat(s,"005D 1C; 70 NX FALSE.\n"); |
1235 | strcat(s,"005E 1D; 71 J STMT TRUE. GO PROCESS STATEMENT\n"); |
1246 | strcat(s,"005E 1D; 71 J STMT TRUE. GO PROCESS STATEMENT\n"); |
1236 | strcat(s,"005F 380D; 72 .\n"); |
1247 | strcat(s,"005F 380D; 72 .\n"); |
1237 | strcat(s,"0061 ; 73 :INPT BC RETN \"INPUT\"\n"); |
1248 | strcat(s,"0061 ; 73 :INPT BC RETN \"INPUT\"\n"); |
1238 | strcat(s,"0061 9A494E5055D4;\n"); |
1249 | strcat(s,"0061 9A494E5055D4;\n"); |
1239 | strcat(s,"0067 ; 74 :I2 BV * GET VARIABLE\n"); |
1250 | strcat(s,"0067 ; 74 :I2 BV * GET VARIABLE\n"); |
1240 | strcat(s,"0067 A0; 75 SB SWAP POINTERS\n"); |
1251 | strcat(s,"0067 A0; 75 SB SWAP POINTERS\n"); |
1241 | strcat(s,"0068 10; 76 BE I4\n"); |
1252 | strcat(s,"0068 10; 76 BE I4\n"); |
1242 | strcat(s,"0069 E7; 77 :I3 PC \"? Q^\" LINE IS EMPTY; TYPE PROMPT\n"); |
1253 | strcat(s,"0069 E7; 77 :I3 PC \"? Q^\" LINE IS EMPTY; TYPE PROMPT\n"); |
1243 | strcat(s,"006A 243F2091;\n"); |
1254 | strcat(s,"006A 243F2091;\n"); |
1244 | strcat(s,"006E ; 78 GL READ INPUT LINE\n"); |
1255 | strcat(s,"006E ; 78 GL READ INPUT LINE\n"); |
1245 | strcat(s,"006E 27; 79 BE I4 DID ANYTHING COME?\n"); |
1256 | strcat(s,"006E 27; 79 BE I4 DID ANYTHING COME?\n"); |
1246 | strcat(s,"006F E1; 80 BR I3 NO, TRY AGAIN\n"); |
1257 | strcat(s,"006F E1; 80 BR I3 NO, TRY AGAIN\n"); |
1247 | strcat(s,"0070 59; 81 :I4 BC I5 \",\" OPTIONAL COMMA\n"); |
1258 | strcat(s,"0070 59; 81 :I4 BC I5 \",\" OPTIONAL COMMA\n"); |
1248 | strcat(s,"0071 81AC; 82 :I5 JS EXPR READ A NUMBER\n"); |
1259 | strcat(s,"0071 81AC; 82 :I5 JS EXPR READ A NUMBER\n"); |
1249 | strcat(s,"0073 30BC; 83 SV STORE INTO VARIABLE\n"); |
1260 | strcat(s,"0073 30BC; 83 SV STORE INTO VARIABLE\n"); |
1250 | strcat(s,"0075 13; 84 RB SWAP BACK\n"); |
1261 | strcat(s,"0075 13; 84 RB SWAP BACK\n"); |
1251 | strcat(s,"0076 11; 85 BC I6 \",\" ANOTHER?\n"); |
1262 | strcat(s,"0076 11; 85 BC I6 \",\" ANOTHER?\n"); |
1252 | strcat(s,"0077 82AC; 86 BR I2 YES IF COMMA\n"); |
1263 | strcat(s,"0077 82AC; 86 BR I2 YES IF COMMA\n"); |
1253 | strcat(s,"0079 4D; 87 :I6 BE * OTHERWISE QUIT\n"); |
1264 | strcat(s,"0079 4D; 87 :I6 BE * OTHERWISE QUIT\n"); |
1254 | strcat(s,"007A E0; 88 NX\n"); |
1265 | strcat(s,"007A E0; 88 NX\n"); |
1255 | strcat(s,"007B 1D; 89 .\n"); |
1266 | strcat(s,"007B 1D; 89 .\n"); |
1256 | strcat(s,"007C ; 90 :RETN BC END \"RETURN\"\n"); |
1267 | strcat(s,"007C ; 90 :RETN BC END \"RETURN\"\n"); |
1257 | strcat(s,"007C 895245545552CE;\n"); |
1268 | strcat(s,"007C 895245545552CE;\n"); |
1258 | strcat(s,"0083 ; 91 BE *\n"); |
1269 | strcat(s,"0083 ; 91 BE *\n"); |
1259 | strcat(s,"0083 E0; 92 RS RECOVER SAVED LINE\n"); |
1270 | strcat(s,"0083 E0; 92 RS RECOVER SAVED LINE\n"); |
1260 | strcat(s,"0084 15; 93 NX\n"); |
1271 | strcat(s,"0084 15; 93 NX\n"); |
1261 | strcat(s,"0085 1D; 94 .\n"); |
1272 | strcat(s,"0085 1D; 94 .\n"); |
1262 | strcat(s,"0086 ; 95 :END BC LIST \"END\"\n"); |
1273 | strcat(s,"0086 ; 95 :END BC LIST \"END\"\n"); |
1263 | strcat(s,"0086 85454EC4;\n"); |
1274 | strcat(s,"0086 85454EC4;\n"); |
1264 | strcat(s,"008A ; 96 BE *\n"); |
1275 | strcat(s,"008A ; 96 BE *\n"); |
1265 | strcat(s,"008A E0; 97 WS\n"); |
1276 | strcat(s,"008A E0; 97 WS\n"); |
1266 | strcat(s,"008B 2D; 98 .\n"); |
1277 | strcat(s,"008B 2D; 98 .\n"); |
1267 | strcat(s,"008C ; 99 :LIST BC RUN \"LIST\"\n"); |
1278 | strcat(s,"008C ; 99 :LIST BC RUN \"LIST\"\n"); |
1268 | strcat(s,"008C 984C4953D4;\n"); |
1279 | strcat(s,"008C 984C4953D4;\n"); |
1269 | strcat(s,"0091 ; 100 BE L2\n"); |
1280 | strcat(s,"0091 ; 100 BE L2\n"); |
1270 | strcat(s,"0091 EC; 101 :L1 PC \"@^@^@^@^J^@^\" PUNCH LEADER\n"); |
1281 | strcat(s,"0091 EC; 101 :L1 PC \"@^@^@^@^J^@^\" PUNCH LEADER\n"); |
1271 | strcat(s,"0092 24000000000A80;\n"); |
1282 | strcat(s,"0092 24000000000A80;\n"); |
1272 | strcat(s,"0099 ; 102 LS LIST\n"); |
1283 | strcat(s,"0099 ; 102 LS LIST\n"); |
1273 | strcat(s,"0099 1F; 103 PC \"S^\" PUNCH X-OFF\n"); |
1284 | strcat(s,"0099 1F; 103 PC \"S^\" PUNCH X-OFF\n"); |
1274 | strcat(s,"009A 2493; 104 NL\n"); |
1285 | strcat(s,"009A 2493; 104 NL\n"); |
1275 | strcat(s,"009C 23; 105 NX\n"); |
1286 | strcat(s,"009C 23; 105 NX\n"); |
1276 | strcat(s,"009D 1D; 106 :L2 JS EXPR GET A LINE NUMBER\n"); |
1287 | strcat(s,"009D 1D; 106 :L2 JS EXPR GET A LINE NUMBER\n"); |
1277 | strcat(s,"009E 30BC; 107 BE L3\n"); |
1288 | strcat(s,"009E 30BC; 107 BE L3\n"); |
1278 | strcat(s,"00A0 E1; 108 BR L1\n"); |
1289 | strcat(s,"00A0 E1; 108 BR L1\n"); |
1279 | strcat(s,"00A1 50; 109 :L3 BC * \",\" SEPARATED BY COMMAS\n"); |
1290 | strcat(s,"00A1 50; 109 :L3 BC * \",\" SEPARATED BY COMMAS\n"); |
1280 | strcat(s,"00A2 80AC; 110 BR L2\n"); |
1291 | strcat(s,"00A2 80AC; 110 BR L2\n"); |
1281 | strcat(s,"00A4 59; 111 .\n"); |
1292 | strcat(s,"00A4 59; 111 .\n"); |
1282 | strcat(s,"00A5 ; 112 :RUN BC CLER \"RUN\"\n"); |
1293 | strcat(s,"00A5 ; 112 :RUN BC CLER \"RUN\"\n"); |
1283 | strcat(s,"00A5 855255CE;\n"); |
1294 | strcat(s,"00A5 855255CE;\n"); |
1284 | strcat(s,"00A9 ; 113 J XEC\n"); |
1295 | strcat(s,"00A9 ; 113 J XEC\n"); |
1285 | strcat(s,"00A9 380A; 114 .\n"); |
1296 | strcat(s,"00A9 380A; 114 .\n"); |
1286 | strcat(s,"00AB ; 115 :CLER BC REM \"CLEAR\"\n"); |
1297 | strcat(s,"00AB ; 115 :CLER BC REM \"CLEAR\"\n"); |
1287 | strcat(s,"00AB 86434C4541D2;\n"); |
1298 | strcat(s,"00AB 86434C4541D2;\n"); |
1288 | strcat(s,"00B1 ; 116 MT\n"); |
1299 | strcat(s,"00B1 ; 116 MT\n"); |
1289 | strcat(s,"00B1 2B; 117 .\n"); |
1300 | strcat(s,"00B1 2B; 117 .\n"); |
1290 | strcat(s,"00B2 ; 118 :REM BC DFLT \"REM\"\n"); |
1301 | strcat(s,"00B2 ; 118 :REM BC DFLT \"REM\"\n"); |
1291 | strcat(s,"00B2 845245CD;\n"); |
1302 | strcat(s,"00B2 845245CD;\n"); |
1292 | strcat(s,"00B6 ; 119 NX\n"); |
1303 | strcat(s,"00B6 ; 119 NX\n"); |
1293 | strcat(s,"00B6 1D; 120 .\n"); |
1304 | strcat(s,"00B6 1D; 120 .\n"); |
1294 | strcat(s,"00B7 ; 121 :DFLT BV * NO KEYWORD...\n"); |
1305 | strcat(s,"00B7 ; 121 :DFLT BV * NO KEYWORD...\n"); |
1295 | strcat(s,"00B7 A0; 122 BC * \"=\" TRY FOR LET\n"); |
1306 | strcat(s,"00B7 A0; 122 BC * \"=\" TRY FOR LET\n"); |
1296 | strcat(s,"00B8 80BD; 123 J LET IT'S A GOOD BET.\n"); |
1307 | strcat(s,"00B8 80BD; 123 J LET IT'S A GOOD BET.\n"); |
1297 | strcat(s,"00BA 3814; 124 .\n"); |
1308 | strcat(s,"00BA 3814; 124 .\n"); |
1298 | strcat(s,"00BC ; 125 . SUBROUTINES\n"); |
1309 | strcat(s,"00BC ; 125 . SUBROUTINES\n"); |
1299 | strcat(s,"00BC ; 126 .\n"); |
1310 | strcat(s,"00BC ; 126 .\n"); |
1300 | strcat(s,"00BC ; 127 :EXPR BC E0 \"-\" TRY FOR UNARY MINUS\n"); |
1311 | strcat(s,"00BC ; 127 :EXPR BC E0 \"-\" TRY FOR UNARY MINUS\n"); |
1301 | strcat(s,"00BC 85AD; 128 JS TERM AHA\n"); |
1312 | strcat(s,"00BC 85AD; 128 JS TERM AHA\n"); |
1302 | strcat(s,"00BE 30D3; 129 NE\n"); |
1313 | strcat(s,"00BE 30D3; 129 NE\n"); |
1303 | strcat(s,"00C0 17; 130 BR E1\n"); |
1314 | strcat(s,"00C0 17; 130 BR E1\n"); |
1304 | strcat(s,"00C1 64; 131 :E0 BC E4 \"+\" IGNORE UNARY PLUS\n"); |
1315 | strcat(s,"00C1 64; 131 :E0 BC E4 \"+\" IGNORE UNARY PLUS\n"); |
1305 | strcat(s,"00C2 81AB; 132 :E4 JS TERM\n"); |
1316 | strcat(s,"00C2 81AB; 132 :E4 JS TERM\n"); |
1306 | strcat(s,"00C4 30D3; 133 :E1 BC E2 \"+\" TERMS SEPARATED BY PLUS\n"); |
1317 | strcat(s,"00C4 30D3; 133 :E1 BC E2 \"+\" TERMS SEPARATED BY PLUS\n"); |
1307 | strcat(s,"00C6 85AB; 134 JS TERM\n"); |
1318 | strcat(s,"00C6 85AB; 134 JS TERM\n"); |
1308 | strcat(s,"00C8 30D3; 135 AD\n"); |
1319 | strcat(s,"00C8 30D3; 135 AD\n"); |
1309 | strcat(s,"00CA 18; 136 BR E1\n"); |
1320 | strcat(s,"00CA 18; 136 BR E1\n"); |
1310 | strcat(s,"00CB 5A; 137 :E2 BC E3 \"-\" TERMS SEPARATED BY MINUS\n"); |
1321 | strcat(s,"00CB 5A; 137 :E2 BC E3 \"-\" TERMS SEPARATED BY MINUS\n"); |
1311 | strcat(s,"00CC 85AD; 138 JS TERM\n"); |
1322 | strcat(s,"00CC 85AD; 138 JS TERM\n"); |
1312 | strcat(s,"00CE 30D3; 139 SU\n"); |
1323 | strcat(s,"00CE 30D3; 139 SU\n"); |
1313 | strcat(s,"00D0 19; 140 BR E1\n"); |
1324 | strcat(s,"00D0 19; 140 BR E1\n"); |
1314 | strcat(s,"00D1 54; 141 :E3 RT\n"); |
1325 | strcat(s,"00D1 54; 141 :E3 RT\n"); |
1315 | strcat(s,"00D2 2F; 142 .\n"); |
1326 | strcat(s,"00D2 2F; 142 .\n"); |
1316 | strcat(s,"00D3 ; 143 :TERM JS FACT\n"); |
1327 | strcat(s,"00D3 ; 143 :TERM JS FACT\n"); |
1317 | strcat(s,"00D3 30E2; 144 :T0 BC T1 \"*\" FACTORS SEPARATED BY TIMES\n"); |
1328 | strcat(s,"00D3 30E2; 144 :T0 BC T1 \"*\" FACTORS SEPARATED BY TIMES\n"); |
1318 | strcat(s,"00D5 85AA; 145 JS FACT\n"); |
1329 | strcat(s,"00D5 85AA; 145 JS FACT\n"); |
1319 | strcat(s,"00D7 30E2; 146 MP\n"); |
1330 | strcat(s,"00D7 30E2; 146 MP\n"); |
1320 | strcat(s,"00D9 1A; 147 BR T0\n"); |
1331 | strcat(s,"00D9 1A; 147 BR T0\n"); |
1321 | strcat(s,"00DA 5A; 148 :T1 BC T2 \"/\" FACTORS SEPARATED BY DIVIDE\n"); |
1332 | strcat(s,"00DA 5A; 148 :T1 BC T2 \"/\" FACTORS SEPARATED BY DIVIDE\n"); |
1322 | strcat(s,"00DB 85AF; 149 JS FACT\n"); |
1333 | strcat(s,"00DB 85AF; 149 JS FACT\n"); |
1323 | strcat(s,"00DD 30E2; 150 DV\n"); |
1334 | strcat(s,"00DD 30E2; 150 DV\n"); |
1324 | strcat(s,"00DF 1B; 151 BR T0\n"); |
1335 | strcat(s,"00DF 1B; 151 BR T0\n"); |
1325 | strcat(s,"00E0 54; 152 :T2 RT\n"); |
1336 | strcat(s,"00E0 54; 152 :T2 RT\n"); |
1326 | strcat(s,"00E1 2F; 153 .\n"); |
1337 | strcat(s,"00E1 2F; 153 .\n"); |
1327 | strcat(s,"00E2 ; 154 :FACT BC F0 \"RND\" *RND FUNCTION*\n"); |
1338 | strcat(s,"00E2 ; 154 :FACT BC F0 \"RND\" *RND FUNCTION*\n"); |
1328 | strcat(s,"00E2 97524EC4;\n"); |
1339 | strcat(s,"00E2 97524EC4;\n"); |
1329 | strcat(s,"00E6 ; 155 LN 257*128 STACK POINTER FOR STORE\n"); |
1340 | strcat(s,"00E6 ; 155 LN 257*128 STACK POINTER FOR STORE\n"); |
1330 | strcat(s,"00E6 0A;\n"); |
1341 | strcat(s,"00E6 0A;\n"); |
1331 | strcat(s,"00E7 8080; 156 FV THEN GET RNDM\n"); |
1342 | strcat(s,"00E7 8080; 156 FV THEN GET RNDM\n"); |
1332 | strcat(s,"00E9 12; 157 LN 2345 R:=R*2345+6789\n"); |
1343 | strcat(s,"00E9 12; 157 LN 2345 R:=R*2345+6789\n"); |
1333 | strcat(s,"00EA 0A;\n"); |
1344 | strcat(s,"00EA 0A;\n"); |
1334 | strcat(s,"00EB 0929; 158 MP\n"); |
1345 | strcat(s,"00EB 0929; 158 MP\n"); |
1335 | strcat(s,"00ED 1A; 159 LN 6789\n"); |
1346 | strcat(s,"00ED 1A; 159 LN 6789\n"); |
1336 | strcat(s,"00EE 0A;\n"); |
1347 | strcat(s,"00EE 0A;\n"); |
1337 | strcat(s,"00EF 1A85; 160 AD\n"); |
1348 | strcat(s,"00EF 1A85; 160 AD\n"); |
1338 | strcat(s,"00F1 18; 161 SV\n"); |
1349 | strcat(s,"00F1 18; 161 SV\n"); |
1339 | strcat(s,"00F2 13; 162 LB 128 GET IT AGAIN\n"); |
1350 | strcat(s,"00F2 13; 162 LB 128 GET IT AGAIN\n"); |
1340 | strcat(s,"00F3 0980; 163 FV\n"); |
1351 | strcat(s,"00F3 0980; 163 FV\n"); |
1341 | strcat(s,"00F5 12; 164 DS\n"); |
1352 | strcat(s,"00F5 12; 164 DS\n"); |
1342 | strcat(s,"00F6 0B; 165 JS FUNC GET ARGUMENT\n"); |
1353 | strcat(s,"00F6 0B; 165 JS FUNC GET ARGUMENT\n"); |
1343 | strcat(s,"00F7 3130; 166 BR F1\n"); |
1354 | strcat(s,"00F7 3130; 166 BR F1\n"); |
1344 | strcat(s,"00F9 61; 167 :F0 BR F2 (SKIPPING)\n"); |
1355 | strcat(s,"00F9 61; 167 :F0 BR F2 (SKIPPING)\n"); |
1345 | strcat(s,"00FA 73; 168 :F1 DS\n"); |
1356 | strcat(s,"00FA 73; 168 :F1 DS\n"); |
1346 | strcat(s,"00FB 0B; 169 SX 2 PUSH TOP INTO STACK\n"); |
1357 | strcat(s,"00FB 0B; 169 SX 2 PUSH TOP INTO STACK\n"); |
1347 | strcat(s,"00FC 02; 170 SX 4\n"); |
1358 | strcat(s,"00FC 02; 170 SX 4\n"); |
1348 | strcat(s,"00FD 04; 171 SX 2\n"); |
1359 | strcat(s,"00FD 04; 171 SX 2\n"); |
1349 | strcat(s,"00FE 02; 172 SX 3\n"); |
1360 | strcat(s,"00FE 02; 172 SX 3\n"); |
1350 | strcat(s,"00FF 03; 173 SX 5\n"); |
1361 | strcat(s,"00FF 03; 173 SX 5\n"); |
1351 | strcat(s,"0100 05; 174 SX 3\n"); |
1362 | strcat(s,"0100 05; 174 SX 3\n"); |
1352 | strcat(s,"0101 03; 175 DV PERFORM MOD FUNCTION\n"); |
1363 | strcat(s,"0101 03; 175 DV PERFORM MOD FUNCTION\n"); |
1353 | strcat(s,"0102 1B; 176 MP\n"); |
1364 | strcat(s,"0102 1B; 176 MP\n"); |
1354 | strcat(s,"0103 1A; 177 SU\n"); |
1365 | strcat(s,"0103 1A; 177 SU\n"); |
1355 | strcat(s,"0104 19; 178 DS PERFORM ABS FUNCTION\n"); |
1366 | strcat(s,"0104 19; 178 DS PERFORM ABS FUNCTION\n"); |
1356 | strcat(s,"0105 0B; 179 LB 6\n"); |
1367 | strcat(s,"0105 0B; 179 LB 6\n"); |
1357 | strcat(s,"0106 0906; 180 LN 0\n"); |
1368 | strcat(s,"0106 0906; 180 LN 0\n"); |
1358 | strcat(s,"0108 0A;\n"); |
1369 | strcat(s,"0108 0A;\n"); |
1359 | strcat(s,"0109 0000; 181 CP (SKIP IF + OR 0)\n"); |
1370 | strcat(s,"0109 0000; 181 CP (SKIP IF + OR 0)\n"); |
1360 | strcat(s,"010B 1C; 182 NE\n"); |
1371 | strcat(s,"010B 1C; 182 NE\n"); |
1361 | strcat(s,"010C 17; 183 RT\n"); |
1372 | strcat(s,"010C 17; 183 RT\n"); |
1362 | strcat(s,"010D 2F; 184 :F2 BC F3 \"USR\" *USR FUNCTION*\n"); |
1373 | strcat(s,"010D 2F; 184 :F2 BC F3 \"USR\" *USR FUNCTION*\n"); |
1363 | strcat(s,"010E 8F5553D2;\n"); |
1374 | strcat(s,"010E 8F5553D2;\n"); |
1364 | strcat(s,"0112 ; 185 BC * \"(\" 3 ARGUMENTS POSSIBLE\n"); |
1375 | strcat(s,"0112 ; 185 BC * \"(\" 3 ARGUMENTS POSSIBLE\n"); |
1365 | strcat(s,"0112 80A8; 186 JS EXPR ONE REQUIRED\n"); |
1376 | strcat(s,"0112 80A8; 186 JS EXPR ONE REQUIRED\n"); |
1366 | strcat(s,"0114 30BC; 187 JS ARG\n"); |
1377 | strcat(s,"0114 30BC; 187 JS ARG\n"); |
1367 | strcat(s,"0116 312A; 188 JS ARG\n"); |
1378 | strcat(s,"0116 312A; 188 JS ARG\n"); |
1368 | strcat(s,"0118 312A; 189 BC * \")\"\n"); |
1379 | strcat(s,"0118 312A; 189 BC * \")\"\n"); |
1369 | strcat(s,"011A 80A9; 190 US GO DO IT\n"); |
1380 | strcat(s,"011A 80A9; 190 US GO DO IT\n"); |
1370 | strcat(s,"011C 2E; 191 RT\n"); |
1381 | strcat(s,"011C 2E; 191 RT\n"); |
1371 | strcat(s,"011D 2F; 192 :F3 BV F4 VARIABLE?\n"); |
1382 | strcat(s,"011D 2F; 192 :F3 BV F4 VARIABLE?\n"); |
1372 | strcat(s,"011E A2; 193 FV YES. GET IT\n"); |
1383 | strcat(s,"011E A2; 193 FV YES. GET IT\n"); |
1373 | strcat(s,"011F 12; 194 RT\n"); |
1384 | strcat(s,"011F 12; 194 RT\n"); |
1374 | strcat(s,"0120 2F; 195 :F4 BN F5 NUMBER?\n"); |
1385 | strcat(s,"0120 2F; 195 :F4 BN F5 NUMBER?\n"); |
1375 | strcat(s,"0121 C1; 196 RT GOT IT.\n"); |
1386 | strcat(s,"0121 C1; 196 RT GOT IT.\n"); |
1376 | strcat(s,"0122 2F; 197 :F5 BC * \"(\" OTHERWISE MUST BE (EXPR)\n"); |
1387 | strcat(s,"0122 2F; 197 :F5 BC * \"(\" OTHERWISE MUST BE (EXPR)\n"); |
1377 | strcat(s,"0123 80A8; 198 :F6 JS EXPR\n"); |
1388 | strcat(s,"0123 80A8; 198 :F6 JS EXPR\n"); |
1378 | strcat(s,"0125 30BC; 199 BC * \")\"\n"); |
1389 | strcat(s,"0125 30BC; 199 BC * \")\"\n"); |
1379 | strcat(s,"0127 80A9; 200 RT\n"); |
1390 | strcat(s,"0127 80A9; 200 RT\n"); |
1380 | strcat(s,"0129 2F; 201 .\n"); |
1391 | strcat(s,"0129 2F; 201 .\n"); |
1381 | strcat(s,"012A ; 202 :ARG BC A0 \",\" COMMA?\n"); |
1392 | strcat(s,"012A ; 202 :ARG BC A0 \",\" COMMA?\n"); |
1382 | strcat(s,"012A 83AC; 203 J EXPR YES, GET EXPRESSION\n"); |
1393 | strcat(s,"012A 83AC; 203 J EXPR YES, GET EXPRESSION\n"); |
1383 | strcat(s,"012C 38BC; 204 :A0 DS NO, DUPLICATE STACK TOP\n"); |
1394 | strcat(s,"012C 38BC; 204 :A0 DS NO, DUPLICATE STACK TOP\n"); |
1384 | strcat(s,"012E 0B; 205 RT\n"); |
1395 | strcat(s,"012E 0B; 205 RT\n"); |
1385 | strcat(s,"012F 2F; 206 .\n"); |
1396 | strcat(s,"012F 2F; 206 .\n"); |
1386 | strcat(s,"0130 ; 207 :FUNC BC * \"(\"\n"); |
1397 | strcat(s,"0130 ; 207 :FUNC BC * \"(\"\n"); |
1387 | strcat(s,"0130 80A8; 208 BR F6\n"); |
1398 | strcat(s,"0130 80A8; 208 BR F6\n"); |
1388 | strcat(s,"0132 52; 209 RT\n"); |
1399 | strcat(s,"0132 52; 209 RT\n"); |
1389 | strcat(s,"0133 2F; 210 .\n"); |
1400 | strcat(s,"0133 2F; 210 .\n"); |
1390 | strcat(s,"0134 ; 211 :RELO BC R0 \"=\" CONVERT RELATION OPERATORS\n"); |
1401 | strcat(s,"0134 ; 211 :RELO BC R0 \"=\" CONVERT RELATION OPERATORS\n"); |
1391 | strcat(s,"0134 84BD; 212 LB 2 TO CODE BYTE ON STACK\n"); |
1402 | strcat(s,"0134 84BD; 212 LB 2 TO CODE BYTE ON STACK\n"); |
1392 | strcat(s,"0136 0902; 213 RT =\n"); |
1403 | strcat(s,"0136 0902; 213 RT =\n"); |
1393 | strcat(s,"0138 2F; 214 :R0 BC R4 \"<\"\n"); |
1404 | strcat(s,"0138 2F; 214 :R0 BC R4 \"<\"\n"); |
1394 | strcat(s,"0139 8EBC; 215 BC R1 \"=\"\n"); |
1405 | strcat(s,"0139 8EBC; 215 BC R1 \"=\"\n"); |
1395 | strcat(s,"013B 84BD; 216 LB 3 <=\n"); |
1406 | strcat(s,"013B 84BD; 216 LB 3 <=\n"); |
1396 | strcat(s,"013D 0903; 217 RT\n"); |
1407 | strcat(s,"013D 0903; 217 RT\n"); |
1397 | strcat(s,"013F 2F; 218 :R1 BC R3 \">\"\n"); |
1408 | strcat(s,"013F 2F; 218 :R1 BC R3 \">\"\n"); |
1398 | strcat(s,"0140 84BE; 219 LB 5 <>\n"); |
1409 | strcat(s,"0140 84BE; 219 LB 5 <>\n"); |
1399 | strcat(s,"0142 0905; 220 RT\n"); |
1410 | strcat(s,"0142 0905; 220 RT\n"); |
1400 | strcat(s,"0144 2F; 221 :R3 LB 1 <\n"); |
1411 | strcat(s,"0144 2F; 221 :R3 LB 1 <\n"); |
1401 | strcat(s,"0145 0901; 222 RT\n"); |
1412 | strcat(s,"0145 0901; 222 RT\n"); |
1402 | strcat(s,"0147 2F; 223 :R4 BC * \">\"\n"); |
1413 | strcat(s,"0147 2F; 223 :R4 BC * \">\"\n"); |
1403 | strcat(s,"0148 80BE; 224 BC R5 \"=\"\n"); |
1414 | strcat(s,"0148 80BE; 224 BC R5 \"=\"\n"); |
1404 | strcat(s,"014A 84BD; 225 LB 6 >=\n"); |
1415 | strcat(s,"014A 84BD; 225 LB 6 >=\n"); |
1405 | strcat(s,"014C 0906; 226 RT\n"); |
1416 | strcat(s,"014C 0906; 226 RT\n"); |
1406 | strcat(s,"014E 2F; 227 :R5 BC R6 \"<\"\n"); |
1417 | strcat(s,"014E 2F; 227 :R5 BC R6 \"<\"\n"); |
1407 | strcat(s,"014F 84BC; 228 LB 5 ><\n"); |
1418 | strcat(s,"014F 84BC; 228 LB 5 ><\n"); |
1408 | strcat(s,"0151 0905; 229 RT\n"); |
1419 | strcat(s,"0151 0905; 229 RT\n"); |
1409 | strcat(s,"0153 2F; 230 :R6 LB 4 >\n"); |
1420 | strcat(s,"0153 2F; 230 :R6 LB 4 >\n"); |
1410 | strcat(s,"0154 0904; 231 RT\n"); |
1421 | strcat(s,"0154 0904; 231 RT\n"); |
1411 | strcat(s,"0156 2F; 232 .\n"); |
1422 | strcat(s,"0156 2F; 232 .\n"); |
1412 | strcat(s,"0157 ; 0000\n"); |
1423 | strcat(s,"0157 ; 0000\n"); |
1413 | return s;} /* ~DefaultIL */ |
1424 | return s;} /* ~DefaultIL */ |
1414 | 1425 | ||
1415 | /**************************** Startup Code ****************************/ |
1426 | /**************************** Startup Code ****************************/ |
1416 | 1427 | ||
1417 | void StartTinyBasic(char* ILtext) { |
1428 | void StartTinyBasic(char* ILtext) { |
1418 | int nx; |
1429 | int nx; |
1419 | for (nx=0; nx |
1430 | for (nx=0; nx |
1420 | Poke2(ExpnStk,8191); /* random number seed */ |
1431 | Poke2(ExpnStk,8191); /* random number seed */ |
1421 | Core[BScode] = 8; /* backspace */ |
1432 | Core[BScode] = 8; /* backspace */ |
1422 | Core[CanCode] = 27; /*escape */ |
1433 | Core[CanCode] = 27; /*escape */ |
1423 | for (nx=0; nx<32; nx++) DeCaps[nx] = '\0'; /* fill caps table.. */ |
1434 | for (nx=0; nx<32; nx++) DeCaps[nx] = '\0'; /* fill caps table.. */ |
1424 | for (nx=32; nx<127; nx++) DeCaps[nx] = (char)nx; |
1435 | for (nx=32; nx<127; nx++) DeCaps[nx] = (char)nx; |
1425 | for (nx=65; nx<91; nx++) DeCaps[nx+32] = (char)nx; |
1436 | for (nx=65; nx<91; nx++) DeCaps[nx+32] = (char)nx; |
1426 | DeCaps[9] = ' '; |
1437 | DeCaps[9] = ' '; |
1427 | DeCaps[10] = '\r'; |
1438 | DeCaps[10] = '\r'; |
1428 | DeCaps[13] = '\r'; |
1439 | DeCaps[13] = '\r'; |
1429 | DeCaps[127] = '\0'; |
1440 | DeCaps[127] = '\0'; |
1430 | if (ILtext == NULL) ILtext = DefaultIL(); /* no IL given, use mine */ |
1441 | if (ILtext == NULL) ILtext = DefaultIL(); /* no IL given, use mine */ |
1431 | ConvtIL(ILtext); /* convert IL assembly code to binary */ |
1442 | ConvtIL(ILtext); /* convert IL assembly code to binary */ |
1432 | ColdStart(); |
1443 | ColdStart(); |
1433 | Interp(); /* go do it */ |
1444 | Interp(); /* go do it */ |
1434 | if (oFile != NULL) IoFileClose(oFile); /* close output file */ |
1445 | if (oFile != NULL) IoFileClose(oFile); /* close output file */ |
1435 | if (inFile != NULL) IoFileClose(inFile); /* close input file */ |
1446 | if (inFile != NULL) IoFileClose(inFile); /* close input file */ |
1436 | oFile = NULL; |
1447 | oFile = NULL; |
1437 | inFile = NULL;} /* ~StartTinyBasic */ |
1448 | inFile = NULL;} /* ~StartTinyBasic */ |
1438 | 1449 | ||
1439 | int main(int argc, char* argv[]) { |
1450 | int main(int argc, char* argv[]) { |
1440 | /* CONSOLE_INIT("TinyBasic"); */ |
1451 | /* CONSOLE_INIT("TinyBasic"); */ |
1441 | #if defined(__TINYC__) |
- | |
1442 | if (con_init_console_dll()) return 1; // init fail |
1452 | if (con_init_console_dll()) return 1; // init fail |
1443 | #endif |
1453 | con_set_title("TinyBasic"); |
1444 | 1454 | ||
1445 | int nx; |
1455 | int nx; |
1446 | long int len; |
1456 | long int len; |
1447 | char* IL = NULL; |
1457 | char* IL = NULL; |
1448 | FileType tmpFile; |
1458 | FileType tmpFile; |
1449 | inFile = NULL; |
1459 | inFile = NULL; |
1450 | oFile = NULL; |
1460 | oFile = NULL; |
1451 | for (nx=1; nx |
1461 | for (nx=1; nx |
1452 | if (strcmp(argv[nx],"-b")==0 && ++nx |
1462 | if (strcmp(argv[nx],"-b")==0 && ++nx |
1453 | tmpFile = fopen(argv[nx],"r"); |
1463 | tmpFile = fopen(argv[nx],"r"); |
1454 | if (tmpFile != NULL) if (fseek(tmpFile,0,SEEK_END)==0) { |
1464 | if (tmpFile != NULL) if (fseek(tmpFile,0,SEEK_END)==0) { |
1455 | len = ftell(tmpFile); /* get file size.. */ |
1465 | len = ftell(tmpFile); /* get file size.. */ |
1456 | if (fseek(tmpFile,0,SEEK_SET)==0) if (len>9) { |
1466 | if (fseek(tmpFile,0,SEEK_SET)==0) if (len>9) { |
1457 | len = len/8+len; /* allow for line end expansion */ |
1467 | len = len/8+len; /* allow for line end expansion */ |
1458 | IL = (char*)malloc(len+1); |
1468 | IL = (char*)malloc(len+1); |
1459 | if (IL != NULL) len = fread(IL,1,len,tmpFile); |
1469 | if (IL != NULL) len = fread(IL,1,len,tmpFile); |
1460 | IL[len] = '\0'; |
1470 | IL[len] = '\0'; |
1461 | IoFileClose(tmpFile);}} |
1471 | IoFileClose(tmpFile);}} |
1462 | else printf("Could not open file %s", argv[nx]);} |
1472 | else con_printf("Could not open file %s", argv[nx]);} |
1463 | else if (strcmp(argv[nx],"-o")==0 && ++nx |
1473 | else if (strcmp(argv[nx],"-o")==0 && ++nx |
1464 | oFile = fopen(argv[nx],"w"); |
1474 | oFile = fopen(argv[nx],"w"); |
1465 | else if (strcmp(argv[nx],"-i")==0 && ++nx |
1475 | else if (strcmp(argv[nx],"-i")==0 && ++nx |
1466 | inFile = fopen(argv[nx],"r"); |
1476 | inFile = fopen(argv[nx],"r"); |
1467 | else if (inFile==NULL) /* default (unadorned) is also input file */ |
1477 | else if (inFile==NULL) /* default (unadorned) is also input file */ |
1468 | inFile = fopen(argv[nx],"r");} /* ignore other args */ |
1478 | inFile = fopen(argv[nx],"r");} /* ignore other args */ |
1469 | 1479 | ||
1470 | #ifdef DefaultInputFile |
1480 | #ifdef DefaultInputFile |
1471 | if (inFile==NULL) inFile = fopen(DefaultInputFile,"r"); |
1481 | if (inFile==NULL) inFile = fopen(DefaultInputFile,"r"); |
1472 | #endif |
1482 | #endif |
1473 | #ifdef DefaultOutputFile |
1483 | #ifdef DefaultOutputFile |
1474 | if (oFile==NULL) oFile = fopen(DefaultOutputFile,"w"); |
1484 | if (oFile==NULL) oFile = fopen(DefaultOutputFile,"w"); |
1475 | #endif |
1485 | #endif |
1476 | 1486 | ||
1477 | StartTinyBasic(IL); /* go do it */ |
1487 | StartTinyBasic(IL); /* go do it */ |
1478 | return 0;} /* ~main */ |
1488 | return 0;} /* ~main */ |
1479 | 1489 | ||
1480 | 1490 | ||
1481 | char *ExplainErr(int code) |
1491 | char *ExplainErr(int code) |
1482 | { |
1492 | { |
1483 | switch (code) |
1493 | switch (code) |
1484 | { |
1494 | { |
1485 | case 0: return "Break during execution"; |
1495 | case 0: return "Break during execution"; |
1486 | case 8: return "Memory overflow; line not inserted"; |
1496 | case 8: return "Memory overflow; line not inserted"; |
1487 | case 9: return "Line number 0 not allowed"; |
1497 | case 9: return "Line number 0 not allowed"; |
1488 | case 13: return "RUN with no program in memory"; |
1498 | case 13: return "RUN with no program in memory"; |
1489 | case 18: return "LET is missing a variable name"; |
1499 | case 18: return "LET is missing a variable name"; |
1490 | case 20: return "LET is missing an ="; |
1500 | case 20: return "LET is missing an ="; |
1491 | case 23: return "Improper syntax in LET"; |
1501 | case 23: return "Improper syntax in LET"; |
1492 | case 25: return "LET is not followed by END"; |
1502 | case 25: return "LET is not followed by END"; |
1493 | case 34: return "Improper syntax in GOTO"; |
1503 | case 34: return "Improper syntax in GOTO"; |
1494 | case 37: return "No line to GO TO"; |
1504 | case 37: return "No line to GO TO"; |
1495 | case 39: return "Misspelled GOTO"; |
1505 | case 39: return "Misspelled GOTO"; |
1496 | case 40: |
1506 | case 40: |
1497 | case 41: return "Misspelled GOSUB"; |
1507 | case 41: return "Misspelled GOSUB"; |
1498 | case 46: return "GOSUB subroutine does not exist"; |
1508 | case 46: return "GOSUB subroutine does not exist"; |
1499 | case 59: return "PRINT not followed by END"; |
1509 | case 59: return "PRINT not followed by END"; |
1500 | case 62: return "Missing close quote in PRINT string"; |
1510 | case 62: return "Missing close quote in PRINT string"; |
1501 | case 73: return "Colon in PRINT is not at end of statement"; |
1511 | case 73: return "Colon in PRINT is not at end of statement"; |
1502 | case 75: return "PRINT not followed by END"; |
1512 | case 75: return "PRINT not followed by END"; |
1503 | case 95: return "IF not followed by END"; |
1513 | case 95: return "IF not followed by END"; |
1504 | case 104: return "INPUT syntax bad - expects variable name"; |
1514 | case 104: return "INPUT syntax bad - expects variable name"; |
1505 | case 123: return "INPUT syntax bad - expects comma"; |
1515 | case 123: return "INPUT syntax bad - expects comma"; |
1506 | case 124: return "INPUT not followed by END"; |
1516 | case 124: return "INPUT not followed by END"; |
1507 | case 132: return "RETURN syntax bad"; |
1517 | case 132: return "RETURN syntax bad"; |
1508 | case 133: return "RETURN has no matching GOSUB"; |
1518 | case 133: return "RETURN has no matching GOSUB"; |
1509 | case 134: return "GOSUB not followed by END"; |
1519 | case 134: return "GOSUB not followed by END"; |
1510 | case 139: return "END syntax bad"; |
1520 | case 139: return "END syntax bad"; |
1511 | case 154: return "Can't LIST line number 0"; |
1521 | case 154: return "Can't LIST line number 0"; |
1512 | case 164: return "LIST syntax error - expects comma"; |
1522 | case 164: return "LIST syntax error - expects comma"; |
1513 | case 183: return "REM not followed by END"; |
1523 | case 183: return "REM not followed by END"; |
1514 | case 184: return "Missing statement type keyword"; |
1524 | case 184: return "Missing statement type keyword"; |
1515 | case 186: return "Misspelled statement type keyword"; |
1525 | case 186: return "Misspelled statement type keyword"; |
1516 | case 188: return "Memory overflow: too many GOSUB's ..."; |
1526 | case 188: return "Memory overflow: too many GOSUB's ..."; |
1517 | case 211: return "Memory overflow: ... or expression too complex"; |
1527 | case 211: return "Memory overflow: ... or expression too complex"; |
1518 | case 224: return "Divide by 0"; |
1528 | case 224: return "Divide by 0"; |
1519 | case 226: return "Memory overflow"; |
1529 | case 226: return "Memory overflow"; |
1520 | case 232: return "Expression too complex ..."; |
1530 | case 232: return "Expression too complex ..."; |
1521 | case 233: return "Expression too complex ... using RND ..."; |
1531 | case 233: return "Expression too complex ... using RND ..."; |
1522 | case 234: return "Expression too complex ... in direct evaluation"; |
1532 | case 234: return "Expression too complex ... in direct evaluation"; |
1523 | case 253: return "Expression too complex ... simplify the expression"; |
1533 | case 253: return "Expression too complex ... simplify the expression"; |
1524 | case 259: return "RND (0) not allowed"; |
1534 | case 259: return "RND (0) not allowed"; |
1525 | case 266: return "Expression too complex ..."; |
1535 | case 266: return "Expression too complex ..."; |
1526 | case 267: return "Expression too complex ... for RND"; |
1536 | case 267: return "Expression too complex ... for RND"; |
1527 | case 275: return "USR expects \"(\" before arguments"; |
1537 | case 275: return "USR expects \"(\" before arguments"; |
1528 | case 284: return "USR expects \")\" after arguments"; |
1538 | case 284: return "USR expects \")\" after arguments"; |
1529 | case 287: return "Expression too complex ..."; |
1539 | case 287: return "Expression too complex ..."; |
1530 | case 288: return "Expression too complex ... for USR"; |
1540 | case 288: return "Expression too complex ... for USR"; |
1531 | case 290: return "Expression too complex"; |
1541 | case 290: return "Expression too complex"; |
1532 | case 293: return "Syntax error in expression - expects value"; |
1542 | case 293: return "Syntax error in expression - expects value"; |
1533 | case 296: return "Syntax error - expects \")\""; |
1543 | case 296: return "Syntax error - expects \")\""; |
1534 | case 298: return "Memory overflow (in USR)"; |
1544 | case 298: return "Memory overflow (in USR)"; |
1535 | case 303: return "Expression too complex (in USR)"; |
1545 | case 303: return "Expression too complex (in USR)"; |
1536 | case 304: return "Memory overflow (in function evaluation)"; |
1546 | case 304: return "Memory overflow (in function evaluation)"; |
1537 | case 306: return "Syntax error - expects \"(\" for function arguments"; |
1547 | case 306: return "Syntax error - expects \"(\" for function arguments"; |
1538 | case 330: return "IF syntax error - expects relation operator"; |
1548 | case 330: return "IF syntax error - expects relation operator"; |
1539 | default: return "Unknown error, interpreter is malfunctioning"; |
1549 | default: return "Unknown error, interpreter is malfunctioning"; |
1540 | } |
1550 | } |
1541 | }91;>127;>32;>\n"); |
1551 | }91;>127;>32;>\n"); |
1542 | >\"\n"); |
1552 | >\"\n"); |
1543 | >\n"); |
1553 | >\n"); |
1544 | >>=\n"); |
1554 | >>=\n"); |
1545 | >\"\n"); |
1555 | >\"\n"); |
1546 | >48>=>=>=>16)+here); |
1556 | >48>=>=>=>16)+here); |
1547 | ><16)+here); |
1557 | ><16)+here); |
1548 | >0)>=>'>'>0)>0>0)>0>16)); |
1558 | >0)>=>'>'>0)>0>0)>0>16)); |
1549 | ><16)); |
1559 | ><16)); |
1550 | >0)>0)>=>=ix>='9')>'0'>'A')>'0')>=InLend)>=SrcEnd)>(LogHere&(LOGSIZE-1));>65536)>0)>>>32)>0)>=whom;>0)>='~')> |
1560 | >0)>0)>=>=ix>='9')>'0'>'A')>'0')>=InLend)>=SrcEnd)>(LogHere&(LOGSIZE-1));>65536)>0)>>>32)>0)>=whom;>0)>='~')> |