source: dev/BasicCompiler_Common/Compile.cpp@ 143

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

Smoothie::Metaクラス内を整理

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