source: dev/BasicCompiler_Common/Class.cpp@ 67

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

[32bit Compiler]op_push_value → op_push_V
Nothingに対応。

File size: 33.8 KB
Line 
1#include "common.h"
2
3#ifdef _AMD64_
4#include "../BasicCompiler64/opcode.h"
5#else
6#include "../BasicCompiler32/opcode.h"
7#endif
8
9CDBClass *pobj_DBClass;
10
11CClass *pobj_CompilingClass;
12CClass *pobj_StringClass;
13
14CMember *pCompilingMethod;
15
16
17
18CMember::CMember( CClass *pobj_c, DWORD access, bool isConst, bool isRef, char *buffer, int NowLine ){
19 extern int cp;
20
21 //構文を解析
22 char VarName[VN_SIZE];
23 char init_buf[VN_SIZE];
24 char constract_parameter[VN_SIZE];
25 GetDimentionFormat(buffer,isRef,VarName,SubScripts,&TypeInfo,init_buf,constract_parameter);
26
27 //重複チェック
28 if(pobj_c->DupliCheckAll(VarName)){
29 SetError(15,VarName,cp);
30 }
31
32 if(TypeInfo.type==DEF_OBJECT){
33 if(TypeInfo.u.pobj_Class->IsAbstract()){
34 //抽象クラスだったとき
35 SetError(125,TypeInfo.u.pobj_Class->name,cp);
36 }
37 }
38
39 //メンバ名
40 name=(char *)HeapAlloc(hHeap,0,lstrlen(VarName)+1);
41 lstrcpy(name,VarName);
42
43 //アクセス権
44 dwAccess=access;
45
46 //定数扱いかどうか
47 this->isConst = isConst;
48
49 //参照型かどうか
50 this->isRef = isRef;
51
52 //初期データ
53 InitBuf=(char *)HeapAlloc(hHeap,0,lstrlen(init_buf)+1);
54 lstrcpy(InitBuf,init_buf);
55
56 //コンストラクタ用のパラメータ
57 ConstractParameter=(char *)HeapAlloc(hHeap,0,lstrlen(constract_parameter)+1);
58 lstrcpy(ConstractParameter,constract_parameter);
59
60 //ソースコードの位置
61 source_code_address=NowLine;
62}
63CMember::CMember(CMember *pobj){
64 //コピーコンストラクタ
65 memset(this,0,sizeof(CMember));
66
67 //name
68 name=(char *)HeapAlloc(hHeap,0,lstrlen(pobj->name)+1);
69 lstrcpy(name,pobj->name);
70
71 //定数扱いかどうか
72 isConst = pobj->isConst;
73
74 //参照型かどうか
75 isRef = pobj->isRef;
76
77 //SubScripts
78 memcpy(SubScripts,pobj->SubScripts,MAX_ARRAYDIM*sizeof(int));
79
80 //TypeInfo
81 TypeInfo=pobj->TypeInfo;
82
83 //ソースコードの位置
84 source_code_address=pobj->source_code_address;
85}
86CMember::CMember(){
87 memset(this,0,sizeof(CMember));
88}
89CMember::~CMember(){
90 HeapDefaultFree(name);
91 if(InitBuf) HeapDefaultFree(InitBuf);
92 if(ConstractParameter) HeapDefaultFree(ConstractParameter);
93}
94
95bool CMember::IsConst(){
96 return isConst;
97}
98bool CMember::IsRef(){
99 return isRef;
100}
101
102int CMember::GetSize(){
103 //メンバサイズを取得
104 return GetTypeSize(TypeInfo.type,TypeInfo.u.lpIndex);
105}
106
107void CMember::InitStaticMember(void){
108 //静的メンバをグローバル領域に作成
109
110 //イテレータをリセット
111 extern CDBClass *pobj_DBClass;
112 pobj_DBClass->Iterator_Reset();
113
114 int back_cp=cp;
115
116 while(pobj_DBClass->Iterator_HasNext()){
117 CClass *pobj_c;
118 pobj_c=pobj_DBClass->Iterator_GetNext();
119
120 int i=0;
121 foreach( CMember *member, pobj_c->staticMembers ){
122 char temporary[VN_SIZE];
123 sprintf(temporary,"%s.%s",pobj_c->name,member->name);
124 dim(
125 false,
126 temporary,
127 member->SubScripts,
128 member->TypeInfo,
129 GetTypeSize(member->TypeInfo.type,member->TypeInfo.u.lpIndex),
130 member->InitBuf,
131 member->ConstractParameter,
132 0);
133
134 //ネイティブコードバッファの再確保
135 extern int obp_AllocSize;
136 if(obp_AllocSize<obp+8192){
137 obp_AllocSize+=8192;
138 OpBuffer=(char *)HeapReAlloc(hHeap,0,OpBuffer,obp_AllocSize); //matea
139 }
140 i++;
141 }
142 }
143
144 cp=back_cp;
145}
146
147
148
149CMethod::CMethod(CMethod *pobj){
150 //コピーコンストラクタ
151 memset(this,0,sizeof(CMethod));
152
153 psi=pobj->psi;
154
155 bAbstract=pobj->bAbstract;
156
157 bVirtual=pobj->bVirtual;
158}
159CMethod::CMethod(){
160 memset(this,0,sizeof(CMethod));
161}
162CMethod::~CMethod(){
163}
164
165
166
167
168CClass::CClass(const char *name){
169 memset(this,0,sizeof(CClass));
170
171 vtbl_offset=-1;
172
173 this->name=(char *)HeapAlloc(hHeap,0,lstrlen(name)+1);
174 lstrcpy(this->name,name);
175
176 isCompilingConstructor = false;
177 isCompilingDestructor = false;
178}
179CClass::~CClass(){
180 int i;
181
182 //クラス名
183 HeapDefaultFree(name);
184
185 if(ppobj_Member){
186 //メンバ
187 for(i=0;i<iMemberNum;i++){
188 delete ppobj_Member[i];
189 }
190 HeapDefaultFree(ppobj_Member);
191 ppobj_Member=0;
192 }
193
194 //静的メンバ
195 foreach( CMember *member, staticMembers ){
196 delete member;
197 }
198
199 //メソッド
200 foreach( CMethod *method, methods ){
201 delete method;
202 }
203
204 //静的メソッド
205 foreach( CMethod *method, staticMethods ){
206 delete method;
207 }
208}
209
210bool CClass::IsStructure() const
211{
212 return classType == CClass::Structure;
213}
214
215void CClass::Inherits( CClass *pInheritsClass ){
216 int i3;
217
218 //メンバをコピー
219 ppobj_Member=(CMember **)HeapReAlloc(
220 hHeap,
221 0,
222 ppobj_Member,
223 pInheritsClass->iMemberNum*sizeof(CMember *));
224 iMemberNum=pInheritsClass->iMemberNum;
225 for(i3=0;i3<pInheritsClass->iMemberNum;i3++){
226 ppobj_Member[i3]=new CMember(pInheritsClass->ppobj_Member[i3]);
227
228 //dwAccess
229 if(pInheritsClass->ppobj_Member[i3]->dwAccess==ACCESS_PRIVATE)
230 ppobj_Member[i3]->dwAccess=ACCESS_NON;
231 else ppobj_Member[i3]->dwAccess=pInheritsClass->ppobj_Member[i3]->dwAccess;
232 }
233
234 //メソッドをコピー
235 foreach( CMethod *baseMethod, pInheritsClass->methods ){
236 CMethod *method = new CMethod( baseMethod );
237
238 //dwAccess
239 if(baseMethod->dwAccess==ACCESS_PRIVATE)
240 method->dwAccess=ACCESS_NON;
241 else method->dwAccess=baseMethod->dwAccess;
242
243 //pobj_Inherits
244 // ※継承元のClassIndexをセット(入れ子継承を考慮する)
245 if(baseMethod->pobj_InheritsClass==0)
246 method->pobj_InheritsClass=pInheritsClass;
247 else
248 method->pobj_InheritsClass=
249 baseMethod->pobj_InheritsClass;
250
251 methods.push_back( method );
252 }
253
254 //仮想関数の数
255 vtbl_num=pInheritsClass->vtbl_num;
256
257 //継承先のクラスをメンバとして保持する
258 pobj_InheritsClass = pInheritsClass;
259}
260void CClass::AddMember( DWORD dwAccess, bool isConst, bool isRef, char *buffer ){
261 ppobj_Member = (CMember **)HeapReAlloc( hHeap, 0, ppobj_Member, ( iMemberNum + 1 ) * sizeof(CMember *) );
262 ppobj_Member[iMemberNum] = new CMember( this, dwAccess, isConst, isRef, buffer );
263 iMemberNum++;
264}
265void CClass::AddStaticMember( DWORD dwAccess, bool isConst, bool isRef, char *buffer, int NowLine ){
266 CMember *member = new CMember( this, dwAccess, isConst, isRef, buffer, NowLine );
267 staticMembers.push_back( member );
268}
269void CClass::AddMethod( SUBINFO *psi,DWORD dwAccess, bool isConst, BOOL bAbstract, BOOL bVirtual ){
270 CMethod *method = new CMethod();
271 method->psi = psi;
272 method->dwAccess = dwAccess;
273 method->isConst = isConst;
274 method->bAbstract = bAbstract;
275 method->bVirtual = bVirtual;
276 method->pobj_InheritsClass = 0;
277
278 methods.push_back( method );
279}
280void CClass::AddStaticMethod(SUBINFO *psi,DWORD dwAccess){
281 CMethod *method = new CMethod();
282 method->psi=psi;
283 method->dwAccess=dwAccess;
284 method->bAbstract=0;
285 method->bVirtual=0;
286 method->pobj_InheritsClass=0;
287
288 staticMethods.push_back( method );
289}
290BOOL CClass::DupliCheckAll(const char *name){
291 //重複チェック
292
293 //メンバ
294 if(DupliCheckMember(name)) return 1;
295
296 //メソッド
297 foreach( CMethod *method, methods ){
298 if( lstrcmp( name, method->psi->name ) == 0 ){
299 return 1;
300 }
301 }
302
303 return 0;
304}
305BOOL CClass::DupliCheckMember(const char *name){
306 //重複チェック
307
308 //メンバ
309 for( int i=0;i<iMemberNum;i++){
310 if(lstrcmp(name,ppobj_Member[i]->name)==0){
311 return 1;
312 }
313 }
314
315 //静的メンバ
316 foreach( CMember *member, staticMembers ){
317 if( lstrcmp( name, member->name ) == 0 ){
318 return 1;
319 }
320 }
321
322 return 0;
323}
324CMethod *CClass::GetMethodInfo( SUBINFO *psi ){
325 for( int i=(int)methods.size()-1; i>=0; i-- ){
326 if( psi == methods[i]->psi ) return methods[i];
327 }
328 return NULL;
329}
330CMethod *CClass::GetStaticMethodInfo( SUBINFO *psi ){
331 for( int i=(int)staticMethods.size()-1; i>=0; i-- ){
332 if( psi == staticMethods[i]->psi ) return staticMethods[i];
333 }
334 return NULL;
335}
336bool CClass::IsExistMethod( const char *name ){
337 foreach( CMethod *method, methods ){
338 if( lstrcmp( method->psi->name, name ) == 0 ) return true;
339 }
340 return false;
341}
342bool CClass::IsExistStaticMethod( const char *name ){
343 foreach( CMethod *method, staticMethods ){
344 if( lstrcmp( method->psi->name, name ) == 0 ) return true;
345 }
346 return false;
347}
348
349void CClass::EnumStaticMethod( const char *methodName, std::vector<SUBINFO *> &subs ) const
350{
351 foreach( CMethod *method, staticMethods ){
352 if(lstrcmp(methodName,method->psi->name)==0){
353 subs.push_back( method->psi );
354 }
355 }
356}
357
358void CClass::EnumMethod( const char *methodName, std::vector<SUBINFO *> &subs ) const
359{
360 //オブジェクトのメンバ関数の場合
361 //※オーバーライドされた関数を先にサーチする必要があるため、バックサーチを行う
362 for( int i=(int)methods.size()-1; i>=0; i-- ){
363 if(lstrcmp(methodName,methods[i]->psi->name)==0){
364 subs.push_back( methods[i]->psi );
365 }
366 }
367}
368
369void CClass::EnumMethod( const BYTE idOperatorCalc, std::vector<SUBINFO *> &subs ) const
370{
371 //オブジェクトのメンバ関数の場合
372 //※オーバーライドされた関数を先にサーチする必要があるため、バックサーチを行う
373 for( int i=(int)methods.size()-1; i>=0; i-- ){
374 char *temp;
375 temp=methods[i]->psi->name;
376 if(temp[0]==1&&temp[1]==ESC_OPERATOR){
377 if((BYTE)temp[2]==idOperatorCalc){
378 subs.push_back( methods[i]->psi );
379 }
380 }
381 }
382}
383
384//デフォルト コンストラクタ メソッドを取得
385CMethod *CClass::GetConstructorMethod() const
386{
387 if( ConstructorMemberSubIndex == -1 ) return NULL;
388 return methods[ConstructorMemberSubIndex];
389}
390
391//デフォルト コピーコンストラクタ メソッドを取得
392CMethod *CClass::GetCopyConstructorMethod() const
393{
394 if( CopyConstructorMemberSubIndex == -1 ) return NULL;
395 return methods[CopyConstructorMemberSubIndex];
396}
397
398//デストラクタ メソッドを取得
399CMethod *CClass::GetDestructorMethod() const
400{
401 if( DestructorMemberSubIndex == -1 ) return NULL;
402 return methods[DestructorMemberSubIndex];
403}
404
405//サイズを取得
406int CClass::GetSize() const
407{
408 return GetMemberOffset( NULL, NULL );
409}
410
411//メンバのオフセットを取得
412int CClass::GetMemberOffset( const char *memberName, int *pMemberNum ) const
413{
414 int i,i2,offset;
415
416 //仮想関数が存在する場合は関数リストへのポインタのサイズを追加
417 if(vtbl_num) offset=PTR_SIZE;
418 else offset=0;
419
420 int alignment;
421 if(iAlign) alignment=iAlign;
422 else alignment=1;
423
424 int iMaxAlign=0;
425 for(i=0;i<iMemberNum;i++){
426 CMember *pMember = ppobj_Member[i];
427
428 i2 = pMember->GetSize();
429
430 //アラインメントを算出
431 int member_size;
432 if(pMember->TypeInfo.type==DEF_STRUCT){
433 //メンバクラスのアラインメントを取得
434 member_size=pMember->TypeInfo.u.pobj_Class->GetAlignment();
435 }
436 else{
437 //メンバサイズを取得
438 member_size=i2;
439 }
440 if(iMaxAlign<member_size) iMaxAlign=member_size;
441
442 //アラインメントを考慮
443 if(iAlign&&iAlign<member_size){
444 if(offset%alignment) offset+=alignment-(offset%alignment);
445 }
446 else{
447 if(alignment<member_size) alignment=member_size;
448
449 if(member_size==0){
450 //メンバを持たないクラス
451 //※何もしない(オフセットの計算をしない)
452 }
453 else{
454 if(offset%member_size) offset+=member_size-(offset%member_size);
455 }
456 }
457
458 if(memberName){
459 //メンバ指定がある場合は、オフセットを返す
460 if(lstrcmp(pMember->name,memberName)==0){
461 if(pMemberNum) *pMemberNum=i;
462 return offset;
463 }
464 }
465
466 //配列を考慮したメンバサイズを取得
467 member_size=i2 * JumpSubScripts(pMember->SubScripts);
468
469 //メンバサイズを加算
470 offset+= member_size;
471 }
472
473 if(iMaxAlign<alignment) alignment=iMaxAlign;
474
475 //アラインメントを考慮
476 if(alignment){
477 if(offset%alignment) offset+=alignment-(offset%alignment);
478 }
479
480 if(pMemberNum) *pMemberNum=i;
481 return offset;
482}
483
484int CClass::GetAlignment() const
485{
486 int i;
487 int alignment,member_size;
488
489 if(vtbl_num) alignment=PTR_SIZE;
490 else alignment=0;
491
492 for(i=0;i<iMemberNum;i++){
493 CMember *pMember = ppobj_Member[i];
494
495 if(pMember->TypeInfo.type==DEF_STRUCT){
496 //メンバクラスのアラインメントを取得
497 member_size=pMember->TypeInfo.u.pobj_Class->GetAlignment();
498 }
499 else{
500 //メンバサイズを取得
501 member_size = pMember->GetSize();
502 }
503
504 //アラインメントをセット
505 if(alignment<member_size) alignment=member_size;
506 }
507
508 if(alignment==0) return 0;
509
510 if(iAlign) alignment=iAlign;
511
512 return alignment;
513}
514
515
516
517int CClass::GetFuncNumInVtbl( const SUBINFO *psi ) const
518{
519 int n = 0;
520 foreach( CMethod *method, methods ){
521 if( method->psi == psi ) break;
522 if( method->psi->bVirtual ) n++;
523 }
524 return n;
525}
526LONG_PTR CClass::GetVtblGlobalOffset(void){
527
528 //既に存在する場合はそれを返す
529 if(vtbl_offset!=-1) return vtbl_offset;
530
531
532 //////////////////////////////////////
533 // 存在しないときは新たに生成する
534 //////////////////////////////////////
535
536 SUBINFO **ppsi;
537 ppsi=(SUBINFO **)HeapAlloc(hHeap,0,vtbl_num*sizeof(SUBINFO *));
538
539 //関数テーブルに値をセット
540 int i2 = 0;
541 foreach( CMethod *method, methods ){
542 if(method->bVirtual){
543 method->psi->bUse=1;
544
545 if(method->bAbstract){
546 extern int cp;
547 SetError(300,NULL,cp);
548
549 ppsi[i2]=0;
550 }
551 else ppsi[i2]=method->psi;
552 i2++;
553 }
554 }
555
556 vtbl_offset=dataTable.AddBinary((void *)ppsi,vtbl_num*sizeof(LONG_PTR));
557
558 for( int i=0; i < vtbl_num; i++ ){
559 pobj_Reloc->AddSchedule_DataSection(vtbl_offset+i*sizeof(LONG_PTR));
560 }
561
562 HeapDefaultFree(ppsi);
563
564 return vtbl_offset;
565}
566void CClass::ActionVtblSchedule(LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection){
567 if(vtbl_offset==-1) return;
568
569 LONG_PTR *pVtbl;
570 pVtbl=(LONG_PTR *)((char *)dataTable.GetPtr()+vtbl_offset);
571
572 int i;
573 for(i=0;i<vtbl_num;i++){
574 SUBINFO *psi;
575 psi=(SUBINFO *)pVtbl[i];
576 if(!psi) continue;
577 pVtbl[i]=psi->CompileAddress+ImageBase+MemPos_CodeSection;
578 }
579}
580bool CClass::IsAbstract(){
581 //未実装の仮想関数を持つ場合はtrueを返す
582
583 foreach( CMethod *method, methods ){
584 if(method->bVirtual){
585 if(method->bAbstract){
586 return true;
587 }
588 }
589 }
590
591 //コンポジションの関係にあるメンバも検査する
592 for(int i=0;i < iMemberNum;i++){
593 if(ppobj_Member[i]->TypeInfo.type==DEF_OBJECT){
594 if(ppobj_Member[i]->TypeInfo.u.pobj_Class->IsAbstract())
595 return true;
596 }
597 }
598
599 return false;
600}
601
602// コンストラクタのコンパイルを開始
603void CClass::NotifyStartConstructorCompile(){
604 isCompilingConstructor = true;
605}
606
607//コンストラクタのコンパイルを終了
608void CClass::NotifyFinishConstructorCompile(){
609 isCompilingConstructor = false;
610}
611
612//コンストラクタをコンパイル中かどうかを判別
613bool CClass::IsCompilingConstructor(){
614 return isCompilingConstructor;
615}
616
617//デストラクタのコンパイルを開始
618void CClass::NotifyStartDestructorCompile(){
619 isCompilingDestructor = true;
620}
621
622//デストラクタのコンパイルを終了
623void CClass::NotifyFinishDestructorCompile(){
624 isCompilingDestructor = false;
625}
626
627//デストラクタをコンパイル中かどうかを判別
628bool CClass::IsCompilingDestructor(){
629 return isCompilingDestructor;
630}
631
632
633//自身と等しいクラスかどうかを確認
634bool CClass::IsEquals( CClass *pClass ){
635 if( this == pClass ) return true;
636 return false;
637}
638
639//自身の派生クラスかどうかを確認
640bool CClass::IsSubClass( CClass *pClass ){
641 pClass = pClass->pobj_InheritsClass;
642 while( pClass ){
643 if( this == pClass ) return true;
644 pClass = pClass->pobj_InheritsClass;
645 }
646 return false;
647}
648
649//自身と等しいまたは派生クラスかどうかを確認
650bool CClass::IsEqualsOrSubClass( CClass *pClass ){
651 if( IsEquals( pClass ) ) return true;
652 return IsSubClass( pClass );
653}
654
655
656
657int CDBClass::hash(const char *name){
658 int key;
659
660 for(key=0;*name!='\0';name++){
661 key=((key<<8)+ *name )%MAX_CLASS_HASH;
662 }
663
664 return key;
665}
666
667void CDBClass::DestroyClass(CClass *pobj_c){
668 if(pobj_c->pobj_NextClass){
669 DestroyClass(pobj_c->pobj_NextClass);
670 }
671
672 delete pobj_c;
673}
674
675CDBClass::CDBClass():
676 pStringClass( NULL ),
677 pObjectClass( NULL ),
678 pCompilingClass( NULL ),
679 pCompilingMethod( NULL ),
680 ppobj_IteClass( NULL ),
681 iIteMaxNum( 0 ),
682 iIteNextNum( 0 )
683{
684 memset( pobj_ClassHash, 0, MAX_CLASS_HASH * sizeof(CClass *) );
685}
686CDBClass::~CDBClass(){
687 int i;
688 for(i=0;i<MAX_CLASS_HASH;i++){
689 if(pobj_ClassHash[i]) DestroyClass(pobj_ClassHash[i]);
690 }
691
692 if(ppobj_IteClass) HeapDefaultFree(ppobj_IteClass);
693}
694
695void CDBClass::ActionVtblSchedule(LONG_PTR ImageBase, LONG_PTR MemPos_CodeSection){
696 int i;
697 for(i=0;i<MAX_CLASS_HASH;i++){
698 if(pobj_ClassHash[i]){
699 CClass *pobj_c;
700 pobj_c=pobj_ClassHash[i];
701 while(1){
702 pobj_c->ActionVtblSchedule(ImageBase,MemPos_CodeSection);
703
704 if(pobj_c->pobj_NextClass==0) break;
705 pobj_c=pobj_c->pobj_NextClass;
706 }
707 }
708 }
709}
710
711CClass *CDBClass::check(const char *name){
712 int key;
713 key=hash(name);
714
715 if(pobj_ClassHash[key]){
716 CClass *pobj_c;
717 pobj_c=pobj_ClassHash[key];
718 while(1){
719 if(lstrcmp(name,pobj_c->name)==0){
720 //重複した場合
721 return pobj_c;
722 }
723
724 if(pobj_c->pobj_NextClass==0) break;
725 pobj_c=pobj_c->pobj_NextClass;
726 }
727 }
728 return 0;
729}
730
731CClass *CDBClass::AddClass(const char *name,int NowLine){
732 //////////////////////////////////////////////////////////////////////////
733 // クラスを追加
734 // ※名前のみを登録。その他の情報はSetClassメソッドで!
735 //////////////////////////////////////////////////////////////////////////
736
737 CClass *pobj_c;
738 pobj_c=new CClass(name);
739
740 if(lstrcmp(name,"String")==0){
741 //Stringクラス
742 pobj_StringClass=pobj_c;
743 }
744 if( lstrcmp( name, "Object" ) == 0 ){
745 pObjectClass = pobj_c;
746 }
747
748
749 /////////////////////////////////
750 // ハッシュデータに追加
751 /////////////////////////////////
752
753 int key;
754 key=hash(name);
755
756 if(pobj_ClassHash[key]){
757 CClass *pobj_c2;
758 pobj_c2=pobj_ClassHash[key];
759 while(1){
760 if(lstrcmp(name,pobj_c2->name)==0){
761 //重複した場合
762 SetError(15,name,NowLine);
763 return 0;
764 }
765
766 if(pobj_c2->pobj_NextClass==0) break;
767 pobj_c2=pobj_c2->pobj_NextClass;
768 }
769 pobj_c2->pobj_NextClass=pobj_c;
770 }
771 else{
772 pobj_ClassHash[key]=pobj_c;
773 }
774
775 return pobj_c;
776}
777
778void CDBClass::InitNames(void){
779 extern char *basbuf;
780 int i;
781
782 for(i=0;;i++){
783 if(basbuf[i]=='\0') break;
784
785 if(basbuf[i]==1&&(
786 basbuf[i+1]==ESC_CLASS||
787 basbuf[i+1]==ESC_TYPE||
788 basbuf[i+1]==ESC_INTERFACE
789 )){
790 int NowLine;
791 NowLine=i;
792
793 i+=2;
794 //アラインメント修飾子
795 if(_memicmp(basbuf+i,"Align(",6)==0){
796 i+=6;
797 i=JumpStringInPare(basbuf,i)+1;
798 }
799
800 int i2;
801 char temporary[VN_SIZE];
802 for(i2=0;;i++,i2++){
803 if(!IsVariableChar(basbuf[i])){
804 temporary[i2]=0;
805 break;
806 }
807 temporary[i2]=basbuf[i];
808 }
809
810 //クラスを追加
811 CClass *pClass = pobj_DBClass->AddClass(temporary,NowLine);
812 if( pClass ){
813 if( basbuf[NowLine+1] == ESC_CLASS ){
814 pClass->classType = CClass::Class;
815 }
816 else if( basbuf[NowLine+1] == ESC_INTERFACE ){
817 pClass->classType = CClass::Interface;
818 }
819 else{
820 pClass->classType = CClass::Structure;
821 }
822 }
823 }
824 }
825}
826
827
828void CDBClass::AddMethod(CClass *pobj_c, DWORD dwAccess, BOOL bStatic, bool isConst, BOOL bAbstract,
829 BOOL bVirtual, BOOL bOverride, char *buffer, int NowLine){
830 int i,i2;
831 char temporary[VN_SIZE];
832
833 i=2;
834 for(i2=0;;i++,i2++){
835 if(buffer[i]=='('||buffer[i]=='\0'){
836 temporary[i2]=0;
837 break;
838 }
839 temporary[i2]=buffer[i];
840 }
841
842
843 //関数ハッシュへ登録
844 SUBINFO *psi;
845 psi=AddSubData(buffer,NowLine,bVirtual,pobj_c,bStatic);
846 if(!psi) return;
847
848
849 ////////////////////////////////////////////////////////////
850 // コンストラクタ、デストラクタの場合の処理
851 ////////////////////////////////////////////////////////////
852 BOOL fConstructor=0,bDestructor=0;
853
854 if(lstrcmp(temporary,pobj_c->name)==0){
855 //コンストラクタの場合
856
857 //標準コンストラクタ(引数なし)
858 if(psi->ParmNum==0) fConstructor=1;
859
860 // TODO: 消す
861 //コピーコンストラクタ
862 if(psi->ParmNum==1){
863 if(psi->pParmInfo[0].type==DEF_OBJECT&&
864 psi->pParmInfo[0].u.pobj_c==pobj_c) fConstructor=2;
865 }
866
867 //強制的にConst修飾子をつける
868 isConst = true;
869 }
870 else if(temporary[0]=='~'){
871 //デストラクタの場合はその名前が正しいかチェックを行う
872 if(lstrcmp(temporary+1,pobj_c->name)!=0)
873 SetError(117,NULL,NowLine);
874 else
875 bDestructor=1;
876 }
877 if(fConstructor||bDestructor){
878 // コンストラクタ、デストラクタのアクセシビリティをチェック
879 if(dwAccess!=ACCESS_PUBLIC){
880 SetError(116,NULL,NowLine);
881 dwAccess=ACCESS_PUBLIC;
882 }
883
884 //強制的にConst修飾子をつける
885 isConst = true;
886 }
887
888 if( fConstructor == 1 )
889 pobj_c->ConstructorMemberSubIndex = (int)pobj_c->methods.size();
890 else if( fConstructor == 2 )
891 pobj_c->CopyConstructorMemberSubIndex = (int)pobj_c->methods.size();
892 else if( bDestructor )
893 pobj_c->DestructorMemberSubIndex = (int)pobj_c->methods.size();
894
895
896
897 //////////////////
898 // 重複チェック
899 //////////////////
900
901 if(pobj_c->DupliCheckMember(temporary)){
902 SetError(15,temporary,NowLine);
903 return;
904 }
905
906 //メソッド
907 foreach( CMethod *method, pobj_c->methods ){
908 //基底クラスと重複する場合はオーバーライドを行う
909 if(method->pobj_InheritsClass) continue;
910
911 if(lstrcmp(temporary,method->psi->name)==0){
912 if(CompareParameter(
913 method->psi->pParmInfo,method->psi->ParmNum,
914 psi->pParmInfo,psi->ParmNum
915 )==0){
916 //関数名、パラメータ属性が合致したとき
917 SetError(15,psi->name,NowLine);
918 return;
919 }
920 }
921 }
922
923 //仮想関数の場合
924 if(bAbstract) psi->bCompile=1;
925
926 //メソッドのオーバーライド
927 foreach( CMethod *method, pobj_c->methods ){
928 if(lstrcmp(temporary,method->psi->name)==0){
929 if(CompareParameter(
930 method->psi->pParmInfo,method->psi->ParmNum,
931 psi->pParmInfo,psi->ParmNum
932 )==0){
933
934 if(method->psi->bVirtual){
935 //メンバ関数を上書き
936 method->psi=psi;
937 method->bAbstract=0;
938
939 if(!bOverride){
940 SetError(127,NULL,NowLine);
941 }
942 if(method->dwAccess!=dwAccess){
943 SetError(128,NULL,NowLine);
944 }
945 return;
946 }
947 }
948 }
949 }
950
951 if(psi->bVirtual){
952 pobj_c->vtbl_num++;
953 }
954
955 if(bOverride){
956 SetError(12,"Override",NowLine);
957 }
958
959 if(bStatic){
960 pobj_c->AddStaticMethod(psi,dwAccess);
961 }
962 else{
963 pobj_c->AddMethod(psi, dwAccess, isConst, bAbstract, bVirtual);
964 }
965}
966
967BOOL CDBClass::MemberVar_LoopRefCheck(CClass *pobj_c){
968 int i,i2,bRet=1;
969 for(i=0;i<pobj_c->iMemberNum;i++){
970 CMember *pMember = pobj_c->ppobj_Member[i];
971 if(pMember->TypeInfo.type==DEF_OBJECT){
972 //循環参照でないかをチェック
973 if(pobj_LoopRefCheck->check(pMember->TypeInfo.u.pobj_Class->name)){
974 extern int cp;
975 SetError(124,pMember->TypeInfo.u.pobj_Class->name,cp);
976 return 0;
977 }
978
979 pobj_LoopRefCheck->add(pobj_c->name);
980
981 i2=MemberVar_LoopRefCheck(pMember->TypeInfo.u.pobj_Class);
982 if(bRet==1) bRet=i2;
983
984 pobj_LoopRefCheck->del(pobj_c->name);
985 }
986 }
987
988 return bRet;
989}
990
991void CDBClass::GetClass_recur(const char *lpszInheritsClass){
992 extern char *basbuf;
993 int i,i2,i3,sub_address,top_pos;
994 DWORD dwAccess;
995 char temporary[8192];
996
997 for(i=0;;i++){
998 if(basbuf[i]=='\0') break;
999
1000 CClass *pobj_c;
1001
1002 if(basbuf[i]==1&&basbuf[i+1]==ESC_INTERFACE){
1003 //////////////////////////
1004 // インターフェイス
1005 //////////////////////////
1006
1007 top_pos=i;
1008
1009 i+=2;
1010
1011 //インターフェイス名を取得
1012 GetIdentifierToken( temporary, basbuf, i );
1013
1014 pobj_c=pobj_DBClass->check(temporary);
1015 if(!pobj_c) continue;
1016
1017 if(lpszInheritsClass){
1018 if(lstrcmp(lpszInheritsClass,pobj_c->name)!=0){
1019 //継承先先読み用
1020 continue;
1021 }
1022 }
1023
1024 if(pobj_c->ppobj_Member){
1025 //既に先読みされているとき
1026 continue;
1027 }
1028
1029 //メンバ用メモリを初期化
1030 pobj_c->ppobj_Member=(CMember **)HeapAlloc(hHeap,0,1);
1031 pobj_c->iMemberNum=0;
1032
1033 pobj_c->ConstructorMemberSubIndex=-1;
1034 pobj_c->CopyConstructorMemberSubIndex=-1;
1035 pobj_c->DestructorMemberSubIndex=-1;
1036
1037 if(basbuf[i+1]==1&&basbuf[i+2]==ESC_INHERITS){
1038 //継承を行う場合
1039 for(i+=3,i2=0;;i++,i2++){
1040 if(IsCommandDelimitation(basbuf[i])){
1041 temporary[i2]=0;
1042 break;
1043 }
1044 temporary[i2]=basbuf[i];
1045 }
1046
1047 if(lstrcmpi(temporary,pobj_c->name)==0){
1048 SetError(105,temporary,i);
1049 goto Interface_InheritsError;
1050 }
1051
1052 //継承元クラスを取得
1053 CClass *pInheritsClass = check(temporary);
1054 if( !pInheritsClass ){
1055 SetError(106,temporary,i);
1056 goto Interface_InheritsError;
1057 }
1058
1059 //ループ継承でないかをチェック
1060 if(pobj_LoopRefCheck->check(temporary)){
1061 SetError(123,temporary,i);
1062 goto Interface_InheritsError;
1063 }
1064
1065 if( pInheritsClass->ppobj_Member == 0 ){
1066 //継承先が読み取られていないとき
1067 pobj_LoopRefCheck->add(pobj_c->name);
1068 GetClass_recur(temporary);
1069 pobj_LoopRefCheck->del(pobj_c->name);
1070 }
1071
1072 //継承させる
1073 pobj_c->Inherits( pInheritsClass );
1074 }
1075 else{
1076 //継承無し
1077 pobj_c->pobj_InheritsClass=0;
1078
1079 //仮想関数の数を初期化
1080 pobj_c->vtbl_num=0;
1081 }
1082Interface_InheritsError:
1083
1084 //メンバ変数、関数を取得
1085 while(1){
1086 i++;
1087
1088 //エラー
1089 if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE||basbuf[i+1]==ESC_INTERFACE)){
1090 SetError(22,"Interface",i);
1091 i--;
1092 break;
1093 }
1094
1095 if(basbuf[i]==1&&basbuf[i+1]==ESC_INHERITS){
1096 SetError(111,NULL,i);
1097 break;
1098 }
1099
1100 sub_address=i;
1101
1102 for(i2=0;;i++,i2++){
1103 if(IsCommandDelimitation(basbuf[i])){
1104 temporary[i2]=0;
1105 break;
1106 }
1107 temporary[i2]=basbuf[i];
1108 }
1109 if(temporary[0]=='\0'){
1110 if(basbuf[i]=='\0'){
1111 i--;
1112 SetError(22,"Interface",top_pos);
1113 break;
1114 }
1115 continue;
1116 }
1117
1118 //End Interface記述の場合
1119 if(temporary[0]==1&&temporary[1]==ESC_ENDINTERFACE) break;
1120
1121 if(!(temporary[0]==1&&(
1122 temporary[1]==ESC_SUB||temporary[1]==ESC_FUNCTION
1123 ))){
1124 SetError(1,NULL,i);
1125 break;
1126 }
1127
1128 //メンバ関数を追加
1129 AddMethod(pobj_c,
1130 ACCESS_PUBLIC, //Publicアクセス権
1131 0, //Static指定なし
1132 false, //Constではない
1133 1, //Abstract
1134 1, //Virtual
1135 0,
1136 temporary,
1137 sub_address
1138 );
1139 }
1140 }
1141
1142 if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE)){
1143 //////////////////////////
1144 // クラス
1145 //////////////////////////
1146
1147 top_pos=i;
1148
1149 const DWORD dwClassType=basbuf[i+1];
1150
1151 i+=2;
1152
1153 //アラインメント修飾子
1154 int iAlign=0;
1155 if(_memicmp(basbuf+i,"Align(",6)==0){
1156 i+=6;
1157 i+=GetStringInPare_RemovePare(temporary,basbuf+i)+1;
1158 iAlign=atoi(temporary);
1159
1160 if(!(iAlign==1||iAlign==2||iAlign==4||iAlign==8||iAlign==16))
1161 SetError(51,NULL,i);
1162 }
1163
1164
1165 //クラス名を取得
1166 GetIdentifierToken( temporary, basbuf, i );
1167
1168 pobj_c=pobj_DBClass->check(temporary);
1169 if(!pobj_c) continue;
1170
1171 if(lpszInheritsClass){
1172 if(lstrcmp(lpszInheritsClass,pobj_c->name)!=0){
1173 //継承先先読み用
1174 continue;
1175 }
1176 }
1177
1178 if(pobj_c->ppobj_Member){
1179 //既に先読みされているとき
1180 continue;
1181 }
1182
1183 pobj_c->iAlign=iAlign;
1184
1185 //メンバ用メモリを初期化
1186 pobj_c->ppobj_Member=(CMember **)HeapAlloc(hHeap,0,1);
1187 pobj_c->iMemberNum=0;
1188
1189 pobj_c->ConstructorMemberSubIndex=-1;
1190 pobj_c->CopyConstructorMemberSubIndex=-1;
1191 pobj_c->DestructorMemberSubIndex=-1;
1192
1193 //アクセス制限の初期値をセット
1194 if(dwClassType==ESC_CLASS) dwAccess=ACCESS_PRIVATE;
1195 else dwAccess=ACCESS_PUBLIC;
1196
1197 if( lstrcmp( pobj_c->name, "Object" ) == 0 || dwClassType == ESC_TYPE ){
1198 //継承無し
1199 pobj_c->pobj_InheritsClass=0;
1200
1201 //仮想関数の数を初期化
1202 pobj_c->vtbl_num=0;
1203 }
1204 else{
1205 if(basbuf[i+1]==1&&basbuf[i+2]==ESC_INHERITS){
1206 //継承を行う場合
1207 for(i+=3,i2=0;;i++,i2++){
1208 if(IsCommandDelimitation(basbuf[i])){
1209 temporary[i2]=0;
1210 break;
1211 }
1212 temporary[i2]=basbuf[i];
1213 }
1214
1215 if(lstrcmpi(temporary,pobj_c->name)==0){
1216 SetError(105,temporary,i);
1217 goto InheritsError;
1218 }
1219 }
1220 else{
1221 //Objectを継承する
1222 lstrcpy( temporary, "Object" );
1223 }
1224
1225 //継承元クラスを取得
1226 CClass *pInheritsClass = check(temporary);
1227 if( !pInheritsClass ){
1228 SetError(106,temporary,i);
1229 goto InheritsError;
1230 }
1231
1232 //ループ継承でないかをチェック
1233 if(pobj_LoopRefCheck->check(temporary)){
1234 SetError(123,temporary,i);
1235 goto InheritsError;
1236 }
1237
1238 if( pInheritsClass->ppobj_Member == 0 ){
1239 //継承先が読み取られていないとき
1240 pobj_LoopRefCheck->add(pobj_c->name);
1241 GetClass_recur(temporary);
1242 pobj_LoopRefCheck->del(pobj_c->name);
1243 }
1244
1245 //継承させる
1246 pobj_c->Inherits( pInheritsClass );
1247 }
1248InheritsError:
1249
1250 //メンバとメソッドを取得
1251 while(1){
1252 i++;
1253
1254 //エラー
1255 if(basbuf[i]==1&&(basbuf[i+1]==ESC_CLASS||basbuf[i+1]==ESC_TYPE)){
1256 SetError(22,"Class",i);
1257 i--;
1258 break;
1259 }
1260
1261 if(basbuf[i]==1&&basbuf[i+1]==ESC_INHERITS){
1262 SetError(111,NULL,i);
1263 break;
1264 }
1265
1266 //Static修飾子
1267 BOOL bStatic;
1268 if(basbuf[i]==1&&basbuf[i+1]==ESC_STATIC){
1269 bStatic=1;
1270 i+=2;
1271 }
1272 else bStatic=0;
1273
1274 //Const修飾子
1275 bool isConst = false;
1276 if( basbuf[i] == 1 && basbuf[i + 1] == ESC_CONST ){
1277 isConst = true;
1278 i += 2;
1279 }
1280/*
1281 //Ref修飾子
1282 bool isRef = false;
1283 if( basbuf[i] == 1 && basbuf[i + 1] == ESC_BYREF ){
1284 isRef = true;
1285 i += 2;
1286 }*/
1287
1288 if(basbuf[i]==1&&(
1289 basbuf[i+1]==ESC_ABSTRACT||basbuf[i+1]==ESC_VIRTUAL||basbuf[i+1]==ESC_OVERRIDE||
1290 basbuf[i+1]==ESC_SUB||basbuf[i+1]==ESC_FUNCTION
1291 )){
1292 i3=basbuf[i+1];
1293 sub_address=i;
1294 }
1295 else i3=0;
1296
1297 BOOL bVirtual=0,bAbstract=0,bOverride=0;
1298 if(i3==ESC_ABSTRACT){
1299 bAbstract=1;
1300 bVirtual=1;
1301 i+=2;
1302
1303 i3=basbuf[i+1];
1304 }
1305 else if(i3==ESC_VIRTUAL){
1306 bAbstract=0;
1307 bVirtual=1;
1308 i+=2;
1309
1310 i3=basbuf[i+1];
1311 }
1312 else if(i3==ESC_OVERRIDE){
1313 bOverride=1;
1314 bVirtual=1;
1315
1316 i+=2;
1317
1318 i3=basbuf[i+1];
1319 }
1320
1321 for(i2=0;;i++,i2++){
1322 if(IsCommandDelimitation(basbuf[i])){
1323 temporary[i2]=0;
1324 break;
1325 }
1326 temporary[i2]=basbuf[i];
1327 }
1328 if(temporary[0]=='\0'){
1329 if(basbuf[i]=='\0'){
1330
1331 if(dwClassType==ESC_CLASS)
1332 SetError(22,"Class",top_pos);
1333 else
1334 SetError(22,"Type",top_pos);
1335
1336 i--;
1337 break;
1338 }
1339 continue;
1340 }
1341
1342 //End Class記述の場合
1343 if(temporary[0]==1&&temporary[1]==ESC_ENDCLASS&&dwClassType==ESC_CLASS) break;
1344 if(temporary[0]==1&&temporary[1]==ESC_ENDTYPE&&dwClassType==ESC_TYPE) break;
1345
1346 //アクセスを変更
1347 if(lstrcmpi(temporary,"Private")==0){
1348 dwAccess=ACCESS_PRIVATE;
1349 continue;
1350 }
1351 if(lstrcmpi(temporary,"Public")==0){
1352 dwAccess=ACCESS_PUBLIC;
1353 continue;
1354 }
1355 if(lstrcmpi(temporary,"Protected")==0){
1356 dwAccess=ACCESS_PROTECTED;
1357 continue;
1358 }
1359
1360 extern int cp;
1361 if(i3==0){
1362 if(bStatic){
1363 //静的メンバを追加
1364 cp=i; //エラー用
1365 pobj_c->AddStaticMember( dwAccess, isConst, false, temporary, i);
1366 }
1367 else{
1368 //メンバを追加
1369 cp=i; //エラー用
1370 pobj_c->AddMember( dwAccess, isConst, false, temporary );
1371
1372
1373 if(pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.type==DEF_OBJECT||
1374 pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.type==DEF_STRUCT){
1375 if(pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.u.pobj_Class->ppobj_Member==0){
1376 //参照先が読み取られていないとき
1377 GetClass_recur(pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.u.pobj_Class->name);
1378 }
1379 }
1380
1381
1382 if(pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.type==DEF_OBJECT){
1383 //循環参照のチェック
1384 pobj_LoopRefCheck->add(pobj_c->name);
1385 if(!MemberVar_LoopRefCheck(pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.u.pobj_Class)){
1386 //エラー回避
1387 pobj_c->ppobj_Member[pobj_c->iMemberNum-1]->TypeInfo.type=DEF_PTR_VOID;
1388 }
1389 pobj_LoopRefCheck->del(pobj_c->name);
1390 }
1391 }
1392 }
1393 else{
1394 //メソッドを追加
1395 cp=i; //エラー用
1396 AddMethod(pobj_c,
1397 dwAccess,
1398 bStatic,
1399 isConst,
1400 bAbstract,
1401 bVirtual,
1402 bOverride,
1403 temporary,
1404 sub_address);
1405
1406 if(bAbstract) continue;
1407
1408 for(;;i++){
1409 if(basbuf[i]=='\0'){
1410 i--;
1411 break;
1412 }
1413 if(basbuf[i-1]!='*'&&
1414 basbuf[i]==1&&(
1415 basbuf[i+1]==ESC_SUB||
1416 basbuf[i+1]==ESC_FUNCTION||
1417 basbuf[i+1]==ESC_MACRO||
1418 basbuf[i+1]==ESC_TYPE||
1419 basbuf[i+1]==ESC_CLASS||
1420 basbuf[i+1]==ESC_INTERFACE||
1421 basbuf[i+1]==ESC_ENUM)){
1422 GetDefaultNameFromES(i3,temporary);
1423 SetError(22,temporary,i);
1424 }
1425 if(basbuf[i]==1&&basbuf[i+1]==GetEndXXXCommand((char)i3)){
1426 i+=2;
1427 break;
1428 }
1429 }
1430 }
1431 }
1432 }
1433 }
1434}
1435
1436void CDBClass::GetAllClassInfo(void){
1437 //ループ継承チェック用のクラス
1438 pobj_LoopRefCheck=new CLoopRefCheck();
1439
1440 //クラスを取得
1441 GetClass_recur(0);
1442
1443 delete pobj_LoopRefCheck;
1444 pobj_LoopRefCheck=0;
1445}
1446
1447CClass *CDBClass::GetStringClass() const
1448{
1449 if( !pStringClass ){
1450 SetError();
1451 return NULL;
1452 }
1453 return pStringClass;
1454}
1455CClass *CDBClass::GetObjectClass() const
1456{
1457 if( !pObjectClass ){
1458 SetError();
1459 return NULL;
1460 }
1461 return pObjectClass;
1462}
1463
1464void CDBClass::StartCompile( SUBINFO *psi ){
1465 pCompilingClass = psi->pobj_ParentClass;
1466 if( pCompilingClass ){
1467 pCompilingMethod = pCompilingClass->GetMethodInfo( psi );
1468 if( !pCompilingMethod ){
1469 pCompilingMethod = pCompilingClass->GetStaticMethodInfo( psi );
1470 if( !pCompilingMethod ){
1471 SetError(300,NULL,cp);
1472 }
1473 }
1474 }
1475 else{
1476 pCompilingMethod = NULL;
1477 }
1478}
1479CClass *CDBClass::GetNowCompilingClass(){
1480 return pCompilingClass;
1481}
1482CMethod *CDBClass::GetNowCompilingMethodInfo(){
1483 return pCompilingMethod;
1484}
1485
1486
1487
1488
1489//////////////////////
1490// イテレータ
1491//////////////////////
1492
1493void CDBClass::Iterator_Reset(void){
1494 if(ppobj_IteClass) HeapDefaultFree(ppobj_IteClass);
1495
1496 iIteMaxNum=0;
1497 iIteNextNum=0;
1498 ppobj_IteClass=(CClass **)HeapAlloc(hHeap,0,1);
1499
1500 int i;
1501 for(i=0;i<MAX_CLASS_HASH;i++){
1502 if(pobj_ClassHash[i]){
1503 CClass *pobj_c;
1504 pobj_c=pobj_ClassHash[i];
1505 while(1){
1506 ppobj_IteClass=(CClass **)HeapReAlloc(hHeap,0,ppobj_IteClass,(iIteMaxNum+1)*sizeof(CClass *));
1507 ppobj_IteClass[iIteMaxNum]=pobj_c;
1508 iIteMaxNum++;
1509
1510 if(pobj_c->pobj_NextClass==0) break;
1511 pobj_c=pobj_c->pobj_NextClass;
1512 }
1513 }
1514 }
1515}
1516BOOL CDBClass::Iterator_HasNext(void){
1517 if(iIteNextNum<iIteMaxNum) return 1;
1518 return 0;
1519}
1520CClass *CDBClass::Iterator_GetNext(void){
1521 CClass *pobj_c;
1522 pobj_c=ppobj_IteClass[iIteNextNum];
1523 iIteNextNum++;
1524 return pobj_c;
1525}
1526int CDBClass::Iterator_GetMaxCount(void){
1527 return iIteMaxNum;
1528}
Note: See TracBrowser for help on using the repository browser.