Subversion Repositories Kolibri OS

Rev

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   /* added 08 Oct 31 */
5
#include   /* added 08 Oct 31 */
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=InLend) {
449
  if (here=InLend) {
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=ILend) TBerror();
1019
        if (ix=ILend) TBerror();
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
  }
1551
  }
1542
>
1552
>
1543
>
1553
>
1544
>
1554
>
1545
>
1555
>
1546
>
1556
>
1547
>
1557
>
1548
>
1558
>
1549
>
1559
>
1550
>
1560
>