]> 4ch.mooo.com Git - 16.git/blob - 16/v2/source/VCC/COMPILE.C
2de7ce56aa0e913746c8dae465867b296364ad1a
[16.git] / 16 / v2 / source / VCC / COMPILE.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
18 // ³                  The VergeC Compiler version 2.01                   ³\r
19 // ³              Copyright (C)1998 BJ Eirich (aka vecna)                ³\r
20 // ³                       Code Generation module                        ³\r
21 // ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
22 \r
23 #include <stdio.h>\r
24 #include <stdlib.h>\r
25 #include <string.h>\r
26 \r
27 #include "funclib.h"\r
28 #include "vcc.h"\r
29 #include "vccode.h"\r
30 #include "lexical.h"\r
31 #include "preproc.h"\r
32 \r
33 // ================================= Data ====================================\r
34 \r
35 #define LETTER 1\r
36 #define SPECIAL 3\r
37 \r
38 // -- Function arguements type defs\r
39 \r
40 #define VOID 1\r
41 #define INT 1\r
42 #define CHARPTR 2\r
43 #define STRING 3\r
44 \r
45 unsigned char *source, *src;\r
46 unsigned char *outbuf, *code;\r
47 unsigned char inevent=0;\r
48 \r
49 typedef struct\r
50 {\r
51   char fname[40];\r
52   char argtype[20];\r
53   int numargs, numlocals;\r
54   int returntype;\r
55   int syscodeofs;\r
56 } funcdecl;\r
57 \r
58 funcdecl funcs[700];\r
59 int numfuncs=0;\r
60 \r
61 typedef struct\r
62 {\r
63   char vname[40];\r
64   int varstartofs;\r
65   int arraylen;\r
66 } vardecl;\r
67 \r
68 vardecl vars[500];\r
69 int curstartofs=0;\r
70 int numvars=0;\r
71 int varidx;\r
72 \r
73 typedef struct\r
74 {\r
75   char vname[40];\r
76   int vsofs;\r
77   int arraylen;\r
78 } strdecl;\r
79 \r
80 strdecl str[300];\r
81 int sstartofs=0;\r
82 int numstr=0;\r
83 \r
84 int vctype;        // 0 / 1 :: map / system\r
85 \r
86 // -- local function parameters --\r
87 \r
88 char larg[20][40];\r
89 \r
90 // -- MAP vc stuff --\r
91 \r
92 char *functbl[512];\r
93 int mfuncs=0;\r
94 \r
95 // ================================= Code ====================================\r
96 \r
97 void HandleString();\r
98 void HandleFunction();\r
99 void HandleUserFunction();\r
100 void HandleFunctionType();\r
101 void EmitOperand();\r
102 \r
103 void EmitC (char c)\r
104 {\r
105   if (locate && locate == (int)(code - outbuf))\r
106     vcerr("Located.");\r
107 \r
108   *code++ = c;\r
109 }\r
110 \r
111 void EmitW (short w)\r
112 {\r
113   short *c=(short *)code;\r
114 \r
115   if (locate && locate == (int)(code - outbuf))\r
116     vcerr("Located.");\r
117 \r
118   *c=w; code+=2;\r
119 }\r
120 \r
121 void EmitD (int d)\r
122 {\r
123   long *c=(long *)code;\r
124 \r
125   if (locate && locate == (int)(code - outbuf))\r
126     vcerr("Located.");\r
127 \r
128   *c=d; code+=4;\r
129 }\r
130 \r
131 void EmitString(char *str)\r
132   { while ((*code++ = *str++)) ; }\r
133 \r
134 void HandleStringOperand()\r
135 {\r
136   if (NextIs("\""))\r
137   {\r
138     EmitC(s_IMMEDIATE);\r
139     GetString();\r
140     EmitString(token);\r
141     return;\r
142   }\r
143   GetToken();\r
144   if (token_type==IDENTIFIER && varcategory==op_STRING)\r
145   {\r
146     EmitC(s_GLOBAL);\r
147     EmitW(str[varidx].vsofs);\r
148     return;\r
149   }\r
150   if (token_type==IDENTIFIER && varcategory==op_SARRAY)\r
151   {\r
152     EmitC(s_ARRAY);\r
153     EmitW(str[varidx].vsofs);\r
154     Expect("[");\r
155     EmitOperand();\r
156     Expect("]");\r
157     return;\r
158   }\r
159   if (token_type==IDENTIFIER && varcategory==op_SLOCAL)\r
160   {\r
161     EmitC(s_LOCAL);\r
162     EmitC((char) varidx);\r
163     return;\r
164   }\r
165   if (TokenIs("str"))\r
166   {\r
167     EmitC(s_NUMSTR);\r
168     Expect("(");\r
169     EmitOperand();\r
170     Expect(")");\r
171     return;\r
172   }\r
173   if (TokenIs("left"))\r
174   {\r
175     EmitC(s_LEFT);\r
176     Expect("(");\r
177     HandleString();\r
178     Expect(",");\r
179     EmitOperand();\r
180     Expect(")");\r
181     return;\r
182   }\r
183   if (TokenIs("right"))\r
184   {\r
185     EmitC(s_RIGHT);\r
186     Expect("(");\r
187     HandleString();\r
188     Expect(",");\r
189     EmitOperand();\r
190     Expect(")");\r
191     return;\r
192   }\r
193   if (TokenIs("mid"))\r
194   {\r
195     EmitC(s_MID);\r
196     Expect("(");\r
197     HandleString();\r
198     Expect(",");\r
199     EmitOperand();\r
200     Expect(",");\r
201     EmitOperand();\r
202     Expect(")");\r
203     return;\r
204   }\r
205   if (TokenIs("chr"))\r
206   {\r
207     EmitC(s_CHR);\r
208     Expect("(");\r
209     EmitOperand();\r
210     Expect(")");\r
211     return;\r
212   }\r
213   else vcerr("Unknown string operand. ");\r
214 }\r
215 \r
216 void HandleString()\r
217 {\r
218   while (1)\r
219   {\r
220     HandleStringOperand();\r
221     if (NextIs("+"))\r
222     {\r
223        EmitC(s_ADD);\r
224        GetToken();\r
225        continue;\r
226     }\r
227     else\r
228     {\r
229        EmitC(s_END);\r
230        break;\r
231     }\r
232   }\r
233 }\r
234 \r
235 void EmitOperand();\r
236 void DoSomething();\r
237 \r
238 void HandleOperand()\r
239 {\r
240   GetToken();\r
241   if (token_type==DIGIT)\r
242   {\r
243      EmitC(op_IMMEDIATE);\r
244      EmitD(token_nvalue);\r
245      return;\r
246   }\r
247   if (token_type==IDENTIFIER)\r
248   {\r
249     if (varcategory==op_UVAR)\r
250     {\r
251       EmitC(op_UVAR);\r
252       EmitD(vars[varidx].varstartofs);\r
253       return;\r
254     }\r
255     if (varcategory==op_UVARRAY)\r
256     {\r
257       EmitC(op_UVARRAY);\r
258       EmitD(vars[varidx].varstartofs);\r
259       Expect("[");\r
260       EmitOperand();\r
261       Expect("]");\r
262       return;\r
263     }\r
264     if (varcategory==op_LVAR)\r
265     {\r
266       EmitC(op_LVAR);\r
267       EmitC((char) varidx);\r
268       return;\r
269     }\r
270     if (varcategory==op_HVAR0)\r
271     {\r
272       EmitC(op_HVAR0);\r
273       EmitC((char) varidx);\r
274       return;\r
275     }\r
276     if (varcategory==op_HVAR1)\r
277     {\r
278       EmitC(op_HVAR1);\r
279       EmitC((char) varidx);\r
280       Expect("[");\r
281       EmitOperand();\r
282       Expect("]");\r
283       return;\r
284     }\r
285   }\r
286   if (token_type==FUNCTION && token_subtype==op_BFUNC)\r
287   {\r
288     if (!returntypes[funcidx])\r
289     {\r
290       vcerr("%s() does not return a vlue.", token);\r
291     }\r
292     EmitC(op_BFUNC);\r
293     HandleFunction();\r
294     return;\r
295   }\r
296   if (token_type==FUNCTION && token_subtype==op_UFUNC)\r
297   {\r
298     if (!funcs[funcidx].returntype)\r
299     {\r
300       vcerr("%s() does not return a vlue.", token);\r
301     }\r
302     EmitC(op_UFUNC);\r
303     HandleUserFunction();\r
304     return;\r
305   }\r
306   vcerr("Unknown token.");\r
307 }\r
308 \r
309 void EmitOperand()\r
310 {\r
311   while (1)                // Modifier-process loop.\r
312   {\r
313      if (NextIs("("))\r
314      {\r
315         EmitC(op_GROUP);\r
316         GetToken();\r
317         EmitOperand();\r
318         Expect(")");\r
319      }\r
320      else HandleOperand();\r
321 \r
322      if (NextIs("+"))\r
323      {\r
324         EmitC(op_ADD);\r
325         GetToken();\r
326         continue;\r
327      }\r
328      else if (NextIs("-"))\r
329      {\r
330         EmitC(op_SUB);\r
331         GetToken();\r
332         continue;\r
333      }\r
334      else if (NextIs("/"))\r
335      {\r
336         EmitC(op_DIV);\r
337         GetToken();\r
338         continue;\r
339      }\r
340      else if (NextIs("*"))\r
341      {\r
342         EmitC(op_MULT);\r
343         GetToken();\r
344         continue;\r
345      }\r
346      else if (NextIs("%"))\r
347      {\r
348         EmitC(op_MOD);\r
349         GetToken();\r
350         continue;\r
351      }\r
352      else if (NextIs(">>"))\r
353      {\r
354         EmitC(op_SHR);\r
355         GetToken();\r
356         continue;\r
357      }\r
358      else if (NextIs("<<"))\r
359      {\r
360         EmitC(op_SHL);\r
361         GetToken();\r
362         continue;\r
363      }\r
364      else if (NextIs("&"))\r
365      {\r
366         EmitC(op_AND);\r
367         GetToken();\r
368         continue;\r
369      }\r
370      else if (NextIs("|"))\r
371      {\r
372         EmitC(op_OR);\r
373         GetToken();\r
374         continue;\r
375      }\r
376      else if (NextIs("^"))\r
377      {\r
378         EmitC(op_XOR);\r
379         GetToken();\r
380         continue;\r
381      }\r
382      else\r
383      {\r
384         EmitC(op_END);\r
385         break;\r
386      }\r
387   }\r
388 }\r
389 \r
390 void HandleFunction()\r
391 {\r
392   switch (funcidx)\r
393   {\r
394     case 0: vcfunc_Exit(); break;\r
395     case 1: Message(); break;\r
396     case 2: GenericFunc(3,1); break;\r
397     case 3: GenericFunc(4,1); break;\r
398     case 4: GenericFunc(5,1); break;\r
399     case 5: vc_loadimage(); break;\r
400     case 6: GenericFunc(7,5); break;\r
401     case 7: GenericFunc(8,5); break;\r
402     case 8: GenericFunc(9,0); break;\r
403     case 9: GenericFunc(10,0); break;\r
404     case 10: vc_AllocateEntity(); break;\r
405     case 11: GenericFunc(12,1); break;\r
406     case 12: vc_Map(); break;\r
407     case 13: vc_LoadFont(); break;\r
408     case 14: vc_PlayFLI(); break;\r
409     case 15: GenericFunc(16,2); break;\r
410     case 16: vc_PrintString(); break;\r
411     case 17: vc_LoadRaw(); break;\r
412     case 18: GenericFunc(19,4); break;\r
413     case 19: GenericFunc(20,1); break;\r
414     case 20: GenericFunc(21,7); break;\r
415     case 21: GenericFunc(22,0); break;\r
416     case 22: GenericFunc(23,0); break;\r
417     case 23: GenericFunc(24,1); break;\r
418     case 24: vc_EntityMove(); break;\r
419     case 25: GenericFunc(26,4); break;\r
420     case 26: GenericFunc(27,4); break;\r
421     case 27: GenericFunc(28,5); break;\r
422     case 28: GenericFunc(29,4); break;\r
423     case 29: GenericFunc(30,4); break;\r
424     case 30: GenericFunc(31,5); break;\r
425     case 31: GenericFunc(32,5); break;\r
426     case 32: vc_strlen(); break;\r
427     case 33: vc_strcmp(); break;\r
428     case 34: GenericFunc(35,0); break;\r
429     case 35: GenericFunc(36,1); break;\r
430     case 36: GenericFunc(37,1); break;\r
431     case 37: GenericFunc(38,1); break;\r
432     case 38: GenericFunc(39,3); break;\r
433     case 39: GenericFunc(40,2); break;\r
434     case 40: GenericFunc(41,1); break;\r
435     case 41: GenericFunc(42,1); break;\r
436     case 42: GenericFunc(43,3); break;\r
437     case 43: vc_HookRetrace(); break;\r
438     case 44: vc_HookTimer(); break;\r
439     case 45: GenericFunc(46,2); break;\r
440     case 46: vc_SetRString(); break;\r
441     case 47: GenericFunc(48,4); break;\r
442     case 48: GenericFunc(49,3); break;\r
443     case 49: GenericFunc(50,0); break;\r
444     case 50: vc_PartyMove(); break;\r
445     case 51: GenericFunc(52,1); break;\r
446     case 52: GenericFunc(53,1); break;\r
447     case 53: GenericFunc(54,1); break;\r
448     case 54: GenericFunc(55,0); break;\r
449     case 55: GenericFunc(56,1); break;\r
450     case 56: GenericFunc(57,1); break;\r
451     case 57: GenericFunc(58,5); break;\r
452     case 58: GenericFunc(59,5); break;\r
453     case 59: GenericFunc(60,2); break;\r
454     case 60: vc_HookKey(); break;\r
455     case 61: vc_PlayMusic(); break;\r
456     case 62: GenericFunc(63,0); break;\r
457     case 63: GenericFunc(64,5); break;\r
458     case 64: vc_OpenFile(); break;\r
459     case 65: GenericFunc(66,1); break;\r
460     case 66: vc_QuickRead(); break;\r
461     case 67: GenericFunc(68,1); break;\r
462     case 68: GenericFunc(69,1); break;\r
463     case 69: GenericFunc(70,0); break;\r
464     case 70: GenericFunc(71,0); break;\r
465     case 71: GenericFunc(72,7); break;\r
466     case 72: GenericFunc(73,15); break;\r
467     case 73: vc_CacheSound(); break;\r
468     case 74: GenericFunc(75,0); break;\r
469     case 75: GenericFunc(76,3); break;\r
470     case 76: GenericFunc(77,7); break;\r
471     case 77: GenericFunc(78,4); break;\r
472     case 78: GenericFunc(79,4); break;\r
473     case 79: vc_val(); break;\r
474     case 80: GenericFunc(81,7); break;\r
475     case 81: GenericFunc(82,5); break;\r
476     case 82: vc_Log(); break;\r
477     case 83: GenericFunc(84,2); break;\r
478     case 84: GenericFunc(85,2); break;\r
479     case 85: GenericFunc(86,3); break;\r
480     case 86: GenericFunc(87,1); break;\r
481     case 87: GenericFunc(88,1); break;\r
482     case 88: GenericFunc(89,1); break;\r
483     case 89: vc_fgetline(); break;\r
484     case 90: vc_fgettoken(); break;\r
485     case 91: vc_fwritestring(); break;\r
486     case 92: GenericFunc(93, 3); break;\r
487     case 93: vc_frename(); break;\r
488     case 94: vc_fdelete(); break;\r
489     case 95: vc_fwopen(); break;\r
490     case 96: GenericFunc(97, 1); break;\r
491     case 97: GenericFunc(98, 3); break;\r
492     case 98: GenericFunc(99, 3); break;\r
493     case 99: GenericFunc(100, 6); break;\r
494     case 100: GenericFunc(101, 0); break;\r
495     case 101: GenericFunc(102, 7); break;\r
496     case 102: GenericFunc(103, 1); break;\r
497     case 103: GenericFunc(104, 1); break;\r
498     case 104: GenericFunc(105, 1); break;\r
499     case 105: vc_asc(); break;\r
500     case 106: GenericFunc(107, 1); break;\r
501     case 107: vc_NumForScript(); break;\r
502     case 108: vc_FileSize(); break;\r
503     case 109: GenericFunc(110, 1); break;\r
504     case 110: GenericFunc(111, 0); break;\r
505     default: vcerr("Internal error. Unknown standard function.");\r
506   }\r
507 }\r
508 \r
509 void HandleUserFunction()\r
510 {\r
511   int i, idx;\r
512 \r
513   idx=funcidx;\r
514   EmitW((short) idx);\r
515   Expect("(");\r
516   for (i=0; i<funcs[idx].numargs; i++)\r
517   {\r
518     if (i) Expect(",");\r
519     if (funcs[idx].argtype[i]==INT) EmitOperand();\r
520     if (funcs[idx].argtype[i]==STRING) HandleString();\r
521   }\r
522   Expect(")");\r
523 }\r
524 \r
525 void HandleFunctionType()\r
526 {\r
527   if (token_subtype==op_BFUNC)\r
528   {\r
529     EmitC(opEXEC_STDLIB);\r
530     HandleFunction();\r
531   }\r
532   else\r
533   if (token_subtype==op_UFUNC)\r
534   {\r
535     EmitC(opEXEC_EXTERNFUNC);\r
536     HandleUserFunction();\r
537   }\r
538 }\r
539 \r
540 void HandleIfComponent()\r
541 { char ot=0;\r
542 \r
543   if (NextIs("!"))\r
544   {\r
545    ot=i_ZERO;\r
546    GetToken();\r
547   }\r
548   EmitOperand();\r
549 \r
550   if (NextIs("="))  { ot=i_EQUALTO;            GetToken(); }\r
551   if (NextIs("!=")) { ot=i_NOTEQUAL;           GetToken(); }\r
552   if (NextIs(">"))  { ot=i_GREATERTHAN;        GetToken(); }\r
553   if (NextIs(">=")) { ot=i_GREATERTHANOREQUAL; GetToken(); }\r
554   if (NextIs("<"))  { ot=i_LESSTHAN;           GetToken(); }\r
555   if (NextIs("<=")) { ot=i_LESSTHANOREQUAL;    GetToken(); }\r
556 \r
557   if (!ot) EmitC(i_NONZERO);\r
558   else if (ot==i_ZERO) EmitC(i_ZERO);\r
559   else\r
560   {\r
561     EmitC(ot);\r
562     EmitOperand();\r
563   }\r
564 }\r
565 \r
566 void HandleIfGroup()\r
567 {\r
568   while (1)\r
569   {\r
570     HandleIfComponent();\r
571 \r
572     if (NextIs("&&"))\r
573     {\r
574        EmitC(i_AND);\r
575        GetToken();\r
576        continue;\r
577     }\r
578     else if (NextIs("||"))\r
579     {\r
580        EmitC(i_OR);\r
581        GetToken();\r
582        continue;\r
583     }\r
584     else\r
585     {\r
586        GetToken();\r
587        if (!TokenIs(")") && !TokenIs(";"))\r
588          vcerr("Syntax error.");\r
589        EmitC(i_UNGROUP);\r
590        break;\r
591     }\r
592   }\r
593 }\r
594 \r
595 void ProcessIf()\r
596 {\r
597   char *falseofs = 0;\r
598   char *elseofs = 0;\r
599   char *b = 0;\r
600 \r
601   EmitC(opIF);\r
602   Expect("(");\r
603   HandleIfGroup();\r
604 \r
605   falseofs=code;\r
606   EmitD(0);          // We'll come back to this and fix it up.\r
607 \r
608   if (!NextIs("{"))\r
609   {\r
610     DoSomething();\r
611     if (NextIs("else"))\r
612     {\r
613       EmitC(opGOTO);\r
614       elseofs=code;\r
615       EmitD(0);\r
616     }\r
617   }\r
618   else\r
619   {\r
620     Expect("{");\r
621     while (!NextIs("}")) DoSomething();\r
622     Expect("}");\r
623     if (NextIs("else"))\r
624     {\r
625       EmitC(opGOTO);\r
626       elseofs=code;\r
627       EmitD(0);\r
628     }\r
629   }\r
630 \r
631   b=code;         // Put correct false-execution offset thingy.\r
632   code=falseofs;\r
633   EmitD((int) b - (int) outbuf);\r
634   code=b;\r
635 \r
636   if (NextIs("else"))\r
637   {\r
638     GetToken();\r
639     if (!NextIs("{"))\r
640     {\r
641       DoSomething();\r
642     }\r
643     else\r
644     {\r
645       Expect("{");\r
646       while (!NextIs("}")) DoSomething();\r
647       Expect("}");\r
648     }\r
649     b=code;         // Put correct else-execution offset thingy.\r
650     code=elseofs;\r
651     EmitD((int) b - (int) outbuf);\r
652     code=b;\r
653   }\r
654 }\r
655 \r
656 void ProcessWhile()\r
657 { char *falseofs, *top, *b;\r
658 \r
659   top=code;\r
660   EmitC(opIF);\r
661   Expect("(");\r
662   HandleIfGroup();\r
663 \r
664   falseofs=code;\r
665   EmitD(0);          // We'll come back to this and fix it up.\r
666 \r
667   if (!NextIs("{"))\r
668   {\r
669     DoSomething();\r
670     EmitC(opGOTO);\r
671     EmitD((int) top - (int) outbuf);\r
672   }\r
673   else\r
674   {\r
675     Expect("{");\r
676     while (!NextIs("}")) DoSomething();\r
677     Expect("}");\r
678     EmitC(opGOTO);\r
679     EmitD((int) top - (int) outbuf);\r
680   }\r
681 \r
682   b=code;         // Put correct false-execution offset thingy.\r
683   code=falseofs;\r
684   EmitD((int) b - (int) outbuf);\r
685   code=b;\r
686 }\r
687 \r
688 void ProcessFor()\r
689 { char *src1, *src2, *loopstartpos, *srctmp;\r
690 \r
691   Expect("(");\r
692   while (!TokenIs(";"))\r
693     DoSomething();    // Emit initialization code.\r
694 \r
695   src1=src;         // Store position of loop conditional\r
696   while (!NextIs(";")) GetToken(); GetToken();\r
697   src2=src;         // Store position of end-of-loop code\r
698 \r
699   while (!NextIs(")")) GetToken(); GetToken();\r
700   loopstartpos=(char *) (int) code - (int) outbuf;\r
701 \r
702   if (!NextIs("{"))\r
703   {\r
704     DoSomething();\r
705   }\r
706   else\r
707   {\r
708     Expect("{");\r
709     while (!NextIs("}")) DoSomething();\r
710     Expect("}");\r
711   }\r
712   srctmp=src;\r
713   src=src2;\r
714   while (!TokenIs(")"))\r
715     DoSomething();\r
716   src=src1;\r
717   EmitC(opIF);\r
718   HandleIfGroup();\r
719   EmitD((int) code - (int) outbuf +9);\r
720   EmitC(opGOTO);\r
721   EmitD((int) loopstartpos);\r
722 \r
723   src=srctmp;\r
724 }\r
725 \r
726 void HandleAssign()\r
727 {\r
728   int vc;\r
729 \r
730   vc=varcategory;\r
731   EmitC(opASSIGN);\r
732   if (vc==op_UVAR)\r
733   {\r
734     EmitC(op_UVAR);\r
735     EmitD(vars[varidx].varstartofs);\r
736   }\r
737   else if (vc==op_UVARRAY)\r
738   {\r
739     EmitC(op_UVARRAY);\r
740     EmitD(vars[varidx].varstartofs);\r
741     Expect("[");\r
742     EmitOperand();\r
743     Expect("]");\r
744   }\r
745   else if (vc==op_LVAR)\r
746   {\r
747     EmitC(op_LVAR);\r
748     EmitC((char) varidx);\r
749   }\r
750   else if (vc==op_HVAR0)\r
751   {\r
752     EmitC(op_HVAR0);\r
753     EmitC((char) varidx);\r
754   }\r
755   else if (vc==op_HVAR1)\r
756   {\r
757     EmitC(op_HVAR1);\r
758     EmitC((char) varidx);\r
759     Expect("[");\r
760     EmitOperand();\r
761     Expect("]");\r
762   }\r
763   else if (vc==op_STRING)\r
764   {\r
765     EmitC(op_STRING);\r
766     EmitW((short) str[varidx].vsofs);\r
767   }\r
768   else if (vc==op_SARRAY)\r
769   {\r
770     EmitC(op_SARRAY);\r
771     EmitW((short) str[varidx].vsofs);\r
772     Expect("[");\r
773     EmitOperand();\r
774     Expect("]");\r
775   }\r
776   else if (vc==op_SLOCAL)\r
777   {\r
778     EmitC(op_SLOCAL);\r
779     EmitW((short) varidx);\r
780   }\r
781   GetToken();\r
782   if (TokenIs("++")) { EmitC(a_INC); GetToken(); return; } else\r
783   if (TokenIs("--")) { EmitC(a_DEC); GetToken(); return; } else\r
784   if (TokenIs("+=")) { EmitC(a_INCSET); } else\r
785   if (TokenIs("-=")) { EmitC(a_DECSET); } else\r
786   if (TokenIs("="))  { EmitC(a_SET); } else\r
787   vcerr("Invalid assignment operator.");\r
788   if (vc==op_STRING) HandleString();\r
789   else if (vc==op_SARRAY) HandleString();\r
790   else if (vc==op_SLOCAL) HandleString();\r
791   else EmitOperand();\r
792   GetToken();\r
793 }\r
794 \r
795 int c=0;\r
796 \r
797 void HandleReturn()\r
798 {\r
799   if (!vctype)\r
800   {\r
801     Expect(";");\r
802     EmitC(opRETURN);\r
803     return;\r
804   }\r
805   if (!funcs[c].returntype)\r
806   {\r
807     Expect(";");\r
808     EmitC(opRETURN);\r
809     return;\r
810   }\r
811   if (funcs[c].returntype==1)\r
812   {\r
813     EmitC(opSETRETVAL);\r
814     EmitOperand();\r
815     Expect(";");\r
816     EmitC(opRETURN);\r
817     return;\r
818   }\r
819 }\r
820 \r
821 void ProcessSwitch()\r
822 { char *buf,*retrptr;\r
823 \r
824   EmitC(opSWITCH);\r
825   Expect("(");\r
826   EmitOperand();\r
827   Expect(")");\r
828   Expect("{");\r
829 \r
830   // case .. option loop\r
831 \r
832   while (!NextIs("}"))\r
833   {\r
834     Expect("case");\r
835     EmitC(opCASE);\r
836     EmitOperand();\r
837     Expect(":");\r
838     retrptr=code;\r
839     EmitD(0);\r
840     while (!NextIs("case") && !NextIs("}")) DoSomething();\r
841     EmitC(opRETURN);\r
842     buf=code;\r
843     code=retrptr;\r
844     EmitD((int) buf - (int) outbuf);\r
845     code=buf;\r
846   }\r
847   Expect("}");\r
848   EmitC(opRETURN);\r
849 }\r
850 \r
851 void DoSomething(void)\r
852 {\r
853   GetToken();\r
854   if (TokenIs("return"))      { HandleReturn(); return; }\r
855   if (token_type==FUNCTION)   { HandleFunctionType(); Expect(";"); return; }\r
856   if (token_type==IDENTIFIER) { HandleAssign(); return; }\r
857   if (TokenIs("if"))          { ProcessIf(); return; }\r
858   if (TokenIs("while"))       { ProcessWhile(); return; }\r
859   if (TokenIs("for"))         { ProcessFor(); return; }\r
860   if (TokenIs("switch"))      { ProcessSwitch(); return; }\r
861   vcerr("Unknown token.");\r
862 }\r
863 \r
864 void DumpSystemIdx()\r
865 { FILE *f;\r
866 \r
867   vprint("Dumping system.idx index file.");\r
868   f=fopen("system.idx","wb");\r
869 \r
870   fwrite(&numvars, 1, 4, f);\r
871   fwrite(&vars, sizeof vars / 500, numvars, f);\r
872   fwrite(&numfuncs, 1, 4, f);\r
873   fwrite(&funcs, sizeof funcs / 700, numfuncs, f);\r
874   fwrite(&numstr, 1, 4, f);\r
875   fwrite(&str, sizeof str / 300, numstr, f);\r
876   fclose(f);\r
877 }\r
878 \r
879 void ReadSystemIdx()\r
880 { FILE *f;\r
881 \r
882   if (!(f=fopen("system.idx","rb")))\r
883     err("Could not access system.idx.");\r
884 \r
885   fread(&numvars, 1, 4, f);\r
886   fread(&vars, sizeof vars / 500, numvars, f);\r
887   fread(&numfuncs, 1, 4, f);\r
888   fread(&funcs, sizeof funcs / 700, numfuncs, f);\r
889   fread(&numstr, 1, 4, f);\r
890   fread(&str, sizeof str / 300, numstr, f);\r
891   fclose(f);\r
892 }\r
893 \r
894 void DoLocalVariables(int c)\r
895 {\r
896   int na;\r
897 \r
898   na=funcs[c].numargs;\r
899   while (NextIs("int") || NextIs("string"))\r
900   {\r
901     GetToken();\r
902     if (TokenIs("int"))\r
903     {\r
904       funcs[c].argtype[na]=INT;\r
905       GetToken();\r
906       memcpy(larg[na++], token, 40);\r
907       while (!NextIs(";"))\r
908       {\r
909         Expect(",");\r
910         funcs[c].argtype[na]=INT;\r
911         GetToken();\r
912         memcpy(larg[na++], token, 40);\r
913       }\r
914       Expect(";");\r
915     }\r
916     if (TokenIs("string"))\r
917     {\r
918       funcs[c].argtype[na]=STRING;\r
919       GetToken();\r
920       memcpy(larg[na++], token, 40);\r
921       while (!NextIs(";"))\r
922       {\r
923         Expect(",");\r
924         funcs[c].argtype[na]=STRING;\r
925         GetToken();\r
926         memcpy(larg[na++], token, 40);\r
927       }\r
928       Expect(";");\r
929     }\r
930   }\r
931   funcs[c].numlocals=na;\r
932 }\r
933 \r
934 void CompileMAP(char *fname)\r
935 { FILE *f;\r
936   int i;\r
937 \r
938   // Compiles a map-based VC.\r
939   i=strlen(fname);\r
940   memcpy(strbuf, fname, i);\r
941   strbuf[i]='.';\r
942   strbuf[i+1]='V';\r
943   strbuf[i+2]='C';\r
944   strbuf[i+3]=0;\r
945 \r
946   PreProcess(strbuf);\r
947 \r
948   source=(char *) malloc(1000000);\r
949   memset(source, 0, 1000000);\r
950   outbuf=(char *) malloc(1000000);\r
951   memset(outbuf, 0, 1000000);\r
952   if (!(f=fopen("vcctemp.$$$","rb")))\r
953     err("Could not open source file.");\r
954   fread(source, 1, 1000000, f);\r
955   fclose(f);\r
956 \r
957   ReadSystemIdx();\r
958 \r
959   src=source;\r
960   code=outbuf;\r
961   vctype=0;\r
962 \r
963   while (*src)\r
964   {\r
965     functbl[mfuncs]=(char *) (int) code - (int) outbuf;\r
966     mfuncs++;\r
967     Expect("event");\r
968     Expect("{");\r
969     while (!NextIs("}")) DoSomething();\r
970     Expect("}");\r
971     EmitC(opRETURN);\r
972     ParseWhitespace();\r
973   }\r
974   dprint("%s.vc (%i lines)", fname, lines);\r
975 }\r
976 \r
977 void SkipBrackets()\r
978 {\r
979   while (!NextIs("}"))\r
980   {\r
981     if (!*src)\r
982       err("No matching bracket.");\r
983     GetToken();\r
984     if (TokenIs("{")) SkipBrackets();\r
985   }\r
986   GetToken();\r
987 }\r
988 \r
989 void CheckDup()\r
990 {\r
991   int i=0; // bitch!\r
992 \r
993   while (i<numhardfuncs)\r
994   {\r
995     if (!strcmp(hardfuncs[i], token)) break;\r
996     i++;\r
997   }\r
998   if (i<numhardfuncs)\r
999   {\r
1000     vcerr("%s: Duplicate identifier.", token);\r
1001   }\r
1002   i=0;\r
1003   while (i<numhardvar0)\r
1004   {\r
1005     if (!strcmp(hardvar0[i], token)) break;\r
1006     i++;\r
1007   }\r
1008   if (i<numhardvar0)\r
1009   {\r
1010     vcerr("%s: Duplicate identifier.", token);\r
1011   }\r
1012   i=0;\r
1013   while (i<numhardvar1)\r
1014   {\r
1015     if (!strcmp(hardvar1[i], token)) break;\r
1016     i++;\r
1017   }\r
1018   if (i<numhardvar1)\r
1019   {\r
1020     vcerr("%s: Duplicate identifier.", token);\r
1021   }\r
1022   i=0;\r
1023   while (i<numfuncs)\r
1024   {\r
1025     if (!strcmp(funcs[i].fname, token)) break;\r
1026     i++;\r
1027   }\r
1028   if (i<numfuncs)\r
1029   {\r
1030     vcerr("%s: Duplicate identifier.", token);\r
1031   }\r
1032 \r
1033   i=0;\r
1034   while (i<numvars)\r
1035   {\r
1036     if (!strcmp(vars[i].vname, token)) break;\r
1037     i++;\r
1038   }\r
1039   if (i<numvars)\r
1040   {\r
1041     vcerr("%s: Duplicate identifier.", token);\r
1042   }\r
1043   i=0;\r
1044   while (i<numstr)\r
1045   {\r
1046     if (!strcmp(str[i].vname, token)) break;\r
1047     i++;\r
1048   }\r
1049   if (i<numstr)\r
1050   {\r
1051     vcerr("%s: Duplicate identifier.", token);\r
1052   }\r
1053 }\r
1054 \r
1055 void CompileSystem()\r
1056 {\r
1057   FILE *f = 0;\r
1058   int na = 0;\r
1059   int type = 0;\r
1060   int i = 0;\r
1061 \r
1062   // Compiles a map-based VC.\r
1063 \r
1064   PreProcess("system.vc");\r
1065 \r
1066   source = (char *) malloc(1000000);\r
1067   memset(source, 0, 1000000);\r
1068   outbuf = (char *) malloc(1000000);\r
1069   memset(outbuf, 0, 1000000);\r
1070 \r
1071   if (!(f=fopen("vcctemp.$$$","rb")))\r
1072     err("Could not open source file.");\r
1073 \r
1074   fread(source, 1, 1000000, f);\r
1075 \r
1076   fclose(f);\r
1077 \r
1078   src=source;\r
1079   code=outbuf;\r
1080 \r
1081   vprint("First pass...");\r
1082   vctype=1; tlines=0;\r
1083   while (*src)\r
1084   {\r
1085     // system.vc is compiled in a two-pass system. The first pass simply\r
1086     // goes through the system.vc file and sets up declarations for all\r
1087     // global variables and function declarations. So system.vc won't\r
1088     // have to worry about forward declarations or anything.\r
1089 \r
1090     na=(int) src;\r
1091     GetToken();\r
1092     if (TokenIs("string"))\r
1093     {\r
1094       while (1)\r
1095       {\r
1096         GetToken();\r
1097         CheckDup();\r
1098         memcpy(str[numstr].vname, token, strlen(token));\r
1099         str[numstr].vsofs=sstartofs;\r
1100         if (NextIs("["))\r
1101         {\r
1102           GetToken();\r
1103           GetToken();\r
1104           str[numstr].arraylen=token_nvalue;\r
1105           Expect("]");\r
1106         }\r
1107         else str[numstr].arraylen=1;\r
1108         sstartofs+=str[numstr].arraylen;\r
1109         vprint("Decl %s of type string, size %i. [%i]",\r
1110           str[numstr].vname, str[numstr].arraylen, str[numstr].vsofs);\r
1111         numstr++;\r
1112         if (!NextIs(",")) break;\r
1113         GetToken();\r
1114       }\r
1115       Expect(";");\r
1116     }\r
1117     if (TokenIs("int"))\r
1118     {\r
1119       GetToken();\r
1120       if (NextIs("(")) type=0; else type=1;\r
1121       src=(char *) na;\r
1122       GetToken();\r
1123     }\r
1124     if (TokenIs("void") || (TokenIs("int") && !type))\r
1125     {\r
1126       if (TokenIs("void")) funcs[numfuncs].returntype=0;\r
1127       if (TokenIs("int")) funcs[numfuncs].returntype=1;\r
1128       GetToken();\r
1129       CheckDup();\r
1130       memcpy(funcs[numfuncs].fname,token,strlen(token));\r
1131       funcs[numfuncs].numargs=0;\r
1132       Expect("(");\r
1133       while (!NextIs(")"))\r
1134       {\r
1135         GetToken();\r
1136         na=funcs[numfuncs].numargs;\r
1137         if (TokenIs("int")) { funcs[numfuncs].argtype[na]=INT; } else\r
1138         if (TokenIs("string")) { funcs[numfuncs].argtype[na]=STRING; }\r
1139         else vcerr("Invalid arguement declaration.");\r
1140         GetToken();\r
1141         if (NextIs(",")) GetToken();\r
1142         funcs[numfuncs].numargs++;\r
1143       }\r
1144       Expect(")");\r
1145       Expect("{");\r
1146       SkipBrackets();\r
1147       vprint("Found %s declaration for %s, %i parameters.",\r
1148         funcs[numfuncs].returntype ? "int" : "void",\r
1149         funcs[numfuncs].fname, funcs[numfuncs].numargs);\r
1150       numfuncs++;\r
1151     }\r
1152     if (TokenIs("int") && type)\r
1153     {\r
1154       while (1)\r
1155       {\r
1156         GetToken();\r
1157         CheckDup();\r
1158         memcpy(vars[numvars].vname, token, strlen(token));\r
1159         vars[numvars].varstartofs=curstartofs;\r
1160         if (NextIs("["))\r
1161         {\r
1162           GetToken();\r
1163           GetToken();\r
1164           vars[numvars].arraylen=token_nvalue;\r
1165           Expect("]");\r
1166         }\r
1167         else vars[numvars].arraylen=1;\r
1168         curstartofs+=vars[numvars].arraylen;\r
1169         vprint("Decl %s of type int, size %i. [%i]", vars[numvars].vname,\r
1170           vars[numvars].arraylen, vars[numvars].varstartofs);\r
1171         numvars++;\r
1172         if (!NextIs(",")) break;\r
1173         GetToken();\r
1174       }\r
1175       Expect(";");\r
1176     }\r
1177   }\r
1178   dprint("system.vc: %i ints, %i strings, %i functions",\r
1179     numvars, numstr, numfuncs);\r
1180 \r
1181   vprint("Second pass...");\r
1182   src=source; tlines=0;\r
1183   while (*src)\r
1184   {\r
1185     // Everything in system.vc will either be a global var decl or\r
1186     // a function definition.\r
1187 \r
1188     na=(int) src;\r
1189     GetToken();\r
1190     if (TokenIs("string"))\r
1191     {\r
1192       while (1)\r
1193       {\r
1194         GetToken();\r
1195         if (NextIs("["))\r
1196         {\r
1197           GetToken();\r
1198           GetToken();\r
1199           Expect("]");\r
1200         }\r
1201         if (!NextIs(",")) break;\r
1202         GetToken();\r
1203       }\r
1204       Expect(";");\r
1205     }\r
1206    if (TokenIs("int"))\r
1207     {\r
1208       GetToken();\r
1209       if (NextIs("(")) type=0; else type=1;\r
1210       src=(char *) na;\r
1211       GetToken();\r
1212     }\r
1213     if (TokenIs("void") || (TokenIs("int") && !type))\r
1214     {\r
1215       funcs[c].syscodeofs=(int) code - (int) outbuf;\r
1216       GetToken();\r
1217       Expect("(");\r
1218       i=0;\r
1219       memset(&larg, 0, 480);\r
1220       while (!NextIs(")"))\r
1221       {\r
1222         GetToken();\r
1223         GetToken();\r
1224         memcpy(larg[i], token, 40);\r
1225         if (NextIs(",")) GetToken();\r
1226         i++;\r
1227       }\r
1228       Expect(")");\r
1229       Expect("{");\r
1230       DoLocalVariables(c);\r
1231       while (!NextIs("}")) DoSomething();\r
1232       EmitC(opRETURN);\r
1233       Expect("}");\r
1234       c++;\r
1235     }\r
1236     if (TokenIs("int") && type)\r
1237     {\r
1238       while (1)\r
1239       {\r
1240         GetToken();\r
1241         if (NextIs("["))\r
1242         {\r
1243           GetToken();\r
1244           GetToken();\r
1245           Expect("]");\r
1246         }\r
1247         if (!NextIs(",")) break;\r
1248         GetToken();\r
1249       }\r
1250       Expect(";");\r
1251     }\r
1252   }\r
1253   dprint("system.vc (%i lines, %i total)", lines, tlines);\r
1254 \r
1255   DumpSystemIdx();\r
1256 }\r