-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInterpreter.cpp
More file actions
7834 lines (7158 loc) · 229 KB
/
Interpreter.cpp
File metadata and controls
7834 lines (7158 loc) · 229 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/** Copyright (C) 2006, Ian Paul Larsen.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License along
** with this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
**/
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <string>
#include <errno.h>
#ifdef WIN32
#include <winsock.h>
#include <windows.h>
typedef int socklen_t;
// for parallel port operations
#ifdef WIN32PORTIO
HINSTANCE inpout32dll = NULL;
typedef unsigned char (CALLBACK* InpOut32InpType)(short int);
typedef void (CALLBACK* InpOut32OutType)(short int, unsigned char);
InpOut32InpType Inp32 = NULL;
InpOut32OutType Out32 = NULL;
#endif
#else
// unix, mac, android
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <poll.h>
#include <arpa/inet.h>
#include <net/if.h>
#ifndef ANDROID
#include <ifaddrs.h>
#endif
#include <unistd.h>
#endif
#include <QString>
#include <QPainter>
#include <QPixmap>
#include <QColor>
#include <QPen>
#include <QBrush>
#include <QTime>
#include <QMutex>
#include <QWaitCondition>
#include <QCoreApplication>
#include <QDir>
#include <QtWidgets/QMessageBox>
#include "LEX/basicParse.tab.h"
#include "WordCodes.h"
#include "CompileErrors.h"
#include "Interpreter.h"
#include "md5.h"
#include "Settings.h"
#include "Sound.h"
#include "Constants.h"
#include "BasicEdit.h"
#include "BasicKeyboard.h"
extern SoundSystem *sound;
extern QMutex* mymutex;
extern QMutex* mydebugmutex;
extern QWaitCondition* waitCond;
extern QWaitCondition* waitDebugCond;
extern BasicGraph * graphwin;
extern BasicEdit * editwin;
extern BasicKeyboard * basicKeyboard;
Error *error; // define the extern here
extern "C" {
//extern int yydebug;
extern int basicParse(char *);
extern char* include_filenames[]; // filenames being LEXd
extern char* include_exec_path; //path to executable
extern int linenumber; // linenumber being LEXd
extern int column; // column on line being LEXd
extern char* lexingfilename; // current included file name being LEXd
extern int numparsewarnings;
extern int initializeBasicParse();
extern void freeBasicParse();
extern int bytesToFullWords(int size);
extern int *wordCode;
extern unsigned int wordOffset;
extern unsigned int maxwordoffset;
extern char **symtable; // table of variables and labels (strings)
extern int *symtableaddress; // associated label address
extern int *symtableaddresstype; // associated address type
extern int *symtableaddressargs; // number of arguments expected by function/subroutine
extern int numsyms; // number of symbols
// arrays to return warnings from compiler
// defined in basicParse.y
extern int parsewarningtable[];
extern int parsewarningtablelinenumber[];
extern int parsewarningtablecolumn[];
extern int parsewarningtablelexingfilenumber[];
}
Interpreter::Interpreter(QLocale *applocale) {
//yydebug = 1;
fastgraphics = false;
directorypointer=NULL;
status = R_STOPPED;
printing = false;
sleeper = new Sleeper();
error = new Error();
locale = applocale;
downloader = NULL;
sys = NULL;
#ifdef WIN32
// WINDOWS
// initialize the winsock network library
WSAData wsaData;
int nCode;
if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) {
emit(outputReady(tr("ERROR - Unable to initialize Winsock library.\n")));
}
//
#ifdef WIN32PORTIO
// initialize the inpout32 dll
inpout32dll = LoadLibrary(L"inpout32.dll");
if (inpout32dll==NULL) {
emit(outputError(tr("ERROR - Unable to find inpout32.dll - direct port I/O disabled.\n")));
} else {
Inp32 = (InpOut32InpType) GetProcAddress(inpout32dll, "Inp32");
if (Inp32==NULL) {
emit(outputError(tr("ERROR - Unable to find Inp32 in inpout32.dll - direct port I/O disabled.\n")));
}
Out32 = (InpOut32OutType) GetProcAddress(inpout32dll, "Out32");
if (Inp32==NULL) {
emit(outputError(tr("ERROR - Unable to find Out32 in inpout32.dll - direct port I/O disabled.\n")));
}
}
#endif
#endif
}
Interpreter::~Interpreter() {
// on a windows box stop winsock
#ifdef WIN32
WSACleanup();
#endif
delete downloader;
delete sleeper;
delete error;
}
#define optype(op) (OPTYPE_MASK & op) //faster
/*
int Interpreter::optype(int op) {
// use constantants found in WordCodes.h
return (OPTYPE_MASK & op) ;
}
*/
QString Interpreter::opname(int op) {
// used to convert opcode number in debuginfo to opcode name
switch (op) {
case OP_ABS : return QString("OP_ABS");
case OP_ACOS : return QString("OP_ACOS");
case OP_ADD : return QString("OP_ADD");
case OP_ALEN : return QString("OP_ALEN");
case OP_ALENCOLS : return QString("OP_ALENCOLS");
case OP_ALENROWS : return QString("OP_ALENROWS");
case OP_ALERT : return QString("OP_ALERT");
case OP_AND : return QString("OP_AND");
case OP_ARC : return QString("OP_ARC");
case OP_ARRAY2STACK : return QString("OP_ARRAY2STACK");
case OP_ARRAYFILL : return QString("OP_ARRAYFILL");
case OP_ARRAYLISTASSIGN : return QString("OP_ARRAYLISTASSIGN");
case OP_ARR_ASSIGNED : return QString("OP_ARR_ASSIGNED");
case OP_ARR_GET : return QString("OP_ARR_GET");
case OP_ARR_SET : return QString("OP_ARR_SET");
case OP_ARR_UN : return QString("OP_ARR_UN");
case OP_ASC : return QString("OP_ASC");
case OP_ASIN : return QString("OP_ASIN");
case OP_ATAN : return QString("OP_ATAN");
case OP_BINARYAND : return QString("OP_BINARYAND");
case OP_BINARYNOT : return QString("OP_BINARYNOT");
case OP_BINARYOR : return QString("OP_BINARYOR");
case OP_BITSHIFTL : return QString("OP_BITSHIFTL");
case OP_BITSHIFTR : return QString("OP_BITSHIFTR");
case OP_BRANCH : return QString("OP_BRANCH");
case OP_CALLFUNCTION : return QString("OP_CALLFUNCTION");
case OP_CALLSUBROUTINE : return QString("OP_CALLSUBROUTINE");
case OP_CEIL : return QString("OP_CEIL");
case OP_CHANGEDIR : return QString("OP_CHANGEDIR");
case OP_CHORD : return QString("OP_CHORD");
case OP_CHR : return QString("OP_CHR");
case OP_CIRCLE : return QString("OP_CIRCLE");
case OP_CLG : return QString("OP_CLG");
case OP_CLICKB : return QString("OP_CLICKB");
case OP_CLICKCLEAR : return QString("OP_CLICKCLEAR");
case OP_CLICKX : return QString("OP_CLICKX");
case OP_CLICKY : return QString("OP_CLICKY");
case OP_CLOSE : return QString("OP_CLOSE");
case OP_CLS : return QString("OP_CLS");
case OP_CONCATENATE : return QString("OP_CONCATENATE");
case OP_CONFIRM : return QString("OP_CONFIRM");
case OP_COS : return QString("OP_COS");
case OP_COUNT : return QString("OP_COUNT");
case OP_COUNTX : return QString("OP_COUNTX");
case OP_CURRENTDIR : return QString("OP_CURRENTDIR");
case OP_CURRLINE : return QString("OP_CURRLINE");
case OP_DAY : return QString("OP_DAY");
case OP_DBCLOSE : return QString("OP_DBCLOSE");
case OP_DBCLOSESET : return QString("OP_DBCLOSESET");
case OP_DBEXECUTE : return QString("OP_DBEXECUTE");
case OP_DBFLOAT : return QString("OP_DBFLOAT");
case OP_DBINT : return QString("OP_DBINT");
case OP_DBNULL : return QString("OP_DBNULL");
case OP_DBNULLS : return QString("OP_DBNULLS");
case OP_DBOPEN : return QString("OP_DBOPEN");
case OP_DBOPENSET : return QString("OP_DBOPENSET");
case OP_DBROW : return QString("OP_DBROW");
case OP_DBSTRING : return QString("OP_DBSTRING");
case OP_DEBUGINFO : return QString("OP_DEBUGINFO");
case OP_DECREASERECURSE : return QString("OP_DECREASERECURSE");
case OP_DEGREES : return QString("OP_DEGREES");
case OP_DIM : return QString("OP_DIM");
case OP_DIR : return QString("OP_DIR");
case OP_DIV : return QString("OP_DIV");
case OP_EDITVISIBLE : return QString("OP_EDITVISIBLE");
case OP_ELLIPSE : return QString("OP_ELLIPSE");
case OP_END : return QString("OP_END");
case OP_EOF : return QString("OP_EOF");
case OP_EQUAL : return QString("OP_EQUAL");
case OP_EX : return QString("OP_EX");
case OP_EXISTS : return QString("OP_EXISTS");
case OP_EXITFOR : return QString("OP_EXITFOR");
case OP_EXP : return QString("OP_EXP");
case OP_EXPLODE : return QString("OP_EXPLODE");
case OP_EXPLODEX : return QString("OP_EXPLODEX");
case OP_FASTGRAPHICS : return QString("OP_FASTGRAPHICS");
case OP_FLOAT : return QString("OP_FLOAT");
case OP_FLOOR : return QString("OP_FLOOR");
case OP_FMOD: return QString("OP_FMOD");
case OP_FONT : return QString("OP_FONT");
case OP_FOR : return QString("OP_FOR");
case OP_FOREACH : return QString("OP_FOREACH");
case OP_FREEDB : return QString("OP_FREEDB");
case OP_FREEDBSET : return QString("OP_FREEDBSET");
case OP_FREEFILE : return QString("OP_FREEFILE");
case OP_FREENET : return QString("OP_FREENET");
case OP_FROMRADIX : return QString("OP_FROMRADIX");
case OP_GETARRAYBASE : return QString("OP_GETARRAYBASE");
case OP_GETBRUSHCOLOR : return QString("OP_GETBRUSHCOLOR");
case OP_GETCOLOR : return QString("OP_GETCOLOR");
case OP_GETPENWIDTH : return QString("OP_GETPENWIDTH");
case OP_GETSETTING : return QString("OP_GETSETTING");
case OP_GETSLICE : return QString("OP_GETSLICE");
case OP_GLOBAL : return QString("OP_GLOBAL");
case OP_GOSUB : return QString("OP_GOSUB");
case OP_GOTO : return QString("OP_GOTO");
case OP_GRAPHHEIGHT : return QString("OP_GRAPHHEIGHT");
case OP_GRAPHSIZE : return QString("OP_GRAPHSIZE");
case OP_GRAPHVISIBLE : return QString("OP_GRAPHVISIBLE");
case OP_GRAPHTOOLBARVISIBLE : return QString("OP_GRAPHTOOLBARVISIBLE");
case OP_GRAPHWIDTH : return QString("OP_GRAPHWIDTH");
case OP_GT : return QString("OP_GT");
case OP_GTE : return QString("OP_GTE");
case OP_HOUR : return QString("OP_HOUR");
case OP_IMAGEAUTOCROP : return QString("OP_IMAGEAUTOCROP");
case OP_IMAGECENTERED : return QString("OP_IMAGECENTERED");
case OP_IMAGECOPY : return QString("OP_IMAGECOPY");
case OP_IMAGECROP : return QString("OP_IMAGECROP");
case OP_IMAGEDRAW : return QString("OP_IMAGEDRAW");
case OP_IMAGEFLIP : return QString("OP_IMAGEFLIP");
case OP_IMAGEHEIGHT : return QString("OP_IMAGEHEIGHT");
case OP_IMAGELOAD : return QString("OP_IMAGELOAD");
case OP_IMAGENEW : return QString("OP_IMAGENEW");
case OP_IMAGEPIXEL : return QString("OP_IMAGEPIXEL");
case OP_IMAGERESIZE : return QString("OP_IMAGERESIZE");
case OP_IMAGEROTATE : return QString("OP_IMAGEROTATE");
case OP_IMAGESETPIXEL : return QString("OP_IMAGESETPIXEL");
case OP_IMAGESMOOTH : return QString("OP_IMAGESMOOTH");
case OP_IMAGETRANSFORMED : return QString("OP_IMAGETRANSFORMED");
case OP_IMAGEWIDTH : return QString("OP_IMAGEWIDTH");
case OP_IMGLOAD : return QString("OP_IMGLOAD");
case OP_IMGSAVE : return QString("OP_IMGSAVE");
case OP_IMPLODE : return QString("OP_IMPLODE");
case OP_IN : return QString("OP_IN");
case OP_INCREASERECURSE : return QString("OP_INCREASERECURSE");
case OP_INPUT : return QString("OP_INPUT");
case OP_INSTR : return QString("OP_INSTR");
case OP_INSTRX : return QString("OP_INSTRX");
case OP_INT : return QString("OP_INT");
case OP_INTDIV : return QString("OP_INTDIV");
case OP_ISNUMERIC : return QString("OP_ISNUMERIC");
case OP_KEY : return QString("OP_KEY");
case OP_KEYPRESSED : return QString("OP_KEYPRESSED");
case OP_KILL : return QString("OP_KILL");
case OP_LASTERROR : return QString("OP_LASTERROR");
case OP_LASTERROREXTRA : return QString("OP_LASTERROREXTRA");
case OP_LASTERRORLINE : return QString("OP_LASTERRORLINE");
case OP_LASTERRORMESSAGE : return QString("OP_LASTERRORMESSAGE");
case OP_LEFT : return QString("OP_LEFT");
case OP_LENGTH : return QString("OP_LENGTH");
case OP_LINE : return QString("OP_LINE");
case OP_LIST2ARRAY : return QString("OP_LIST2ARRAY");
case OP_LIST2MAP : return QString("OP_LIST2MAP");
case OP_LOG : return QString("OP_LOG");
case OP_LOGTEN : return QString("OP_LOGTEN");
case OP_LOWER : return QString("OP_LOWER");
case OP_LT : return QString("OP_LT");
case OP_LTE : return QString("OP_LTE");
case OP_LTRIM : return QString("OP_LTRIM");
case OP_MAINTOOLBARVISIBLE : return QString("OP_MAINTOOLBARVISIBLE");
case OP_MAP_DIM : return QString("OP_MAP_DIM");
case OP_MD5 : return QString("OP_MD5");
case OP_MID : return QString("OP_MID");
case OP_MIDX : return QString("OP_MIDX");
case OP_MINUTE : return QString("OP_MINUTE");
case OP_MKDIR : return QString("OP_MKDIR");
case OP_MOD : return QString("OP_MOD");
case OP_MONTH : return QString("OP_MONTH");
case OP_MOUSEB : return QString("OP_MOUSEB");
case OP_MOUSEX : return QString("OP_MOUSEX");
case OP_MOUSEY : return QString("OP_MOUSEY");
case OP_MSEC : return QString("OP_MSEC");
case OP_MUL : return QString("OP_MUL");
case OP_NEGATE : return QString("OP_NEGATE");
case OP_NEQUAL : return QString("OP_NEQUAL");
case OP_NETADDRESS : return QString("OP_NETADDRESS");
case OP_NETCLOSE : return QString("OP_NETCLOSE");
case OP_NETCONNECT : return QString("OP_NETCONNECT");
case OP_NETDATA : return QString("OP_NETDATA");
case OP_NETLISTEN : return QString("OP_NETLISTEN");
case OP_NETREAD : return QString("OP_NETREAD");
case OP_NETWRITE : return QString("OP_NETWRITE");
case OP_NEXT : return QString("OP_NEXT");
case OP_NOP : return QString("OP_NOP");
case OP_NOT : return QString("OP_NOT");
case OP_OFFERROR : return QString("OP_OFFERROR");
case OP_OFFERRORCATCH : return QString("OP_OFFERRORCATCH");
case OP_ONERRORCALL : return QString("OP_ONERRORCALL");
case OP_ONERRORCATCH : return QString("OP_ONERRORCATCH");
case OP_ONERRORGOSUB : return QString("OP_ONERRORGOSUB");
case OP_ONSTOPCALL : return QString("OP_ONSTOPCALL");
case OP_OPEN : return QString("OP_OPEN");
case OP_OPENFILEDIALOG : return QString("OP_OPENFILEDIALOG");
case OP_OPENSERIAL : return QString("OP_OPENSERIAL");
case OP_OR : return QString("OP_OR");
case OP_OSTYPE : return QString("OP_OSTYPE");
case OP_OUTPUTVISIBLE : return QString("OP_OUTPUTVISIBLE");
case OP_OUTPUTTOOLBARVISIBLE : return QString("OP_OUTPUTTOOLBARVISIBLE");
case OP_PAUSE : return QString("OP_PAUSE");
case OP_PENWIDTH : return QString("OP_PENWIDTH");
case OP_PIE : return QString("OP_PIE");
case OP_PIXEL : return QString("OP_PIXEL");
case OP_PLOT : return QString("OP_PLOT");
case OP_POLY : return QString("OP_POLY");
case OP_PORTIN : return QString("OP_PORTIN");
case OP_PORTOUT : return QString("OP_PORTOUT");
case OP_PRINT : return QString("OP_PRINT");
case OP_PRINTAT : return QString("OP_PRINTAT");
case OP_PRINTERCANCEL : return QString("OP_PRINTERCANCEL");
case OP_PRINTEROFF : return QString("OP_PRINTEROFF");
case OP_PRINTERON : return QString("OP_PRINTERON");
case OP_PRINTERPAGE : return QString("OP_PRINTERPAGE");
case OP_PROMPT : return QString("OP_PROMPT");
case OP_PUSHFLOAT : return QString("OP_PUSHFLOAT");
case OP_PUSHINT : return QString("OP_PUSHINT");
case OP_PUSHLABEL : return QString("OP_PUSHLABEL");
case OP_PUSHLONG : return QString("OP_PUSHLONG");
case OP_PUSHSTRING : return QString("OP_PUSHSTRING");
case OP_PUTSLICE : return QString("OP_PUTSLICE");
case OP_RADIANS : return QString("OP_RADIANS");
case OP_RAND : return QString("OP_RAND");
case OP_READ : return QString("OP_READ");
case OP_READBYTE : return QString("OP_READBYTE");
case OP_READLINE : return QString("OP_READLINE");
case OP_RECT : return QString("OP_RECT");
case OP_REDIM : return QString("OP_REDIM");
case OP_REFRESH : return QString("OP_REFRESH");
case OP_REGEXMINIMAL : return QString("OP_REGEXMINIMAL");
case OP_REPLACE : return QString("OP_REPLACE");
case OP_REPLACEX : return QString("OP_REPLACEX");
case OP_RESET : return QString("OP_RESET");
case OP_RETURN : return QString("OP_RETURN");
case OP_RGB : return QString("OP_RGB");
case OP_RIGHT : return QString("OP_RIGHT");
case OP_RMDIR : return QString("OP_RMDIR");
case OP_ROUNDEDRECT : return QString("OP_ROUNDEDRECT");
case OP_RTRIM : return QString("OP_RTRIM");
case OP_SAVEFILEDIALOG : return QString("OP_SAVEFILEDIALOG");
case OP_SAY : return QString("OP_SAY");
case OP_SECOND : return QString("OP_SECOND");
case OP_SEED : return QString("OP_SEED");
case OP_SEEK : return QString("OP_SEEK");
case OP_SERIALIZE : return QString("OP_SERIALIZE");
case OP_SETCOLOR : return QString("OP_SETCOLOR");
case OP_SETGRAPH : return QString("OP_SETGRAPH");
case OP_SETSETTING : return QString("OP_SETSETTING");
case OP_SIN : return QString("OP_SIN");
case OP_SIZE : return QString("OP_SIZE");
case OP_SOUND : return QString("OP_SOUND");
case OP_SOUNDENVELOPE : return QString("OP_SOUNDENVELOPE");
case OP_SOUNDFADE : return QString("OP_SOUNDFADE");
case OP_SOUNDHARMONICS : return QString("OP_SOUNDHARMONICS");
case OP_SOUNDHARMONICS_A : return QString("OP_SOUNDHARMONICS_A");
case OP_SOUNDID : return QString("OP_SOUNDID");
case OP_SOUNDLENGTH : return QString("OP_SOUNDLENGTH");
case OP_SOUNDLOAD : return QString("OP_SOUNDLOAD");
case OP_SOUNDLOADRAW : return QString("OP_SOUNDLOADRAW");
case OP_SOUNDLOOP : return QString("OP_SOUNDLOOP");
case OP_SOUNDNOHARMONICS : return QString("OP_SOUNDNOHARMONICS");
case OP_SOUNDPAUSE : return QString("OP_SOUNDPAUSE");
case OP_SOUNDPLAY : return QString("OP_SOUNDPLAY");
case OP_SOUNDPLAYER : return QString("OP_SOUNDPLAYER");
case OP_SOUNDPLAYEROFF : return QString("OP_SOUNDPLAYEROFF");
case OP_SOUNDPOSITION : return QString("OP_SOUNDPOSITION");
case OP_SOUNDSAMPLERATE : return QString("OP_SOUNDSAMPLERATE");
case OP_SOUNDSEEK : return QString("OP_SOUNDSEEK");
case OP_SOUNDSTATE : return QString("OP_SOUNDSTATE");
case OP_SOUNDSTOP : return QString("OP_SOUNDSTOP");
case OP_SOUNDSYSTEM : return QString("OP_SOUNDSYSTEM");
case OP_SOUNDVOLUME : return QString("OP_SOUNDVOLUME");
case OP_SOUNDWAIT : return QString("OP_SOUNDWAIT");
case OP_SOUNDWAVEFORM : return QString("OP_SOUNDWAVEFORM");
case OP_SPRITECOLLIDE : return QString("OP_SPRITECOLLIDE");
case OP_SPRITEDIM : return QString("OP_SPRITEDIM");
case OP_SPRITEH : return QString("OP_SPRITEH");
case OP_SPRITEHIDE : return QString("OP_SPRITEHIDE");
case OP_SPRITELOAD : return QString("OP_SPRITELOAD");
case OP_SPRITEMOVE : return QString("OP_SPRITEMOVE");
case OP_SPRITEO : return QString("OP_SPRITEO");
case OP_SPRITEPLACE : return QString("OP_SPRITEPLACE");
case OP_SPRITEPOLY : return QString("OP_SPRITEPOLY");
case OP_SPRITER : return QString("OP_SPRITER");
case OP_SPRITES : return QString("OP_SPRITES");
case OP_SPRITESHOW : return QString("OP_SPRITESHOW");
case OP_SPRITESLICE : return QString("OP_SPRITESLICE");
case OP_SPRITETEXT : return QString("OP_SPRITETEXT");
case OP_SPRITEV : return QString("OP_SPRITEV");
case OP_SPRITEW : return QString("OP_SPRITEW");
case OP_SPRITEX : return QString("OP_SPRITEX");
case OP_SPRITEY : return QString("OP_SPRITEY");
case OP_SQR : return QString("OP_SQR");
case OP_STACKDUP : return QString("OP_STACKDUP");
case OP_STACKDUP2 : return QString("OP_STACKDUP2");
case OP_STACKSAVE : return QString("OP_STACKSAVE");
case OP_STACKSWAP : return QString("OP_STACKSWAP");
case OP_STACKSWAP2 : return QString("OP_STACKSWAP2");
case OP_STACKTOPTO2 : return QString("OP_STACKTOPTO2");
case OP_STACKUNSAVE : return QString("OP_STACKUNSAVE");
case OP_STAMP : return QString("OP_STAMP");
case OP_STRING : return QString("OP_STRING");
case OP_SUB : return QString("OP_SUB");
case OP_SYSTEM : return QString("OP_SYSTEM");
case OP_TAN : return QString("OP_TAN");
case OP_TEXT : return QString("OP_TEXT");
case OP_TEXTBOXHEIGHT : return QString("OP_TEXTBOXHEIGHT");
case OP_TEXTBOXWIDTH : return QString("OP_TEXTBOXWIDTH");
case OP_TEXTHEIGHT : return QString("OP_TEXTHEIGHT");
case OP_TEXTWIDTH : return QString("OP_TEXTWIDTH");
case OP_THROWERROR : return QString("OP_THROWERROR");
case OP_TORADIX : return QString("OP_TORADIX");
case OP_TRIM : return QString("OP_TRIM");
case OP_TYPEOF : return QString("OP_TYPEOF");
case OP_UNLOAD : return QString("OP_UNLOAD");
case OP_UNSERIALIZE : return QString("OP_UNSERIALIZE");
case OP_UPPER : return QString("OP_UPPER");
case OP_VARIABLECOPY : return QString("OP_VARIABLECOPY");
case OP_VARIABLEWATCH : return QString("OP_VARIABLEWATCH");
case OP_VAR_ASSIGNED : return QString("OP_VAR_ASSIGNED");
case OP_VAR_GET : return QString("OP_VAR_GET");
case OP_VAR_REF : return QString("OP_VAR_REF");
case OP_VAR_SET : return QString("OP_VAR_SET");
case OP_VAR_UN : return QString("OP_VAR_UN");
case OP_VOLUME : return QString("OP_VOLUME");
case OP_WAVLENGTH : return QString("OP_WAVLENGTH");
case OP_WAVPAUSE : return QString("OP_WAVPAUSE");
case OP_WAVPLAY : return QString("OP_WAVPLAY");
case OP_WAVPOS : return QString("OP_WAVPOS");
case OP_WAVSEEK : return QString("OP_WAVSEEK");
case OP_WAVSTATE : return QString("OP_WAVSTATE");
case OP_WAVSTOP : return QString("OP_WAVSTOP");
case OP_WAVWAIT : return QString("OP_WAVWAIT");
case OP_WRITE : return QString("OP_WRITE");
case OP_WRITEBYTE : return QString("OP_WRITEBYTE");
case OP_WRITELINE : return QString("OP_WRITELINE");
case OP_XOR : return QString("OP_XOR");
case OP_YEAR : return QString("OP_YEAR");
case OP_SETCLIPBOARDIMAGE : return QString("OP_SETCLIPBOARDIMAGE");
case OP_SETCLIPBOARDSTRING : return QString("OP_SETCLIPBOARDSTRING");
case OP_GETCLIPBOARDIMAGE : return QString("OP_GETCLIPBOARDIMAGE");
case OP_GETCLIPBOARDSTRING : return QString("OP_GETCLIPBOARDSTRING");
default: return QString("OP_UNKNOWN");
}
}
void Interpreter::printError() {
QString msg;
if (error->isFatal()) {
msg = tr("ERROR");
} else {
msg = tr("WARNING");
}
if (includeFileNumber!=0) {
msg += tr(" in included file '") + include_filenames[includeFileNumber] + QStringLiteral("'");
}
msg += tr(" on line ") + QString::number(error->line) + QStringLiteral(": ") + error->getErrorMessage(symtable);
msg += QStringLiteral(".\n");
emit(outputError(msg));
}
int Interpreter::netSockClose(int fd) {
// tidy up a network socket and return NULL to assign to the
// fd variable to mark as closed as closed
// call f = netSockClose(f);
if(fd>=0) {
#ifdef WIN32
shutdown(fd,2);
closesocket(fd);
#else
shutdown(fd,2);
close(fd);
#endif
}
return(-1);
}
void Interpreter::netSockCloseAll() {
// close network connections
listensockfd = netSockClose(listensockfd);
for (int t=0; t<NUMSOCKETS; t++) {
netsockfd[t] = netSockClose(netsockfd[t]);
}
}
void Interpreter::setInputString(QString s) {
inputString = s;
}
bool Interpreter::isRunning() {
return (status != R_STOPPED);
}
bool Interpreter::isStopped() {
return (status == R_STOPPED);
}
bool Interpreter::isStopping() {
// interpreter is stopped or is about to stop
// to avoid RunController::stopRun() to be triggered while status == R_STOPING too
return (status == R_STOPPED || status == R_STOPING);
}
void Interpreter::setStatus(run_status s) {
status = s;
}
void Interpreter::watchvariable(bool doit, int i) {
// send an event to the variable watch window to display a variable/array content
if (doit) {
int level = variables->getrecurse();
int varnum = i;
Variable* v = variables->getAt(i, level);
while (DataElement::getType(v->data) == T_REF) {
emit(varWinAssign(&variables, varnum, level));
varnum = v->data->intval;
level = v->data->level;
v = variables->getAt(i, level);
}
emit(varWinAssign(&variables, varnum, level));
}
}
void Interpreter::watchvariable(bool doit, int i, int x, int y) {
// send an event to the variable watch window to display aan array element's value
if (doit) {
int level = variables->getrecurse();
int varnum = i;
Variable* v = variables->getAt(i, level);
while (DataElement::getType(v->data) == T_REF) {
emit(varWinAssign(&variables, varnum, level));
varnum = v->data->intval;
level = v->data->level;
v = variables->getAt(i, level);
}
emit(varWinAssign(&variables, varnum, level, x ,y));
}
}
void Interpreter::watchvariable(bool doit, int i, QString k) {
// send an event to the variable watch window to display a map element's value
if (doit) {
int level = variables->getrecurse();
int varnum = i;
Variable* v = variables->getAt(i, level);
while (DataElement::getType(v->data) == T_REF) {
emit(varWinAssign(&variables, varnum, level));
varnum = v->data->intval;
level = v->data->level;
v = variables->getAt(i, level);
}
emit(varWinAssign(&variables, varnum, level, k));
}
}
void Interpreter::watchdecurse(bool doit) {
// send an event to the variable watch window to remove a function's variables
if (doit) {
emit(varWinDropLevel(variables->getrecurse()));
}
}
void Interpreter::decreaserecurse() {
//clear current forstack
while (forstack) {
forframe *temp = forstack;
forstack = temp->next;
delete temp;
}
watchdecurse(debugMode);
variables->decreaserecurse();
//pop forstack from forstacklevel
int recurse = variables->getrecurse();
forstack = forstacklevel[recurse];
//delete try/catch traps from non-existent recurse level
while(trycatchstack && trycatchstack->recurseLevel > recurse){
trycatchframe *temp_trycatchstack = trycatchstack;
trycatchstack=trycatchstack->next;
delete temp_trycatchstack;
}
}
int Interpreter::compileProgram(char *code) {
if (initializeBasicParse() != 0) {
emit(outputError(tr("COMPILE ERROR") + QStringLiteral(": ") + tr("Out of memory") + QStringLiteral(".\n")));
return -1;
}
include_exec_path = QCoreApplication::applicationDirPath().toUtf8().data();
int result = basicParse(code);
//
// display warnings from compile and free the lexing file name string
bool gotowarning = (debugMode==0);
// go to line only for first warning and only if program is not running in debugMode
// because in debugMode it already call goToLine(1) at start
for(int i=0; i<numparsewarnings; i++) {
QString msg = tr("COMPILE WARNING");
if (parsewarningtablelexingfilenumber[i]!=0) {
msg += tr(" in included file '") + QString(include_filenames[parsewarningtablelexingfilenumber[i]]) + QStringLiteral("'");
} else if(gotowarning){
emit(goToLine(parsewarningtablelinenumber[i]));
gotowarning = false;
}
msg += tr(" on line ") + QString::number(parsewarningtablelinenumber[i]) + QStringLiteral(": ");
switch(parsewarningtable[i]) {
case COMPWARNING_MAXIMUMWARNINGS:
msg += tr("The maximum number of compiler warnings have been displayed");
break;
case COMPWARNING_DEPRECATED_FORM:
msg += tr("Statement format has been deprecated. It is recommended that you reauthor");
break;
case COMPWARNING_DEPRECATED_REF:
msg += tr("You should use REF() when passing arguments, not in the SUBROUTINE/FUNCTION definition");
break;
default:
msg += tr("Unknown compiler warning #") + QString::number(parsewarningtable[i]);
}
msg += QStringLiteral(".\n");
emit(outputError(msg));
//
}
//
// now display fatal error if there is one
bool gotoerror = true; // go to line only for first error in this file
if (result != COMPERR_NONE) {
QString msg = tr("COMPILE ERROR");
if (strlen(lexingfilename)!=0) {
msg += tr(" in included file '") + QString(lexingfilename) + QStringLiteral("'");
} else if(gotoerror){
emit(goToLine(linenumber));
gotoerror = false;
}
msg += tr(" on line ") + QString::number(linenumber) + QStringLiteral(": ");
switch(result) {
case COMPERR_FUNCTIONGOTO:
msg += tr("You may not define a label or use a GOTO or GOSUB statement in a FUNCTION/SUBROUTINE declaration");
break;
case COMPERR_GLOBALNOTHERE:
msg += tr("You may not define GLOBAL variable(s) inside an IF, loop, TRY, CATCH, or FUNCTION/SUBROUTINE");
break;
case COMPERR_FUNCTIONNOTHERE:
msg += tr("You may not define a FUNCTION/SUBROUTINE inside an IF, loop, TRY, CATCH, or other FUNCTION/SUBROUTINE");
break;
case COMPERR_ENDFUNCTION:
msg += tr("END FUNCTION without matching FUNCTION");
break;
case COMPERR_ENDSUBROUTINE:
msg += tr("END SUBROUTINE without matching SUBROUTINE");
break;
case COMPERR_FUNCTIONNOEND:
msg += tr("FUNCTION without matching END FUNCTION statement");
break;
case COMPERR_SUBROUTINENOEND:
msg += tr("SUBROUTINE without matching END SUBROUTINE statement");
break;
case COMPERR_FORNOEND:
msg += tr("FOR without matching NEXT statement");
break;
case COMPERR_WHILENOEND:
msg += tr("WHILE without matching END WHILE statement");
break;
case COMPERR_DONOEND:
msg += tr("DO without matching UNTIL statement");
break;
case COMPERR_ELSENOEND:
msg += tr("ELSE without matching END IF or END CASE statement");
break;
case COMPERR_IFNOEND:
msg += tr("IF without matching END IF or ELSE statement");
break;
case COMPERR_UNTIL:
msg += tr("UNTIL without matching DO");
break;
case COMPERR_ENDWHILE:
msg += tr("END WHILE without matching WHILE");
break;
case COMPERR_ELSE:
msg += tr("ELSE without matching IF");
break;
case COMPERR_ENDIF:
msg += tr("END IF without matching IF");
break;
case COMPERR_NEXT:
msg += tr("NEXT without matching FOR");
break;
case COMPERR_RETURNVALUE:
msg += tr("RETURN with a value is only valid inside a FUNCTION");
break;
case COMPERR_CONTINUEDO:
msg += tr("CONTINUE DO without matching DO");
break;
case COMPERR_CONTINUEFOR:
msg += tr("CONTINUE DO without matching DO");
break;
case COMPERR_CONTINUEWHILE:
msg += tr("CONTINUE WHILE without matching WHILE");
break;
case COMPERR_EXITDO:
msg += tr("EXIT DO without matching DO");
break;
case COMPERR_EXITFOR:
msg += tr("EXIT FOR without matching FOR");
break;
case COMPERR_EXITWHILE:
msg += tr("EXIT WHILE without matching WHILE");
break;
case COMPERR_INCLUDEFILE:
msg += tr("Unable to open INCLUDE file");
break;
case COMPERR_INCLUDEDEPTH:
msg += tr("Maximum depth of INCLUDE files");
break;
case COMPERR_TRYNOEND:
msg += tr("TRY without matching CATCH statement");
break;
case COMPERR_CATCH:
msg += tr("CATCH without matching TRY statement");
break;
case COMPERR_CATCHNOEND:
msg += tr("CATCH without matching ENDTRY statement");
break;
case COMPERR_ENDTRY:
msg += tr("ENDTRY without matching CATCH statement");
break;
case COMPERR_ENDBEGINCASE:
msg += tr("CASE without matching BEGIN CASE statement");
break;
case COMPERR_ENDENDCASEBEGIN:
msg += tr("END CASE without matching BEGIN CASE statement");
break;
case COMPERR_ENDENDCASE:
msg += tr("END CASE without matching CASE statement");
break;
case COMPERR_BEGINCASENOEND:
msg += tr("BEGIN CASE without matching END CASE statement");
break;
case COMPERR_CASENOEND:
msg += tr("CASE without next CASE or matching END CASE statement");
break;
case COMPERR_LABELREDEFINED:
msg += tr("Labels, functions and subroutines must have a unique name");
break;
case COMPERR_NEXTWRONGFOR:
msg += tr("Variable in NEXT does not match FOR");
break;
case COMPERR_INCLUDEMAX:
msg += tr("Maximum number of INCLUDE files");
break;
case COMPERR_INCLUDENOTALONE:
msg += tr("INCLUDE must be placed in a separate line");
break;
case COMPERR_INCLUDENOFILE:
msg += tr("No file specified for INCLUDE");
break;
case COMPERR_ONERRORCALL:
msg += tr("Cannot pass arguments to a SUBROUTINE used by ONERROR statement");
break;
case COMPERR_INTEGERTOOLARGE:
msg += tr("Integer number too large");
break;
case COMPERR_FLOATTOOLARGE:
msg += tr("Floating point number too large");
break;
default:
if(column==0) {
msg += tr("Syntax error around beginning line");
} else {
msg += tr("Syntax error around character ") + QString::number(column);
}
}
msg += QStringLiteral(".\n");
emit(outputError(msg));
freeBasicParse();
status = R_STOPPED;
return -1;
}
currentLine = 1;
return 0;
}
void
Interpreter::initialize() {
error->loadSettings();
imageSmooth = false;
op = wordCode;
callstack = new addrStack();
onerrorstack = new addrStack();
onstopaddr = NULL;
trycatchstack = NULL;
forstack = NULL;
forstacklevelsize = 0;
status = R_RUNNING;
//initialize random
double_random_max = (double) RAND_MAX * (double) RAND_MAX + (double) RAND_MAX + 1.0;
currentLine = 1;
includeFileNumber = 0;
emit(resizeGraphWindow(GSIZE_INITIAL_WIDTH, GSIZE_INITIAL_HEIGHT, 1.0));
painter = new QPainter();
painter_custom_font_flag = false;
setGraph(""); //after resizeGraphWindow()
defaultfontfamily = painter->font().family();
defaultfontpointsize = painter->font().pointSize();
defaultfontweight = painter->font().weight();
defaultfontitalic = painter->font().italic();
drawingpen = QPen(Qt::black); // default pen color
drawingbrush = QBrush(Qt::black, Qt::SolidPattern); // default brush color
painter_pen_color = Qt::black; //last color
painter_brush_color = Qt::black; //last color
CompositionModeClear = false;
PenColorIsClear = false;
fastgraphics = false;
nsprites = 0;
printing = false;
regexMinimal = false;
basicKeyboard->reset();
// clickclear mouse status
graphwin->clickX = 0;
graphwin->clickY = 0;
graphwin->clickB = 0;
// create the convert and comparer object
convert = new Convert(locale);
// now build the new stack object
stack = new Stack(convert);
savestack = new Stack(convert); // secondary stack to hold stuff (OP_STACKSAVE, OP_STACKUNSAVE)
// now create the variable storage and set arraybase
variables = new Variables(numsyms);
arraybase = 0;
// initialize the sockets to nothing
listensockfd = -1;
for (int t=0; t<NUMSOCKETS; t++) netsockfd[t]=-1;
// initialize pointers used for database recordsets (querries)
for (int t=0; t<NUMDBCONN; t++) {
for (int u=0; u<NUMDBSET; u++) {
dbSet[t][u] = NULL;
}
}
// initialize files to NULL (closed)
filehandle = (QIODevice**) malloc(NUMFILES * sizeof(QIODevice*));
filehandletype = (int*) malloc(NUMFILES * sizeof(int));
for (int t=0; t<NUMFILES; t++) {
filehandle[t] = NULL;
filehandletype[t] = 0;
}
// save IDE path so that it can be restored after program terminates
originalPath = QDir::currentPath();
}
void
Interpreter::cleanup() {
// cleanup that MUST happen for run to early terminate is in runHalted
// called by run() once the run is terminated
//
// Clean up run time objects
if(sys) sys->kill();
// stop timers
sleeper->wake();
// stop downloading
if(downloader!=NULL) downloader->stop();
delete (downloader);
downloader = NULL;
// stop playing any sound
if(sound!=NULL) sound->exit();
// close network connections
netSockCloseAll();
// delete the stack
delete(stack);
delete(savestack);
//delete stack used by nested for statements
int level = variables->getrecurse();
forframe *temp_forstack;
while(level>=0){
while (forstack!=NULL) {
temp_forstack = forstack;
forstack = temp_forstack->next;
delete(temp_forstack);
}
level--;
if(level>0) forstack=forstacklevel[level];
}
delete(convert);
// Clean up sprites
clearsprites();
// Clean up, for frames, etc.
freeBasicParse();
// close open files (set to NULL if closed)
for (int t=0; t<NUMFILES; t++) {
if (filehandle[t]) {
filehandle[t]->close();
filehandle[t] = NULL;
filehandletype[t] = 0;
}
}