• R/O
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revision37 (tree)
Zeit2019-03-18 00:10:49
Autorkenkenmkiisr

Log Message

オブジェクト指向対応

Ändern Zusammenfassung

Diff

--- trunk/args.c (nonexistent)
+++ trunk/args.c (revision 37)
@@ -0,0 +1,106 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+const unsigned int g_initial_s5_stack[3]={
15+ 0, // -8($s5): no object
16+ (unsigned int) &g_initial_s5_stack[2], // -4($s5): previous $s5 (recursive)
17+ 0 // 0($s5): no parameter
18+};
19+
20+static int g_args_stack;
21+/*
22+ See ARGS_SP_XXXX and ARGS_S5_XXXX in compiler.h
23+ At least 4 stacks are needed even without argument
24+ 4($sp) = -12($s5): $sp
25+ 8($sp) = -8($s5): $v0 - pointer to object or previous -8($s5)
26+ 12($sp) = -4($s5): previous $s5
27+ 16($sp) = 0($s5): number of arguments
28+ 20($sp) = 4($s5): first argument
29+ $v0 must be the pointer to an object before comming to this code.
30+ After this code, -12($s5) must be set to $sp: 0xAEBDFFF4 sw sp,-12(s5)
31+*/
32+char* prepare_args_stack(char start_char){
33+ // start_char is either ',' or '('
34+ // When ',' mode, there must be a ',' if argument(s) exist(s).
35+ // When '(' mode, there shouldn't be a '(', because this character has passed.
36+ char* err;
37+ int opos,stack;
38+ stack=0;
39+ opos=g_objpos;
40+ check_obj_space(2);
41+ g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
42+ // 8(sp) is for $v0, which is pointer to an object
43+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
44+ next_position();
45+ do {
46+ if (!stack) {
47+ // First parameter if exists
48+ stack=16;
49+ if (start_char==','){
50+ if (g_source[g_srcpos]!=',') break;
51+ } else if (start_char=='('){
52+ next_position();
53+ if (g_source[g_srcpos]==')') break;
54+ g_srcpos--;
55+ } else {
56+ return ERR_UNKNOWN;
57+ }
58+ }
59+ g_srcpos++;
60+ stack+=4;
61+ err=get_stringFloatOrValue();
62+ if (err) return err;
63+ check_obj_space(1);
64+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
65+ next_position();
66+ } while (g_source[g_srcpos]==',');
67+ // 12(sp) is for $s5, 16(sp) is for # of parameters
68+ check_obj_space(5);
69+ g_object[g_objpos++]=0xAFB5000C; // sw s5,12(sp)
70+ g_object[g_objpos++]=0x34020000|(stack/4-4); // ori v0,zero,xx
71+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
72+ g_object[g_objpos++]=0x27B50010; // addiu s5,sp,16
73+ g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
74+ // All done. Register # of stacks to global var.
75+ g_args_stack=stack;
76+ return 0;
77+}
78+
79+char* remove_args_stack(void){
80+ // Remove stack
81+ check_obj_space(2);
82+ g_object[g_objpos++]=0x8FB5000C; // lw s5,12(sp)
83+ g_object[g_objpos++]=0x27BD0000|g_args_stack; // addiu sp,sp,xx
84+ return 0;
85+}
86+
87+char* args_function_main(void){
88+ char* err;
89+ int i;
90+ err=get_value();
91+ if (err) return err;
92+ i=g_object[g_objpos-1];
93+ if ((i>>16)==0x3402) {
94+ // Previous object is "ori v0,zero,xxxx".
95+ i&=0xffff;
96+ i=i<<2;
97+ g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
98+ } else {
99+ check_obj_space(3);
100+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
101+ g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
102+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0)
103+ }
104+ return 0;
105+}
106+
--- trunk/class.c (nonexistent)
+++ trunk/class.c (revision 37)
@@ -0,0 +1,922 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by K.Tanaka & Katsumi
4+ http://www.ze.em-net.ne.jp/~kenken/index.html
5+ http://hp.vector.co.jp/authors/VA016157/
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "compiler.h"
13+
14+static int* g_class_structure;
15+
16+/*
17+ CMPDATA_CLASS structure
18+ type: CMPDATA_CLASS (2)
19+ len: 3
20+ data16: n/a (0)
21+ record[1]: class name as integer
22+ record[2]: pointer to class structure
23+*/
24+
25+/*
26+ CMPDATA_FIELD structure
27+ type: CMPDATA_FIELD (3)
28+ len: 2 or 3 (2: field; 3: method)
29+ data16: field or method
30+ CMPTYPE_PUBLIC_FIELD: 0
31+ CMPTYPE_PRIVATE_FIELD: 1
32+ CMPTYPE_PUBLIC_METHOD: 2
33+ record[1]: field/method name as integer
34+ record[2]: pointer to method
35+*/
36+
37+/*
38+ CMPDATA_STATIC structure
39+ type: CMPDATA_STATIC (4)
40+ len: 3
41+ data16: variable number; add ALLOC_LNV_BLOCK when using
42+ record[1]: class name as integer
43+ record[2]: variable name as integer
44+*/
45+
46+/*
47+ CMPDATA_UNSOLVED structure
48+ type: CMPDATA_UNSOLVED (5)
49+ len: 4
50+ data16: CMPTYPE_NEW_FUNCTION (0)
51+ record[1]: class name as integer
52+ record[2]: address of code for pointer to class structure
53+ record[3]: address of code for size definition
54+
55+ type: CMPDATA_UNSOLVED (5)
56+ len: 4
57+ data16: CMPTYPE_STATIC_METHOD (1)
58+ record[1]: class name as integer
59+ record[2]: method name as integer
60+ record[3]: address of code for pointer to method
61+
62+*/
63+
64+/*
65+ Local prototyping
66+*/
67+char* obj_method(int method);
68+
69+/*
70+ Return code used for calling null method
71+*/
72+static const unsigned int g_return_code[]={
73+ 0x8FA30004, // lw v1,4(sp)
74+ 0x00600008, // jr v1
75+ 0x27BD0004, // addiu sp,sp,4
76+};
77+
78+
79+
80+char* begin_compiling_class(int class){
81+ // Initialize parameters
82+ g_compiling_class=class;
83+ g_class_structure=0;
84+ // Register the class to cmpdata without class structure
85+ return update_class_info(class);
86+}
87+
88+char* end_compiling_class(int class){
89+ char* err;
90+ g_compiling_class=0;
91+ // Construct class structure
92+ err=construct_class_structure(class);
93+ if (err) return err;
94+ // Uppdate class information.
95+ err=update_class_info(class);
96+ if (err) return err;
97+ // Resolve CMPDATA_UNSOLVED.
98+ err=resolve_unresolved(class);
99+ if (err) return err;
100+ // Delete some cmpdata.
101+ delete_cmpdata_for_class(class);
102+ return 0;
103+}
104+
105+void* search_method(int* classdata,int method){
106+ int pos,i;
107+ int nums=classdata[1];
108+
109+ classdata+=2; // exclude first 2 words
110+ classdata+=2*(nums&0xff); // exclude public field
111+ classdata+=2*((nums>>8)&0xff); // exclude private field
112+ nums=(nums>>16)&0xff; // number of methods
113+ for(i=0;i<nums;i++){
114+ if (classdata[0]==method) return (void*)classdata[1];
115+ classdata+=2;
116+ }
117+ return 0; // not found
118+}
119+
120+char* resolve_unresolved(int class){
121+ int* classdata;
122+ int* record;
123+ int* code;
124+ int i;
125+ // Get class structure
126+ cmpdata_reset();
127+ while(record=cmpdata_find(CMPDATA_CLASS)){
128+ if (record[1]==class) break;
129+ }
130+ if (!record) return ERR_UNKNOWN;
131+ classdata=(int*)record[2];
132+ // Explore CMPDATA_UNSOLVED
133+ cmpdata_reset();
134+ while(record=cmpdata_find(CMPDATA_UNSOLVED)){
135+ // Note: don't use cmpdata_find() again in the loop.
136+ // If used, the solved CMPDATA_UNSOLVED must be removed before.
137+ if (record[1]!=class) continue;
138+ switch (record[0]&0xffff) {
139+ case CMPTYPE_NEW_FUNCTION:
140+ // Resolve address of code for pointer to class structure
141+ code=(int*)(record[2]);
142+ code[0]=(code[0]&0xFFFF0000) | (((unsigned int)classdata)>>16);
143+ code[1]=(code[1]&0xFFFF0000) | (((unsigned int)classdata) & 0x0000FFFF);
144+ // Resolve size of object
145+ code=(int*)(record[3]);
146+ code[0]=(code[0]&0xFFFF0000) | (object_size(classdata) & 0x0000FFFF);
147+ // All done
148+ break;
149+ case CMPTYPE_STATIC_METHOD:
150+ // Resolve address of code for pointer to method
151+ // Find method
152+ i=(int)search_method(classdata,record[2]);
153+ if (!i) return ERR_NOT_FIELD;
154+ code=(int*)(record[3]);
155+ code[0]=(code[0]&0xFC000000)|((i&0x0FFFFFFF)>>2);
156+ // All done
157+ break;
158+ default:
159+ return ERR_UNKNOWN;
160+ } + }
161+ return 0;
162+}
163+
164+char* update_class_info(int class){
165+ int* record;
166+ int data[2];
167+ // Update record if exist.
168+ cmpdata_reset();
169+ while(record=cmpdata_find(CMPDATA_CLASS)){
170+ if (record[1]==class) {
171+ record[2]=(int)g_class_structure;
172+ return 0;
173+ }
174+ }
175+ // No record of this class yet. Insert a record.
176+ data[0]=class;
177+ data[1]=(int)g_class_structure;
178+ return cmpdata_insert(CMPDATA_CLASS,0,&data[0],2);
179+}
180+
181+/*
182+ Class structure:
183+ cstruct[0]: class name as integer
184+ cstruct[1]: number of fields and methods:
185+ bit 0-7: # of public fields
186+ bit 8-15: # of private fields
187+ bit 16-23: # of public methods
188+ bit 24-31: reserved
189+ cstruct[x]: public field name
190+ cstruct[x+1]: public field var number
191+ cstruct[y]: private field name
192+ cstruct[y+1]: private field var number
193+ cstruct[z]: public method name
194+ cstruct[z+1]: public method pointer
195+*/
196+
197+char* construct_class_structure(int class){
198+ int* record;
199+ int i;
200+ int num=0;
201+ // Register current address to global var
202+ g_class_structure=&g_object[g_objpos];
203+ // Construct a class structure in object area in following lines
204+ // Class name
205+ check_obj_space(2);
206+ g_object[g_objpos++]=class; // Class name
207+ g_objpos++; // Number of fields/methods
208+ // Public fields
209+ cmpdata_reset();
210+ while(record=cmpdata_find(CMPDATA_FIELD)){
211+ if ((record[0]&0xffff)==CMPTYPE_PUBLIC_FIELD) {
212+ num+=1<<0;
213+ check_obj_space(2);
214+ g_object[g_objpos++]=record[1]; // Field name
215+ g_objpos++; // Var number (see below)
216+ }
217+ }
218+ // Private fields
219+ cmpdata_reset();
220+ while(record=cmpdata_find(CMPDATA_FIELD)){
221+ if ((record[0]&0xffff)==CMPTYPE_PRIVATE_FIELD) {
222+ num+=1<<8;
223+ check_obj_space(2);
224+ g_object[g_objpos++]=record[1]; // Field name
225+ g_objpos++; // Var number (see below)
226+ }
227+ }
228+ // Public methods
229+ cmpdata_reset();
230+ while(record=cmpdata_find(CMPDATA_FIELD)){
231+ if ((record[0]&0xffff)==CMPTYPE_PUBLIC_METHOD) {
232+ num+=1<<16;
233+ check_obj_space(2);
234+ g_object[g_objpos++]=record[1]; // Method name
235+ g_object[g_objpos++]=record[2]; // pointer
236+ }
237+ }
238+ // Update number info
239+ g_class_structure[1]=num;
240+ // Update var numbers of fields
241+ num=((num>>8)&0xff)+(num&0xff);
242+ for(i=1;i<=num;i++){
243+ if ((
244+ g_class_structure[i*2+1]=search_var_name(0x7FFFFFFF & g_class_structure[i*2])+ALLOC_LNV_BLOCK
245+ )<ALLOC_LNV_BLOCK) return ERR_UNKNOWN;
246+ }
247+ return 0;
248+}
249+
250+void delete_cmpdata_for_class(int class){
251+ int* record;
252+ // Delete field/method data
253+ cmpdata_reset();
254+ while(record=cmpdata_find(CMPDATA_FIELD)){
255+ cmpdata_delete(record);
256+ cmpdata_reset();
257+ }
258+ // Delete longvar data
259+ cmpdata_reset();
260+ while(record=cmpdata_find(CMPDATA_USEVAR)){
261+ cmpdata_delete(record);
262+ cmpdata_reset();
263+ }
264+ // Delete solved class codes
265+ cmpdata_reset();
266+ while(record=cmpdata_find(CMPDATA_UNSOLVED)){
267+ if (record[1]!=class) continue;
268+ cmpdata_delete(record);
269+ cmpdata_reset();
270+ }
271+}
272+
273+int object_size(int* classdata){
274+ int nums=classdata[1];
275+ int size=nums&0xff; // public field
276+ size+=(nums>>8)&0xff; // private
277+ // Add 1 for pointer to class data.
278+ return size+1;
279+}
280+
281+char* new_function(){
282+ char* err;
283+ int class,size;
284+ int i,stack, opos;
285+ int* data;
286+ int* classdata;
287+ int record[3];
288+ void* init_method;
289+ // Resolve class name
290+ err=get_label();
291+ if (err) return err;
292+ if (!g_label) return ERR_SYNTAX;
293+ class=g_label;
294+ record[0]=class;
295+ next_position();
296+ // Get class data from cmpdata
297+ // Note that the address of class structure can be resolved
298+ // by using cmpdata when compiling NEW function but not running.
299+ // Therefore, class table is not requred when running.
300+ cmpdata_reset();
301+ while(data=cmpdata_find(CMPDATA_CLASS)){
302+ if (data[1]==class) break;
303+ }
304+ if (!data) return ERR_NO_CLASS;
305+ classdata=(int*)data[2];
306+ if (classdata) {
307+ size=object_size(classdata);
308+ } else {
309+ // Class structure is unsolved.
310+ size=0;
311+ }
312+ // Create object
313+ record[2]=(int)&g_object[g_objpos+3];
314+ call_quicklib_code(lib_calloc_memory,ASM_ORI_A0_ZERO_|size);
315+ // First word of object is pointer to classdata
316+ check_obj_space(3);
317+ record[1]=(int)&g_object[g_objpos];
318+ g_object[g_objpos++]=0x3C080000|(((unsigned int)classdata)>>16); // lui t0,xxxx
319+ g_object[g_objpos++]=0x35080000|(((unsigned int)classdata)&0x0000FFFF); // ori t0,t0,xxxx
320+ g_object[g_objpos++]=0xAC480000; // sw t0,0(v0)
321+ // Check if INIT method exists
322+ if (classdata) {
323+ init_method=search_method(classdata,LABEL_INIT);
324+ } else {
325+ // Class structure is unknown. Use null method.
326+ init_method=(int*)&g_return_code[0];
327+ // Register CMPDATA
328+ cmpdata_insert(CMPDATA_UNSOLVED,CMPTYPE_NEW_FUNCTION,(int*)&record[0],3);
329+ g_allow_shift_obj=0;
330+ }
331+ if (!init_method) {
332+ // All done
333+ // Note that $v0 is address of object here.
334+ // There should not be parameter(s).
335+ if (g_source[g_srcpos]==',') return ERR_NO_INIT;
336+ return 0;
337+ }
338+ // INIT method exists. Note that $v0 is address of object here.
339+ if (g_source[g_srcpos]==',') g_srcpos++;
340+ else if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
341+ check_obj_space(2);
342+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
343+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
344+ err=obj_method(LABEL_INIT);
345+ if (err) return err;
346+ g_srcpos--; // Leave ')' character for detecting end of "new" function
347+ check_obj_space(2);
348+ g_object[g_objpos++]=0x8FA20004; //lw v0,4(sp)
349+ g_object[g_objpos++]=0x27BD0004; //addiu sp,sp,4
350+ // All done
351+ // Note that $v0 is address of object here.
352+ return 0;
353+}
354+
355+char* field_statement(){
356+ char* err;
357+ int i;
358+ int data[1];
359+ int is_private=0;
360+ // This statement is valid only in class file.
361+ if (!g_compiling_class) return ERR_INVALID_NON_CLASS;
362+ // Check which private or public
363+ next_position();
364+ if (nextCodeIs("PRIVATE ")) {
365+ is_private=1;
366+ } else if (nextCodeIs("PUBLIC ")) {
367+ is_private=0;
368+ }
369+ do {
370+ next_position();
371+ i=check_var_name();
372+ if (i<65536) return ERR_SYNTAX;
373+ // Register varname
374+ err=register_var_name(i);
375+ if (err) return err;
376+ if (g_source[g_srcpos]=='#') {
377+ g_srcpos++;
378+ } else if (g_source[g_srcpos]=='$') {
379+ // String field. Raise 31st bit.
380+ g_srcpos++;
381+ i|=0x80000000;
382+ } else if (g_source[g_srcpos]=='(' && g_source[g_srcpos+1]==')' && is_private) {
383+ // Dimension field (private only). Raise 31st bit.
384+ g_srcpos++;
385+ g_srcpos++;
386+ i|=0x80000000;
387+ }
388+ // Register field
389+ data[0]=i;
390+ if (is_private) {
391+ err=cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PRIVATE_FIELD,(int*)&data[0],1);
392+ } else {
393+ err=cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PUBLIC_FIELD,(int*)&data[0],1);
394+ }
395+ next_position();
396+ if (g_source[g_srcpos]==',') {
397+ g_srcpos++;
398+ } else {
399+ break;
400+ }
401+ } while(1);
402+ return 0;
403+}
404+
405+/*
406+ char* obj_method(int method);
407+ Implementation of access to method of object.
408+*/
409+char* obj_method(int method){
410+ // $v0 contains the address of object.
411+ // Note that '(' has been passed.
412+ char* err;
413+ int stack,opos;
414+ // When method of an object is called from object,
415+ // current variables must be saved to object fields
416+ if (g_compiling_class) {
417+ check_obj_space(1);
418+ g_object[g_objpos++]=0x00402821; // addu a1,v0,zero
419+ call_quicklib_code(lib_save_vars_to_fields,ASM_LW_A0_XXXX_S5|ARGS_S5_V0_OBJ);
420+ }
421+ // Parameters preparation (to $s5) here.
422+ next_position();
423+ opos=g_objpos;
424+ // Begin parameter(s) construction routine
425+ err=prepare_args_stack('(');
426+ if (err) return err;
427+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
428+ g_srcpos++;
429+ // Determine address of method and store fields to local variables.
430+ check_obj_space(3);
431+ g_object[g_objpos++]=0x8FA20000|ARGS_SP_V0_OBJ; // lw v0,8(sp)
432+ g_object[g_objpos++]=0x3C050000|((method>>16)&0x0000FFFF); // lui a1,xxxx
433+ g_object[g_objpos++]=0x34A50000|(method&0x0000FFFF); // ori a1,a1,xxxx
434+ call_quicklib_code(lib_pre_method,ASM_ADDU_A0_V0_ZERO);
435+ // Call method address here. Same routine for GOSUB statement with integer value is used.
436+ check_obj_space(6);
437+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
438+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
439+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
440+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
441+ g_object[g_objpos++]=0x00000000; // nop
442+ // label1:
443+ g_object[g_objpos++]=0x00400008; // jr v0
444+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp) // label2:
445+ // Restore fields from local variables.
446+ check_obj_space(3);
447+ g_object[g_objpos++]=0x8FA40008; // lw a0,8(sp)
448+ call_quicklib_code(lib_post_method,ASM_ADDU_A1_V0_ZERO);
449+ // Remove stack
450+ err=remove_args_stack();
451+ if (err) return err;
452+ // When method of an object is called from object,
453+ // current variables must be saved to object fields
454+ if (g_compiling_class) {
455+ check_obj_space(1);
456+ g_object[g_objpos++]=0x00402821; // addu a1,v0,zero
457+ call_quicklib_code(lib_load_vars_from_fields,ASM_LW_A0_XXXX_S5|ARGS_S5_V0_OBJ);
458+ }
459+ return 0;
460+}
461+
462+/*
463+ char* integer_obj_field();
464+ char* string_obj_field();
465+ char* float_obj_field();
466+ Implementation of access to field of object.
467+ This feature is recursive. When an object is applied to the field of another object,
468+ following expression is possible (for example):
469+ obj1.field1.field2
470+
471+*/
472+
473+#define OBJ_FIELD_INTEGER 0
474+#define OBJ_FIELD_STRING '$'
475+#define OBJ_FIELD_FLOAT '#'
476+
477+char* _obj_field(char mode){
478+ // $v0 contains the address of object.
479+ int i;
480+ char* err;
481+ do {
482+ i=check_var_name();
483+ if (i<65536) return ERR_SYNTAX;
484+ if (g_source[g_srcpos]=='(' && mode==OBJ_FIELD_INTEGER) {
485+ // This is a method
486+ g_srcpos++;
487+ return obj_method(i);
488+ } else if (g_source[g_srcpos+1]=='(') {
489+ if (g_source[g_srcpos]==mode) {
490+ // This is a string/float method
491+ g_srcpos++;
492+ g_srcpos++;
493+ return obj_method(i);
494+ }
495+ } else if (g_source[g_srcpos]==mode && mode==OBJ_FIELD_STRING) {
496+ // This is a string field. Raise 31st bit.
497+ i|=0x80000000;
498+ }
499+ check_obj_space(2);
500+ g_object[g_objpos++]=0x3C050000|((i>>16)&0x0000FFFF); // lui a1,xxxx
501+ g_object[g_objpos++]=0x34A50000|(i&0x0000FFFF); // ori a1,a1,xxxx
502+ // First and second arguments are address of object and field name, respectively.
503+ call_quicklib_code(lib_obj_field,ASM_ADDU_A0_V0_ZERO);
504+ // Check if "." follows
505+ if (g_source[g_srcpos]=='.') {
506+ // "." found. $v0 is adress of an object. See the field.
507+ g_srcpos++;
508+ continue;
509+ }
510+ } while(0);
511+ // All done. Check variable type
512+ if (mode==OBJ_FIELD_INTEGER) return 0;
513+ else if (g_source[g_srcpos]==mode) {
514+ g_srcpos++;
515+ return 0;
516+ } else return ERR_SYNTAX;
517+}
518+
519+char* integer_obj_field(){
520+ return _obj_field(OBJ_FIELD_INTEGER);
521+}
522+
523+char* string_obj_field(){
524+ return _obj_field(OBJ_FIELD_STRING);
525+}
526+
527+char* float_obj_field(){
528+ return _obj_field(OBJ_FIELD_FLOAT);
529+}
530+
531+int lib_obj_field(int* object, int fieldname){
532+ int* class;
533+ int i,numfield;
534+ // Check if this is an object (if within the RAM).
535+ if (!withinRAM(object)) err_not_obj();
536+ class=(int*)object[0];
537+ if (!withinRAM(class)) err_not_obj();
538+ // Obtain # of public field
539+ numfield=class[1]&0xff;
540+ for(i=0;i<numfield;i++){
541+ if (class[2+i*2]==fieldname) break;
542+ }
543+ if (i==numfield) err_not_field(fieldname,class[0]);
544+ // Got address of field. Return value as $v0 and address as $v1.
545+ g_temp=(int)(&object[1+i]);
546+ asm volatile("la $v1,%0"::"i"(&g_temp));
547+ asm volatile("lw $v1,0($v1)");
548+ return object[1+i];
549+}
550+
551+/*
552+ Library for letting string field
553+*/
554+
555+void lib_let_str_field(char* prev_str, char* new_str){
556+ int var_num=get_permanent_var_num();
557+ free_perm_str(prev_str);
558+ lib_let_str(new_str,var_num);
559+ return;
560+}
561+
562+/*
563+ Library for calling method statement
564+*/
565+
566+int lib_load_vars_from_fields(int* object, int v0){
567+ // Do nothing if no object
568+ if (object) lib_pre_method(object,LABEL_INIT);
569+ return v0;
570+}
571+
572+int lib_pre_method(int* object, int methodname){
573+ int i,num,nums;
574+ int* class;
575+ // Check if this is an object (if within the RAM).
576+ if (!withinRAM(object)) err_not_obj();
577+ class=(int*)object[0];
578+ if (!withinRAM(class)) err_not_obj();
579+ // Save object field values in local variables in class
580+ nums=class[1];
581+ num=nums&0xff;
582+ for(i=0;i<num;i++){
583+ // Public fields
584+ class+=2;
585+ g_var_mem[class[1]]=object[i+1];
586+ // When string, move from permanent block
587+ if (0x80000000&class[0]) move_from_perm_block_if_exists(class[1]);
588+ }
589+ num+=(nums>>8)&0xff;
590+ for(i=i;i<num;i++){
591+ // Private fields
592+ class+=2;
593+ g_var_mem[class[1]]=object[i+1];
594+ // When string/dimension, move from permanent block
595+ if (0x80000000&class[0]) move_from_perm_block_if_exists(class[1]);
596+ }
597+ // Seek method
598+ num+=(nums>>16)&0xff;
599+ for(i=i;i<num;i++){
600+ class+=2;
601+ if (class[0]==methodname) break;
602+ }
603+ if (i==num) {
604+ // Method not found
605+ if (methodname==LABEL_INIT) {
606+ // INIT method not found
607+ // Call null function
608+ return (int)(&g_return_code[0]);
609+ } else {
610+ class=(int*)object[0];
611+ err_not_field(methodname,class[0]);
612+ }
613+ }
614+ // Method found. return it.
615+ return class[1];
616+}
617+
618+int lib_save_vars_to_fields(int* object,int v0){
619+ int* class;
620+ // Do nothing if no object
621+ if (!object) return;
622+ // Check if this is an object (if within the RAM).
623+ if (!withinRAM(object)) err_not_obj();
624+ class=(int*)object[0];
625+ if (!withinRAM(class)) err_not_obj();
626+ // save vars
627+ lib_post_method(object,0);
628+ return v0;
629+}
630+
631+int lib_post_method(int* object, int v0){
632+ // Note that v0 (a1) contains the return value from a method.
633+ int i,num,nums;
634+ int* class;
635+ // Restore local variables to object field values
636+ class=(int*)object[0];
637+ nums=class[1];
638+ num=nums&0xff;
639+ for(i=0;i<num;i++){
640+ // Public fields
641+ class+=2;
642+ object[i+1]=g_var_mem[class[1]];
643+ // When string, move to permanent block
644+ if (0x80000000&class[0]) {
645+ if (g_var_size[class[1]]) move_to_perm_block(class[1]);
646+ }
647+ }
648+ num+=(nums>>8)&0xff;
649+ for(i=i;i<num;i++){
650+ // Private fields
651+ class+=2;
652+ object[i+1]=g_var_mem[class[1]];
653+ // When string/dimension, move to permanent block
654+ if (0x80000000&class[0]) {
655+ if (g_var_size[class[1]]) move_to_perm_block(class[1]);
656+ }
657+ }
658+ // all done
659+ return v0;
660+}
661+
662+/*
663+ Method statement
664+*/
665+
666+char* method_statement(){
667+ char* err;
668+ int data[2];
669+ int opos=g_objpos;
670+ // This statement is valid only in class file.
671+ if (!g_compiling_class) return ERR_INVALID_NON_CLASS;
672+ // Insert label for setting $s6
673+ err=label_statement();
674+ if (err) return err;
675+ // Register cmpdata
676+ data[0]=g_label;
677+ data[1]=(int)(&g_object[opos]);
678+ return cmpdata_insert(CMPDATA_FIELD,CMPTYPE_PUBLIC_METHOD,(int*)&data[0],2);
679+}
680+
681+/*
682+ Delete statement
683+*/
684+
685+char* delete_statement(){
686+ char* err;
687+ next_position();
688+ g_srcpos--;
689+ do{
690+ g_srcpos++;
691+ err=get_value();
692+ if (err) return err;
693+ call_quicklib_code(lib_delete,ASM_ADDU_A0_V0_ZERO);
694+ next_position();
695+ } while (g_source[g_srcpos]==',');
696+ return 0;
697+}
698+
699+/*
700+ Call statement
701+*/
702+
703+char* call_statement(){
704+ // Just get an integer value. That is it.
705+ return get_value();
706+}
707+
708+/*
709+ Static statement
710+*/
711+
712+char* static_statement(){
713+ char* err;
714+ int* record;
715+ int data[2];
716+ int i;
717+ int is_private=0;
718+ // This statement is valid only in class file.
719+ if (!g_compiling_class) return ERR_INVALID_NON_CLASS;
720+ // Check which private or public
721+ next_position();
722+ if (nextCodeIs("PRIVATE ")) {
723+ is_private=1;
724+ } else if (nextCodeIs("PUBLIC ")) {
725+ is_private=0;
726+ }
727+ do {
728+ next_position();
729+ i=check_var_name();
730+ if (i<65536) return ERR_SYNTAX;
731+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') {
732+ g_srcpos++;
733+ }
734+ // Register public static field
735+ if (is_private) {
736+ // This is the same as USEVAR
737+ // Register varname
738+ err=register_var_name(i);
739+ if (err) return err;
740+ } else {
741+ // Check if there is already a CMPDATA record
742+ cmpdata_reset();
743+ while(record=cmpdata_find(CMPDATA_STATIC)){
744+ if (record[1]!=g_compiling_class) continue;
745+ if (record[2]!=i) continue;
746+ break;
747+ }
748+ if (record) {
749+ // There is already a record.
750+ // Do not allocate new number but use the registered number;
751+ i=record[0]&0xffff;
752+ err=cmpdata_insert(CMPDATA_USEVAR,i,&record[2],1);
753+ if (err) return err;
754+ } else {
755+ // Register varname
756+ err=register_var_name(i);
757+ if (err) return err;
758+ // Insert a CMDATA_STATIC record
759+ data[0]=g_compiling_class; // class name as integer
760+ data[1]=i; // static var name as integer
761+ i=search_var_name(i); // var number of this static field
762+ if (i<0) return ERR_UNKNOWN;
763+ err=cmpdata_insert(CMPDATA_STATIC,i,(int*)&data[0],2);
764+ if (err) return err;
765+ }
766+ }
767+ next_position();
768+ if (g_source[g_srcpos]==',') {
769+ g_srcpos++;
770+ } else {
771+ break;
772+ }
773+ } while(1);
774+ return 0;
775+
776+}
777+
778+/*
779+ Static method
780+ Type is either 0, '$', or '#',
781+ for integer, string, or float
782+*/
783+
784+char* static_method(char type){
785+ char* err;
786+ int* data;
787+ int record[3];
788+ int i,opos,method,stack;
789+ next_position();
790+ // Check class name
791+ i=check_var_name();
792+ if (i<65536) return ERR_SYNTAX;
793+ record[0]=i;
794+ // Check if the class exists
795+ cmpdata_reset();
796+ while(data=cmpdata_find(CMPDATA_CLASS)){
797+ if (data[1]==i) {
798+ // The class was already defined.
799+ i=0;
800+ break;
801+ }
802+ }
803+ // Check '::'
804+ if (g_source[g_srcpos]!=':') return ERR_SYNTAX;
805+ g_srcpos++;
806+ if (g_source[g_srcpos]!=':') return ERR_SYNTAX;
807+ g_srcpos++;
808+ if (i) return ERR_NO_CLASS;
809+ data=(int*)data[2];
810+ // Check method
811+ i=check_var_name();
812+ if (i<65536) return ERR_SYNTAX;
813+ if (data) {
814+ method=(int)search_method(data,i);
815+ if (!method) return ERR_NOT_FIELD;
816+ } else {
817+ method=(int)&g_return_code[0];
818+ record[1]=i;
819+ }
820+ // Check type and '('
821+ if (type) {// Either 0, '$', or '#'
822+ if (g_source[g_srcpos]!=type) return ERR_SYNTAX;
823+ g_srcpos++;
824+
825+ }
826+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
827+ g_srcpos++;
828+ // Begin parameter(s) construction routine
829+ check_obj_space(1);
830+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
831+ err=prepare_args_stack('(');
832+ if (err) return err;
833+ // Calling subroutine, which is static method of class
834+ record[2]=(int)&g_object[g_objpos+5];
835+ check_obj_space(7);
836+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
837+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
838+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
839+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
840+ g_object[g_objpos++]=0x00000000; // nop
841+ // label1:
842+ g_object[g_objpos++]=0x08000000|((method&0x0FFFFFFF)>>2); // j xxxx
843+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
844+ // label2:
845+ // Register CMPDATA if required.
846+ if (!data) {
847+ cmpdata_insert(CMPDATA_UNSOLVED,CMPTYPE_STATIC_METHOD,(int*)&record[0],3);
848+ g_allow_shift_obj=0;
849+ }
850+ // Remove stack
851+ err=remove_args_stack();
852+ if (err) return err;
853+ return 0;
854+}
855+
856+/*
857+ Let object.field statement
858+*/
859+
860+char* let_object_field(){
861+ char* err;
862+ char b3;
863+ int spos,opos;
864+ // $v0 contains the pointer to object
865+ spos=g_srcpos;
866+ opos=g_objpos;
867+ // Try string field, first
868+ err=string_obj_field();
869+ if (err) {
870+ // Integer or float field
871+ g_srcpos=spos;
872+ g_objpos=opos;
873+ err=integer_obj_field();
874+ if (err) return err;
875+ b3=g_source[g_srcpos];
876+ if (b3=='#') g_srcpos++;
877+ } else {
878+ // String field
879+ b3='$';
880+ }
881+ if (g_source[g_srcpos-1]==')') {
882+ // This is a CALL statement
883+ return 0;
884+ }
885+ // $v1 is address to store value. Save it in stack.
886+ check_obj_space(1);
887+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
888+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
889+ if (b3=='$') {
890+ // String field
891+ // Get value
892+ next_position();
893+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
894+ g_srcpos++;
895+ err=get_string();
896+ } else if (b3=='#') {
897+ // Float field
898+ // Get value
899+ next_position();
900+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
901+ g_srcpos++;
902+ err=get_float();
903+ } else {
904+ // Integer field
905+ // Get value
906+ next_position();
907+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
908+ g_srcpos++;
909+ err=get_value();
910+ }
911+ if (err) return err;
912+ // Store in field of object
913+ check_obj_space(4);
914+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
915+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
916+ g_object[g_objpos++]=0x8C640000; // lw a0,0(v1)
917+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
918+ // Handle permanent block for string field
919+ if (b3=='$') call_quicklib_code(lib_let_str_field,ASM_ADDU_A1_V0_ZERO);
920+ return 0;
921+}
\ No newline at end of file
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
--- trunk/class.txt (nonexistent)
+++ trunk/class.txt (revision 37)
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
--- trunk/cmpdata.c (revision 36)
+++ trunk/cmpdata.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913
1014 /*
@@ -21,10 +25,22 @@
2125 data16: general 16 bit data (short)
2226 */
2327
28+/*
29+ CMPDATA_TEMP structure
30+ type: CMPDATA_TEMP (6)
31+ len: n+1
32+ data16: id
33+ record[1]: any data
34+ record[2]: any data
35+ ...
36+ record[n]: any data
37+*/
38+
2439 #define g_cmpdata g_objmax
2540
2641 static int* g_cmpdata_end;
2742 static int* g_cmpdata_point;
43+static unsigned short g_cmpdata_id;
2844
2945 /*
3046 Initialize routine must be called when starting compiler.
@@ -32,9 +48,18 @@
3248 void cmpdata_init(){
3349 g_cmpdata_end=g_objmax;
3450 g_cmpdata_point=g_objmax;
51+ g_cmpdata_id=1;
3552 }
3653
3754 /*
55+ Returns ID as 16 bit indivisual number
56+*/
57+unsigned short cmpdata_get_id(){
58+ if ((++g_cmpdata_id)==0) printstr("CMPDATA: no more ID!\n");
59+ return g_cmpdata_id;
60+}
61+
62+/*
3863 Function to insert a data. The data must be defined by a pointer to int array.
3964 unsigned char type: Data type number (0-255)
4065 short data16: 16 bit data. If not required, set 0.
@@ -84,3 +109,22 @@
84109 cmpdata_reset();
85110 return cmpdata_find(type);
86111 }
112+
113+/*
114+ Delete a record.
115+*/
116+void cmpdata_delete(int* record){
117+ int delnum;
118+ int* data;
119+ // Ignore if invalid record.
120+ if (record<g_cmpdata || g_cmpdata_end<record) return;
121+ // Get number of word to delete.
122+ delnum=(record[0]&0x00ff0000)>>16;
123+ // Delete record by shifting data.
124+ for(data=record-1;g_cmpdata<=data;data--){
125+ data[delnum]=data[0];
126+ }
127+ g_cmpdata+=delnum;
128+ // Reset
129+ cmpdata_reset();
130+}
--- trunk/compiler.c (revision 36)
+++ trunk/compiler.c (revision 37)
@@ -5,6 +5,31 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+/*
13+ Usage of MIPS32 registors
14+ $zero: always zero
15+ $at: not used
16+ $v0: return value or result of last calculation
17+ $v1: for calculation (like $v0=$v1*$v0)
18+ $a0-$a2: parameters for calling library ($a2=$v0)
19+ $a3: function # for library
20+ $t0-$t7: used as temporary registors
21+ $s0-$s4: not used
22+ $s5: pointer to parameters list
23+ $s6: line or label number
24+ $s7: address of call_library()
25+ $t8-$t9: used as temporary registors
26+ $k0-$k1: not used
27+ $gp: for accessing global valiables by C
28+ $sp: stack pointer
29+ $fp($s8) for accessing valiables by BASIC
30+ $ra: contains return address
31+*/
32+
833 #include "compiler.h"
934
1035 void start_program(void* addr, void* memory){
@@ -32,6 +57,8 @@
3257 asm volatile("la $v0,%0"::"i"(&g_end_addr));
3358 asm volatile("la $v1,label");
3459 asm volatile("sw $v1,0($v0)");
60+ // Set s5 for initial_s5_stack
61+ asm volatile("la $s5,%0"::"i"(&g_initial_s5_stack[2]));
3562 // Set s7 for easy calling call_library()
3663 asm volatile("la $s7,%0"::"i"(&call_library));
3764 // Set fp and execute program
--- trunk/compiler.h (revision 36)
+++ trunk/compiler.h (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 // Include envilonment specific configurations
913 #include "envspecific.h"
1014
@@ -24,7 +28,7 @@
2428 // Start # of permanent blocks
2529 #define ALLOC_PERM_BLOCK 229
2630 // Number of blocks that can be assigned for memory allocation (including all above)
27-#define ALLOC_BLOCK_NUM 239
31+#define ALLOC_BLOCK_NUM 329
2832
2933 // Persistent RAM bytes used for object, heap and exception data
3034 #ifndef PERSISTENT_RAM_SIZE
@@ -118,6 +122,9 @@
118122 LIB_FILE =LIB_STEP*48,
119123 LIB_PLAYWAVE =LIB_STEP*49,
120124 LIB_PLAYWAVEFUNC =LIB_STEP*50,
125+ LIB_SETDIR =LIB_STEP*51,
126+ LIB_SETDIRFUNC =LIB_STEP*52,
127+ LIB_GETDIR =LIB_STEP*53,
121128 LIB_DEBUG =LIB_STEP*127,
122129 };
123130
@@ -185,6 +192,7 @@
185192 extern unsigned int g_label;
186193 extern int g_sdepth;
187194 extern int g_maxsdepth;
195+extern char g_allow_shift_obj;
188196 extern enum variable g_lastvar;
189197 extern char* g_source;
190198 extern int g_srcpos;
@@ -213,6 +221,8 @@
213221 extern unsigned short* g_graphic_area;
214222 extern int* g_libparams;
215223 extern int g_long_name_var_num;
224+extern int g_class;
225+extern int g_compiling_class;
216226 extern int g_temp;
217227
218228 /* Prototypes */
@@ -228,6 +238,9 @@
228238 void close_file();
229239 void read_file(int blocklen);
230240 char* compile_file();
241+int compile_and_link_file(char* buff,char* appname);
242+int compile_and_link_main_file(char* buff,char* appname);
243+int compile_and_link_class(char* buff,int class);
231244
232245 void err_break(void);
233246 void err_music(char* str);
@@ -242,6 +255,9 @@
242255 void err_invalid_param(void);
243256 void err_file(void);
244257 void err_wave(void);
258+void err_not_obj(void);
259+void err_not_field(int fieldname, int classname);
260+void err_str(char* str);
245261 char* resolve_label(int s6);
246262
247263 void set_sound(unsigned long* data, int flagsLR);
@@ -260,6 +276,7 @@
260276 char* fput_statement();
261277 char* fputc_statement();
262278 char* fremove_statement();
279+char* label_statement();
263280
264281 char* function(void);
265282 char* str_function(void);
@@ -269,11 +286,17 @@
269286 void reset_dataread();
270287
271288 void free_temp_str(char* str);
289+void free_non_temp_str(char* str);
290+void free_perm_str(char* str);
272291 void* alloc_memory(int size, int var_num);
273292 void* calloc_memory(int size, int var_num);
274293 void move_to_perm_block(int var_num);
275294 void move_from_perm_block(int var_num);
295+int move_from_perm_block_if_exists(int var_num);
276296 int get_permanent_var_num(void);
297+int get_varnum_from_address(void* address);
298+void* lib_calloc_memory(int size);
299+void lib_delete(int* object);
277300
278301 char* link(void);
279302 char* get_label(void);
@@ -301,10 +324,12 @@
301324 char* get_float();
302325
303326 void cmpdata_init();
327+unsigned short cmpdata_get_id();
304328 char* cmpdata_insert(unsigned char type, short data16, int* data, unsigned char num);
305329 void cmpdata_reset();
306330 int* cmpdata_find(unsigned char type);
307331 int* cmpdata_findfirst(unsigned char type);
332+void cmpdata_delete(int* record);
308333
309334 int check_var_name();
310335 int get_var_number();
@@ -311,7 +336,37 @@
311336 int search_var_name(int nameint);
312337 char* register_var_name(int nameint);
313338
339+char* update_class_info(int class);
340+char* construct_class_structure(int class);
341+void delete_cmpdata_for_class(int class);
314342
343+extern const unsigned int g_initial_s5_stack[3];
344+char* prepare_args_stack(char start_char);
345+char* remove_args_stack(void);
346+char* args_function_main(void);
347+
348+char* begin_compiling_class(int class);
349+char* end_compiling_class(int class);
350+char* new_function();
351+char* field_statement();
352+char* integer_obj_field();
353+char* string_obj_field();
354+char* float_obj_field();
355+int lib_obj_field(int* object, int fieldname);
356+int lib_pre_method(int* object, int methodname);
357+int lib_post_method(int* object, int v0);
358+int lib_save_vars_to_fields(int* object,int v0);
359+int lib_load_vars_from_fields(int* object, int v0);
360+
361+char* method_statement();
362+char* delete_statement();
363+char* call_statement();
364+void lib_let_str_field(char* str, char* prev_str);
365+char* let_object_field();
366+char* static_statement();
367+char* static_method(char type);
368+char* resolve_unresolved(int class);
369+
315370 /* Error messages */
316371 #define ERR_SYNTAX (char*)(g_err_str[0])
317372 #define ERR_NE_BINARY (char*)(g_err_str[1])
@@ -335,13 +390,51 @@
335390 #define ERR_FILE (char*)(g_err_str[19])
336391 #define ERR_INVALID_VAR_NAME (char*)(g_err_str[20])
337392 #define ERR_WAVE (char*)(g_err_str[21])
393+#define ERR_COMPILE_CLASS (char*)(g_err_str[22])
394+#define ERR_NO_CLASS (char*)(g_err_str[23])
395+#define ERR_NOT_OBJ (char*)(g_err_str[24])
396+#define ERR_NOT_FIELD (char*)(g_err_str[25])
397+#define ERR_INVALID_NON_CLASS (char*)(g_err_str[26])
398+#define ERR_INVALID_CLASS (char*)(g_err_str[27])
399+#define ERR_NO_INIT (char*)(g_err_str[28])
338400
339-/* comple data type numbers */
401+/* compile data type numbers */
340402 #define CMPDATA_RESERVED 0
341403 #define CMPDATA_USEVAR 1
404+#define CMPDATA_CLASS 2
405+#define CMPDATA_FIELD 3
406+#define CMPDATA_STATIC 4
407+#define CMPDATA_UNSOLVED 5
408+#define CMPDATA_TEMP 6
409+// Sub types follow
410+#define CMPTYPE_PUBLIC_FIELD 0
411+#define CMPTYPE_PRIVATE_FIELD 1
412+#define CMPTYPE_PUBLIC_METHOD 2
413+#define CMPTYPE_NEW_FUNCTION 0
414+#define CMPTYPE_STATIC_METHOD 1
342415
416+
417+/* Stack position for values in args.c */
418+#define ARGS_SP_SP 4
419+#define ARGS_SP_V0_OBJ 8
420+#define ARGS_SP_PREV_S5 12
421+#define ARGS_SP_NUM_ARGS 16
422+#define ARGS_S5_SP (-12 & 0xFFFF)
423+#define ARGS_S5_V0_OBJ (-8 & 0xFFFF)
424+#define ARGS_S5_PREV_S5 (-4 & 0xFFFF)
425+#define ARGS_S5_NUM_ARGS (0 & 0xFFFF)
426+
427+/*
428+ Hidden varname 31 bit values
429+ Note that max number of 31 bit value is 0x61504BFF (for ZZZZZZ)
430+*/
431+#define HIDDEN_VAR_THIS_OBJECT 0x7FFF0000
432+
343433 /* Macros */
344434
435+// Lables as 31 bit integer
436+#define LABEL_INIT 0x0007df55
437+
345438 // Skip blanc(s) in source code
346439 #define next_position() while(g_source[g_srcpos]==' ') {g_srcpos++;}
347440
@@ -359,6 +452,28 @@
359452 g_object[g_objpos++]=0x02E0F809;\
360453 g_object[g_objpos++]=0x24070000|((x)&0x0000FFFF)
361454
455+// Insert code for calling quick library
456+//3C081234 lui t0,0x1234
457+//35085678 ori t0,t0,0x5678
458+//0100F809 jalr ra,t0
459+//00000000 nop
460+#define call_quicklib_code(x,y) do {\
461+ check_obj_space(4);\
462+ g_object[g_objpos++]=0x3C080000|(((unsigned int)(x))>>16);\
463+ g_object[g_objpos++]=0x35080000|(((unsigned int)(x))&0x0000FFFF);\
464+ g_object[g_objpos++]=0x0100F809;\
465+ g_object[g_objpos++]=(y);\
466+ } while (0)
467+
468+#define ASM_NOP 0x00000000
469+#define ASM_ADDU_A0_V0_ZERO 0x00402021
470+#define ASM_ADDU_A1_V0_ZERO 0x00402821
471+#define ASM_ADDU_A2_V0_ZERO 0x00403021
472+#define ASM_ADDU_A3_V0_ZERO 0x00403821
473+#define ASM_ORI_A0_ZERO_ 0x34040000
474+#define ASM_LW_A0_XXXX_S8 0x8FC40000
475+#define ASM_LW_A0_XXXX_S5 0x8EA40000
476+
362477 // Division macro for unsigned long
363478 // Valid for 31 bits for all cases and 32 bits for some cases
364479 #define div32(x,y,z) ((((unsigned long long)((unsigned long)(x)))*((unsigned long long)((unsigned long)(y))))>>(z))
@@ -374,3 +489,6 @@
374489 // Divide by 36 (valid for 32 bits)
375490 #define div36_32(x) div32(x,0xe38e38e4,37)
376491 #define rem36_32(x) (x-36*div36_32(x))
492+
493+// Check if within RAM
494+#define withinRAM(x) ((&RAM[0])<=((char*)(x)) && ((char*)(x))<(&RAM[RAMSIZE]))
--- trunk/debug.c (revision 36)
+++ trunk/debug.c (revision 37)
@@ -32,6 +32,8 @@
3232
3333 static const char initext[];
3434 static const char bastext[];
35+static const char class1text[];
36+static const char class2text[];
3537
3638 static char* readtext;
3739 static int filepos;
@@ -129,8 +131,15 @@
129131 // INI file
130132 readtext=(char*)&initext[0];
131133 } else if (fileName[i+1]=='B' && fileName[i+2]=='A' && fileName[i+3]=='S') {
132- // BAS file
133- readtext=(char*)&bastext[0];
134+ // Select BAS file
135+ if (fileName[i-6]=='C' && fileName[i-5]=='L' && fileName[i-4]=='A' &&
136+ fileName[i-3]=='S' && fileName[i-2]=='S') {
137+ if (fileName[i-1]=='1') readtext=(char*)&class1text[0];
138+ else if (fileName[i-1]=='2') readtext=(char*)&class2text[0];
139+ else readtext=(char*)&bastext[0];
140+ } else {
141+ readtext=(char*)&bastext[0];
142+ }
134143 // Try debugDump.
135144 if (debugDump()) return 0;
136145 } else {
@@ -218,29 +227,60 @@
218227 "#PRINT\n"
219228 "#PRINT\n";
220229
221-
222230 static const char bastext[]=
223-"I2C 100\n"
224-"DIM D(5)\n"
225-"T$=\"Hello MachiKania!\"\n"
226-"I2CREADDATA 0x50,D,18,0x00,0x00\n"
227-"PRINT I2CERROR()\n"
228-"PRINT D$\n"
229-"I2CWRITEDATA 0x50,T,18,0x00,0x00\n"
230-"PRINT I2CERROR()\n"
231-"WAIT 60\n"
232-"I2CREADDATA 0x50,D,18,0x00,0x00\n"
231+"print getdir$()\n"
232+"end\n"
233233 "\n"
234+"\n"
235+"\n"
236+"\n"
237+"\n"
234238 "\n";
235239
240+static const char class1text[]=
241+"STATIC T1\n"
242+"useclass CLASS2\n"
243+"method T3\n"
244+" return CLASS2::T2\n"
245+"method T5\n"
246+" return T1\n"
247+"\n"
248+"\n";
249+
250+static const char class2text[]=
251+"STATIC T2\n"
252+"useclass CLASS1\n"
253+"method T4\n"
254+" return CLASS1::T1\n"
255+"method T6\n"
256+" return T2\n"
257+"\n"
258+"\n"
259+"\n"
260+"\n";
261+
236262 /*
237263 Test function for constructing assemblies from C codes.
238264 */
239265
266+static const void* debugjumptable[]={
267+ FSfread,
268+ FSfopen,
269+};
270+
240271 int _debug_test(int a0, int a1, int a2, int a3, int param4, int param5){
241-// if (a0<0xa0008192) return 0xa0000000;
242- asm volatile("lw $sp,18($fp)");
243- asm volatile("addiu $sp,$sp,2044");
272+ asm volatile(".set noreorder");
273+ asm volatile("lw $a0,4($s5)");
274+ asm volatile("lw $a1,8($s5)");
275+ asm volatile("lw $a2,12($s5)");
276+ asm volatile("lw $a3,16($s5)");
277+ asm volatile("nop");
278+ asm volatile("nop");
279+ asm volatile("nop");
280+ asm volatile("nop");
281+ asm volatile("nop");
282+ asm volatile("nop");
283+ asm volatile("nop");
244284 return a2+a3;
245285 }
246286
--- trunk/debug.h (revision 36)
+++ trunk/debug.h (revision 37)
@@ -5,6 +5,10 @@
55 http://hp.vector.co.jp/authors/VA016157/
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #ifdef __DEBUG
913
1014 // Pseudo reading config setting for debug mode
--- trunk/envspecific.c (revision 36)
+++ trunk/envspecific.c (revision 37)
@@ -107,7 +107,7 @@
107107 return;
108108 } else {
109109 // Clear previous area here
110- free_temp_str((char*)g_graphic_area);
110+ free_non_temp_str((char*)g_graphic_area);
111111 g_graphic_area=0;
112112 }
113113 }
--- trunk/error.c (revision 36)
+++ trunk/error.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913
1014 const char* g_err_str[]={
@@ -30,6 +34,13 @@
3034 "File error",
3135 "Invalid variable name",
3236 "WAVE format error",
37+ "ERR_COMPILE_CLASS",
38+ "Class not found",
39+ "Not an object",
40+ " is not public field/method",
41+ "Valid only in class file",
42+ "Invalid in class file",
43+ "INIT method does not exist",
3344 };
3445
3546 char* resolve_label(int s6){
@@ -168,3 +179,20 @@
168179 end_exec();
169180 }
170181
182+void err_not_obj(void){
183+ printstr(ERR_NOT_OBJ);
184+ end_exec();
185+}
186+
187+void err_not_field(int fieldname, int classname){
188+ printstr(resolve_label(classname));
189+ printchar('.');
190+ printstr(resolve_label(fieldname & 0x7FFFFFFF));
191+ printstr(ERR_NOT_FIELD);
192+ end_exec();
193+}
194+
195+void err_str(char* str){
196+ printstr(str);
197+ end_exec();
198+}
\ No newline at end of file
--- trunk/exception.c (revision 36)
+++ trunk/exception.c (revision 37)
@@ -5,6 +5,10 @@
55 http://hp.vector.co.jp/authors/VA016157/
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include <xc.h>
913 #include "api.h"
1014 #include "main.h"
--- trunk/file.c (revision 36)
+++ trunk/file.c (revision 37)
@@ -5,6 +5,10 @@
55 http://hp.vector.co.jp/authors/VA016157/
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include <xc.h>
913 #include "api.h"
1014 #include "compiler.h"
@@ -19,9 +23,12 @@
1923 if (!g_fhandle) {
2024 return ERR_UNKNOWN;
2125 }
26+ // Initialize parameters
2227 g_fbuff=buff;
2328 g_line=0;
2429 g_fileline=0;
30+ g_source=buff;
31+ g_srcpos=0;
2532 return 0;
2633 }
2734
@@ -88,7 +95,11 @@
8895 if (err) return err;
8996 }
9097 // Add "DATA 0" and "END" statements.
91- g_source="DATA 0:END\n";
98+ if (g_compiling_class) {
99+ g_source="END\n";
100+ } else {
101+ g_source="DATA 0:END\n";
102+ }
92103 g_srcpos=0;
93104 err=compile_line();
94105 if (err) return err;
@@ -97,3 +108,165 @@
97108 return 0;
98109 }
99110
111+int compile_and_link_file(char* buff,char* appname){
112+ int i,j;
113+ char* err;
114+
115+ while(1){
116+ // Initialize SD card file system
117+ err=init_file(buff,appname);
118+ if (err) {
119+ //setcursorcolor(COLOR_ERRORTEXT);
120+ printstr("Can't Open ");
121+ printstr(appname);
122+ printchar('\n');
123+ return -1;
124+ }
125+
126+ // Compile the file
127+ err=compile_file();
128+ close_file();
129+
130+ // If compiling a class file is required, do it.
131+ if (err==ERR_COMPILE_CLASS) {
132+ j=g_compiling_class;
133+ i=compile_and_link_class(buff, g_class);
134+ g_compiling_class=j;
135+ if (i) return i;
136+ // Continue compiling current file from the beginning.
137+ continue;
138+ }
139+ break;
140+ }
141+
142+ if (err) {
143+ // Compile error
144+ printstr(err);
145+ printstr("\nAround: '");
146+ for(i=0;i<5;i++){
147+ printchar(g_source[g_srcpos-2+i]);
148+ }
149+ printstr("' in line ");
150+ printdec(g_line);
151+ printstr("\n");
152+ for(i=g_srcpos;0x20<=g_source[i];i++);
153+ g_source[i]=0x00;
154+ for(i=g_srcpos;0x20<=g_source[i];i--);
155+ printstr(g_source+i);
156+ return g_fileline;
157+ }
158+
159+ // Link
160+ err=link();
161+ if (err) {
162+ // Link error
163+ printstr(err);
164+ printstr(resolve_label(g_label));
165+ return -2;
166+ }
167+
168+ // All done
169+ return 0;
170+}
171+
172+int compile_and_link_class(char* buff,int class){
173+ int i,j;
174+ char* err;
175+ char* classname;
176+ char classfile[13];
177+ char classdir[11];
178+ int data[2];
179+ unsigned short cwd_id;
180+ int* record;
181+ while(1){
182+ // Begin compiling class
183+ err=begin_compiling_class(class);
184+ if (err) break;
185+ // Determine class file name
186+ classname=resolve_label(class);
187+ for(i=0;classfile[i]=classname[i];i++);
188+ classfile[i++]='.';
189+ classfile[i++]='B';
190+ classfile[i++]='A';
191+ classfile[i++]='S';
192+ classfile[i]=0;
193+ // Check if file exists in current directory
194+ err=init_file(buff,&classfile[0]);
195+ if (!err) {
196+ // Class file found in current directory
197+ close_file();
198+ // Compile it
199+ i=compile_and_link_file(buff,&classfile[0]);
200+ if (i) break;
201+ } else {
202+ // Class file not found in current directory.
203+ // Try library directory, for example, \LIB\CLASS1\CLASS1.BAS
204+ // Store current directory, first
205+ if (!FSgetcwd(buff,256)) break;
206+ for(i=0;buff[i];i++);
207+ cwd_id=cmpdata_get_id();
208+ if (!cwd_id) break;
209+ err=cmpdata_insert(CMPDATA_TEMP,cwd_id,(int*)(&buff[0]),(i+1+3)>>2);
210+ if (err) break;
211+ // Change current directory to class library directory
212+ for(i=0;classdir[i]="\\LIB\\"[i];i++);
213+ for(j=0;classdir[i++]=classname[j];j++);
214+ classdir[i]=0;
215+ FSchdir(classdir);
216+ // Compile class file
217+ i=compile_and_link_file(buff,&classfile[0]);
218+ // Restore current dirctory
219+ cmpdata_reset();
220+ while(record=cmpdata_find(CMPDATA_TEMP)){
221+ if (cwd_id=(record[0]&0xffff)) break;
222+ }
223+ if (!record) break;
224+ FSchdir((char*)(&record[1]));
225+ cmpdata_delete(record);
226+ if (i) break;
227+ }
228+ // End compiling class
229+ err=end_compiling_class(class);
230+ if (err) break;
231+ // Initial assembly is a jump statement to jump to the end of class file
232+ // Note that there is at least a code (set line # to $s6) before reaching here
233+ g_object[0]=0x08000000 | ((((int)(&g_object[g_objpos]))&0x0FFFFFFF)>>2); // j xxxxxxxx
234+ // In the next link, current region of object is ignored.
235+ g_object+=g_objpos;
236+ g_objpos=0;
237+ // All done
238+ return 0;
239+ }
240+ // Error occured
241+ printstr("/nError in class: ");
242+ printstr((char*)&classfile[0]);
243+ printchar('\n');
244+ if (err) printstr(err);
245+ return -2;
246+}
247+
248+int compile_and_link_main_file(char* buff,char* appname){
249+ int i;
250+ g_compiling_class=0;
251+ i=compile_and_link_file(buff,appname);
252+ if (i) return i;
253+ return 0;
254+ /*
255+ After compiling class code, g_object is set to the beginning of next code.
256+ Therefore, after the all, g_object is set toe the beginnig of main code,
257+ and class code(s) is/are excluded. This will affect following features when running:
258+ READ/DATA/RESTORE function/statements
259+ The linker also works withing the g_object dimension. Therefore, the label only works withing the file,
260+ but not in the other file. This feature allows using the same label name in different files without
261+ causing error/misjumping
262+
263+ After compiling class code, following cmpdata are destroyed (see delete_cmpdata_for_class() function):
264+ CMPDATA_FIELD : object field and method information
265+ CMPDATA_USEVAR : long var name information
266+ but following cmpdata remains:
267+ CMPDATA_CLASS : class name and address of class structure
268+ This feature allows compiler to use class information (name and structure) for "NEW" function,
269+ to use the same long var name in different files (note that g_long_name_var_num is not reseted after
270+ compiling each class code).
271+ */
272+}
\ No newline at end of file
--- trunk/float.c (revision 36)
+++ trunk/float.c (revision 37)
@@ -1,3 +1,14 @@
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
112 #include "./compiler.h"
213 #include "stdlib.h"
314
@@ -57,6 +68,21 @@
5768 // Must be a function.
5869 return float_function();
5970 }
71+ if (g_source[g_srcpos]=='.') {
72+ // This is an object field or method to return string
73+ check_obj_space(1);
74+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
75+ g_srcpos++;
76+ return float_obj_field();
77+ } else if (g_source[g_srcpos]=='(') {
78+ // An array element contains pointer to an object.
79+ g_srcpos++;
80+ err=get_dim_value(i);
81+ if (err) return err;
82+ if (g_source[g_srcpos]!='.') return ERR_SYNTAX;
83+ g_srcpos++;
84+ return float_obj_field();
85+ }
6086 if (g_source[g_srcpos]!='#') return ERR_SYNTAX;
6187 g_srcpos++;
6288 if (g_source[g_srcpos]=='(') {
@@ -122,7 +148,7 @@
122148 prevpos=g_objpos;
123149 // Stack decrement command will be filled later
124150 check_obj_space(1);
125- g_objpos++;
151+ g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx")
126152 }
127153 err=get_float_sub(priority(OP_VOID));
128154 if (err) return err;
@@ -129,8 +155,10 @@
129155 if (g_sdepth==0) {
130156 if (g_maxsdepth==0) {
131157 // Stack was not used.
132- shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
133- g_objpos--;
158+ if (g_allow_shift_obj) {
159+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
160+ g_objpos--;
161+ }
134162 } else {
135163 // Stack was used.
136164 check_obj_space(1);
--- trunk/function.c (revision 36)
+++ trunk/function.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913 #include "api.h"
1014
@@ -23,6 +27,8 @@
2327 }
2428
2529 char* read_function(){
30+ // This function is not valid in class file.
31+ if (g_compiling_class) return ERR_INVALID_CLASS;
2632 call_lib_code(LIB_READ);
2733 return 0;
2834 }
@@ -92,12 +98,23 @@
9298 return 0;
9399 }
94100
95-char* peek_function(){
101+char* peek_function_sub(int bits){
96102 char* err;
97103 err=get_value();
98104 if (err) return err;
99105 check_obj_space(1);
100- g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
106+ switch(bits){
107+ case 32:
108+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0)
109+ break;
110+ case 16:
111+ g_object[g_objpos++]=0x94420000; // lhu v0,0(v0)
112+ break;
113+ case 8:
114+ default:
115+ g_object[g_objpos++]=0x90420000; // lbu v0,0(v0)
116+ break;
117+ }
101118 return 0;
102119 }
103120
@@ -244,23 +261,7 @@
244261 }
245262
246263 char* args_function(void){
247- char* err;
248- int i;
249- err=get_value();
250- if (err) return err;
251- i=g_object[g_objpos-1];
252- if ((i>>16)==0x3402) {
253- // Previous object is "ori v0,zero,xxxx".
254- i&=0xffff;
255- i=(i+1)<<2;
256- g_object[g_objpos-1]=0x8EA20000|i; // lw v0,xx(s5)
257- } else {
258- check_obj_space(3);
259- g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
260- g_object[g_objpos++]=0x02A21021; // addu v0,s5,v0
261- g_object[g_objpos++]=0x8C420004; // lw v0,4(v0)
262- }
263- return 0;
264+ return args_function_main();
264265 }
265266
266267 char* system_function(void){
@@ -378,6 +379,19 @@
378379 return 0;
379380 }
380381
382+char* setdir_function(){
383+ char* err;
384+ err=get_string();
385+ if (err) return err;
386+ call_lib_code(LIB_SETDIRFUNC);
387+ return 0;
388+}
389+
390+char* getdir_function(){
391+ call_lib_code(LIB_GETDIR);
392+ return 0;
393+}
394+
381395 char* float_constant(float val){
382396 volatile int i;
383397 ((float*)(&i))[0]=val;
@@ -475,7 +489,9 @@
475489 } else if (nextCodeIs("PI#")) {
476490 return float_constant(3.141593);
477491 } else {
478- return ERR_SYNTAX;
492+ // Check if static method of a class
493+ err=static_method('#');
494+ //return ERR_SYNTAX;
479495 }
480496 if (err) return err;
481497 if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
@@ -495,6 +511,7 @@
495511 "FLOAT$(",floatstr_function,
496512 "SYSTEM$(",system_function,
497513 "FINPUT$(",finput_function,
514+ "GETDIR$(",getdir_function,
498515 // Additional functions follow
499516 ADDITIONAL_STR_FUNCTIONS
500517 };
@@ -512,7 +529,9 @@
512529 f=str_func_list[i+1];
513530 err=f();
514531 } else {
515- return ERR_SYNTAX;
532+ // Check if static method of a class
533+ err=static_method('$');
534+ //return ERR_SYNTAX;
516535 }
517536 if (err) return err;
518537 if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
@@ -522,6 +541,18 @@
522541
523542 // Aliases follow
524543
544+char* peek_function(){
545+ return peek_function_sub(8);
546+}
547+
548+char* peek16_function(){
549+ return peek_function_sub(16);
550+}
551+
552+char* peek32_function(){
553+ return peek_function_sub(32);
554+}
555+
525556 char* gcolor_function(){
526557 return graphic_statement(FUNC_GCOLOR);
527558 }
@@ -541,6 +572,8 @@
541572 "GOSUB(",gosub_function,
542573 "STRNCMP(",strncmp_function,
543574 "PEEK(",peek_function,
575+ "PEEK16(",peek16_function,
576+ "PEEK32(",peek32_function,
544577 "LEN(",len_function,
545578 "ASC(",asc_function,
546579 "SGN(",sgn_function,
@@ -562,6 +595,8 @@
562595 "FREMOVE(",fremove_statement,
563596 "FEOF(",feof_function,
564597 "PLAYWAVE(",playwave_function,
598+ "NEW(",new_function,
599+ "SETDIR(",setdir_function,
565600 // Additional functions follow
566601 ADDITIONAL_INT_FUNCTIONS
567602 };
@@ -579,7 +614,9 @@
579614 f=int_func_list[i+1];
580615 err=f();
581616 } else {
582- return ERR_SYNTAX;
617+ // Check if static method of a class
618+ err=static_method(0);
619+ //return ERR_SYNTAX;
583620 }
584621 if (err) return err;
585622 if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
--- trunk/globalvars.c (revision 36)
+++ trunk/globalvars.c (revision 37)
@@ -5,6 +5,10 @@
55 http://hp.vector.co.jp/authors/VA016157/
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913 #include "main.h"
1014
@@ -24,6 +28,7 @@
2428 // handling values and strings.
2529 int g_sdepth;
2630 int g_maxsdepth;
31+char g_allow_shift_obj;
2732
2833 // Following var shows what type of variable was defined
2934 // in compiling the last code.
@@ -75,5 +80,10 @@
7580 // Number of long name variables
7681 int g_long_name_var_num;
7782
83+// Class name being compiled
84+int g_class;
85+// Flag to compile class file
86+int g_compiling_class;
87+
7888 // General purpose integer used for asigning value with pointer
7989 int g_temp;
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
--- trunk/io.c (revision 36)
+++ trunk/io.c (revision 37)
@@ -57,13 +57,13 @@
5757 IEC1bits.U1TXIE=0;
5858 IEC1bits.U1RXIE=0;
5959 // Free buffer area
60- if (g_serial_buff) free_temp_str((char*)g_serial_buff);
60+ if (g_serial_buff) free_non_temp_str((char*)g_serial_buff);
6161 g_serial_buff=0;
6262 } else {
6363 // Prepare buffer for SERIALIN
6464 if (bsize==0) bsize=baud/400; // Area corresponds to ~1/40 sec (> 1/60 sec)
6565 g_serial_buff_size=bsize;
66- if (g_serial_buff) free_temp_str((char*)g_serial_buff);
66+ if (g_serial_buff) free_non_temp_str((char*)g_serial_buff);
6767 g_serial_buff=(short*)alloc_memory((bsize+1)/2,get_permanent_var_num());
6868 g_serial_buff_read_pos=g_serial_buff_write_pos=0;
6969 // Initialize I/O ports
--- trunk/library.c (revision 36)
+++ trunk/library.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include <xc.h>
913 #include "main.h"
1014 #include "compiler.h"
@@ -21,6 +25,20 @@
2125 static int g_prev_x=0;
2226 static int g_prev_y=0;
2327
28+int lib_setdir(int mode,char* path){
29+ int ret;
30+ ret=FSchdir(path);
31+ if (mode==LIB_SETDIR && ret) err_file();
32+ return ret;
33+}
34+
35+int lib_getdir(){
36+ char* path;
37+ path=calloc_memory(32,-1);
38+ FSgetcwd (path,128);
39+ return (int)path;
40+}
41+
2442 int lib_read(int mode, unsigned int label){
2543 unsigned int i,code,code2;
2644 static unsigned int pos=0;
@@ -405,7 +423,7 @@
405423 case 2:
406424 // Reset PCG and use it
407425 if (g_pcg_font) {
408- free_temp_str(g_pcg_font);
426+ free_non_temp_str(g_pcg_font);
409427 g_pcg_font=0;
410428 }
411429 // Continue to case 1:
@@ -1012,6 +1030,11 @@
10121030 case LIB_SETDRAWCOUNT:
10131031 drawcount=(v0&0x0000FFFF);
10141032 return v0;
1033+ case LIB_GETDIR:
1034+ return lib_getdir();
1035+ case LIB_SETDIRFUNC:
1036+ case LIB_SETDIR:
1037+ return lib_setdir(a3,(char*)v0);
10151038 case LIB_DRAWCOUNT:
10161039 return drawcount;
10171040 case LIB_SYSTEM:
--- trunk/linker.c (revision 36)
+++ trunk/linker.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913
1014 unsigned int g_label;
--- trunk/main.h (revision 36)
+++ trunk/main.h (revision 37)
@@ -7,8 +7,8 @@
77
88 #define MEGALOPA
99 #define SYSVER1 "Megalopa"
10-#define SYSVER2 "1.1"
11-#define BASVER "KM-1301"
10+#define SYSVER2 "1.2"
11+#define BASVER "KM-1302"
1212
1313 #define INIFILE "MACHIKAM.INI" // 初期設定ファイル
1414 #define HEXFILE "MACHIKAM.HEX" // 実行中HEXファイル名がこれと一致した場合はエディタ起動
--- trunk/memory.c (revision 36)
+++ trunk/memory.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913
1014 /*
@@ -13,17 +17,35 @@
1317 This number also includes temporary area used for string construction etc.
1418 Temporary area is cleared every line of BASIC code in alloc_memory().
1519 ALLOC_BLOCK_NUM: # of blocks that can be used for memory allocation.
16- This # also includes the ones for ALLOC_VAR_NUM.
20+ This # includes the ones for ALLOC_VAR_NUM, ALLOC_PCG_BLOCK etc, ALLOC_LNV_BLOCK,
21+ ALLOC_PERM_BLOCK.
1722 After ALLOC_VAR_NUM area, dedicated memory area and permanent area follows.
18- Currently, only PCG is used for permanent pourpose.
19- 10 permanant blocks can be used.
20- Therefore, ALLOC_VAR_NUM+11 == ALLOC_BLOCK_NUM
2123 ALLOC_PERM_BLOCK: Start # of permanent blocks.
2224 The blocks after this number is permanently stored.
2325 Therefore, it must be released when it's not used any more.
2426 */
2527
28+static int g_temp_var_num_candidate=ALLOC_PERM_BLOCK;
29+
30+#define DELETE_LIST_SIZE 10
31+static int g_deleted_num;
32+static int g_deleted_pointer[DELETE_LIST_SIZE];
33+static int g_deleted_size[DELETE_LIST_SIZE];
34+
35+void register_deleted_block(int pointer, int size){
36+ // There is maximum
37+ if (DELETE_LIST_SIZE<=g_deleted_num) return;
38+ if (g_deleted_num) {
39+ // Avoid duplication
40+ if (g_deleted_pointer[g_deleted_num-1]==pointer) return;
41+ }
42+ g_deleted_pointer[g_deleted_num]=pointer;
43+ g_deleted_size[g_deleted_num]=size;
44+ g_deleted_num++;
45+}
46+
2647 void set_free_area(void* begin, void* end){
48+ // Initialize heap area
2749 int i;
2850 for(i=0;i<ALLOC_BLOCK_NUM;i++){
2951 g_var_size[i]=0;
@@ -30,6 +52,7 @@
3052 }
3153 g_heap_mem=(int*)begin;
3254 g_max_mem=(int)((end-begin)/4);
55+ g_deleted_num=0;
3356 }
3457
3558 void* calloc_memory(int size, int var_num){
@@ -85,6 +108,24 @@
85108 g_var_size[var_num]=0;
86109 g_var_pointer[var_num]=0;
87110 while(1){
111+ // Try the block previously deleted, not for temporary block.
112+ // This is for fast allocation of memory for class object.
113+ if (var_num<26 || ALLOC_VAR_NUM<=var_num) {
114+ candidate=0;
115+ while(g_deleted_num){
116+ // Check if the last deleted block fits
117+ // If not, these cannot be used anymore
118+ g_deleted_num--;
119+ if (size<=g_deleted_size[g_deleted_num]) {
120+ candidate=g_deleted_pointer[g_deleted_num];
121+ break;
122+ }
123+ }
124+ if (candidate || g_deleted_num) {
125+ // Candidate found
126+ break;
127+ }
128+ }
88129 // Try the block after last block
89130 candidate=0;
90131 for(i=0;i<ALLOC_BLOCK_NUM;i++){
@@ -93,7 +134,29 @@
93134 candidate=g_var_pointer[i]+g_var_size[i];
94135 }
95136 }
96- if (candidate+size<=g_max_mem) break;
137+ if (candidate+size<=g_max_mem) {
138+ // Check after deleted block
139+ j=candidate;
140+ for(i=0;i<g_deleted_num;i++){
141+ if (j<g_deleted_pointer[i]+g_deleted_size[i]) {
142+ j=g_deleted_pointer[i]+g_deleted_size[i];
143+ }
144+ }
145+ if (j+size<=g_max_mem) {
146+ // Candidate block found after previously deleted blokcs
147+ candidate=j;
148+ break;
149+ } else {
150+ // Candidate is before previously deleted blocks,
151+ // and there is no candidate block after previously deleted blocks.
152+ // Therefore, use the current candidate, which may invade previously
153+ // deleted blocks. Therefore, erase the previously deleted blocks list.
154+ g_deleted_num=0;
155+ break;
156+ }
157+ }
158+ // Peviously deleted blocks cannot be used any more
159+ g_deleted_num=0;
97160 // Check between blocks
98161 // Note that there is at least one block with zero pointer and zero size (see above).
99162 for(i=0;i<ALLOC_BLOCK_NUM;i++){
@@ -132,21 +195,64 @@
132195 if (!str) return;
133196 pointer=(int)str-(int)g_heap_mem;
134197 pointer>>=2;
135- for(i=0;i<ALLOC_BLOCK_NUM;i++){
198+ for(i=26;i<ALLOC_VAR_NUM;i++){
136199 if (g_var_pointer[i]==pointer) {
137- g_var_size[i]=0;
138- break;
200+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
201+ register_deleted_block(pointer,g_var_size[i]);
202+ g_var_size[i]=0;
203+ }
139204 }
140205 }
141206 }
142207
208+void free_non_temp_str(char* str){
209+ int i,pointer;
210+ if (!str) return;
211+ pointer=(int)str-(int)g_heap_mem;
212+ pointer>>=2;
213+ for(i=0;i<26;i++){
214+ if (g_var_pointer[i]==pointer) {
215+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
216+ register_deleted_block(pointer,g_var_size[i]);
217+ g_var_size[i]=0;
218+ g_var_mem[i]=0;
219+ }
220+ }
221+ }
222+ for(i=ALLOC_VAR_NUM;i<ALLOC_BLOCK_NUM;i++){
223+ if (g_var_pointer[i]==pointer) {
224+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
225+ register_deleted_block(pointer,g_var_size[i]);
226+ g_var_size[i]=0;
227+ g_var_mem[i]=0;
228+ if (ALLOC_PERM_BLOCK<=i) g_temp_var_num_candidate=i;
229+ }
230+ }
231+ }
232+}
233+
234+void free_perm_str(char* str){
235+ int i,pointer;
236+ if (!str) return;
237+ pointer=(int)str-(int)g_heap_mem;
238+ pointer>>=2;
239+ // Search permanent block and delete a block if found.
240+ for(i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
241+ if (g_var_pointer[i]==pointer) {
242+ if (g_var_size[i] && g_var_mem[i]==(int)str) {
243+ register_deleted_block(pointer,g_var_size[i]);
244+ g_var_size[i]=0;
245+ g_temp_var_num_candidate=i;
246+ break;
247+ }
248+ }
249+ }
250+}
251+
143252 void move_to_perm_block(int var_num){
144253 int i;
145254 // Find available permanent block
146- for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
147- if (g_var_size[i]==0) break;
148- }
149- if (ALLOC_BLOCK_NUM<=i) err_no_block(); // Not found
255+ i=get_permanent_var_num();
150256 // Available block found.
151257 // Copy value from variable.
152258 g_var_size[i]=g_var_size[var_num];
@@ -157,7 +263,7 @@
157263 g_var_mem[var_num]=0;
158264 }
159265
160-void move_from_perm_block(int var_num){
266+int move_from_perm_block_if_exists(int var_num){
161267 int i,pointer;
162268 pointer=(int)g_var_mem[var_num]-(int)g_heap_mem;
163269 pointer>>=2;
@@ -165,7 +271,7 @@
165271 for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++){
166272 if (0<g_var_size[i] && g_var_pointer[i]==pointer) break;
167273 }
168- if (ALLOC_BLOCK_NUM<=i) err_unknown(); // Not found
274+ if (ALLOC_BLOCK_NUM<=i) return 0; // Not found
169275 // Stored block found.
170276 // Replace pointer
171277 g_var_size[var_num]=g_var_size[i];
@@ -172,13 +278,50 @@
172278 g_var_pointer[var_num]=g_var_pointer[i];
173279 // Clear block
174280 g_var_size[i]=0;
281+ g_temp_var_num_candidate=i;
282+ return 1;
175283 }
176284
285+void move_from_perm_block(int var_num){
286+ if (move_from_perm_block_if_exists(var_num)) return; // Found
287+ err_unknown(); // Not found
288+}
289+
177290 int get_permanent_var_num(){
178291 int i;
292+ // Try candidate first
293+ if (!g_var_size[g_temp_var_num_candidate]) {
294+ if (ALLOC_PERM_BLOCK<g_temp_var_num_candidate &&
295+ g_temp_var_num_candidate<ALLOC_BLOCK_NUM) {
296+ return g_temp_var_num_candidate++;
297+ }
298+ }
299+ // Candidate is not available. Seek all.
179300 for (i=ALLOC_PERM_BLOCK;i<ALLOC_BLOCK_NUM;i++) {
180- if (g_var_size[i]==0) return i;
301+ if (g_var_size[i]==0) {
302+ g_temp_var_num_candidate=i+1;
303+ return i;
304+ }
181305 }
182306 err_no_block();
183307 return 0;
184308 }
309+
310+int get_varnum_from_address(void* address){
311+ int i;
312+ for (i=0;i<ALLOC_BLOCK_NUM;i++){
313+ if (g_var_mem[i]==(int)address) return i;
314+ }
315+ // not found
316+ return -1;
317+}
318+
319+void* lib_calloc_memory(int size){
320+ // Allocate memory and return address
321+ return calloc_memory(size,get_permanent_var_num());
322+}
323+
324+void lib_delete(int* object){
325+ // Remove region that fit to object
326+ free_non_temp_str((char*)object);
327+}
--- trunk/operator.c (revision 36)
+++ trunk/operator.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913
1014 /*
--- trunk/run.c (revision 36)
+++ trunk/run.c (revision 37)
@@ -5,6 +5,10 @@
55 http://hp.vector.co.jp/authors/VA016157/
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include <xc.h>
913 #include "api.h"
1014 #include "compiler.h"
@@ -44,10 +48,8 @@
4448
4549 // Set grobal pointer
4650 g_gp=get_gp();
47- // Set source positions
51+ // Set buffer positions
4852 buff=(char*)&(RAM[RAMSIZE-512]);
49- g_source=(char*)(&buff[0]);
50- g_srcpos=0;
5153 // Set object positions
5254 g_object=(int*)(&RAM[0]);
5355 g_objpos=0;
@@ -54,7 +56,8 @@
5456 g_objmax=g_object+(RAMSIZE-512)/4; // Buffer area excluded.
5557 // Clear object area
5658 for(i=0;i<RAMSIZE/4;i++) g_object[i]=0x00000000;
57- // Initialize SD card file system
59+
60+ // Check file error
5861 err=init_file(buff,appname);
5962 if (err) {
6063 setcursorcolor(COLOR_ERRORTEXT);
@@ -63,6 +66,7 @@
6366 printchar('\n');
6467 return -1;
6568 }
69+ close_file();
6670
6771 // Initialize parameters
6872 g_pcg_font=0;
@@ -82,34 +86,9 @@
8286 printstr("Compiling...");
8387
8488 // Compile the file
85- err=compile_file();
86- close_file();
87- if (err) {
88- // Compile error
89- printstr(err);
90- printstr("\nAround: '");
91- for(i=0;i<5;i++){
92- printchar(g_source[g_srcpos-2+i]);
93- }
94- printstr("' in line ");
95- printdec(g_line);
96- printstr("\n");
97- for(i=g_srcpos;0x20<=g_source[i];i++);
98- g_source[i]=0x00;
99- for(i=g_srcpos;0x20<=g_source[i];i--);
100- printstr(g_source+i);
101- return g_fileline;
102- }
89+ i=compile_and_link_main_file(buff,appname);
90+ if (i) return i;
10391
104- // Link
105- err=link();
106- if (err) {
107- // Link error
108- printstr(err);
109- printstr(resolve_label(g_label));
110- return -2;
111- }
112-
11392 // All done
11493 printstr("done\n");
11594 if(test) return 0; //コンパイルのみの場合
--- trunk/statement.c (revision 36)
+++ trunk/statement.c (revision 37)
@@ -1,1646 +1,1743 @@
1-/*
2- This file is provided under the LGPL license ver 2.1.
3- Written by Katsumi.
4- http://hp.vector.co.jp/authors/VA016157/
5- kmorimatsu@users.sourceforge.jp
6-*/
7-
8-#include "api.h"
9-#include "compiler.h"
10-
11-char* rem_statement(){
12- if (g_source[g_srcpos-4]<0x20) {
13- // This line contains only "REM" statement
14- // Delete $s6-setting command if exists.
15- if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
16- }
17- while(0x20<=g_source[g_srcpos]){
18- g_srcpos++;
19- }
20- return 0;
21-}
22-
23-char* sound_statement(){
24- char *err;
25- err=get_label();
26- if (err) return err;
27- if (g_label) {
28- // Label/number is constant.
29- // Linker will change following codes later.
30- // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
31- check_obj_space(2);
32- g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
33- g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
34- } else {
35- // Label/number will be dynamically set when executing code.
36- err=get_value();
37- if (err) return err;
38- call_lib_code(LIB_LABEL);
39- }
40- // 2nd param is optional
41- next_position();
42- if (g_source[g_srcpos]==',') {
43- g_srcpos++;
44- check_obj_space(2);
45- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
46- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
47- err=get_value();
48- if (err) return err;
49- check_obj_space(3);
50- g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
51- g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
52- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
53- } else {
54- // Set 3 if omitted
55- check_obj_space(1);
56- g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
57- }
58- call_lib_code(LIB_SOUND);
59- return 0;
60-}
61-char* music_statement(){
62- char *err;
63- err=get_string();
64- if (err) return err;
65- // 2nd param is optional
66- next_position();
67- if (g_source[g_srcpos]==',') {
68- g_srcpos++;
69- check_obj_space(2);
70- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
71- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
72- err=get_value();
73- if (err) return err;
74- check_obj_space(3);
75- g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
76- g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
77- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
78- } else {
79- // Set 3 if omitted
80- check_obj_space(1);
81- g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
82- }
83- call_lib_code(LIB_MUSIC);
84- return 0;
85-}
86-
87-char* exec_statement(){
88- char *err;
89- char b1;
90- int i,prevpos;
91- b1=g_source[g_srcpos];
92- while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
93- prevpos=g_objpos;
94- g_valueisconst=1;
95- err=get_simple_value();
96- if (!g_valueisconst) err=ERR_SYNTAX;
97- if (err) return err;
98- check_obj_space(1);
99- g_objpos=prevpos;
100- g_object[g_objpos++]=g_intconst;
101- next_position();
102- b1=g_source[g_srcpos];
103- if (b1!=',') break;
104- g_srcpos++;
105- next_position();
106- b1=g_source[g_srcpos];
107- if (b1==0x0d || b1==0x0a) {
108- // Multiline DATA/EXEC statement
109- g_line++;
110- g_fileline++;
111- if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
112- g_srcpos++;
113- // Maintain at least 256 characters in cache.
114- if (256<=g_srcpos) read_file(256);
115- next_position();
116- b1=g_source[g_srcpos];
117- }
118- }
119- return 0;
120-}
121-
122-char* cdata_statement(){
123- // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
124- // are the sign of data region
125- int beginpos,prevpos;
126- char* err;
127- char b1;
128- char* cpy;
129- int shift=0;
130- int i=0;
131- beginpos=g_objpos;
132- check_obj_space(2);
133- g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
134- g_object[g_objpos++]=0x00000020; // add zero,zero,zero
135- next_position();
136- b1=g_source[g_srcpos];
137- while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
138- prevpos=g_objpos;
139- g_valueisconst=1;
140- err=get_simple_value();
141- if (!g_valueisconst) err=ERR_SYNTAX;
142- if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
143- if (err) return err;
144- g_objpos=prevpos;
145- i|=g_intconst<<shift;
146- shift+=8;
147- if (32<=shift) {
148- check_obj_space(1);
149- g_object[g_objpos++]=i;
150- shift=0;
151- i=0;
152- }
153- next_position();
154- b1=g_source[g_srcpos];
155- if (b1!=',') break;
156- g_srcpos++;
157- next_position();
158- b1=g_source[g_srcpos];
159- if (b1==0x0d || b1==0x0a) {
160- // Multiline CDATA statement
161- g_line++;
162- g_fileline++;
163- if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
164- g_srcpos++;
165- // Maintain at least 256 characters in cache.
166- if (256<=g_srcpos) read_file(256);
167- next_position();
168- b1=g_source[g_srcpos];
169- }
170- }
171- // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
172- if (0<shift) {
173- // Convert shift value from bit-shift to data byte-shift.
174- shift=4-shift/8;
175- check_obj_space(1);
176- g_object[g_objpos++]=i;
177- for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
178- cpy[0]=cpy[0-shift];
179- }
180- }
181- // Determine the size of data
182- i=g_objpos-beginpos-1;
183- g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
184- g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
185- return 0;
186-}
187-
188-char* data_statement(){
189- // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
190- // are the sign of data region
191- int i,prevpos;
192- char* err;
193- while(1){
194- prevpos=g_objpos;
195- check_obj_space(2);
196- g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
197- g_object[g_objpos++]=0x00000020; // add zero,zero,zero
198- next_position();
199- if (g_source[g_srcpos]=='"') {
200- // Constant string
201- // Store pointer to string. This is 3 words bellow of current position
202- g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
203- g_objpos++;
204- g_object[prevpos]=0x04110002; // bgezal zero,xxxx
205- err=simple_string();
206- if (err) return err;
207- next_position();
208- if (g_source[g_srcpos]==',') {
209- g_srcpos++;
210- continue;
211- }
212- return 0;
213- }
214- err=exec_statement();
215- if (err) return err;
216- // Determine the size of data
217- i=g_objpos-prevpos-1;
218- g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
219- if (g_source[g_srcpos]=='"') {
220- // Constant string
221- continue;
222- }
223- return 0;
224- }
225-}
226-
227-char* clear_statement(){
228- call_lib_code(LIB_CLEAR);
229- return 0;
230-}
231-
232-char* poke_statement(){
233- char* err;
234- err=get_value();
235- if (err) return err;
236- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
237- g_srcpos++;
238- check_obj_space(2);
239- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
240- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
241- err=get_value();
242- if (err) return err;
243- check_obj_space(3);
244- g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
245- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
246- g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
247- return 0;
248-}
249-
250-char* dim_statement(){
251- char* err;
252- char b1;
253- int i;
254- int spos;
255- int stack;
256- while(1){
257- stack=0;
258- next_position();
259- i=get_var_number();
260- if (i<0) return ERR_SYNTAX;
261- if (g_source[g_srcpos]=='#') g_srcpos++;
262- next_position();
263- if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
264- check_obj_space(1);
265- spos=g_objpos++; // addiu sp,sp,xxxx
266- do {
267- g_srcpos++;
268- err=get_value();
269- if (err) return err;
270- stack+=4;
271- check_obj_space(1);
272- g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
273- } while (g_source[g_srcpos]==',');
274- if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
275- g_srcpos++;
276- check_obj_space(3);
277- g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx
278- g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
279- g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
280- call_lib_code(LIB_DIM);
281- // Stack -/+
282- check_obj_space(1);
283- g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
284- stack=(0-stack)&0x0000FFFF;
285- g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
286- next_position();
287- if (g_source[g_srcpos]!=',') break;
288- g_srcpos++;
289- }
290- return 0;
291-}
292-
293-char* label_statement(){
294- char* err;
295- char b1;
296- b1=g_source[g_srcpos];
297- if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
298- err=get_label();
299- if (err) return err;
300- // Check existing label with the same name here.
301- if (search_label(g_label)) {
302- // Error: duplicate labels
303- printstr("Label ");
304- printstr(resolve_label(g_label));
305- return ERR_MULTIPLE_LABEL;
306- }
307- check_obj_space(2);
308- g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
309- g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
310- return 0;
311-}
312-
313-char* restore_statement(){
314- char* err;
315- err=get_label();
316- if (err) return err;
317- if (g_label) {
318- // Constant label/number
319- // Use 32 bit mode also for values<65536
320- // This code will be replaced to code for v0 for pointer in linker.
321- check_obj_space(2);
322- g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
323- g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
324- } else {
325- // Dynamic number
326- err=get_value();
327- if (err) return err;
328- }
329- call_lib_code(LIB_RESTORE);
330- return 0;
331-}
332-
333-char* gosub_statement_sub(){
334- char* err;
335- err=get_label();
336- if (err) return err;
337- if (g_label) {
338- // Label/number is constant.
339- // Linker will change following codes later.
340- // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
341- check_obj_space(6);
342- g_object[g_objpos++]=0x04130003; // bgezall zero,label1
343- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
344- g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
345- g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
346- // label1:
347- g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
348- g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
349- // label2:
350- } else {
351- // Label/number will be dynamically set when executing code.
352- err=get_value();
353- if (err) return err;
354- call_lib_code(LIB_LABEL);
355- check_obj_space(6);
356- g_object[g_objpos++]=0x04130003; // bgezall zero,label1
357- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
358- g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
359- g_object[g_objpos++]=0x00000000; // nop
360- // label1:
361- g_object[g_objpos++]=0x00400008; // jr v0
362- g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
363- // label2:
364- }
365- return 0;
366-}
367-
368-char* gosub_statement(){
369- char* err;
370- int opos,spos,stack;
371- opos=g_objpos;
372- spos=g_srcpos;
373- err=gosub_statement_sub();
374- if (err) return err;
375- next_position();
376- // If there is no 2nd argument, return.
377- if (g_source[g_srcpos]!=',') return 0;
378-
379- // There is (at least) 2nd argument.
380- // Rewind object and construct argument-creating routine.
381- g_objpos=opos;
382- stack=4;
383- g_object[g_objpos++]=0x27BD0000; // addiu sp,sp,-xx
384- do {
385- g_srcpos++;
386- stack+=4;
387- err=get_stringFloatOrValue();
388- if (err) return err;
389- check_obj_space(1);
390- g_object[g_objpos++]=0xAFA20000|stack; // sw v0,xx(sp)
391- next_position();
392- } while(g_source[g_srcpos]==',');
393- check_obj_space(2);
394- g_object[g_objpos++]=0xAFB50004; // sw s5,4(sp)
395- g_object[g_objpos++]=0x03A0A821; // addu s5,sp,zero
396- g_object[opos]|=((0-stack)&0xFFFF); // addiu sp,sp,-xx (See above)
397- // Rewind source and construct GOSUB routine again.
398- opos=spos;
399- spos=g_srcpos;
400- g_srcpos=opos;
401- err=gosub_statement_sub();
402- if (err) return err;
403- // Remove stack
404- check_obj_space(2);
405- g_object[g_objpos++]=0x8FB50004; // lw s5,4(sp)
406- g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
407- // All done, go back to wright source position
408- g_srcpos=spos;
409- return 0;
410-}
411-
412-char* return_statement(){
413- char* err;
414- char b1;
415- next_position();
416- b1=g_source[g_srcpos];
417- if (0x20<b1 && b1!=':') {
418- // There is a return value.
419- err=get_stringFloatOrValue();
420- if (err) return err;
421- }
422- check_obj_space(3);
423- g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
424- g_object[g_objpos++]=0x00600008; // jr v1
425- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
426- return 0;
427-}
428-
429-char* goto_statement(){
430- char* err;
431- err=get_label();
432- if (err) return err;
433- if (g_label) {
434- // Label/number is constant.
435- // Linker will change following codes later.
436- // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
437- check_obj_space(2);
438- g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
439- g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
440- } else {
441- // Label/number will be dynamically set when executing code.
442- err=get_value();
443- if (err) return err;
444- call_lib_code(LIB_LABEL);
445- check_obj_space(2);
446- g_object[g_objpos++]=0x00400008; // jr v0
447- g_object[g_objpos++]=0x00000000; // nop
448- }
449- return 0;
450-}
451-
452-char* if_statement(){
453- char* err;
454- int prevpos,bpos;
455- // Get value.
456- err=get_floatOrValue();
457- if (err) return err;
458- // Check "THEN"
459- if (!nextCodeIs("THEN")) return ERR_SYNTAX;
460- // Check if statement follows after THEN statement
461- next_position();
462- if (nextCodeIs("REM")) {
463- // If REM statement follows, skip comment words.
464- rem_statement();
465- }
466- if (g_source[g_srcpos]<0x20) {
467- // End of line.
468- // Use IF-THEN-ENDIF mode (multiple line mode)
469- check_obj_space(3);
470- g_object[g_objpos++]=0x30000000; // nop (see linker)
471- g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
472- g_object[g_objpos++]=0x30000000; // nop (see linker)
473- return 0;
474- }
475- // One line mode
476- // If $v0=0 then skip.
477- bpos=g_objpos;
478- check_obj_space(2);
479- g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
480- g_object[g_objpos++]=0x00000000; // nop
481- prevpos=g_srcpos;
482- if (statement()) {
483- // May be label
484- g_srcpos=prevpos;
485- err=goto_statement();
486- if (err) return err;
487- } else {
488- // Must be statement(s)
489- while(1) {
490- if (g_source[g_srcpos]!=':') break;
491- g_srcpos++;
492- err=statement();
493- if (err) return err;
494- }
495- }
496- // Check if "ELSE" exists.
497- if (!nextCodeIs("ELSE ")) {
498- // "ELSE" not found. This is the end of "IF" statement.
499- // Previous branch command must jump to this position.
500- g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
501- return 0;
502- }
503- // Skip after ELSE if required.
504- check_obj_space(2);
505- g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
506- g_object[g_objpos++]=0x00000000; // nop
507- // Previous branch command must jump to this position.
508- g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
509- bpos=g_objpos-2;
510- // Next statement is either label or general statement
511- prevpos=g_srcpos;
512- if (statement()) {
513- // May be label
514- g_srcpos=prevpos;
515- err=goto_statement();
516- if (err) return err;
517- } else {
518- // Must be statement(s)
519- while(1) {
520- if (g_source[g_srcpos]!=':') break;
521- g_srcpos++;
522- err=statement();
523- if (err) return err;
524- }
525- }
526- // Previous branch command must jump to this position.
527- g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
528- return 0;
529-}
530-
531-char* elseif_statement(void){
532- // Multiple line mode
533- char* err;
534- g_object[g_objpos++]=0x08160100; // breakif (see linker)
535- g_object[g_objpos++]=0x30008000; // nop (see linker)
536- // Get value.
537- err=get_floatOrValue();
538- if (err) return err;
539- // Check "THEN"
540- if (!nextCodeIs("THEN")) return ERR_SYNTAX;
541- // Check if statement follows after THEN statement
542- if (nextCodeIs("REM")) {
543- // If REM statement follows, skip comment words.
544- rem_statement();
545- }
546- if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
547- // Statement didn't follow after THEM statement (that is correct).
548- g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
549- g_object[g_objpos++]=0x30000000; // nop (see linker)
550- return 0;
551-
552-}
553-
554-char* else_statement(void){
555- // Multiple line mode
556- g_object[g_objpos++]=0x08160100; // breakif (see linker)
557- g_object[g_objpos++]=0x30008000; // nop (see linker)
558- g_object[g_objpos++]=0x30000000; // nop (see linker)
559- // Check if statement follows after THEN statement
560- if (nextCodeIs("REM")) {
561- // If REM statement follows, skip comment words.
562- rem_statement();
563- }
564- if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
565- // Statement didn't follow after THEM statement (that is correct).
566- return 0;
567-}
568-
569-char* endif_statement(void){
570- // Multiple line mode
571- g_object[g_objpos++]=0x30008000; // nop (see linker)
572- g_object[g_objpos++]=0x30008000; // nop (see linker)
573- // Check if statement follows after THEN statement
574- if (nextCodeIs("REM")) {
575- // If REM statement follows, skip comment words.
576- rem_statement();
577- }
578- if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
579- // Statement didn't follow after THEM statement (that is correct).
580- return 0;
581-}
582-
583-char* end_statement(void){
584- int i;
585- i=(int)&g_end_addr;
586- i-=g_gp;
587- check_obj_space(3);
588- g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
589- g_object[g_objpos++]=0x00400008; // jr v0
590- g_object[g_objpos++]=0x00000000; // nop
591- return 0;
592-}
593-
594-char* let_dim_sub(int i){
595- char* err;
596- g_srcpos++;
597- err=get_value();
598- if (err) return err;
599- check_obj_space(4);
600- g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
601- g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
602- g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
603- g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
604- while(g_source[g_srcpos]==','){
605- g_srcpos++;
606- err=get_value();
607- if (err) return err;
608- check_obj_space(4);
609- g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
610- g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
611- g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
612- g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
613- g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
614- }
615- if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
616- g_srcpos++;
617- return 0;
618-};
619-
620-char* let_statement(){
621- char* err;
622- char b2,b3;
623- int i;
624- next_position();
625- i=get_var_number();
626- if (i<0) return ERR_SYNTAX;
627- b2=g_source[g_srcpos];
628- b3=g_source[g_srcpos+1];
629- if (b2=='#' && b3=='(') {
630- // Float dimension
631- g_srcpos++;
632- check_obj_space(1);
633- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
634- let_dim_sub(i);
635- next_position();
636- if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
637- g_srcpos++;
638- err=get_float();
639- if (err) return err;
640- check_obj_space(3);
641- g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
642- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
643- g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
644- return 0;
645- } else if (b2=='#') {
646- // Float A-Z
647- g_srcpos++;
648- next_position();
649- if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
650- g_srcpos++;
651- err=get_float();
652- if (err) return err;
653- check_obj_space(1);
654- g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
655- return 0;
656- } else if (b2=='$') {
657- // String
658- g_srcpos++;
659- next_position();
660- if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
661- g_srcpos++;
662- err=get_string();
663- if (err) return err;
664- check_obj_space(1);
665- g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx
666- call_lib_code(LIB_LETSTR);
667- return 0;
668- } else if (b2=='(') {
669- // Dimension
670- check_obj_space(1);
671- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
672- let_dim_sub(i);
673- next_position();
674- if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
675- g_srcpos++;
676- err=get_value();
677- if (err) return err;
678- check_obj_space(3);
679- g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
680- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
681- g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
682- return 0;
683- } else {
684- // Integer A-Z
685- next_position();
686- if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
687- g_srcpos++;
688- err=get_value();
689- if (err) return err;
690- check_obj_space(1);
691- g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
692- }
693- return 0;
694-}
695-
696-char* print_statement_main(enum libs lib_printstr, enum libs lib_string){
697- char* err;
698- char b1;
699- int i;
700- int status=0;// 1:',' 2:';' 0:none
701- while(1){
702- next_position();
703- if (endOfStatement()) break;
704- if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
705- err=get_stringFloatOrValue();
706- if (err) return err;
707- switch(g_lastvar){
708- case VAR_INTEGER:
709- // Use DEC$() function.
710- call_lib_code(LIB_DEC);
711- break;
712- case VAR_FLOAT:
713- // Use FLOAT$() function.
714- check_obj_space(2);
715- g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
716- g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
717- call_lib_code(LIB_SPRINTF);
718- break;
719- case VAR_STRING:
720- default:
721- break;
722- }
723- // Call printstr() function
724- // First argument is the pointer to string
725- call_lib_code(lib_printstr);
726- next_position();
727- b1=g_source[g_srcpos];
728- if (b1==',') {
729- status=1;
730- g_srcpos++;
731- // Call lib_string() function for comma (,)
732- check_obj_space(1);
733- g_object[g_objpos++]=0x34020001; // ori v0,zero,1
734- call_lib_code(lib_string);
735- } else if (b1==';') {
736- status=2;
737- g_srcpos++;
738- } else {
739- status=0;
740- }
741- }
742- if (status==0) {
743- // Call lib_string() function for CR (\n)
744- check_obj_space(1);
745- g_object[g_objpos++]=0x34020000; // ori v0,zero,0
746- call_lib_code(lib_string);
747- }
748- return 0;
749-}
750-
751-char* break_statement(){
752- check_obj_space(2);
753- g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
754- g_object[g_objpos++]=0x00000000; // nop
755- return 0;
756-}
757-
758-char* continue_statement(){
759- check_obj_space(2);
760- g_object[g_objpos++]=0x08160008; // j xxxx (See link() function)
761- g_object[g_objpos++]=0x00000000; // nop
762- return 0;
763-}
764-
765-char* for_statement(){
766- char* err;
767-// char b1;
768- int i;
769- int prepos=g_srcpos;
770- // Initialization of variable
771-// next_position();
772-// b1=g_source[g_srcpos];
773- i=get_var_number();
774-// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
775- if (i<0) return ERR_SYNTAX;
776- g_srcpos=prepos;
777- err=let_statement();
778- if (err) return err;
779- // Check if "TO" exists
780- if (!nextCodeIs("TO ")) return ERR_SYNTAX;
781- err=get_value();
782- if (err) return err;
783- // Usage of stack:
784- // 12(sp): "TO" value
785- // 8(sp): "STEP" value
786- // 4(sp): Address to return to in "NEXT" statement.
787- // Store "TO" value in stack
788- check_obj_space(2);
789- g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
790- g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
791- // Check if "STEP" exists
792- g_valueisconst=1;
793- if (nextCodeIs("STEP ")) {
794- // "STEP" exists. Get value
795- err=get_value();
796- if (err) return err;
797- } else {
798- // "STEP" not exist. Use "1".
799- check_obj_space(1);
800- g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
801- g_intconst=1;
802- }
803- check_obj_space(14);
804- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
805- g_object[g_objpos++]=0x04130004; // bgezall zero,check
806-// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
807- g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
808- // After executing "NEXT" statement, process reaches following line.
809- // Update variable value by adding STEP value
810- // Note that STEP value is loaded onto $v0 in NEXT statement
811-// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
812- g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
813- g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
814-// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
815- g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value)
816- // Value-checking routine and storing ra in stack
817- // check:
818- g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
819- g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
820- g_object[g_objpos++]=0x04420001; // bltzl v0,negative
821- g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
822- // negative:
823- g_object[g_objpos++]=0x04610003; // bgez v1,continue
824- g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
825- break_statement(); // (2 words)
826- // continue:
827- return 0;
828-}
829-
830-char* next_statement(){
831- // Return to address stored in 4($sp)
832- // while set $v0 to 8($sp) (see for_statement)
833- // Following assembly must be 4 words.
834- // If the number of words will be changed, link.c must be reviced for CONTINUE statement.
835- check_obj_space(4);
836- g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
837- g_object[g_objpos++]=0x03E00008; // jr ra
838- g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
839- g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
840- return 0;
841-}
842-
843-char* do_statement(){
844- char* err;
845- // Usage of stack:
846- // 4(sp): Address to return to in "DO" statement.
847- check_obj_space(3);
848- g_object[g_objpos++]=0x04130001;// bgezall zero,label1:
849- g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
850- // label1:
851- g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
852- if (nextCodeIs("WHILE ")) {
853- // DO WHILE
854- err=get_floatOrValue();
855- if (err) return err;
856- check_obj_space(2);
857- g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
858- g_object[g_objpos++]=0x00000000; // nop
859- return break_statement(); // (2 words)
860- // label2:
861-
862- } else if (nextCodeIs("UNTIL ")) {
863- // DO UNTIL
864- err=get_floatOrValue();
865- if (err) return err;
866- check_obj_space(2);
867- g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
868- g_object[g_objpos++]=0x00000000; // nop
869- return break_statement(); // (2 words)
870- // label2:
871- } else {
872- // DO statement without WHILE/UNTIL
873- return 0;
874- }
875-}
876-
877-char* loop_statement(){
878- char* err;
879- int opos;
880- opos=g_objpos;
881- if (nextCodeIs("WHILE ")) {
882- // LOOP WHILE
883- err=get_floatOrValue();
884- if (err) return err;
885- check_obj_space(1);
886- g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
887- } else if (nextCodeIs("UNTIL ")) {
888- // LOOP UNTIL
889- err=get_floatOrValue();
890- if (err) return err;
891- check_obj_space(1);
892- g_object[g_objpos++]=0x14400003; // bne v0,zero,label
893- } else {
894- // LOOP statement without WHILE/UNTIL
895- }
896- check_obj_space(4);
897- g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
898- g_object[g_objpos++]=0x03E00008; // jr ra
899- opos=g_objpos+1-opos;
900- g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement)
901- // label1:
902- g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
903- return 0;
904-}
905-
906-char* while_statement(){
907- char* err;
908- check_obj_space(3);
909- g_object[g_objpos++]=0x04130001; // bgezall zero,label1:
910- g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
911- // label1:
912- g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
913- err=get_floatOrValue();
914- if (err) return err;
915- check_obj_space(2);
916- g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
917- g_object[g_objpos++]=0x00000000; // nop
918- return break_statement(); // (2 words)
919- // label2:
920-}
921-
922-char* wend_statement(){
923- check_obj_space(4);
924- g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
925- g_object[g_objpos++]=0x03E00008; // jr ra
926- g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement)
927- // label1:
928- g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
929- return 0;
930-}
931-
932-char* param4_statement(enum libs lib){
933- // lib is either LIB_PALETTE or LIB_GPALETTE
934- // PALETTE N,R,G,B
935- char* err;
936- // Get N
937- err=get_value();
938- if (err) return err;
939- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
940- g_srcpos++;
941- check_obj_space(2);
942- g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
943- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
944- // Get R
945- err=get_value();
946- if (err) return err;
947- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
948- g_srcpos++;
949- check_obj_space(1);
950- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
951- // Get G
952- err=get_value();
953- if (err) return err;
954- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
955- g_srcpos++;
956- check_obj_space(1);
957- g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
958- // Get B
959- err=get_value();
960- if (err) return err;
961- call_lib_code(lib);
962- check_obj_space(1);
963- g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
964- return 0;
965-}
966-
967-char* param3_statement(enum libs lib){
968- char* err;
969- // Get 1st parameter
970- err=get_value();
971- if (err) return err;
972- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
973- g_srcpos++;
974- check_obj_space(2);
975- g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
976- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
977- // Get 2nd parameter
978- err=get_value();
979- if (err) return err;
980- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
981- g_srcpos++;
982- check_obj_space(1);
983- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
984- // Get 3rd parameter
985- err=get_value();
986- if (err) return err;
987- call_lib_code(lib);
988- check_obj_space(1);
989- g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
990- return 0;
991-}
992-
993-char* bgcolor_statement(){
994- // BGCOLOR R,G,B
995- return param3_statement(LIB_BGCOLOR);
996-}
997-
998-char* pcg_statement(){
999- // PCG ASCII,D1,D2
1000- return param3_statement(LIB_PCG);
1001-}
1002-
1003-char* usepcg_statement(){
1004- int objpos=g_objpos;
1005- if (get_value()) {
1006- // Getting integer failed.
1007- // It supporsed to be not parameter
1008- // and same as parameter=1.
1009- g_objpos=objpos;
1010- check_obj_space(1);
1011- g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1012- }
1013- call_lib_code(LIB_USEPCG);
1014- return 0;
1015-}
1016-
1017-char* usegraphic_statement(){
1018- int objpos=g_objpos;
1019- if (get_value()) {
1020- // Getting integer failed.
1021- // It supporsed to be not parameter
1022- // and same as parameter=1.
1023- g_objpos=objpos;
1024- check_obj_space(1);
1025- g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1026- }
1027- call_lib_code(LIB_USEGRAPHIC);
1028- return 0;
1029-}
1030-
1031-char* cls_statement(){
1032- call_lib_code(LIB_CLS);
1033- return 0;
1034-}
1035-
1036-char* gcls_statement(){
1037- call_lib_code(LIB_GCLS);
1038- return 0;
1039-}
1040-
1041-char* color_statement(){
1042- char* err;
1043- err=get_value();
1044- if (err) return err;
1045- call_lib_code(LIB_COLOR);
1046- return 0;
1047-}
1048-
1049-char* gcolor_statement(){
1050- char* err;
1051- err=get_value();
1052- if (err) return err;
1053- call_lib_code(LIB_GCOLOR);
1054- return 0;
1055-}
1056-
1057-char* param2_statement(enum libs lib){
1058- char* err;
1059- // Get 1st
1060- err=get_value();
1061- if (err) return err;
1062- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1063- g_srcpos++;
1064- check_obj_space(2);
1065- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1066- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1067- // Get 2nd
1068- err=get_value();
1069- if (err) return err;
1070- call_lib_code(lib);
1071- check_obj_space(1);
1072- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1073- return 0;
1074-}
1075-
1076-char* system_statement(){
1077- // SYSTEM X,Y
1078- char* err;
1079- // Get 1st
1080- err=get_value();
1081- if (err) return err;
1082- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1083- g_srcpos++;
1084- check_obj_space(2);
1085- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1086- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1087- // Get 2nd
1088- err=get_value();
1089- if (err) return err;
1090- check_obj_space(2);
1091- g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1092- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1093- call_lib_code(LIB_SYSTEM);
1094- return 0;
1095-}
1096-
1097-char* cursor_statement(){
1098- // CURSOR X,Y
1099- return param2_statement(LIB_CURSOR);
1100-}
1101-
1102-char* scroll_statement(){
1103- // SCROLL X,Y
1104- return param2_statement(LIB_SCROLL);
1105-}
1106-
1107-char* drawcount_statement(){
1108- char* err;
1109- err=get_value();
1110- if (err) return err;
1111- call_lib_code(LIB_SETDRAWCOUNT);
1112- return 0;
1113-}
1114-
1115-char* wait_statement(){
1116- char* err;
1117- err=get_value();
1118- if (err) return err;
1119- call_lib_code(LIB_WAIT);
1120- return 0;
1121-}
1122-
1123-char* width_statement(){
1124- char* err;
1125- err=get_value();
1126- if (err) return err;
1127- call_lib_code(LIB_WIDTH);
1128- return 0;
1129-}
1130-
1131-char* var_statement_sub(int a0, int a1){
1132- // Construct parameter-setting scripts
1133- if (a0&0xffff0000) {
1134- check_obj_space(1);
1135- g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX
1136- if (a0&0x0000ffff) {
1137- check_obj_space(1);
1138- g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX
1139- }
1140- } else if (a0&0x0000ffff) {
1141- check_obj_space(1);
1142- g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx
1143- }
1144- if (a1&0xffff0000) {
1145- check_obj_space(1);
1146- g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX
1147- if (a1&0x0000ffff) {
1148- check_obj_space(1);
1149- g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX
1150- }
1151- } else if (a1&0x0000ffff) {
1152- check_obj_space(1);
1153- g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx
1154- } else if (a0&0xff000000) {
1155- // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store.
1156- check_obj_space(1);
1157- g_object[g_objpos++]=0x34050000; // ori a1,zero,0
1158- }
1159- return 0;
1160-}
1161-
1162-char* var_statement(){
1163- char* err;
1164- int i,j,a0,a1;
1165- static int prevpos;
1166- short stack;
1167- do {
1168- // For stack, 4 bytes are used for return address,
1169- // 4 bytes are used in lib_var(),
1170- // and additinal bytes are used for storing variable values.
1171- stack=8;
1172- a0=a1=0;
1173- for (i=0;i<8;i++){
1174- // Determine the variable number from source code
1175- j=get_var_number();
1176- if (j<0) return ERR_SYNTAX;
1177- stack+=4;
1178- // Create parameters in $a0, or $a1
1179- if (i<4) {
1180- a0=(a0<<8)|(j+1);
1181- } else {
1182- a1=(a1<<8)|(j+1);
1183- }
1184- // Check remaining variable(s)
1185- if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1186- next_position();
1187- if (g_source[g_srcpos]!=',') break;
1188- g_srcpos++;
1189- }
1190- // Jump to push routine, first
1191- check_obj_space(2);
1192- prevpos=g_objpos;
1193- g_object[g_objpos++]=0x04130000; // bgezall zero,label1
1194- g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1195- // Process will be here after RETURN statement
1196- // Pop routine
1197- err=var_statement_sub(a0,a1); // Prepare a0, and a1
1198- if (err) return err;
1199- call_lib_code(LIB_VAR_POP);
1200- // Restore stack and return
1201- check_obj_space(3);
1202- g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1203- g_object[g_objpos++]=0x00600008; // jr v1
1204- g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1205- // Push rotine
1206- g_object[prevpos]|=g_objpos-prevpos-1; // label1:
1207- check_obj_space(1);
1208- g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1209- err=var_statement_sub(a0,a1); // Prepare a0, and a1
1210- if (err) return err;
1211- call_lib_code(LIB_VAR_PUSH);
1212-
1213- } while (g_source[g_srcpos-1]==',');
1214- return 0;
1215-}
1216-
1217-
1218-char* graphic_statement(enum functions func){
1219- /*
1220- PSET X1,Y1[,C]
1221- LINE X1,Y1,X2,Y2[,C]
1222- BOXFILL X1,Y1,X2,Y2[,C]
1223- CIRCLE X1,Y1,R[,C]
1224- CIRCLEFILL X1,Y1,R[,C]
1225- GPRINT X1,Y1,C,BC,S$
1226- PUTBMP X1,Y1,M,N,BMP
1227- 4(sp): X1
1228- 8(sp): Y1
1229- 12(sp): X2/R/M
1230- 16(sp): Y2/N
1231- v0: C/S$/BMP
1232- */
1233- char* err;
1234- int spos;
1235- int paramnum;
1236- switch(func){
1237- case FUNC_PSET:// X1,Y1[,C]
1238- case FUNC_GCOLOR:// X1,Y1
1239- case FUNC_POINT:// X1,Y1
1240- paramnum=2;
1241- break;
1242- case FUNC_CIRCLE:// X1,Y1,R[,C]
1243- case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1244- paramnum=3;
1245- break;
1246- case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1247- case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1248- paramnum=4;
1249- break;
1250- case FUNC_GPRINT:// X1,Y1,C,BC,S$
1251- case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1252- paramnum=5;
1253- break;
1254- default:
1255- return ERR_UNKNOWN;
1256- }
1257-
1258- next_position();
1259- if (g_source[g_srcpos]==',') {
1260- // X1 and Y1 is omitted. Set 0x80000000 for both.
1261- check_obj_space(4);
1262- g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1263- g_object[g_objpos++]=0x3C028000; // lui v0,0x0080
1264- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1265- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1266- } else {
1267- // X1
1268- err=get_value();
1269- if (err) return err;
1270- check_obj_space(2);
1271- g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1272- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1273- // Y1
1274- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1275- g_srcpos++;
1276- err=get_value();
1277- if (err) return err;
1278- check_obj_space(1);
1279- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1280- }
1281- if (2<paramnum) {
1282- // X2, R, or M
1283- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1284- g_srcpos++;
1285- err=get_value();
1286- if (err) return err;
1287- check_obj_space(1);
1288- g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
1289- if (3<paramnum) {
1290- // Y2, BC, or N
1291- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1292- g_srcpos++;
1293- err=get_value();
1294- if (err) return err;
1295- check_obj_space(1);
1296- g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
1297- }
1298- }
1299- if (func==FUNC_GPRINT) {
1300- // S$
1301- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1302- g_srcpos++;
1303- err=get_string();
1304- if (err) return err;
1305- } else if (func==FUNC_PUTBMP) {
1306- // BMP
1307- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1308- g_srcpos++;
1309- spos=g_srcpos;
1310- err=get_label();
1311- if (g_label && !err) {
1312- if (search_var_name(g_label)!=-1) {
1313- // This is a long var name.
1314- g_label=0;
1315- g_srcpos=spos;
1316- }
1317- }
1318- if (g_label && !err) {
1319- // Label/number is constant.
1320- // Linker will change following codes later.
1321- // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1322- check_obj_space(2);
1323- g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1324- g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1325- // Change func to FUNC_PUTBMP2 (label mode).
1326- func=FUNC_PUTBMP2;
1327- } else {
1328- err=get_value();
1329- if (err) return err;
1330- }
1331- } else {
1332- // [,C]
1333- if (g_source[g_srcpos]==',') {
1334- g_srcpos++;
1335- err=get_value();
1336- if (err) return err;
1337- } else {
1338- // If C is omitted, use -1.
1339- check_obj_space(1);
1340- g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1341- }
1342- }
1343- // Call library
1344- call_lib_code(LIB_GRAPHIC | func);
1345- // Restore stack pointer
1346- check_obj_space(1);
1347- g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16
1348- return 0;
1349-}
1350-
1351-char* fopen_statement_main(enum functions func){
1352- // func is either FUNC_FOPENST or FUNC_FOPEN
1353- char* err;
1354- // Get 1st
1355- err=get_string();
1356- if (err) return err;
1357- if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1358- g_srcpos++;
1359- check_obj_space(2);
1360- g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1361- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1362- // Get 2nd
1363- err=get_string();
1364- if (err) return err;
1365- check_obj_space(1);
1366- g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1367- // Get 3rd
1368- if (g_source[g_srcpos]==',') {
1369- g_srcpos++;
1370- err=get_value();
1371- if (err) return err;
1372- } else {
1373- // If 3rd parameter is omitted, use 0.
1374- check_obj_space(1);
1375- g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1376- }
1377- call_lib_code(LIB_FILE | func);
1378- check_obj_space(1);
1379- g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1380- return 0;
1381-}
1382-
1383-char* file_statement(){
1384- char* err;
1385- err=get_value();
1386- if (err) return err;
1387- call_lib_code(LIB_FILE | FUNC_FILE);
1388- return 0;
1389-}
1390-
1391-char* fclose_statement(){
1392- char* err;
1393- int orgpos=g_srcpos;
1394- if (endOfStatement()) {
1395- // If no argument, use 0
1396- check_obj_space(1);
1397- g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1398- } else {
1399- err=get_value();
1400- if (err) return err;
1401- }
1402- call_lib_code(LIB_FILE | FUNC_FCLOSE);
1403- return 0;
1404-}
1405-
1406-char* fget_statement(){
1407- return param2_statement(LIB_FILE | FUNC_FGET);
1408-}
1409-
1410-char* fput_statement(){
1411- return param2_statement(LIB_FILE | FUNC_FPUT);
1412-}
1413-
1414-char* fseek_statement(){
1415- char* err;
1416- err=get_value();
1417- if (err) return err;
1418- call_lib_code(LIB_FILE | FUNC_FSEEK);
1419- return 0;
1420-}
1421-
1422-char* fputc_statement(){
1423- char* err;
1424- err=get_value();
1425- if (err) return err;
1426- call_lib_code(LIB_FILE | FUNC_FPUTC);
1427- return 0;
1428-}
1429-
1430-char* fremove_statement(){
1431- char* err;
1432- err=get_string();
1433- if (err) return err;
1434- call_lib_code(LIB_FILE | FUNC_FREMOVE);
1435- return 0;
1436-}
1437-
1438-char* usevar_statement(){
1439- char* err;
1440- int i;
1441- do {
1442- next_position();
1443- i=check_var_name();
1444- if (i<65536) return ERR_SYNTAX;
1445- err=register_var_name(i);
1446- if (err) return err;
1447- if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1448- next_position();
1449- if (g_source[g_srcpos]==',') {
1450- g_srcpos++;
1451- } else {
1452- break;
1453- }
1454- } while(1);
1455- return 0;
1456-}
1457-
1458-char* playwave_statement(){
1459- char* err;
1460- err=get_string();
1461- if (err) return err;
1462- check_obj_space(2);
1463- g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1464- g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1465- if (g_source[g_srcpos]==',') {
1466- g_srcpos++;
1467- // Get 2nd
1468- err=get_value();
1469- if (err) return err;
1470- } else {
1471- // If 2rd parameter is omitted, use 0.
1472- check_obj_space(1);
1473- g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1474- }
1475- call_lib_code(LIB_PLAYWAVE);
1476- check_obj_space(1);
1477- g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1478- return 0;
1479-}
1480-
1481-#ifdef __DEBUG
1482- char* debug_statement(){
1483- call_lib_code(LIB_DEBUG);
1484- return 0;
1485- }
1486-#endif
1487-
1488-// Aliases follow
1489-
1490-char* palette_statement(){
1491- return param4_statement(LIB_PALETTE);
1492-}
1493-
1494-char* gpalette_statement(){
1495- return param4_statement(LIB_GPALETTE);
1496-}
1497-
1498-char* print_statement(){
1499- return print_statement_main(LIB_PRINTSTR,LIB_STRING);
1500-}
1501-
1502-char* pset_statement(){
1503- return graphic_statement(FUNC_PSET);
1504-}
1505-
1506-char* line_statement(){
1507- return graphic_statement(FUNC_LINE);
1508-}
1509-
1510-char* boxfill_statement(){
1511- return graphic_statement(FUNC_BOXFILL);
1512-}
1513-
1514-char* circle_statement(){
1515- return graphic_statement(FUNC_CIRCLE);
1516-}
1517-
1518-char* circlefill_statement(){
1519- return graphic_statement(FUNC_CIRCLEFILL);
1520-}
1521-
1522-char* gprint_statement(){
1523- return graphic_statement(FUNC_GPRINT);
1524-}
1525-
1526-char* putbmp_statement(){
1527- return graphic_statement(FUNC_PUTBMP);
1528-}
1529-
1530-char* point_statement(){
1531- return graphic_statement(FUNC_POINT);
1532-}
1533-
1534-char* fopen_statement(){
1535- return fopen_statement_main(FUNC_FOPENST);
1536-}
1537-
1538-char* fprint_statement(){
1539- return print_statement_main(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING);
1540-}
1541-
1542-static const void* statement_list[]={
1543- "REM",rem_statement,
1544- "SOUND ",sound_statement,
1545- "MUSIC ",music_statement,
1546- "DRAWCOUNT ",drawcount_statement,
1547- "CURSOR ",cursor_statement,
1548- "PALETTE ",palette_statement,
1549- "GPALETTE ",gpalette_statement,
1550- "BGCOLOR ",bgcolor_statement,
1551- "CLS",cls_statement,
1552- "GCLS",gcls_statement,
1553- "COLOR ",color_statement,
1554- "GCOLOR ",gcolor_statement,
1555- "RESTORE ",restore_statement,
1556- "DATA ",data_statement,
1557- "CDATA ",cdata_statement,
1558- "LABEL ",label_statement,
1559- "DIM ",dim_statement,
1560- "CLEAR",clear_statement,
1561- "PRINT",print_statement,
1562- "IF ",if_statement,
1563- "ELSEIF ",elseif_statement,
1564- "ELSE",else_statement,
1565- "ENDIF",endif_statement,
1566- "END",end_statement,
1567- "EXEC ",exec_statement,
1568- "GOTO ",goto_statement,
1569- "GOSUB ",gosub_statement,
1570- "RETURN",return_statement,
1571- "POKE ",poke_statement,
1572- "FOR ",for_statement,
1573- "NEXT",next_statement,
1574- "LET ",let_statement,
1575- "PCG ",pcg_statement,
1576- "USEPCG",usepcg_statement,
1577- "SCROLL ",scroll_statement,
1578- "WAIT ",wait_statement,
1579- "USEGRAPHIC",usegraphic_statement,
1580- "PSET ",pset_statement,
1581- "LINE ",line_statement,
1582- "BOXFILL ",boxfill_statement,
1583- "CIRCLE ",circle_statement,
1584- "CIRCLEFILL ",circlefill_statement,
1585- "GPRINT ",gprint_statement,
1586- "PUTBMP ",putbmp_statement,
1587- "POINT ",point_statement,
1588- "VAR ",var_statement,
1589- "DO",do_statement,
1590- "LOOP",loop_statement,
1591- "WHILE ",while_statement,
1592- "WEND",wend_statement,
1593- "BREAK",break_statement,
1594- "CONTINUE",continue_statement,
1595- "SYSTEM",system_statement,
1596- "WIDTH ",width_statement,
1597- "FOPEN ",fopen_statement,
1598- "FILE ",file_statement,
1599- "FCLOSE",fclose_statement,
1600- "FPRINT ",fprint_statement,
1601- "FGET ",fget_statement,
1602- "FPUT ",fput_statement,
1603- "FPUTC ",fputc_statement,
1604- "FSEEK ",fseek_statement,
1605- "FREMOVE ",fremove_statement,
1606- "USEVAR ",usevar_statement,
1607- "PLAYWAVE ",playwave_statement,
1608- // List of additional statements follows
1609- ADDITIONAL_STATEMENTS
1610-};
1611-
1612-char* statement(void){
1613- char* err;
1614- int prevpos;
1615- int i;
1616- char* (*f)();
1617- // Clear flag for temp area usage.
1618- g_temp_area_used=0;
1619- // Initialize stack handler used for value
1620- g_sdepth=g_maxsdepth=0;
1621- // Seek the statement
1622- for (i=0;i<sizeof(statement_list)/sizeof(statement_list[0]);i+=2){
1623- if (nextCodeIs((char*)statement_list[i])) break;
1624- }
1625- if (i<sizeof(statement_list)/sizeof(statement_list[0])) {
1626- // Statement found. Call it.
1627- f=statement_list[i+1];
1628- err=f();
1629-#ifdef __DEBUG
1630- } else if (nextCodeIs("DEBUG")) {
1631- err=debug_statement();
1632-#endif
1633- } else {
1634- err=let_statement();
1635- }
1636- if (err) return err;
1637- // Stack handler must be zero here.
1638- if (g_sdepth!=0) return ERR_UNKNOWN;
1639- // Check if temp area is used
1640- if (g_temp_area_used) {
1641- // Temp area is used. Insert a garbage collection flag setting routine.
1642- check_obj_space(1);
1643- g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1644- }
1645- return 0;
1646-}
1+/*
2+ This file is provided under the LGPL license ver 2.1.
3+ Written by Katsumi.
4+ http://hp.vector.co.jp/authors/VA016157/
5+ kmorimatsu@users.sourceforge.jp
6+*/
7+
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+#include "api.h"
13+#include "compiler.h"
14+
15+char* rem_statement(){
16+ if (g_source[g_srcpos-4]<0x20) {
17+ // This line contains only "REM" statement
18+ // Delete $s6-setting command if exists.
19+ if ((g_object[g_objpos-1]&0xffff0000)==0x34160000) g_objpos--;
20+ }
21+ while(0xE0 & g_source[g_srcpos]){
22+ g_srcpos++;
23+ }
24+ return 0;
25+}
26+
27+char* sound_statement(){
28+ char *err;
29+ err=get_label();
30+ if (err) return err;
31+ if (g_label) {
32+ // Label/number is constant.
33+ // Linker will change following codes later.
34+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
35+ check_obj_space(2);
36+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
37+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
38+ } else {
39+ // Label/number will be dynamically set when executing code.
40+ err=get_value();
41+ if (err) return err;
42+ call_lib_code(LIB_LABEL);
43+ }
44+ // 2nd param is optional
45+ next_position();
46+ if (g_source[g_srcpos]==',') {
47+ g_srcpos++;
48+ check_obj_space(2);
49+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
50+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
51+ err=get_value();
52+ if (err) return err;
53+ check_obj_space(3);
54+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
55+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
56+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
57+ } else {
58+ // Set 3 if omitted
59+ check_obj_space(1);
60+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
61+ }
62+ call_lib_code(LIB_SOUND);
63+ return 0;
64+}
65+char* music_statement(){
66+ char *err;
67+ err=get_string();
68+ if (err) return err;
69+ // 2nd param is optional
70+ next_position();
71+ if (g_source[g_srcpos]==',') {
72+ g_srcpos++;
73+ check_obj_space(2);
74+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
75+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
76+ err=get_value();
77+ if (err) return err;
78+ check_obj_space(3);
79+ g_object[g_objpos++]=0x00402021; // addu a0,v0,zero
80+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
81+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
82+ } else {
83+ // Set 3 if omitted
84+ check_obj_space(1);
85+ g_object[g_objpos++]=0x24040003; // addiu a0,zero,xx
86+ }
87+ call_lib_code(LIB_MUSIC);
88+ return 0;
89+}
90+
91+char* exec_statement(){
92+ char *err;
93+ char b1;
94+ int i,prevpos;
95+ b1=g_source[g_srcpos];
96+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
97+ prevpos=g_objpos;
98+ g_valueisconst=1;
99+ err=get_simple_value();
100+ if (!g_valueisconst) err=ERR_SYNTAX;
101+ if (err) return err;
102+ check_obj_space(1);
103+ g_objpos=prevpos;
104+ g_object[g_objpos++]=g_intconst;
105+ next_position();
106+ b1=g_source[g_srcpos];
107+ if (b1!=',') break;
108+ g_srcpos++;
109+ next_position();
110+ b1=g_source[g_srcpos];
111+ if (b1==0x0d || b1==0x0a) {
112+ // Multiline DATA/EXEC statement
113+ g_line++;
114+ g_fileline++;
115+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
116+ g_srcpos++;
117+ // Maintain at least 256 characters in cache.
118+ if (256<=g_srcpos) read_file(256);
119+ next_position();
120+ b1=g_source[g_srcpos];
121+ }
122+ }
123+ return 0;
124+}
125+
126+char* cdata_statement(){
127+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
128+ // are the sign of data region
129+ int beginpos,prevpos;
130+ char* err;
131+ char b1;
132+ char* cpy;
133+ int shift=0;
134+ int i=0;
135+ // This statement is not valid in class file.
136+ if (g_compiling_class) return ERR_INVALID_CLASS;
137+ beginpos=g_objpos;
138+ check_obj_space(2);
139+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
140+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
141+ next_position();
142+ b1=g_source[g_srcpos];
143+ while('0'<=b1 && b1<='9' || b1=='-' || b1=='$'){
144+ prevpos=g_objpos;
145+ g_valueisconst=1;
146+ err=get_simple_value();
147+ if (!g_valueisconst) err=ERR_SYNTAX;
148+ if (g_intconst<0x00 || 0xff<g_intconst) err=ERR_SYNTAX;
149+ if (err) return err;
150+ g_objpos=prevpos;
151+ i|=g_intconst<<shift;
152+ shift+=8;
153+ if (32<=shift) {
154+ check_obj_space(1);
155+ g_object[g_objpos++]=i;
156+ shift=0;
157+ i=0;
158+ }
159+ next_position();
160+ b1=g_source[g_srcpos];
161+ if (b1!=',') break;
162+ g_srcpos++;
163+ next_position();
164+ b1=g_source[g_srcpos];
165+ if (b1==0x0d || b1==0x0a) {
166+ // Multiline CDATA statement
167+ g_line++;
168+ g_fileline++;
169+ if (b1==0x0D && g_source[g_srcpos+1]==0x0A) g_srcpos++;
170+ g_srcpos++;
171+ // Maintain at least 256 characters in cache.
172+ if (256<=g_srcpos) read_file(256);
173+ next_position();
174+ b1=g_source[g_srcpos];
175+ }
176+ }
177+ // Write the last 1-3 bytes and shift data if total # is not multipes of 4.
178+ if (0<shift) {
179+ // Convert shift value from bit-shift to data byte-shift.
180+ shift=4-shift/8;
181+ check_obj_space(1);
182+ g_object[g_objpos++]=i;
183+ for(cpy=(char*)&g_object[g_objpos]-1;(char*)&g_object[beginpos+2]<cpy;cpy--){
184+ cpy[0]=cpy[0-shift];
185+ }
186+ }
187+ // Determine the size of data
188+ i=g_objpos-beginpos-1;
189+ g_object[beginpos] =0x04110000|i; // bgezal zero,xxxx
190+ g_object[beginpos+1]=0x00000020|shift; // add zero,zero,zero
191+ return 0;
192+}
193+
194+char* data_statement(){
195+ // 0x00000020, 0x00000021, 0x00000022, and 0x00000023 (add/addu/sub/subu zero,zero,zero)
196+ // are the sign of data region
197+ int i,prevpos;
198+ char* err;
199+ // This statement is not valid in class file.
200+ if (g_compiling_class) return ERR_INVALID_CLASS;
201+ while(1){
202+ prevpos=g_objpos;
203+ check_obj_space(2);
204+ g_object[g_objpos++]=0x04110000; // bgezal zero,xxxx
205+ g_object[g_objpos++]=0x00000020; // add zero,zero,zero
206+ next_position();
207+ if (g_source[g_srcpos]=='"') {
208+ // Constant string
209+ // Store pointer to string. This is 3 words bellow of current position
210+ g_object[g_objpos]=(int)(&g_object[g_objpos+3]);
211+ g_objpos++;
212+ g_object[prevpos]=0x04110002; // bgezal zero,xxxx
213+ err=simple_string();
214+ if (err) return err;
215+ next_position();
216+ if (g_source[g_srcpos]==',') {
217+ g_srcpos++;
218+ continue;
219+ }
220+ return 0;
221+ }
222+ err=exec_statement();
223+ if (err) return err;
224+ // Determine the size of data
225+ i=g_objpos-prevpos-1;
226+ g_object[prevpos]=0x04110000|i; // bgezal zero,xxxx
227+ if (g_source[g_srcpos]=='"') {
228+ // Constant string
229+ continue;
230+ }
231+ return 0;
232+ }
233+}
234+
235+char* clear_statement(){
236+ call_lib_code(LIB_CLEAR);
237+ return 0;
238+}
239+
240+char* poke_statement_sub(int bits){
241+ char* err;
242+ err=get_value();
243+ if (err) return err;
244+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
245+ g_srcpos++;
246+ check_obj_space(2);
247+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
248+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
249+ err=get_value();
250+ if (err) return err;
251+ check_obj_space(3);
252+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
253+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
254+ switch(bits){
255+ case 32:
256+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
257+ break;
258+ case 16:
259+ g_object[g_objpos++]=0xA4620000; // sh v0,0(v1)
260+ break;
261+ case 8:
262+ default:
263+ g_object[g_objpos++]=0xA0620000; // sb v0,0(v1)
264+ break;
265+ }
266+ return 0;
267+}
268+
269+char* dim_statement(){
270+ char* err;
271+ char b1;
272+ int i;
273+ int spos;
274+ int stack;
275+ while(1){
276+ stack=0;
277+ next_position();
278+ i=get_var_number();
279+ if (i<0) return ERR_SYNTAX;
280+ if (g_source[g_srcpos]=='#') g_srcpos++;
281+ next_position();
282+ if (g_source[g_srcpos]!='(') return ERR_SYNTAX;
283+ check_obj_space(1);
284+ spos=g_objpos++; // addiu sp,sp,xxxx
285+ do {
286+ g_srcpos++;
287+ err=get_value();
288+ if (err) return err;
289+ stack+=4;
290+ check_obj_space(1);
291+ g_object[g_objpos++]=0xAFA20000|stack; // sw v0,8(sp)
292+ } while (g_source[g_srcpos]==',');
293+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
294+ g_srcpos++;
295+ check_obj_space(3);
296+ g_object[g_objpos++]=0x24040000|(i); // addiu a0,zero,xx
297+ g_object[g_objpos++]=0x24050000|(stack/4); // addiu a1,zero,xxxx
298+ g_object[g_objpos++]=0x03A01025; // or v0,sp,zero
299+ call_lib_code(LIB_DIM);
300+ // Stack -/+
301+ check_obj_space(1);
302+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xxxx
303+ stack=(0-stack)&0x0000FFFF;
304+ g_object[spos]=0x27BD0000|stack; // addiu sp,sp,xxxx
305+ next_position();
306+ if (g_source[g_srcpos]!=',') break;
307+ g_srcpos++;
308+ }
309+ return 0;
310+}
311+
312+char* label_statement(){
313+ char* err;
314+ char b1;
315+ b1=g_source[g_srcpos];
316+ if (b1<'A' || 'Z'<b1) return ERR_SYNTAX; // Number is not allowed here.
317+ err=get_label();
318+ if (err) return err;
319+ // Check existing label with the same name here.
320+ if (search_label(g_label)) {
321+ // Error: duplicate labels
322+ printstr("Label ");
323+ printstr(resolve_label(g_label));
324+ return ERR_MULTIPLE_LABEL;
325+ }
326+ check_obj_space(2);
327+ g_object[g_objpos++]=0x3C160000|((g_label>>16)&0x0000FFFF); //lui s6,yyyy;
328+ g_object[g_objpos++]=0x36D60000|(g_label&0x0000FFFF); //ori s6,s6,zzzz;
329+ return 0;
330+}
331+
332+char* restore_statement(){
333+ char* err;
334+ // This statement is not valid in class file.
335+ if (g_compiling_class) return ERR_INVALID_CLASS;
336+ err=get_label();
337+ if (err) return err;
338+ if (g_label) {
339+ // Constant label/number
340+ // Use 32 bit mode also for values<65536
341+ // This code will be replaced to code for v0 for pointer in linker.
342+ check_obj_space(2);
343+ g_object[g_objpos++]=0x3C020000|(g_label>>16); // lui v0,xxxx
344+ g_object[g_objpos++]=0x34420000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
345+ } else {
346+ // Dynamic number
347+ err=get_value();
348+ if (err) return err;
349+ }
350+ call_lib_code(LIB_RESTORE);
351+ return 0;
352+}
353+
354+char* gosub_statement_sub(){
355+ char* err;
356+ err=get_label();
357+ if (err) return err;
358+ if (g_label) {
359+ // Label/number is constant.
360+ // Linker will change following codes later.
361+ // Note that 0x0812xxxx and 0x0813xxxx are specific codes for these.
362+ check_obj_space(7);
363+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
364+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
365+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
366+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
367+ g_object[g_objpos++]=0x08120000|((g_label>>16)&0x0000FFFF); // nop
368+ // label1:
369+ g_object[g_objpos++]=0x08130000|(g_label&0x0000FFFF); // j xxxx
370+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
371+ // label2:
372+ } else {
373+ // Label/number will be dynamically set when executing code.
374+ err=get_value();
375+ if (err) return err;
376+ call_lib_code(LIB_LABEL);
377+ check_obj_space(7);
378+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
379+ g_object[g_objpos++]=0x04130003; // bgezall zero,label1
380+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
381+ g_object[g_objpos++]=0x10000003; // beq zero,zero,label2
382+ g_object[g_objpos++]=0x00000000; // nop
383+ // label1:
384+ g_object[g_objpos++]=0x00400008; // jr v0
385+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
386+ // label2:
387+ }
388+ return 0;
389+}
390+
391+char* gosub_statement(){
392+ char* err;
393+ int opos,spos,stack;
394+ // Skip label first (see below)
395+ opos=g_objpos;
396+ spos=g_srcpos;
397+ err=gosub_statement_sub();
398+ if (err) return err;
399+ next_position();
400+ // Rewind object and construct argument-creating routine.
401+ g_objpos=opos;
402+ // Begin parameter(s) construction routine
403+ g_object[g_objpos++]=0x8EA20000|ARGS_S5_V0_OBJ; // lw v0,-8(s5)
404+ err=prepare_args_stack(',');
405+ if (err) return err;
406+ // Rewind source and construct GOSUB routine again.
407+ opos=spos;
408+ spos=g_srcpos;
409+ g_srcpos=opos;
410+ err=gosub_statement_sub();
411+ if (err) return err;
412+ // Remove stack
413+ err=remove_args_stack();
414+ if (err) return err;
415+ // All done, go back to right source position
416+ g_srcpos=spos;
417+ return 0;
418+}
419+
420+char* return_statement(){
421+ char* err;
422+ char b1;
423+ next_position();
424+ b1=g_source[g_srcpos];
425+ if (0x20<b1 && b1!=':') {
426+ // There is a return value.
427+ err=get_stringFloatOrValue();
428+ if (err) return err;
429+ }
430+ check_obj_space(4);
431+ g_object[g_objpos++]=0x8EBD0000|ARGS_S5_SP; // lw sp,-12(s5)
432+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
433+ g_object[g_objpos++]=0x00600008; // jr v1
434+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
435+ return 0;
436+}
437+
438+char* goto_statement(){
439+ char* err;
440+ err=get_label();
441+ if (err) return err;
442+ if (g_label) {
443+ // Label/number is constant.
444+ // Linker will change following codes later.
445+ // Note that 0x0810xxxx and 0x0811xxxx are specific codes for these.
446+ check_obj_space(2);
447+ g_object[g_objpos++]=0x08100000|((g_label>>16)&0x0000FFFF); // j xxxx
448+ g_object[g_objpos++]=0x08110000|(g_label&0x0000FFFF); // nop
449+ } else {
450+ // Label/number will be dynamically set when executing code.
451+ err=get_value();
452+ if (err) return err;
453+ call_lib_code(LIB_LABEL);
454+ check_obj_space(2);
455+ g_object[g_objpos++]=0x00400008; // jr v0
456+ g_object[g_objpos++]=0x00000000; // nop
457+ }
458+ return 0;
459+}
460+
461+char* if_statement(){
462+ char* err;
463+ int prevpos,bpos;
464+ // Get value.
465+ err=get_floatOrValue();
466+ if (err) return err;
467+ // Check "THEN"
468+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
469+ // Check if statement follows after THEN statement
470+ next_position();
471+ if (nextCodeIs("REM")) {
472+ // If REM statement follows, skip comment words.
473+ rem_statement();
474+ }
475+ if (g_source[g_srcpos]<0x20) {
476+ // End of line.
477+ // Use IF-THEN-ENDIF mode (multiple line mode)
478+ check_obj_space(3);
479+ g_object[g_objpos++]=0x30000000; // nop (see linker)
480+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
481+ g_object[g_objpos++]=0x30000000; // nop (see linker)
482+ return 0;
483+ }
484+ // One line mode
485+ // If $v0=0 then skip.
486+ bpos=g_objpos;
487+ check_obj_space(2);
488+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
489+ g_object[g_objpos++]=0x00000000; // nop
490+ prevpos=g_srcpos;
491+ if (statement()) {
492+ // May be label
493+ g_srcpos=prevpos;
494+ err=goto_statement();
495+ if (err) return err;
496+ } else {
497+ // Must be statement(s)
498+ while(1) {
499+ if (g_source[g_srcpos]!=':') break;
500+ g_srcpos++;
501+ err=statement();
502+ if (err) return err;
503+ }
504+ }
505+ // Check if "ELSE" exists.
506+ if (!nextCodeIs("ELSE ")) {
507+ // "ELSE" not found. This is the end of "IF" statement.
508+ // Previous branch command must jump to this position.
509+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
510+ return 0;
511+ }
512+ // Skip after ELSE if required.
513+ check_obj_space(2);
514+ g_object[g_objpos++]=0x10000000; // beq zero,zero,xxxx
515+ g_object[g_objpos++]=0x00000000; // nop
516+ // Previous branch command must jump to this position.
517+ g_object[bpos]=0x10400000|(g_objpos-bpos-1); // beq v0,zero,xxxx
518+ bpos=g_objpos-2;
519+ // Next statement is either label or general statement
520+ prevpos=g_srcpos;
521+ if (statement()) {
522+ // May be label
523+ g_srcpos=prevpos;
524+ err=goto_statement();
525+ if (err) return err;
526+ } else {
527+ // Must be statement(s)
528+ while(1) {
529+ if (g_source[g_srcpos]!=':') break;
530+ g_srcpos++;
531+ err=statement();
532+ if (err) return err;
533+ }
534+ }
535+ // Previous branch command must jump to this position.
536+ g_object[bpos]=0x10000000|(g_objpos-bpos-1); // beq zero,zero,xxxx
537+ return 0;
538+}
539+
540+char* elseif_statement(void){
541+ // Multiple line mode
542+ char* err;
543+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
544+ g_object[g_objpos++]=0x30008000; // nop (see linker)
545+ // Get value.
546+ err=get_floatOrValue();
547+ if (err) return err;
548+ // Check "THEN"
549+ if (!nextCodeIs("THEN")) return ERR_SYNTAX;
550+ // Check if statement follows after THEN statement
551+ if (nextCodeIs("REM")) {
552+ // If REM statement follows, skip comment words.
553+ rem_statement();
554+ }
555+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
556+ // Statement didn't follow after THEM statement (that is correct).
557+ g_object[g_objpos++]=0x10400000; // beq v0,zero,xxxx
558+ g_object[g_objpos++]=0x30000000; // nop (see linker)
559+ return 0;
560+
561+}
562+
563+char* else_statement(void){
564+ // Multiple line mode
565+ g_object[g_objpos++]=0x08160100; // breakif (see linker)
566+ g_object[g_objpos++]=0x30008000; // nop (see linker)
567+ g_object[g_objpos++]=0x30000000; // nop (see linker)
568+ // Check if statement follows after THEN statement
569+ if (nextCodeIs("REM")) {
570+ // If REM statement follows, skip comment words.
571+ rem_statement();
572+ }
573+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
574+ // Statement didn't follow after THEM statement (that is correct).
575+ return 0;
576+}
577+
578+char* endif_statement(void){
579+ // Multiple line mode
580+ g_object[g_objpos++]=0x30008000; // nop (see linker)
581+ g_object[g_objpos++]=0x30008000; // nop (see linker)
582+ // Check if statement follows after THEN statement
583+ if (nextCodeIs("REM")) {
584+ // If REM statement follows, skip comment words.
585+ rem_statement();
586+ }
587+ if (0x20<=g_source[g_srcpos]) return ERR_SYNTAX;
588+ // Statement didn't follow after THEM statement (that is correct).
589+ return 0;
590+}
591+
592+char* end_statement(void){
593+ int i;
594+ i=(int)&g_end_addr;
595+ i-=g_gp;
596+ check_obj_space(3);
597+ g_object[g_objpos++]=0x8F820000|(i&0x0000FFFF); // lw v0,xxxx(gp)
598+ g_object[g_objpos++]=0x00400008; // jr v0
599+ g_object[g_objpos++]=0x00000000; // nop
600+ return 0;
601+}
602+
603+char* let_dim_sub(int i){
604+ char* err;
605+ g_srcpos++;
606+ err=get_value();
607+ if (err) return err;
608+ check_obj_space(4);
609+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
610+ g_object[g_objpos++]=0x8FC30000|(i*4); // lw v1,xx(s8)
611+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
612+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
613+ while(g_source[g_srcpos]==','){
614+ g_srcpos++;
615+ err=get_value();
616+ if (err) return err;
617+ check_obj_space(4);
618+ g_object[g_objpos++]=0x00021080; // sll v0,v0,0x2
619+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
620+ g_object[g_objpos++]=0x8C630000; // lw v1,0(v1)
621+ g_object[g_objpos++]=0x00621821; // addu v1,v1,v0
622+ g_object[g_objpos++]=0xAFA30004; // sw v1,4(sp)
623+ }
624+ if (g_source[g_srcpos]!=')') return ERR_SYNTAX;
625+ g_srcpos++;
626+ return 0;
627+};
628+
629+char* let_statement(){
630+ char* err;
631+ char b2,b3;
632+ int i,spos,opos;
633+ next_position();
634+ i=get_var_number();
635+ if (i<0) return ERR_SYNTAX;
636+ b2=g_source[g_srcpos];
637+ b3=g_source[g_srcpos+1];
638+ if (b2=='#' && b3=='(') {
639+ // Float dimension
640+ g_srcpos++;
641+ check_obj_space(1);
642+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
643+ let_dim_sub(i);
644+ next_position();
645+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
646+ g_srcpos++;
647+ err=get_float();
648+ if (err) return err;
649+ check_obj_space(3);
650+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
651+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
652+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
653+ return 0;
654+ } else if (b2=='#') {
655+ // Float A-Z
656+ g_srcpos++;
657+ next_position();
658+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
659+ g_srcpos++;
660+ err=get_float();
661+ if (err) return err;
662+ check_obj_space(1);
663+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
664+ return 0;
665+ } else if (b2=='$') {
666+ // String
667+ g_srcpos++;
668+ next_position();
669+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
670+ g_srcpos++;
671+ err=get_string();
672+ if (err) return err;
673+ check_obj_space(1);
674+ g_object[g_objpos++]=0x24040000|(i); //addiu a0,zero,xx
675+ call_lib_code(LIB_LETSTR);
676+ return 0;
677+ } else if (b2=='(') {
678+ // Dimension
679+ check_obj_space(1);
680+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
681+ let_dim_sub(i);
682+ if (g_source[g_srcpos]=='.') {
683+ // This is an object. Determine the filed of this object.
684+ // 4(sp) contains the address of dimension value
685+ // The dimension value is the pointer to object
686+ g_srcpos++;
687+ check_obj_space(3);
688+ g_object[g_objpos++]=0x8FA20004; // lw v0,4(sp)
689+ g_object[g_objpos++]=0x8C420000; // lw v0,0(v0) + g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
690+ return let_object_field();
691+ }
692+ next_position();
693+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
694+ g_srcpos++;
695+ err=get_value();
696+ if (err) return err;
697+ check_obj_space(3);
698+ g_object[g_objpos++]=0x8FA30004; // lw v1,4(sp)
699+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
700+ g_object[g_objpos++]=0xAC620000; // sw v0,0(v1)
701+ return 0;
702+ } else if (b2=='.') {
703+ // Field of object
704+ g_srcpos++;
705+ check_obj_space(1);
706+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
707+ return let_object_field();
708+ } else {
709+ // Integer A-Z
710+ next_position();
711+ if (g_source[g_srcpos]!='=') return ERR_SYNTAX;
712+ g_srcpos++;
713+ err=get_value();
714+ if (err) return err;
715+ check_obj_space(1);
716+ g_object[g_objpos++]=0xAFC20000|(i*4); // sw v0,xxx(s8)
717+ }
718+ return 0;
719+}
720+
721+char* print_statement_main(enum libs lib_printstr, enum libs lib_string){
722+ char* err;
723+ char b1;
724+ int i;
725+ int status=0;// 1:',' 2:';' 0:none
726+ while(1){
727+ next_position();
728+ if (endOfStatement()) break;
729+ if (!strncmp(g_source+g_srcpos,"ELSE " ,5)) break;
730+ err=get_stringFloatOrValue();
731+ if (err) return err;
732+ switch(g_lastvar){
733+ case VAR_INTEGER:
734+ // Use DEC$() function.
735+ call_lib_code(LIB_DEC);
736+ break;
737+ case VAR_FLOAT:
738+ // Use FLOAT$() function.
739+ check_obj_space(2);
740+ g_object[g_objpos++]=0x00022021; //addu a0,zero,v0
741+ g_object[g_objpos++]=0x34020000; //ori v0,zero,0x0000
742+ call_lib_code(LIB_SPRINTF);
743+ break;
744+ case VAR_STRING:
745+ default:
746+ break;
747+ }
748+ // Call printstr() function
749+ // First argument is the pointer to string
750+ call_lib_code(lib_printstr);
751+ next_position();
752+ b1=g_source[g_srcpos];
753+ if (b1==',') {
754+ status=1;
755+ g_srcpos++;
756+ // Call lib_string() function for comma (,)
757+ check_obj_space(1);
758+ g_object[g_objpos++]=0x34020001; // ori v0,zero,1
759+ call_lib_code(lib_string);
760+ } else if (b1==';') {
761+ status=2;
762+ g_srcpos++;
763+ } else {
764+ status=0;
765+ }
766+ }
767+ if (status==0) {
768+ // Call lib_string() function for CR (\n)
769+ check_obj_space(1);
770+ g_object[g_objpos++]=0x34020000; // ori v0,zero,0
771+ call_lib_code(lib_string);
772+ }
773+ return 0;
774+}
775+
776+char* break_statement(){
777+ check_obj_space(2);
778+ g_object[g_objpos++]=0x08160000; // j xxxx (See link() function)
779+ g_object[g_objpos++]=0x00000000; // nop
780+ return 0;
781+}
782+
783+char* continue_statement(){
784+ check_obj_space(2);
785+ g_object[g_objpos++]=0x08160008; // j xxxx (See link() function)
786+ g_object[g_objpos++]=0x00000000; // nop
787+ return 0;
788+}
789+
790+char* for_statement(){
791+ char* err;
792+// char b1;
793+ int i;
794+ int prepos=g_srcpos;
795+ // Initialization of variable
796+// next_position();
797+// b1=g_source[g_srcpos];
798+ i=get_var_number();
799+// if (b1<'A' || 'Z'<b1) return ERR_SYNTAX;
800+ if (i<0) return ERR_SYNTAX;
801+ g_srcpos=prepos;
802+ err=let_statement();
803+ if (err) return err;
804+ // Check if "TO" exists
805+ if (!nextCodeIs("TO ")) return ERR_SYNTAX;
806+ err=get_value();
807+ if (err) return err;
808+ // Usage of stack:
809+ // 12(sp): "TO" value
810+ // 8(sp): "STEP" value
811+ // 4(sp): Address to return to in "NEXT" statement.
812+ // Store "TO" value in stack
813+ check_obj_space(2);
814+ g_object[g_objpos++]=0x0820FFF4; // addiu sp,sp,-12 (see linker)
815+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
816+ // Check if "STEP" exists
817+ g_valueisconst=1;
818+ if (nextCodeIs("STEP ")) {
819+ // "STEP" exists. Get value
820+ err=get_value();
821+ if (err) return err;
822+ } else {
823+ // "STEP" not exist. Use "1".
824+ check_obj_space(1);
825+ g_object[g_objpos++]=0x24020001; // addiu v0,zero,1
826+ g_intconst=1;
827+ }
828+ check_obj_space(14);
829+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp) (STEP value)
830+ g_object[g_objpos++]=0x04130004; // bgezall zero,check
831+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
832+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
833+ // After executing "NEXT" statement, process reaches following line.
834+ // Update variable value by adding STEP value
835+ // Note that STEP value is loaded onto $v0 in NEXT statement
836+// g_object[g_objpos++]=0x8FC40000|((b1-'A')*4); // lw a0,xx(s8) (current var value)
837+ g_object[g_objpos++]=0x8FC40000|(i*4); // lw a0,xx(s8) (current var value)
838+ g_object[g_objpos++]=0x00822021; // addu a0,a0,v0
839+// g_object[g_objpos++]=0xAFC40000|((b1-'A')*4); // sw a0,xx(s8) (new var value)
840+ g_object[g_objpos++]=0xAFC40000|(i*4); // sw a0,xx(s8) (new var value)
841+ // Value-checking routine and storing ra in stack
842+ // check:
843+ g_object[g_objpos++]=0x8FA3000C; // lw v1,12(sp) (TO value)
844+ g_object[g_objpos++]=0x00641823; // subu v1,v1,a0
845+ g_object[g_objpos++]=0x04420001; // bltzl v0,negative
846+ g_object[g_objpos++]=0x00031823; // subu v1,zero,v1
847+ // negative:
848+ g_object[g_objpos++]=0x04610003; // bgez v1,continue
849+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
850+ break_statement(); // (2 words)
851+ // continue:
852+ return 0;
853+}
854+
855+char* next_statement(){
856+ // Return to address stored in 4($sp)
857+ // while set $v0 to 8($sp) (see for_statement)
858+ // Following assembly must be 4 words.
859+ // If the number of words will be changed, link.c must be reviced for CONTINUE statement.
860+ check_obj_space(4);
861+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
862+ g_object[g_objpos++]=0x03E00008; // jr ra
863+ g_object[g_objpos++]=0x8FA20008; // lw v0,8(sp) (STEP value)
864+ g_object[g_objpos++]=0x0830000C; // addiu sp,sp,12 (see linker)
865+ return 0;
866+}
867+
868+char* do_statement(){
869+ char* err;
870+ // Usage of stack:
871+ // 4(sp): Address to return to in "DO" statement.
872+ check_obj_space(3);
873+ g_object[g_objpos++]=0x04130001;// bgezall zero,label1:
874+ g_object[g_objpos++]=0x0822FFFC;// addiu sp,sp,-4 (see linker)
875+ // label1:
876+ g_object[g_objpos++]=0xAFBF0004;// sw ra,4(sp)
877+ if (nextCodeIs("WHILE ")) {
878+ // DO WHILE
879+ err=get_floatOrValue();
880+ if (err) return err;
881+ check_obj_space(2);
882+ g_object[g_objpos++]=0x14400003; // bne v0,zero,labe2
883+ g_object[g_objpos++]=0x00000000; // nop
884+ return break_statement(); // (2 words)
885+ // label2:
886+
887+ } else if (nextCodeIs("UNTIL ")) {
888+ // DO UNTIL
889+ err=get_floatOrValue();
890+ if (err) return err;
891+ check_obj_space(2);
892+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label2
893+ g_object[g_objpos++]=0x00000000; // nop
894+ return break_statement(); // (2 words)
895+ // label2:
896+ } else {
897+ // DO statement without WHILE/UNTIL
898+ return 0;
899+ }
900+}
901+
902+char* loop_statement(){
903+ char* err;
904+ int opos;
905+ opos=g_objpos;
906+ if (nextCodeIs("WHILE ")) {
907+ // LOOP WHILE
908+ err=get_floatOrValue();
909+ if (err) return err;
910+ check_obj_space(1);
911+ g_object[g_objpos++]=0x10400003; // beq v0,zero,label1
912+ } else if (nextCodeIs("UNTIL ")) {
913+ // LOOP UNTIL
914+ err=get_floatOrValue();
915+ if (err) return err;
916+ check_obj_space(1);
917+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label
918+ } else {
919+ // LOOP statement without WHILE/UNTIL
920+ }
921+ check_obj_space(4);
922+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
923+ g_object[g_objpos++]=0x03E00008; // jr ra
924+ opos=g_objpos+1-opos;
925+ g_object[g_objpos++]=0x3000F000|opos; // nop (See linker, used for CONTINUE statement)
926+ // label1:
927+ g_object[g_objpos++]=0x08320004; // addiu sp,sp,4 (See link() function)
928+ return 0;
929+}
930+
931+char* while_statement(){
932+ char* err;
933+ check_obj_space(3);
934+ g_object[g_objpos++]=0x04130001; // bgezall zero,label1:
935+ g_object[g_objpos++]=0x0821FFFC; // addiu sp,sp,-4 (see linker)
936+ // label1:
937+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
938+ err=get_floatOrValue();
939+ if (err) return err;
940+ check_obj_space(2);
941+ g_object[g_objpos++]=0x14400003; // bne v0,zero,label2
942+ g_object[g_objpos++]=0x00000000; // nop
943+ return break_statement(); // (2 words)
944+ // label2:
945+}
946+
947+char* wend_statement(){
948+ check_obj_space(4);
949+ g_object[g_objpos++]=0x8FBF0004; // lw ra,4(sp)
950+ g_object[g_objpos++]=0x03E00008; // jr ra
951+ g_object[g_objpos++]=0x3000F003; // nop (See linker, used for CONTINUE statement)
952+ // label1:
953+ g_object[g_objpos++]=0x08310004; // addiu sp,sp,4 (See link() function)
954+ return 0;
955+}
956+
957+char* param4_statement(enum libs lib){
958+ // lib is either LIB_PALETTE or LIB_GPALETTE
959+ // PALETTE N,R,G,B
960+ char* err;
961+ // Get N
962+ err=get_value();
963+ if (err) return err;
964+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
965+ g_srcpos++;
966+ check_obj_space(2);
967+ g_object[g_objpos++]=0x27BDFFF4; // addiu sp,sp,-12
968+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
969+ // Get R
970+ err=get_value();
971+ if (err) return err;
972+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
973+ g_srcpos++;
974+ check_obj_space(1);
975+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
976+ // Get G
977+ err=get_value();
978+ if (err) return err;
979+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
980+ g_srcpos++;
981+ check_obj_space(1);
982+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
983+ // Get B
984+ err=get_value();
985+ if (err) return err;
986+ call_lib_code(lib);
987+ check_obj_space(1);
988+ g_object[g_objpos++]=0x27BD000C; // addiu sp,sp,12
989+ return 0;
990+}
991+
992+char* param3_statement(enum libs lib){
993+ char* err;
994+ // Get 1st parameter
995+ err=get_value();
996+ if (err) return err;
997+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
998+ g_srcpos++;
999+ check_obj_space(2);
1000+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1001+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1002+ // Get 2nd parameter
1003+ err=get_value();
1004+ if (err) return err;
1005+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1006+ g_srcpos++;
1007+ check_obj_space(1);
1008+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1009+ // Get 3rd parameter
1010+ err=get_value();
1011+ if (err) return err;
1012+ call_lib_code(lib);
1013+ check_obj_space(1);
1014+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1015+ return 0;
1016+}
1017+
1018+char* bgcolor_statement(){
1019+ // BGCOLOR R,G,B
1020+ return param3_statement(LIB_BGCOLOR);
1021+}
1022+
1023+char* pcg_statement(){
1024+ // PCG ASCII,D1,D2
1025+ return param3_statement(LIB_PCG);
1026+}
1027+
1028+char* usepcg_statement(){
1029+ int objpos=g_objpos;
1030+ if (get_value()) {
1031+ // Getting integer failed.
1032+ // It supporsed to be not parameter
1033+ // and same as parameter=1.
1034+ g_objpos=objpos;
1035+ check_obj_space(1);
1036+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1037+ }
1038+ call_lib_code(LIB_USEPCG);
1039+ return 0;
1040+}
1041+
1042+char* usegraphic_statement(){
1043+ int objpos=g_objpos;
1044+ if (get_value()) {
1045+ // Getting integer failed.
1046+ // It supporsed to be not parameter
1047+ // and same as parameter=1.
1048+ g_objpos=objpos;
1049+ check_obj_space(1);
1050+ g_object[g_objpos++]=0x34020001; //ori v0,zero,0x01
1051+ }
1052+ call_lib_code(LIB_USEGRAPHIC);
1053+ return 0;
1054+}
1055+
1056+char* cls_statement(){
1057+ call_lib_code(LIB_CLS);
1058+ return 0;
1059+}
1060+
1061+char* gcls_statement(){
1062+ call_lib_code(LIB_GCLS);
1063+ return 0;
1064+}
1065+
1066+char* color_statement(){
1067+ char* err;
1068+ err=get_value();
1069+ if (err) return err;
1070+ call_lib_code(LIB_COLOR);
1071+ return 0;
1072+}
1073+
1074+char* gcolor_statement(){
1075+ char* err;
1076+ err=get_value();
1077+ if (err) return err;
1078+ call_lib_code(LIB_GCOLOR);
1079+ return 0;
1080+}
1081+
1082+char* param2_statement(enum libs lib){
1083+ char* err;
1084+ // Get 1st
1085+ err=get_value();
1086+ if (err) return err;
1087+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1088+ g_srcpos++;
1089+ check_obj_space(2);
1090+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1091+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1092+ // Get 2nd
1093+ err=get_value();
1094+ if (err) return err;
1095+ call_lib_code(lib);
1096+ check_obj_space(1);
1097+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1098+ return 0;
1099+}
1100+
1101+char* system_statement(){
1102+ // SYSTEM X,Y
1103+ char* err;
1104+ // Get 1st
1105+ err=get_value();
1106+ if (err) return err;
1107+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1108+ g_srcpos++;
1109+ check_obj_space(2);
1110+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1111+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1112+ // Get 2nd
1113+ err=get_value();
1114+ if (err) return err;
1115+ check_obj_space(2);
1116+ g_object[g_objpos++]=0x8FA40004; // lw a0,4(sp)
1117+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1118+ call_lib_code(LIB_SYSTEM);
1119+ return 0;
1120+}
1121+
1122+char* cursor_statement(){
1123+ // CURSOR X,Y
1124+ return param2_statement(LIB_CURSOR);
1125+}
1126+
1127+char* scroll_statement(){
1128+ // SCROLL X,Y
1129+ return param2_statement(LIB_SCROLL);
1130+}
1131+
1132+char* drawcount_statement(){
1133+ char* err;
1134+ err=get_value();
1135+ if (err) return err;
1136+ call_lib_code(LIB_SETDRAWCOUNT);
1137+ return 0;
1138+}
1139+
1140+char* wait_statement(){
1141+ char* err;
1142+ err=get_value();
1143+ if (err) return err;
1144+ call_lib_code(LIB_WAIT);
1145+ return 0;
1146+}
1147+
1148+char* width_statement(){
1149+ char* err;
1150+ err=get_value();
1151+ if (err) return err;
1152+ call_lib_code(LIB_WIDTH);
1153+ return 0;
1154+}
1155+
1156+char* var_statement_sub(int a0, int a1){
1157+ // Construct parameter-setting scripts
1158+ if (a0&0xffff0000) {
1159+ check_obj_space(1);
1160+ g_object[g_objpos++]=0x3C040000|(a0>>16); // lui a0,XXXX
1161+ if (a0&0x0000ffff) {
1162+ check_obj_space(1);
1163+ g_object[g_objpos++]=0x34840000|(a0&0xffff); // ori a0,a0,XXXX
1164+ }
1165+ } else if (a0&0x0000ffff) {
1166+ check_obj_space(1);
1167+ g_object[g_objpos++]=0x34040000|(a0&0xffff); // ori a0,zero,xxxx
1168+ }
1169+ if (a1&0xffff0000) {
1170+ check_obj_space(1);
1171+ g_object[g_objpos++]=0x3C050000|(a1>>16); // lui a1,XXXX
1172+ if (a1&0x0000ffff) {
1173+ check_obj_space(1);
1174+ g_object[g_objpos++]=0x34A50000|(a1&0xffff); // ori a1,a1,XXXX
1175+ }
1176+ } else if (a1&0x0000ffff) {
1177+ check_obj_space(1);
1178+ g_object[g_objpos++]=0x34050000|(a1&0xffff); // ori a1,zero,xxxx
1179+ } else if (a0&0xff000000) {
1180+ // # of variables is 4. Reset $a1 to let lib_var() know that there is no more variables to store.
1181+ check_obj_space(1);
1182+ g_object[g_objpos++]=0x34050000; // ori a1,zero,0
1183+ }
1184+ return 0;
1185+}
1186+
1187+char* var_statement(){
1188+ char* err;
1189+ int i,j,a0,a1;
1190+ static int prevpos;
1191+ short stack;
1192+ do {
1193+ // For stack, 4 bytes are used for return address,
1194+ // 4 bytes are used in lib_var(),
1195+ // and additinal bytes are used for storing variable values.
1196+ stack=8;
1197+ a0=a1=0;
1198+ for (i=0;i<8;i++){
1199+ // Determine the variable number from source code
1200+ j=get_var_number();
1201+ if (j<0) return ERR_SYNTAX;
1202+ stack+=4;
1203+ // Create parameters in $a0, or $a1
1204+ if (i<4) {
1205+ a0=(a0<<8)|(j+1);
1206+ } else {
1207+ a1=(a1<<8)|(j+1);
1208+ }
1209+ // Check remaining variable(s)
1210+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1211+ next_position();
1212+ if (g_source[g_srcpos]!=',') break;
1213+ g_srcpos++;
1214+ }
1215+ // Jump to push routine, first
1216+ check_obj_space(2);
1217+ prevpos=g_objpos;
1218+ g_object[g_objpos++]=0x04130000; // bgezall zero,label1
1219+ g_object[g_objpos++]=0x27BD0000|((0-stack)&0xffff); // addiu sp,sp,-xx
1220+ // Process will be here after RETURN statement
1221+ // Pop routine
1222+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1223+ if (err) return err;
1224+ call_lib_code(LIB_VAR_POP);
1225+ // Restore stack and return
1226+ check_obj_space(3);
1227+ g_object[g_objpos++]=0x8FA30000|stack; // lw v1,xx(sp)
1228+ g_object[g_objpos++]=0x00600008; // jr v1
1229+ g_object[g_objpos++]=0x27BD0000|stack; // addiu sp,sp,xx
1230+ // Push rotine
1231+ g_object[prevpos]|=g_objpos-prevpos-1; // label1:
1232+ check_obj_space(1);
1233+ g_object[g_objpos++]=0xAFBF0004; // sw ra,4(sp)
1234+ err=var_statement_sub(a0,a1); // Prepare a0, and a1
1235+ if (err) return err;
1236+ call_lib_code(LIB_VAR_PUSH);
1237+
1238+ } while (g_source[g_srcpos-1]==',');
1239+ // Renew sp stored in s5 stack.
1240+ check_obj_space(1);
1241+ g_object[g_objpos++]=0xAEBD0000|ARGS_S5_SP; // sw sp,-12(s5)
1242+ return 0;
1243+}
1244+
1245+
1246+char* graphic_statement(enum functions func){
1247+ /*
1248+ PSET X1,Y1[,C]
1249+ LINE X1,Y1,X2,Y2[,C]
1250+ BOXFILL X1,Y1,X2,Y2[,C]
1251+ CIRCLE X1,Y1,R[,C]
1252+ CIRCLEFILL X1,Y1,R[,C]
1253+ GPRINT X1,Y1,C,BC,S$
1254+ PUTBMP X1,Y1,M,N,BMP
1255+ 4(sp): X1
1256+ 8(sp): Y1
1257+ 12(sp): X2/R/M
1258+ 16(sp): Y2/N
1259+ v0: C/S$/BMP
1260+ */
1261+ char* err;
1262+ int spos;
1263+ int paramnum;
1264+ switch(func){
1265+ case FUNC_PSET:// X1,Y1[,C]
1266+ case FUNC_GCOLOR:// X1,Y1
1267+ case FUNC_POINT:// X1,Y1
1268+ paramnum=2;
1269+ break;
1270+ case FUNC_CIRCLE:// X1,Y1,R[,C]
1271+ case FUNC_CIRCLEFILL:// X1,Y1,R[,C]
1272+ paramnum=3;
1273+ break;
1274+ case FUNC_LINE:// X1,Y1,X2,Y2[,C]
1275+ case FUNC_BOXFILL:// X1,Y1,X2,Y2[,C]
1276+ paramnum=4;
1277+ break;
1278+ case FUNC_GPRINT:// X1,Y1,C,BC,S$
1279+ case FUNC_PUTBMP:// X1,Y1,M,N,BMP
1280+ paramnum=5;
1281+ break;
1282+ default:
1283+ return ERR_UNKNOWN;
1284+ }
1285+
1286+ next_position();
1287+ if (g_source[g_srcpos]==',') {
1288+ // X1 and Y1 is omitted. Set 0x80000000 for both.
1289+ check_obj_space(4);
1290+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1291+ g_object[g_objpos++]=0x3C028000; // lui v0,0x0080
1292+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1293+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1294+ } else {
1295+ // X1
1296+ err=get_value();
1297+ if (err) return err;
1298+ check_obj_space(2);
1299+ g_object[g_objpos++]=0x27BDFFF0; // addiu sp,sp,-16
1300+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1301+ // Y1
1302+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1303+ g_srcpos++;
1304+ err=get_value();
1305+ if (err) return err;
1306+ check_obj_space(1);
1307+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1308+ }
1309+ if (2<paramnum) {
1310+ // X2, R, or M
1311+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1312+ g_srcpos++;
1313+ err=get_value();
1314+ if (err) return err;
1315+ check_obj_space(1);
1316+ g_object[g_objpos++]=0xAFA2000C; // sw v0,12(sp)
1317+ if (3<paramnum) {
1318+ // Y2, BC, or N
1319+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1320+ g_srcpos++;
1321+ err=get_value();
1322+ if (err) return err;
1323+ check_obj_space(1);
1324+ g_object[g_objpos++]=0xAFA20010; // sw v0,16(sp)
1325+ }
1326+ }
1327+ if (func==FUNC_GPRINT) {
1328+ // S$
1329+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1330+ g_srcpos++;
1331+ err=get_string();
1332+ if (err) return err;
1333+ } else if (func==FUNC_PUTBMP) {
1334+ // BMP
1335+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1336+ g_srcpos++;
1337+ spos=g_srcpos;
1338+ err=get_label();
1339+ if (g_label && !err) {
1340+ if (search_var_name(g_label)!=-1) {
1341+ // This is a long var name.
1342+ g_label=0;
1343+ g_srcpos=spos;
1344+ }
1345+ }
1346+ if (g_label && !err) {
1347+ // Label/number is constant.
1348+ // Linker will change following codes later.
1349+ // Note that 0x0814xxxx and 0x0815xxxx are specific codes for these.
1350+ check_obj_space(2);
1351+ g_object[g_objpos++]=0x08140000|((g_label>>16)&0x0000FFFF); // lui v0,xxxx
1352+ g_object[g_objpos++]=0x08150000|(g_label&0x0000FFFF); // ori v0,v0,xxxx
1353+ // Change func to FUNC_PUTBMP2 (label mode).
1354+ func=FUNC_PUTBMP2;
1355+ } else {
1356+ err=get_value();
1357+ if (err) return err;
1358+ }
1359+ } else {
1360+ // [,C]
1361+ if (g_source[g_srcpos]==',') {
1362+ g_srcpos++;
1363+ err=get_value();
1364+ if (err) return err;
1365+ } else {
1366+ // If C is omitted, use -1.
1367+ check_obj_space(1);
1368+ g_object[g_objpos++]=0x2402FFFF; // addiu v0,zero,-1
1369+ }
1370+ }
1371+ // Call library
1372+ call_lib_code(LIB_GRAPHIC | func);
1373+ // Restore stack pointer
1374+ check_obj_space(1);
1375+ g_object[g_objpos++]=0x27BD0010; // addiu sp,sp,16
1376+ return 0;
1377+}
1378+
1379+char* fopen_statement_main(enum functions func){
1380+ // func is either FUNC_FOPENST or FUNC_FOPEN
1381+ char* err;
1382+ // Get 1st
1383+ err=get_string();
1384+ if (err) return err;
1385+ if (g_source[g_srcpos]!=',') return ERR_SYNTAX;
1386+ g_srcpos++;
1387+ check_obj_space(2);
1388+ g_object[g_objpos++]=0x27BDFFF8; // addiu sp,sp,-8
1389+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1390+ // Get 2nd
1391+ err=get_string();
1392+ if (err) return err;
1393+ check_obj_space(1);
1394+ g_object[g_objpos++]=0xAFA20008; // sw v0,8(sp)
1395+ // Get 3rd
1396+ if (g_source[g_srcpos]==',') {
1397+ g_srcpos++;
1398+ err=get_value();
1399+ if (err) return err;
1400+ } else {
1401+ // If 3rd parameter is omitted, use 0.
1402+ check_obj_space(1);
1403+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1404+ }
1405+ call_lib_code(LIB_FILE | func);
1406+ check_obj_space(1);
1407+ g_object[g_objpos++]=0x27BD0008; // addiu sp,sp,8
1408+ return 0;
1409+}
1410+
1411+char* file_statement(){
1412+ char* err;
1413+ err=get_value();
1414+ if (err) return err;
1415+ call_lib_code(LIB_FILE | FUNC_FILE);
1416+ return 0;
1417+}
1418+
1419+char* fclose_statement(){
1420+ char* err;
1421+ int orgpos=g_srcpos;
1422+ if (endOfStatement()) {
1423+ // If no argument, use 0
1424+ check_obj_space(1);
1425+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1426+ } else {
1427+ err=get_value();
1428+ if (err) return err;
1429+ }
1430+ call_lib_code(LIB_FILE | FUNC_FCLOSE);
1431+ return 0;
1432+}
1433+
1434+char* fget_statement(){
1435+ return param2_statement(LIB_FILE | FUNC_FGET);
1436+}
1437+
1438+char* fput_statement(){
1439+ return param2_statement(LIB_FILE | FUNC_FPUT);
1440+}
1441+
1442+char* fseek_statement(){
1443+ char* err;
1444+ err=get_value();
1445+ if (err) return err;
1446+ call_lib_code(LIB_FILE | FUNC_FSEEK);
1447+ return 0;
1448+}
1449+
1450+char* fputc_statement(){
1451+ char* err;
1452+ err=get_value();
1453+ if (err) return err;
1454+ call_lib_code(LIB_FILE | FUNC_FPUTC);
1455+ return 0;
1456+}
1457+
1458+char* fremove_statement(){
1459+ char* err;
1460+ err=get_string();
1461+ if (err) return err;
1462+ call_lib_code(LIB_FILE | FUNC_FREMOVE);
1463+ return 0;
1464+}
1465+
1466+char* usevar_statement(){
1467+ char* err;
1468+ int i;
1469+ do {
1470+ next_position();
1471+ i=check_var_name();
1472+ if (i<65536) return ERR_SYNTAX;
1473+ err=register_var_name(i);
1474+ if (err) return err;
1475+ if (g_source[g_srcpos]=='#' || g_source[g_srcpos]=='$') g_srcpos++;
1476+ next_position();
1477+ if (g_source[g_srcpos]==',') {
1478+ g_srcpos++;
1479+ } else {
1480+ break;
1481+ }
1482+ } while(1);
1483+ return 0;
1484+}
1485+
1486+char* playwave_statement(){
1487+ char* err;
1488+ err=get_string();
1489+ if (err) return err;
1490+ check_obj_space(2);
1491+ g_object[g_objpos++]=0x27BDFFFC; // addiu sp,sp,-4
1492+ g_object[g_objpos++]=0xAFA20004; // sw v0,4(sp)
1493+ if (g_source[g_srcpos]==',') {
1494+ g_srcpos++;
1495+ // Get 2nd
1496+ err=get_value();
1497+ if (err) return err;
1498+ } else {
1499+ // If 2rd parameter is omitted, use 0.
1500+ check_obj_space(1);
1501+ g_object[g_objpos++]=0x24020000; // addiu v0,zero,0
1502+ }
1503+ call_lib_code(LIB_PLAYWAVE);
1504+ check_obj_space(1);
1505+ g_object[g_objpos++]=0x27BD0004; // addiu sp,sp,4
1506+ return 0;
1507+}
1508+
1509+char* useclass_statement(){
1510+ char* err;
1511+ int i;
1512+ int* cmpdata;
1513+ do {
1514+ next_position();
1515+ i=check_var_name();
1516+ if (i<65536) return ERR_SYNTAX;
1517+ // Check if the class already exists
1518+ cmpdata_reset();
1519+ while(cmpdata=cmpdata_find(CMPDATA_CLASS)){
1520+ if (cmpdata[1]==i) {
1521+ // The class was already defined.
1522+ i=0;
1523+ break;
1524+ }
1525+ }
1526+ if (i) {
1527+ // Remove a objects before USECLASS statement
1528+ g_objpos=0;
1529+ // Insert a NOP assembly. This will be replaced by jump statement.
1530+ check_obj_space(1);
1531+ g_object[g_objpos++]=0x00000000; // nop
1532+ // Load new file to define class statement.
1533+ g_class=i;
1534+ return ERR_COMPILE_CLASS;
1535+ }
1536+ if (g_source[g_srcpos]==',') {
1537+ g_srcpos++;
1538+ } else {
1539+ break;
1540+ }
1541+ } while(1);
1542+ return 0;
1543+}
1544+
1545+char* setdir_statement(){
1546+ char* err;
1547+ err=get_string();
1548+ if (err) return err;
1549+ call_lib_code(LIB_SETDIR);
1550+ return 0;
1551+}
1552+
1553+#ifdef __DEBUG
1554+ char* debug_statement(){
1555+ call_lib_code(LIB_DEBUG);
1556+ return 0;
1557+ }
1558+#endif
1559+
1560+// Aliases follow
1561+
1562+char* poke_statement(){
1563+ return poke_statement_sub(8);
1564+}
1565+
1566+char* poke16_statement(){
1567+ return poke_statement_sub(16);
1568+}
1569+
1570+char* poke32_statement(){
1571+ return poke_statement_sub(32);
1572+}
1573+
1574+char* palette_statement(){
1575+ return param4_statement(LIB_PALETTE);
1576+}
1577+
1578+char* gpalette_statement(){
1579+ return param4_statement(LIB_GPALETTE);
1580+}
1581+
1582+char* print_statement(){
1583+ return print_statement_main(LIB_PRINTSTR,LIB_STRING);
1584+}
1585+
1586+char* pset_statement(){
1587+ return graphic_statement(FUNC_PSET);
1588+}
1589+
1590+char* line_statement(){
1591+ return graphic_statement(FUNC_LINE);
1592+}
1593+
1594+char* boxfill_statement(){
1595+ return graphic_statement(FUNC_BOXFILL);
1596+}
1597+
1598+char* circle_statement(){
1599+ return graphic_statement(FUNC_CIRCLE);
1600+}
1601+
1602+char* circlefill_statement(){
1603+ return graphic_statement(FUNC_CIRCLEFILL);
1604+}
1605+
1606+char* gprint_statement(){
1607+ return graphic_statement(FUNC_GPRINT);
1608+}
1609+
1610+char* putbmp_statement(){
1611+ return graphic_statement(FUNC_PUTBMP);
1612+}
1613+
1614+char* point_statement(){
1615+ return graphic_statement(FUNC_POINT);
1616+}
1617+
1618+char* fopen_statement(){
1619+ return fopen_statement_main(FUNC_FOPENST);
1620+}
1621+
1622+char* fprint_statement(){
1623+ return print_statement_main(LIB_FILE | FUNC_FPRINTSTR,LIB_FILE | FUNC_FSTRING);
1624+}
1625+
1626+static const void* statement_list[]={
1627+ "REM",rem_statement,
1628+ "SOUND ",sound_statement,
1629+ "MUSIC ",music_statement,
1630+ "DRAWCOUNT ",drawcount_statement,
1631+ "CURSOR ",cursor_statement,
1632+ "PALETTE ",palette_statement,
1633+ "GPALETTE ",gpalette_statement,
1634+ "BGCOLOR ",bgcolor_statement,
1635+ "CLS",cls_statement,
1636+ "GCLS",gcls_statement,
1637+ "COLOR ",color_statement,
1638+ "GCOLOR ",gcolor_statement,
1639+ "RESTORE ",restore_statement,
1640+ "DATA ",data_statement,
1641+ "CDATA ",cdata_statement,
1642+ "LABEL ",label_statement,
1643+ "DIM ",dim_statement,
1644+ "CLEAR",clear_statement,
1645+ "PRINT",print_statement,
1646+ "IF ",if_statement,
1647+ "ELSEIF ",elseif_statement,
1648+ "ELSE",else_statement,
1649+ "ENDIF",endif_statement,
1650+ "END",end_statement,
1651+ "EXEC ",exec_statement,
1652+ "GOTO ",goto_statement,
1653+ "GOSUB ",gosub_statement,
1654+ "RETURN",return_statement,
1655+ "POKE ",poke_statement,
1656+ "POKE16 ",poke16_statement,
1657+ "POKE32 ",poke32_statement,
1658+ "FOR ",for_statement,
1659+ "NEXT",next_statement,
1660+ "LET ",let_statement,
1661+ "PCG ",pcg_statement,
1662+ "USEPCG",usepcg_statement,
1663+ "SCROLL ",scroll_statement,
1664+ "WAIT ",wait_statement,
1665+ "USEGRAPHIC",usegraphic_statement,
1666+ "PSET ",pset_statement,
1667+ "LINE ",line_statement,
1668+ "BOXFILL ",boxfill_statement,
1669+ "CIRCLE ",circle_statement,
1670+ "CIRCLEFILL ",circlefill_statement,
1671+ "GPRINT ",gprint_statement,
1672+ "PUTBMP ",putbmp_statement,
1673+ "POINT ",point_statement,
1674+ "VAR ",var_statement,
1675+ "DO",do_statement,
1676+ "LOOP",loop_statement,
1677+ "WHILE ",while_statement,
1678+ "WEND",wend_statement,
1679+ "BREAK",break_statement,
1680+ "CONTINUE",continue_statement,
1681+ "SYSTEM",system_statement,
1682+ "WIDTH ",width_statement,
1683+ "FOPEN ",fopen_statement,
1684+ "FILE ",file_statement,
1685+ "FCLOSE",fclose_statement,
1686+ "FPRINT ",fprint_statement,
1687+ "FGET ",fget_statement,
1688+ "FPUT ",fput_statement,
1689+ "FPUTC ",fputc_statement,
1690+ "FSEEK ",fseek_statement,
1691+ "FREMOVE ",fremove_statement,
1692+ "USEVAR ",usevar_statement,
1693+ "PLAYWAVE ",playwave_statement,
1694+ "USECLASS ",useclass_statement,
1695+ "FIELD ",field_statement,
1696+ "METHOD ",method_statement,
1697+ "DELETE ",delete_statement,
1698+ "CALL ",call_statement,
1699+ "STATIC ",static_statement,
1700+ "SETDIR ",setdir_statement,
1701+ // List of additional statements follows
1702+ ADDITIONAL_STATEMENTS
1703+};
1704+
1705+char* statement(void){
1706+ char* err;
1707+ int prevpos;
1708+ int i;
1709+ char* (*f)();
1710+ // Clear flag for temp area usage.
1711+ g_temp_area_used=0;
1712+ // Initialize stack handler used for value
1713+ g_sdepth=g_maxsdepth=0;
1714+ // Allow shifting code object when stack is used.
1715+ // This will be disalloed when CMPDATA_UNSOLVED etc is used.
1716+ g_allow_shift_obj=1;
1717+ // Seek the statement
1718+ for (i=0;i<sizeof(statement_list)/sizeof(statement_list[0]);i+=2){
1719+ if (nextCodeIs((char*)statement_list[i])) break;
1720+ }
1721+ if (i<sizeof(statement_list)/sizeof(statement_list[0])) {
1722+ // Statement found. Call it.
1723+ f=statement_list[i+1];
1724+ err=f();
1725+#ifdef __DEBUG
1726+ } else if (nextCodeIs("DEBUG")) {
1727+ err=debug_statement();
1728+#endif
1729+ } else {
1730+ err=let_statement();
1731+ }
1732+ if (err) return err;
1733+ // Stack handler must be zero here.
1734+ if (g_sdepth!=0) return ERR_UNKNOWN;
1735+ // Check if temp area is used
1736+ if (g_temp_area_used) {
1737+ // Temp area is used. Insert a garbage collection flag setting routine.
1738+ check_obj_space(1);
1739+ g_object[g_objpos++]=0x7ED6F000;// ext s6,s6,0,31
1740+ }
1741+ return 0;
1742+}
--- trunk/string.c (revision 36)
+++ trunk/string.c (revision 37)
@@ -6,6 +6,10 @@
66 */
77
88 /*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+/*
913 Public functions:
1014 char* get_string(void);
1115 char* simple_string(void);
@@ -88,6 +92,21 @@
8892 g_temp_area_used=1;
8993 return 0;
9094 }
95+ if (g_source[g_srcpos]=='.') {
96+ // This is an object field or method to return string
97+ check_obj_space(1);
98+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
99+ g_srcpos++;
100+ return string_obj_field();
101+ } else if (g_source[g_srcpos]=='(') {
102+ // An array element contains pointer to an object.
103+ g_srcpos++;
104+ err=get_dim_value(i);
105+ if (err) return err;
106+ if (g_source[g_srcpos]!='.') return ERR_SYNTAX;
107+ g_srcpos++;
108+ return string_obj_field();
109+ }
91110 if (g_source[g_srcpos]!='$') return ERR_SYNTAX;
92111 g_srcpos++;
93112 // String variable
@@ -194,7 +213,7 @@
194213 prevpos=g_objpos;
195214 // Stack decrement command will be filled later
196215 check_obj_space(1);
197- g_objpos++;
216+ g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx")
198217 }
199218 err=get_string_sub();
200219 if (err) return err;
@@ -201,8 +220,10 @@
201220 if (g_sdepth==0) {
202221 if (g_maxsdepth==0) {
203222 // Stack was not used.
204- shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
205- g_objpos--;
223+ if (g_allow_shift_obj) {
224+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
225+ g_objpos--;
226+ }
206227 } else {
207228 // Stack was used.
208229 check_obj_space(1);
--- trunk/value.c (revision 36)
+++ trunk/value.c (revision 37)
@@ -6,6 +6,10 @@
66 */
77
88 /*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
12+/*
913 Public function is only get_value().
1014 */
1115
@@ -73,6 +77,13 @@
7377 check_obj_space(1);
7478 g_object[g_objpos++]=0x00021023; // subu v0,zero,v0
7579 g_intconst=-g_intconst;
80+ } else if (b1=='&') {
81+ // '&' operator
82+ g_srcpos++;
83+ i=get_var_number();
84+ if (i<0) return ERR_SYNTAX;
85+ check_obj_space(1);
86+ g_object[g_objpos++]=0x27C20000|(i*4); // addiu v0,s8,xxxx
7687 } else {
7788 // Main routine of getting value here
7889 if (b1=='+') g_srcpos++; // Ignore unary '+' operator
@@ -92,6 +103,9 @@
92103 } else if ('A'<=b1 && b1<='F') {
93104 i*=16;
94105 i+=b1-'A'+0x0A;
106+ } else if (b1==' ') { // Skip ' '
107+ // Avoid "ELSE" statement etc
108+ if ('F'<g_source[g_srcpos+2]) break;
95109 } else {
96110 break;
97111 }
@@ -116,7 +130,7 @@
116130 if ('0'<=b1 && b1<='9') {
117131 i*=10;
118132 i+=b1-'0';
119- } else {
133+ } else if (b1!=' ') { // Skip ' '
120134 break;
121135 }
122136 g_srcpos++;
@@ -123,7 +137,11 @@
123137 }
124138 // The next character should not be '.' or 'E'.
125139 // Or, it must be recognized as a float value.
126- if (b1=='.' || b1=='E') return ERR_SYNTAX;
140+ if (b1=='.') return ERR_SYNTAX;
141+ if (b1=='E') {
142+ b2=g_source[g_srcpos+1];
143+ if (b2==' ' || '0'<=b2 && b2<='9') return ERR_SYNTAX;
144+ }
127145 g_intconst=i;
128146 if (i&0xFFFF0000) {
129147 // 32 bit
@@ -145,11 +163,19 @@
145163 if (g_source[g_srcpos]=='(') {
146164 // Dimension
147165 g_srcpos++;
148- return get_dim_value(i);
166+ err=get_dim_value(i);
167+ if (err) return err;
168+ } else {
169+ // Simple value
170+ check_obj_space(1);
171+ g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
149172 }
150- // Simple value
151- check_obj_space(1);
152- g_object[g_objpos++]=0x8FC20000|(i*4); // lw v0,xx(s8)
173+ // Check if this is an object
174+ if (g_source[g_srcpos]=='.') {
175+ // This is an object. See the filed of it.
176+ g_srcpos++;
177+ return integer_obj_field();
178+ }
153179 }
154180 }
155181 // No error
@@ -206,7 +232,7 @@
206232 prevpos=g_objpos;
207233 // Stack decrement command will be filled later
208234 check_obj_space(1);
209- g_objpos++;
235+ g_object[g_objpos++]=0x00000000; // nop (will be replaced by "addiu sp,sp,-xx")
210236 }
211237 err=get_value_sub(priority(OP_VOID));
212238 if (err) return err;
@@ -213,8 +239,10 @@
213239 if (g_sdepth==0) {
214240 if (g_maxsdepth==0) {
215241 // Stack was not used.
216- shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
217- g_objpos--;
242+ if (g_allow_shift_obj) {
243+ shift_obj(&g_object[prevpos+1],&g_object[prevpos],g_objpos-prevpos-1);
244+ g_objpos--;
245+ }
218246 } else {
219247 // Stack was used.
220248 check_obj_space(1);
--- trunk/varname.c (revision 36)
+++ trunk/varname.c (revision 37)
@@ -5,6 +5,10 @@
55 kmorimatsu@users.sourceforge.jp
66 */
77
8+/*
9+ This file is shared by Megalopa and Zoea
10+*/
11+
812 #include "compiler.h"
913
1014 /*
@@ -14,106 +18,117 @@
1418 */
1519
1620 static const int reserved_var_names[]={
17- 0x000106b8, //ABS
18- 0x0001f67c, //ACOS
19- 0x0002414c, //ARGS
20- 0x0001090c, //ASC
21- 0x0002469f, //ASIN
22- 0x00024a8f, //ATAN
23- 0x002f7c1e, //ATAN2
24- 0x0047c31c, //BREAK
25- 0x00575afe, //CDATA
26- 0x00036c3d, //CEIL
27- 0x000111af, //CHR
28- 0x0cb1b682, //CIRCLE
29- 0x005d1ea3, //CLEAR
30- 0x00011240, //CLS
31- 0x005f66cb, //COLOR
32- 0x000112ac, //COS
33- 0x0003a041, //COSH
34- 0x00616415, //CREAD
35- 0x0de593fb, //CURSOR
36- 0x00040fbe, //DATA
37- 0x00011644, //DEC
38- 0x000116de, //DIM
39- 0x000100a8, //DO
40- 0x0004fd8e, //ELSE
41- 0x1434a177, //ELSEIF
42- 0x00011c99, //END
43- 0x0091c927, //ENDIF
44- 0x00053854, //EXEC
45- 0x00011e0d, //EXP
46- 0x000579c8, //FABS
47- 0x16e3d4be, //FCLOSE
48- 0x00058fcf, //FEOF
49- 0x00059895, //FGET
50- 0x00a67500, //FGETC
51- 0x0005a3a2, //FILE
52- 0x177f0ca5, //FINPUT
53- 0x0005b1df, //FLEN
54- 0x00aa3445, //FLOAT
55- 0x00aa363b, //FLOOR
56- 0x0005b84d, //FMOD
57- 0x00ac5c9f, //FOPEN
58- 0x000121db, //FOR
59- 0x18352839, //FPRINT
60- 0x0005c865, //FPUT
61- 0x00ad2e40, //FPUTC
62- 0x00aefdec, //FSEEK
63- 0x00063b90, //GCLS
64- 0x1a808bcb, //GCOLOR
65- 0x00c60f03, //GOSUB
66- 0x0006796c, //GOTO
67- 0x1bcfcc39, //GPRINT
68- 0x00012a99, //HEX
69- 0x00010153, //IF
70- 0x00f8701a, //INKEY
71- 0x00f88ba5, //INPUT
72- 0x000130e9, //INT
73- 0x00092084, //KEYS
74- 0x013be43d, //LABEL
75- 0x00013ecf, //LEN
76- 0x00013ed5, //LET
77- 0x0009e96a, //LINE
78- 0x00014030, //LOG
79- 0x0145f324, //LOG10
80- 0x000a07f9, //LOOP
81- 0x000abca3, //MODF
82- 0x016418d4, //MUSIC
83- 0x000b4321, //NEXT
84- 0x00014a5d, //NOT
85- 0x000152c0, //PCG
86- 0x000cacec, //PEEK
87- 0x00010252, //PI
88- 0x01ac8479, //POINT
89- 0x000ce05e, //POKE
90- 0x00015480, //POW
91- 0x01aea739, //PRINT
92- 0x000cf3d5, //PSET
93- 0x3cc0fe21, //PUTBMP
94- 0x000e18d5, //READ
95- 0x00015d2e, //REM
96- 0x425c9703, //RETURN
97- 0x00015e69, //RND
98- 0x45c26d49, //SCROLL
99- 0x00016287, //SGN
100- 0x000162cf, //SIN
101- 0x000ee52d, //SINH
102- 0x01f9a429, //SOUND
103- 0x000f0e49, //SQRT
104- 0x47f711de, //SYSTEM
105- 0x000166bf, //TAN
106- 0x000f72ed, //TANH
107- 0x02182fee, //TVRAM
108- 0x022c2a2d, //UNTIL
109- 0x4e8887d0, //USEPCG
110- 0x4e88a5f3, //USEVAR
111- 0x000170dd, //VAL
112- 0x000170e3, //VAR
113- 0x00119505, //WAIT
114- 0x0011a9e9, //WEND
115- 0x025aef62, //WHILE
116- 0x025b8d75, //WIDTH
21+ 0x000106b8, /*ABS*/
22+ 0x0001f67c, /*ACOS*/
23+ 0x0002414c, /*ARGS*/
24+ 0x0001090c, /*ASC*/
25+ 0x0002469f, /*ASIN*/
26+ 0x00024a8f, /*ATAN*/
27+ 0x002f7c1e, /*ATAN2*/
28+ 0x0047c31c, /*BREAK*/
29+ 0x00035869, /*CALL*/
30+ 0x00575afe, /*CDATA*/
31+ 0x00036c3d, /*CEIL*/
32+ 0x000111af, /*CHR*/
33+ 0x0cb1b682, /*CIRCLE*/
34+ 0x005d1ea3, /*CLEAR*/
35+ 0x00011240, /*CLS*/
36+ 0x005f66cb, /*COLOR*/
37+ 0x000112ac, /*COS*/
38+ 0x0003a041, /*COSH*/
39+ 0x00616415, /*CREAD*/
40+ 0x0de593fb, /*CURSOR*/
41+ 0x00040fbe, /*DATA*/
42+ 0x00011644, /*DEC*/
43+ 0x0fe19c42, /*DELETE*/
44+ 0x000116de, /*DIM*/
45+ 0x000100a8, /*DO*/
46+ 0x0004fd8e, /*ELSE*/
47+ 0x1434a177, /*ELSEIF*/
48+ 0x00011c99, /*END*/
49+ 0x0091c927, /*ENDIF*/
50+ 0x00053854, /*EXEC*/
51+ 0x00011e0d, /*EXP*/
52+ 0x000579c8, /*FABS*/
53+ 0x16e3d4be, /*FCLOSE*/
54+ 0x00058fcf, /*FEOF*/
55+ 0x00059895, /*FGET*/
56+ 0x00a67500, /*FGETC*/
57+ 0x00a7e061, /*FIELD*/
58+ 0x0005a3a2, /*FILE*/
59+ 0x177f0ca5, /*FINPUT*/
60+ 0x0005b1df, /*FLEN*/
61+ 0x00aa3445, /*FLOAT*/
62+ 0x00aa363b, /*FLOOR*/
63+ 0x0005b84d, /*FMOD*/
64+ 0x00ac5c9f, /*FOPEN*/
65+ 0x000121db, /*FOR*/
66+ 0x18352839, /*FPRINT*/
67+ 0x0005c865, /*FPUT*/
68+ 0x00ad2e40, /*FPUTC*/
69+ 0x00aefdec, /*FSEEK*/
70+ 0x00063b90, /*GCLS*/
71+ 0x1a808bcb, /*GCOLOR*/
72+ 0x1ab733b3, /*GETDIR*/
73+ 0x00c60f03, /*GOSUB*/
74+ 0x0006796c, /*GOTO*/
75+ 0x1bcfcc39, /*GPRINT*/
76+ 0x00012a99, /*HEX*/
77+ 0x00010153, /*IF*/
78+ 0x00f8701a, /*INKEY*/
79+ 0x00f88ba5, /*INPUT*/
80+ 0x000130e9, /*INT*/
81+ 0x00092084, /*KEYS*/
82+ 0x013be43d, /*LABEL*/
83+ 0x00013ecf, /*LEN*/
84+ 0x00013ed5, /*LET*/
85+ 0x0009e96a, /*LINE*/
86+ 0x00014030, /*LOG*/
87+ 0x0145f324, /*LOG10*/
88+ 0x000a07f9, /*LOOP*/
89+ 0x000abca3, /*MODF*/
90+ 0x016418d4, /*MUSIC*/
91+ 0x000b4321, /*NEXT*/
92+ 0x000148f8, /*NEW*/
93+ 0x00014a5d, /*NOT*/
94+ 0x000152c0, /*PCG*/
95+ 0x000cacec, /*PEEK*/
96+ 0x3b1c6aea, /*PEEK16*/
97+ 0x3b1c6b2e, /*PEEK32*/
98+ 0x00010252, /*PI*/
99+ 0x01ac8479, /*POINT*/
100+ 0x000ce05e, /*POKE*/
101+ 0x3c20dc0a, /*POKE16*/
102+ 0x3c20dc4e, /*POKE32*/
103+ 0x00015480, /*POW*/
104+ 0x01aea739, /*PRINT*/
105+ 0x000cf3d5, /*PSET*/
106+ 0x3cb45fa4, /*PUBLIC*/
107+ 0x3cc0fe21, /*PUTBMP*/
108+ 0x000e18d5, /*READ*/
109+ 0x00015d2e, /*REM*/
110+ 0x425c9703, /*RETURN*/
111+ 0x00015e69, /*RND*/
112+ 0x45c26d49, /*SCROLL*/
113+ 0x45f6e3b3, /*SETDIR*/
114+ 0x00016287, /*SGN*/
115+ 0x000162cf, /*SIN*/
116+ 0x000ee52d, /*SINH*/
117+ 0x01f9a429, /*SOUND*/
118+ 0x000f0e49, /*SQRT*/
119+ 0x47f711de, /*SYSTEM*/
120+ 0x000166bf, /*TAN*/
121+ 0x000f72ed, /*TANH*/
122+ 0x02182fee, /*TVRAM*/
123+ 0x022c2a2d, /*UNTIL*/
124+ 0x4e8887d0, /*USEPCG*/
125+ 0x4e88a5f3, /*USEVAR*/
126+ 0x000170dd, /*VAL*/
127+ 0x000170e3, /*VAR*/
128+ 0x00119505, /*WAIT*/
129+ 0x0011a9e9, /*WEND*/
130+ 0x025aef62, /*WHILE*/
131+ 0x025b8d75, /*WIDTH*/
117132 // Additional names follow
118133 ADDITIONAL_RESERVED_VAR_NAMES
119134 };
@@ -180,16 +195,41 @@
180195 */
181196
182197 int get_var_number(){
183- int i;
198+ int i,j,spos;
199+ int* record;
184200 // This must be a short or long var name.
201+ spos=g_srcpos;
185202 i=check_var_name();
186203 if (i<0) return -1;
187204 // If it is a short name, immediately return.
188205 if (i<26) return i;
189- // Search long var names registered by USEVAR statement.
190- // If found, returns the value that can be used as the index of $s8
191- i=search_var_name(i);
192- if (i<0) return -1;
206+ // Check if CLASS::STATIC
207+ if (g_source[g_srcpos]==':' && g_source[g_srcpos+1]==':') {
208+ // This is CLASS::STATIC
209+ g_srcpos++;
210+ g_srcpos++;
211+ j=check_var_name();
212+ if (j<26) return -1;
213+ cmpdata_reset();
214+ while(record=cmpdata_find(CMPDATA_STATIC)){
215+ if (record[1]!=i) continue;
216+ if (record[2]!=j) continue;
217+ // Found CLASS::STATIC
218+ i=record[0]&0x0000FFFF;
219+ j=0;
220+ break;
221+ }
222+ if (j) {
223+ // Not found. Maybe a static method
224+ g_srcpos=spos;
225+ return -1;
226+ }
227+ } else {
228+ // Search long var names registered by USEVAR statement.
229+ // If found, returns the value that can be used as the index of $s8
230+ i=search_var_name(i);
231+ if (i<0) return -1;
232+ }
193233 // This var name is defined by USEVAR statement.
194234 return i+ALLOC_LNV_BLOCK;
195235