source: dev/BasicCompiler_Common/Compile.cpp@ 34

Last change on this file since 34 was 34, checked in by dai_9181, 17 years ago

スコープ処理を統一した。関数の途中でReturnしても、スコープにあるローカルオブジェクトを正確に破棄できるようにした。

File size: 15.8 KB
Line 
1#include "../BasicCompiler_Common/common.h"
2
3#ifdef _AMD64_
4#include "../BasicCompiler64/opcode.h"
5#else
6#include "../BasicCompiler32/opcode.h"
7#endif
8
9int obp,obp_AllocSize;
10int GlobalOpBufferSize;
11char *OpBuffer;
12
13//ラベルアドレス
14LABEL *pLabelNames;
15int MaxLabelNum;
16
17//Continueアドレス
18DWORD dwContinueAddress;
19
20//Caseスケジュール
21DWORD *pCaseSchedule;
22int CaseScheduleNum;
23int NowCaseSchedule;
24
25//プロシージャ抜け出しスケジュール(Exit Sub/Function)
26DWORD *pExitSubSchedule;
27int ExitSubScheduleNum;
28
29//Goto未知ラベル スケジュール
30GOTOLABELSCHEDULE *pGotoLabelSchedule;
31int GotoLabelScheduleNum;
32
33//データ テーブル
34char *DataTable;
35int DataTableSize;
36
37//グローバル変数初期バッファ
38BYTE *initGlobalBuf;
39
40//With情報
41WITHINFO WithInfo;
42
43
44///////////////////////////////////////////////////
45// トークンを取得
46///////////////////////////////////////////////////
47void GetIdentifierToken( char *token, const char *source, int &pos ){
48 for( int i=0; ; i++, pos++ ){
49 if( ! IsVariableChar( source[pos] ) ){
50 token[i] = 0;
51 break;
52 }
53 token[i] = source[pos];
54 }
55}
56
57
58///////////////////////////////////////////////////
59// 対になっているステートメントを飛び越す
60// ※グローバル領域用
61///////////////////////////////////////////////////
62int JumpStatement(const char *source, int &pos){
63 if( source[pos] != 1 ) return 0;
64
65 if( ! IsCommandDelimitation( source[pos - 1] ) ){
66 //直前がコマンド区切りではない場合
67 return 0;
68 }
69
70 char cStatement = source[pos + 1];
71
72 char cEnd = GetEndXXXCommand( cStatement );
73 if( cEnd == 0 ) return 0;
74
75 pos += 2;
76 while( ! ( source[pos] == 1 && source[pos + 1] == cEnd ) ){
77
78 if( source[pos] == '\0' ){
79 char temporary[64];
80 GetDefaultNameFromES( cStatement, temporary );
81 SetError( 22, temporary, pos );
82 return -1;
83 }
84
85 pos++;
86 }
87 if( ! ( source[pos] == '\0' || source[pos + 2] == '\0' ) ){
88 pos += 2;
89 }
90
91 return 1;
92}
93
94
95void NextLine(void){
96 extern HANDLE hHeap;
97 extern int MaxLineInfoNum;
98 extern LINEINFO *pLineInfo;
99 if(MaxLineInfoNum){
100 if(pLineInfo[MaxLineInfoNum-1].TopObp==obp){
101 pLineInfo[MaxLineInfoNum-1].TopCp=cp;
102 return;
103 }
104 }
105 pLineInfo=(LINEINFO *)HeapReAlloc(hHeap,0,pLineInfo,(MaxLineInfoNum+1)*sizeof(LINEINFO));
106 pLineInfo[MaxLineInfoNum].TopCp=cp;
107 pLineInfo[MaxLineInfoNum].TopObp=obp;
108
109 extern BOOL bDebugSupportProc;
110 extern BOOL bSystemProc;
111 pLineInfo[MaxLineInfoNum].dwCodeType=0;
112 if(bDebugSupportProc)
113 pLineInfo[MaxLineInfoNum].dwCodeType|=CODETYPE_DEBUGPROC;
114 if(bSystemProc)
115 pLineInfo[MaxLineInfoNum].dwCodeType|=CODETYPE_SYSTEMPROC;
116
117 MaxLineInfoNum++;
118}
119
120void ChangeOpcode(char *Command){
121 extern HANDLE hHeap;
122 int i,i2;
123
124 if(Command[0]=='\0') return;
125 if(Command[0]=='*'&&IsVariableTopChar(Command[1])){
126 //Goto先ラベル
127 pLabelNames=(LABEL *)HeapReAlloc(hHeap,0,pLabelNames,(MaxLabelNum+1)*sizeof(LABEL));
128 pLabelNames[MaxLabelNum].pName=(char *)HeapAlloc(hHeap,0,lstrlen(Command+1)+1);
129 lstrcpy(pLabelNames[MaxLabelNum].pName,Command+1);
130 pLabelNames[MaxLabelNum].address=obp;
131 MaxLabelNum++;
132
133 //書き込みスケジュール
134 for(i=0;i<GotoLabelScheduleNum;i++){
135 if(lstrcmp(pGotoLabelSchedule[i].pName,Command+1)==0){
136 *((long *)(OpBuffer+pGotoLabelSchedule[i].pos))=obp-(pGotoLabelSchedule[i].pos+sizeof(long));
137
138 HeapDefaultFree(pGotoLabelSchedule[i].pName);
139
140 //詰める
141 GotoLabelScheduleNum--;
142 for(i2=i;i2<GotoLabelScheduleNum;i2++){
143 pGotoLabelSchedule[i2].pName=pGotoLabelSchedule[i2+1].pName;
144 pGotoLabelSchedule[i2].line=pGotoLabelSchedule[i2+1].line;
145 pGotoLabelSchedule[i2].pos=pGotoLabelSchedule[i2+1].pos;
146 }
147 i--;
148 continue;
149 }
150 }
151 return;
152 }
153 if(Command[0]==1){
154 switch(Command[1]){
155 case ESC_CONST:
156 OpcodeDim(Command+2, DIMFLAG_CONST);
157 break;
158
159 case ESC_TYPEDEF:
160 break;
161
162 case ESC_STATIC:
163 OpcodeDim(Command+2,DIMFLAG_STATIC);
164 break;
165
166 case ESC_IF:
167 OpcodeIf(Command+2);
168 break;
169 case ESC_EXITWHILE:
170 obj_LexScopes.ExitWhile();
171 break;
172 case ESC_EXITFOR:
173 obj_LexScopes.ExitFor();
174 break;
175 case ESC_EXITDO:
176 obj_LexScopes.ExitDo();
177 break;
178 case ESC_CONTINUE:
179 OpcodeContinue();
180 break;
181
182 case ESC_EXITSUB:
183 case ESC_EXITFUNCTION:
184 case ESC_EXITMACRO:
185 OpcodeExitSub();
186 break;
187
188 case ESC_SELECTCASE:
189 OpcodeSelect(Command+2);
190 break;
191 case ESC_CASE:
192 case ESC_CASEELSE:
193 OpcodeCase(Command+2);
194 break;
195
196 case ESC_WITH:
197 extern WITHINFO WithInfo;
198
199 WithInfo.ppName=(char **)HeapReAlloc(hHeap,0,WithInfo.ppName,(WithInfo.num+1)*sizeof(char **));
200 WithInfo.ppName[WithInfo.num]=(char *)HeapAlloc(hHeap,0,lstrlen(Command+2)+1);
201 lstrcpy(WithInfo.ppName[WithInfo.num],Command+2);
202
203 WithInfo.pWithCp=(int *)HeapReAlloc(hHeap,0,WithInfo.pWithCp,(WithInfo.num+1)*sizeof(int));
204 WithInfo.pWithCp[WithInfo.num]=cp;
205
206 WithInfo.num++;
207 break;
208 case ESC_ENDWITH:
209 if(WithInfo.num<=0){
210 SetError(12,"End With",cp);
211 return;
212 }
213 WithInfo.num--;
214 HeapDefaultFree(WithInfo.ppName[WithInfo.num]);
215 break;
216 case ESC_DECLARE:
217 break;
218
219 //Tryによる例外処理
220 case ESC_TRY:
221 Exception::TryCommand();
222 break;
223 case ESC_CATCH:
224 Exception::CatchCommand();
225 break;
226 case ESC_FINALLY:
227 Exception::FinallyCommand();
228 break;
229 case ESC_ENDTRY:
230 Exception::EndTryCommand();
231 break;
232 case ESC_THROW:
233 Exception::ThrowCommand( Command + 2 );
234 break;
235
236 default:
237 char temporary[64];
238 GetDefaultNameFromES(Command[1],temporary);
239 SetError(30,temporary,cp);
240 break;
241 }
242 return;
243 }
244 switch(MAKEWORD(Command[1],Command[0])){
245 case COM_DIM:
246 OpcodeDim(Command+2,0);
247 break;
248 case COM_DELETE:
249 OpcodeDelete(Command+2);
250 break;
251
252 case COM_GOTO:
253 OpcodeGoto(Command+2);
254 break;
255 case COM_WHILE:
256 OpcodeWhile(Command+2);
257 break;
258 case COM_FOR:
259 OpcodeFor(Command+2);
260 break;
261 case COM_DO:
262 OpcodeDo(Command+2);
263 break;
264
265 case COM_GOSUB:
266 OpcodeGosub(Command+2);
267 break;
268 case COM_RETURN:
269 OpcodeReturn(Command+2);
270 break;
271
272 case COM_SETDOUBLE:
273 OpcodeSetPtrData(Command+2,DEF_DOUBLE);
274 break;
275 case COM_SETSINGLE:
276 OpcodeSetPtrData(Command+2,DEF_SINGLE);
277 break;
278 case COM_SETQWORD:
279 OpcodeSetPtrData(Command+2,DEF_QWORD);
280 break;
281 case COM_SETDWORD:
282 OpcodeSetPtrData(Command+2,DEF_DWORD);
283 break;
284 case COM_SETWORD:
285 OpcodeSetPtrData(Command+2,DEF_WORD);
286 break;
287 case COM_SETBYTE:
288 OpcodeSetPtrData(Command+2,DEF_BYTE);
289 break;
290
291 case COM_DEBUG:
292 extern BOOL bDebugCompile;
293 //int 3
294 if(bDebugCompile) OpBuffer[obp++]=(char)0xCC;
295#if defined(_DEBUG)
296 else OpBuffer[obp++]=(char)0xCC;
297#endif
298 break;
299
300 case COM_LET:
301 OpcodeCalc(Command+2);
302 break;
303 default:
304 OpcodeOthers(Command);
305 break;
306 }
307}
308
309void GetGlobalDataForDll(void){
310 extern char *basbuf;
311 extern HANDLE hHeap;
312 int i2,BufferSize;
313 char *Command;
314 DWORD dwRetCode;
315
316 dwRetCode=0;
317 BufferSize=128;
318 Command=(char *)HeapAlloc(hHeap,0,BufferSize);
319 for(cp++,i2=0;;cp++,i2++){
320 if(i2>=BufferSize){
321 //バッファ領域が足りなくなった場合はバッファを増量する
322 BufferSize+=128;
323 Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize);
324 }
325 if(basbuf[cp]=='\"'){
326 Command[i2]=basbuf[cp];
327 for(cp++,i2++;;cp++,i2++){
328 if(i2>=BufferSize){
329 //バッファ領域が足りなくなった場合はバッファを増量する
330 BufferSize+=128;
331 Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize);
332 }
333 Command[i2]=basbuf[cp];
334 if(basbuf[cp]=='\"') break;
335 }
336 continue;
337 }
338 if(IsCommandDelimitation(basbuf[cp])){
339 Command[i2]=0;
340
341 if(Command[0]==1&&Command[1]==ESC_SUB){
342 i2=cp;
343 while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDSUB)){
344 if(basbuf[cp]=='\0'){
345 SetError(22,"Sub",i2);
346 break;
347 }
348 cp++;
349 }
350 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
351 cp+=2;
352 i2=-1;
353 continue;
354 }
355 if(Command[0]==1&&Command[1]==ESC_FUNCTION){
356 i2=cp;
357 while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDFUNCTION)){
358 if(basbuf[cp]=='\0'){
359 SetError(22,"Function",i2);
360 break;
361 }
362 cp++;
363 }
364 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
365 cp+=2;
366 i2=-1;
367 continue;
368 }
369 if(Command[0]==1&&Command[1]==ESC_MACRO){
370 i2=cp;
371 while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDMACRO)){
372 if(basbuf[cp]=='\0'){
373 SetError(22,"Macro",i2);
374 break;
375 }
376 cp++;
377 }
378 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
379 cp+=2;
380 i2=-1;
381 continue;
382 }
383 if(Command[0]==1&&Command[1]==ESC_TYPE){
384 i2=cp;
385 while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDTYPE)){
386 if(basbuf[cp]=='\0'){
387 SetError(22,"Type",i2);
388 break;
389 }
390 cp++;
391 }
392 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
393 cp+=2;
394 i2=-1;
395 continue;
396 }
397 if(Command[0]==1&&Command[1]==ESC_CLASS){
398 i2=cp;
399 while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDCLASS)){
400 if(basbuf[cp]=='\0'){
401 SetError(22,"Class",i2);
402 break;
403 }
404 cp++;
405 }
406 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
407 cp+=2;
408 i2=-1;
409 continue;
410 }
411 if(Command[0]==1&&Command[1]==ESC_INTERFACE){
412 i2=cp;
413 while(!(basbuf[cp]==1&&basbuf[cp+1]==ESC_ENDINTERFACE)){
414 if(basbuf[cp]=='\0'){
415 SetError(22,"Interface",i2);
416 break;
417 }
418 cp++;
419 }
420 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
421 cp+=2;
422 i2=-1;
423 continue;
424 }
425
426 //DLLのグローバルデータに必要なコマンドだけ
427 if(MAKEWORD(Command[1],Command[0])==COM_DIM)
428 OpcodeDim(Command+2,0);
429
430 if(obp_AllocSize<obp+8192){
431 obp_AllocSize+=8192;
432 OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize);
433 }
434
435 if(basbuf[cp]=='\0') break;
436 i2=-1;
437 continue;
438 }
439 Command[i2]=basbuf[cp];
440 }
441 HeapDefaultFree(Command);
442}
443DWORD CompileBuffer(char Return_Sequence,WORD Return_Command){
444 extern char *basbuf;
445 extern HANDLE hHeap;
446 int i,i2,i3,i4,BufferSize,ScopeStart;
447 char *Command,temporary[VN_SIZE],*temp2,temp3[32];
448 DWORD dwRetCode;
449
450 ScopeStart=cp;
451
452 dwRetCode=0;
453 BufferSize=128;
454 Command=(char *)HeapAlloc(hHeap,0,BufferSize);
455
456 for(cp++,i2=0;;cp++,i2++){
457 if(i2>=BufferSize){
458 //バッファ領域が足りなくなった場合はバッファを増量する
459 BufferSize+=128;
460 Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize);
461 }
462 if(basbuf[cp]=='\"'){
463 Command[i2]=basbuf[cp];
464 for(cp++,i2++;;cp++,i2++){
465 if(i2>=BufferSize){
466 //バッファ領域が足りなくなった場合はバッファを増量する
467 BufferSize+=128;
468 Command=(char *)HeapReAlloc(hHeap,0,Command,BufferSize);
469 }
470 Command[i2]=basbuf[cp];
471 if(basbuf[cp]=='\"') break;
472 }
473 continue;
474 }
475 if(IsCommandDelimitation(basbuf[cp])){
476 Command[i2]=0;
477
478 if(Command[0]==1&&Command[1]==ESC_LINENUM){
479 for(i=2,i2=0;;i++,i2++){
480 if(Command[i]==','){
481 temporary[i2]=0;
482 break;
483 }
484 temporary[i2]=Command[i];
485 }
486 i3=atoi(temporary);
487 i4=i+1;
488
489 //Goto先ラベル
490 pLabelNames=(LABEL *)HeapReAlloc(hHeap,0,pLabelNames,(MaxLabelNum+1)*sizeof(LABEL));
491 pLabelNames[MaxLabelNum].pName=0;
492 pLabelNames[MaxLabelNum].line=i3;
493 pLabelNames[MaxLabelNum].address=obp;
494 MaxLabelNum++;
495
496 //書き込みスケジュール
497 for(i=0;i<GotoLabelScheduleNum;i++){
498 if(pGotoLabelSchedule[i].pName==0&&
499 pGotoLabelSchedule[i].line==i3){
500 *((long *)(OpBuffer+pGotoLabelSchedule[i].pos))=obp-(pGotoLabelSchedule[i].pos+sizeof(long));
501
502 //詰める
503 GotoLabelScheduleNum--;
504 for(i2=i;i2<GotoLabelScheduleNum;i2++){
505 pGotoLabelSchedule[i2].pName=pGotoLabelSchedule[i2+1].pName;
506 pGotoLabelSchedule[i2].line=pGotoLabelSchedule[i2+1].line;
507 pGotoLabelSchedule[i2].pos=pGotoLabelSchedule[i2+1].pos;
508 }
509 i--;
510 }
511 }
512
513 temp2=(char *)HeapAlloc(hHeap,0,lstrlen(Command+i4)+1);
514 lstrcpy(temp2,Command+i4);
515 lstrcpy(Command,temp2);
516 HeapDefaultFree(temp2);
517 }
518
519 if(Command[0]==1&&
520 (((Command[1]==ESC_VIRTUAL||Command[1]==ESC_OVERRIDE)&&Command[2]==1&&(Command[3]==ESC_SUB||Command[3]==ESC_FUNCTION))||
521 Command[1]==ESC_SUB||
522 Command[1]==ESC_FUNCTION||
523 Command[1]==ESC_MACRO||
524 Command[1]==ESC_TYPE||
525 Command[1]==ESC_CLASS||
526 Command[1]==ESC_INTERFACE||
527 Command[1]==ESC_ENUM||
528 (Command[1]==ESC_CONST&&Command[2]==1&&Command[3]==ESC_ENUM)
529 )
530 ){
531 if(Command[1]==ESC_VIRTUAL||Command[1]==ESC_OVERRIDE||Command[1]==ESC_CONST){
532 GetDefaultNameFromES(Command[3],temporary);
533 }
534 else{
535 GetDefaultNameFromES(Command[1],temporary);
536 }
537 if(Return_Sequence){
538 SetError(12,temporary,cp);
539 break;
540 }
541
542 if(Command[1]==ESC_CONST) i3=GetEndXXXCommand(Command[3]);
543 else i3=GetEndXXXCommand(Command[1]);
544 for(i2=cp;;cp++){
545 if(basbuf[cp]==1){
546 if(basbuf[cp+1]==i3) break;
547 if(Command[1]==ESC_CLASS||Command[1]==ESC_INTERFACE){
548 //クラス、インターフェイスではSub、Functionの定義を可能にしておく
549 if(basbuf[cp+1]==ESC_MACRO||
550 basbuf[cp+1]==ESC_TYPE||
551 basbuf[cp+1]==ESC_CLASS||
552 basbuf[cp+1]==ESC_INTERFACE||
553 basbuf[cp+1]==ESC_ENUM){
554 GetDefaultNameFromES(basbuf[cp+1],temp3);
555 SetError(12,temp3,cp);
556 }
557 }
558 else{
559 if(basbuf[cp-1]!='*'&&(
560 basbuf[cp+1]==ESC_VIRTUAL||
561 basbuf[cp+1]==ESC_OVERRIDE||
562 basbuf[cp+1]==ESC_SUB||
563 basbuf[cp+1]==ESC_FUNCTION||
564 basbuf[cp+1]==ESC_MACRO||
565 basbuf[cp+1]==ESC_TYPE||
566 basbuf[cp+1]==ESC_CLASS||
567 basbuf[cp+1]==ESC_INTERFACE||
568 basbuf[cp+1]==ESC_ENUM)){
569 GetDefaultNameFromES(basbuf[cp+1],temp3);
570 SetError(12,temp3,cp);
571 }
572 }
573 }
574 if(basbuf[cp]=='\0'){
575 //error
576 //既にエラー発行済みのため、何もせずに抜ける
577 break;
578 }
579 }
580 if(basbuf[cp+2]=='\0'||basbuf[cp]=='\0') break;
581 cp+=2;
582 i2=-1;
583 continue;
584 }
585
586 if(Command[0]==0x10||Command[0]==0x11){
587 //Wend、Next、Loopなど
588 if(Return_Command==MAKEWORD(Command[1],Command[0])){
589 if(Return_Command==COM_NEXT){
590 //Nextの場合は、パラメータ(省略化)の整合性を判断する必要がある(OpcodeFor関数を参照)
591 extern char szNextVariable[VN_SIZE];
592 if(Command[2]) lstrcpy(szNextVariable,Command+2);
593 else szNextVariable[0]=0;
594 }
595 break;
596 }
597 }
598
599 NextLine();
600
601 if(Command[0]==1){
602 if(Return_Sequence==ESC_ENDIF&&Command[1]==ESC_ELSE){
603 dwRetCode=ESC_ELSE;
604 break;
605 }
606
607 if(Command[1]==Return_Sequence){
608 dwRetCode=Command[1];
609 break;
610 }
611 }
612
613 ChangeOpcode(Command);
614
615#ifdef _DEBUG
616 epi_check();
617#endif
618
619 //コンパイルを中断するとき
620 extern BOOL bStopCompile;
621 if(bStopCompile) return 0;
622
623 if(obp_AllocSize<obp+8192){
624 obp_AllocSize+=8192;
625 OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize);
626 }
627
628 if(basbuf[cp]=='\0'){
629 switch(Return_Command){
630 case COM_WEND:
631 SetError(4,"\"While\" - \"Wend\" ",ScopeStart);
632 break;
633 case COM_NEXT:
634 SetError(4,"\"For\" - \"Next\" ",ScopeStart);
635 break;
636 case COM_LOOP:
637 SetError(4,"\"Do\" - \"Loop\" ",ScopeStart);
638 break;
639 }
640 switch(Return_Sequence){
641 case ESC_ENDSUB:
642 SetError(4,"\"Sub\" - \"End Sub\" ",ScopeStart);
643 break;
644 case ESC_ENDFUNCTION:
645 SetError(4,"\"Function\" - \"End Function\" ",ScopeStart);
646 break;
647 case ESC_ENDMACRO:
648 SetError(4,"\"Macro\" - \"End Macro\" ",ScopeStart);
649 break;
650 case ESC_ENDIF:
651 SetError(22,"If",ScopeStart);
652 break;
653 }
654 break;
655 }
656 i2=-1;
657 continue;
658 }
659 Command[i2]=basbuf[cp];
660 }
661 HeapDefaultFree(Command);
662
663 return dwRetCode;
664}
Note: See TracBrowser for help on using the repository browser.