1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: vc_class.cpp 4297 2010-06-03 22:49:00Z firebrand_kh $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include "vc_local.h"
29 
30 // MACROS ------------------------------------------------------------------
31 
32 // TYPES -------------------------------------------------------------------
33 
34 class DummyClass1
35 {
36 public:
37 	void*		Pointer;
38 	vuint8		Byte1;
~DummyClass1()39 	virtual ~DummyClass1() {}
40 	virtual void Dummy() = 0;
41 };
42 
43 class DummyClass2 : public DummyClass1
44 {
45 public:
46 	vuint8		Byte2;
47 };
48 
49 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
50 
51 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
52 
53 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
54 
55 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
56 
57 // PUBLIC DATA DEFINITIONS -------------------------------------------------
58 
59 TArray<mobjinfo_t>		VClass::GMobjInfos;
60 TArray<mobjinfo_t>		VClass::GScriptIds;
61 TArray<VName>			VClass::GSpriteNames;
62 VClass*					VClass::GLowerCaseHashTable[VClass::LOWER_CASE_HASH_SIZE];
63 
64 // PRIVATE DATA DEFINITIONS ------------------------------------------------
65 
66 // CODE --------------------------------------------------------------------
67 
68 //==========================================================================
69 //
70 //	VClass::VClass
71 //
72 //==========================================================================
73 
VClass(VName AName,VMemberBase * AOuter,TLocation ALoc)74 VClass::VClass(VName AName, VMemberBase* AOuter, TLocation ALoc)
75 : VMemberBase(MEMBER_Class, AName, AOuter, ALoc)
76 , ParentClass(NULL)
77 , Fields(NULL)
78 , States(NULL)
79 , DefaultProperties(NULL)
80 , ParentClassName(NAME_None)
81 , GameExpr(NULL)
82 , MobjInfoExpr(NULL)
83 , ScriptIdExpr(NULL)
84 , Defined(true)
85 , ObjectFlags(0)
86 , LinkNext(NULL)
87 , ClassSize(0)
88 , ClassUnalignedSize(0)
89 , ClassFlags(0)
90 , ClassVTable(NULL)
91 , ClassConstructor(NULL)
92 , ClassNumMethods(0)
93 , ReferenceFields(NULL)
94 , DestructorFields(NULL)
95 , NetFields(NULL)
96 , NetMethods(NULL)
97 , Defaults(NULL)
98 , NetStates(NULL)
99 , NumNetFields(0)
100 , Replacement(NULL)
101 , Replacee(NULL)
102 {
103 	guard(VClass::VClass);
104 	LinkNext = GClasses;
105 	GClasses = this;
106 	HashLowerCased();
107 	unguard;
108 }
109 
110 //==========================================================================
111 //
112 //	VClass::VClass
113 //
114 //==========================================================================
115 
VClass(ENativeConstructor,size_t ASize,vuint32 AClassFlags,VClass * AParent,EName AName,void (* ACtor)())116 VClass::VClass(ENativeConstructor, size_t ASize, vuint32 AClassFlags,
117 	VClass *AParent, EName AName, void(*ACtor)())
118 : VMemberBase(MEMBER_Class, AName, NULL, TLocation())
119 , ParentClass(AParent)
120 , Fields(NULL)
121 , States(NULL)
122 , DefaultProperties(NULL)
123 , ParentClassName(NAME_None)
124 , GameExpr(NULL)
125 , MobjInfoExpr(NULL)
126 , ScriptIdExpr(NULL)
127 , Defined(true)
128 , ObjectFlags(CLASSOF_Native)
129 , LinkNext(NULL)
130 , ClassSize(ASize)
131 , ClassUnalignedSize(ASize)
132 , ClassFlags(AClassFlags)
133 , ClassVTable(NULL)
134 , ClassConstructor(ACtor)
135 , ClassNumMethods(0)
136 , ReferenceFields(NULL)
137 , DestructorFields(NULL)
138 , NetFields(NULL)
139 , NetMethods(NULL)
140 , NetStates(NULL)
141 , NumNetFields(0)
142 , Defaults(NULL)
143 , Replacement(NULL)
144 , Replacee(NULL)
145 {
146 	guard(native VClass::VClass);
147 	LinkNext = GClasses;
148 	GClasses = this;
149 	unguard;
150 }
151 
152 //==========================================================================
153 //
154 //	VClass::~VClass
155 //
156 //==========================================================================
157 
~VClass()158 VClass::~VClass()
159 {
160 	guard(VClass::~VClass);
161 	if (GameExpr)
162 	{
163 		delete GameExpr;
164 		GameExpr = NULL;
165 	}
166 	if (MobjInfoExpr)
167 	{
168 		delete MobjInfoExpr;
169 		MobjInfoExpr = NULL;
170 	}
171 	if (ScriptIdExpr)
172 	{
173 		delete ScriptIdExpr;
174 		ScriptIdExpr = NULL;
175 	}
176 
177 	if (ClassVTable)
178 	{
179 		delete[] ClassVTable;
180 		ClassVTable = NULL;
181 	}
182 #ifndef IN_VCC
183 	if (Defaults)
184 	{
185 		DestructObject((VObject*)Defaults);
186 		delete[] Defaults;
187 		Defaults = NULL;
188 	}
189 #endif
190 
191 	if (!GObjInitialised)
192 	{
193 		return;
194 	}
195 	//	Unlink from classes list.
196 	if (GClasses == this)
197 	{
198 		GClasses = LinkNext;
199 	}
200 	else
201 	{
202 		VClass* Prev = GClasses;
203 		while (Prev && Prev->LinkNext != this)
204 		{
205 			Prev = Prev->LinkNext;
206 		}
207 		if (Prev)
208 		{
209 			Prev->LinkNext = LinkNext;
210 		}
211 		else
212 		{
213 #ifndef IN_VCC
214 			GCon->Log(NAME_Dev, "VClass Unlink: Class not in list");
215 #endif
216 		}
217 	}
218 	unguard;
219 }
220 
221 //==========================================================================
222 //
223 //	VClass::FindClass
224 //
225 //==========================================================================
226 
FindClass(const char * AName)227 VClass *VClass::FindClass(const char *AName)
228 {
229 	guard(VClass::FindClass);
230 	VName TempName(AName, VName::Find);
231 	if (TempName == NAME_None)
232 	{
233 		// No such name, no chance to find a class
234 		return NULL;
235 	}
236 	for (VClass* Cls = GClasses; Cls; Cls = Cls->LinkNext)
237 	{
238 		if (Cls->GetVName() == TempName && Cls->MemberType == MEMBER_Class)
239 		{
240 			return Cls;
241 		}
242 	}
243 	return NULL;
244 	unguard;
245 }
246 
247 //==========================================================================
248 //
249 //	VClass::FindClassNoCase
250 //
251 //==========================================================================
252 
FindClassNoCase(const char * AName)253 VClass *VClass::FindClassNoCase(const char *AName)
254 {
255 	guard(VClass::FindClassNoCase);
256 	for (VClass* Cls = GClasses; Cls; Cls = Cls->LinkNext)
257 	{
258 		if (Cls->MemberType == MEMBER_Class &&
259 			!VStr::ICmp(Cls->GetName(), AName))
260 		{
261 			return Cls;
262 		}
263 	}
264 	return NULL;
265 	unguard;
266 }
267 
268 //==========================================================================
269 //
270 //	VClass::FindSprite
271 //
272 //==========================================================================
273 
FindSprite(VName Name,bool Append)274 int VClass::FindSprite(VName Name, bool Append)
275 {
276 	guard(VClass::FindSprite);
277 	for (int i = 0; i < GSpriteNames.Num(); i++)
278 	{
279 		if (GSpriteNames[i] == Name)
280 		{
281 			return i;
282 		}
283 	}
284 	if (!Append)
285 	{
286 		return -1;
287 	}
288 	return GSpriteNames.Append(Name);
289 	unguard;
290 }
291 
292 #ifndef IN_VCC
293 
294 //==========================================================================
295 //
296 //	VClass::GetSpriteNames
297 //
298 //==========================================================================
299 
GetSpriteNames(TArray<FReplacedString> & List)300 void VClass::GetSpriteNames(TArray<FReplacedString>& List)
301 {
302 	guard(VClass::GetSpriteNames);
303 	for (int i = 0; i < GSpriteNames.Num(); i++)
304 	{
305 		FReplacedString&R = List.Alloc();
306 		R.Index = i;
307 		R.Replaced = false;
308 		R.Old = VStr(*GSpriteNames[i]).ToUpper();
309 	}
310 	unguard;
311 }
312 
313 //==========================================================================
314 //
315 //	VClass::ReplaceSpriteNames
316 //
317 //==========================================================================
318 
ReplaceSpriteNames(TArray<FReplacedString> & List)319 void VClass::ReplaceSpriteNames(TArray<FReplacedString>& List)
320 {
321 	guard(VClass::ReplaceSpriteNames);
322 	for (int i = 0; i < List.Num(); i++)
323 	{
324 		if (!List[i].Replaced)
325 		{
326 			continue;
327 		}
328 		GSpriteNames[List[i].Index] = *List[i].New.ToLower();
329 	}
330 
331 	//	Update sprite names in states.
332 	for (int i = 0; i < VMemberBase::GMembers.Num(); i++)
333 	{
334 		if (GMembers[i] && GMembers[i]->MemberType == MEMBER_State)
335 		{
336 			VState* S = (VState*)GMembers[i];
337 			S->SpriteName = GSpriteNames[S->SpriteIndex];
338 		}
339 	}
340 	unguard;
341 }
342 
343 #endif
344 
345 //==========================================================================
346 //
347 //	VClass::StaticReinitStatesLookup
348 //
349 //==========================================================================
350 
StaticReinitStatesLookup()351 void VClass::StaticReinitStatesLookup()
352 {
353 	guard(VClass::StaticReinitStatesLookup);
354 	//	Clear states lookup tables.
355 	for (VClass* C = GClasses; C; C = C->LinkNext)
356 	{
357 		C->StatesLookup.Clear();
358 	}
359 
360 	//	Now init states lookup tables again.
361 	for (VClass* C = GClasses; C; C = C->LinkNext)
362 	{
363 		C->InitStatesLookup();
364 	}
365 	unguard;
366 }
367 
368 //==========================================================================
369 //
370 //	VClass::Serialise
371 //
372 //==========================================================================
373 
Serialise(VStream & Strm)374 void VClass::Serialise(VStream& Strm)
375 {
376 	guard(VClass::Serialise);
377 	VMemberBase::Serialise(Strm);
378 #ifndef IN_VCC
379 	VClass* PrevParent = ParentClass;
380 #endif
381 	Strm << ParentClass
382 		<< Fields
383 		<< States
384 		<< Methods
385 		<< DefaultProperties
386 		<< RepInfos
387 		<< StateLabels;
388 #ifndef IN_VCC
389 	if ((ObjectFlags & CLASSOF_Native) && ParentClass != PrevParent)
390 	{
391 		Sys_Error("Bad parent class, class %s, C++ %s, VavoomC %s)",
392 			GetName(), PrevParent ? PrevParent->GetName() : "(none)",
393 			ParentClass ? ParentClass->GetName() : "(none)");
394 	}
395 #endif
396 	unguard;
397 }
398 
399 //==========================================================================
400 //
401 //	VClass::Shutdown
402 //
403 //==========================================================================
404 
Shutdown()405 void VClass::Shutdown()
406 {
407 	guard(VClass::Shutdown);
408 	if (ClassVTable)
409 	{
410 		delete[] ClassVTable;
411 		ClassVTable = NULL;
412 	}
413 #ifndef IN_VCC
414 	if (Defaults)
415 	{
416 		DestructObject((VObject*)Defaults);
417 		delete[] Defaults;
418 		Defaults = NULL;
419 	}
420 #endif
421 	StatesLookup.Clear();
422 	RepInfos.Clear();
423 	SpriteEffects.Clear();
424 	StateLabels.Clear();
425 	Structs.Clear();
426 	Constants.Clear();
427 	Properties.Clear();
428 	Methods.Clear();
429 	StateLabelDefs.Clear();
430 	DecorateStateActions.Clear();
431 	SpriteEffects.Clear();
432 	unguard;
433 }
434 
435 //==========================================================================
436 //
437 //	VClass::AddConstant
438 //
439 //==========================================================================
440 
AddConstant(VConstant * c)441 void VClass::AddConstant(VConstant* c)
442 {
443 	guard(VClass::AddConstant);
444 	Constants.Append(c);
445 	unguard;
446 }
447 
448 //==========================================================================
449 //
450 //	VClass::AddField
451 //
452 //==========================================================================
453 
AddField(VField * f)454 void VClass::AddField(VField* f)
455 {
456 	guard(VClass::AddField);
457 	if (!Fields)
458 	{
459 		Fields = f;
460 	}
461 	else
462 	{
463 		VField* Prev = Fields;
464 		while (Prev->Next)
465 		{
466 			Prev = Prev->Next;
467 		}
468 		Prev->Next = f;
469 	}
470 	f->Next = NULL;
471 	unguard;
472 }
473 
474 //==========================================================================
475 //
476 //	VClass::AddProperty
477 //
478 //==========================================================================
479 
AddProperty(VProperty * p)480 void VClass::AddProperty(VProperty* p)
481 {
482 	guard(VClass::AddProperty);
483 	Properties.Append(p);
484 	unguard;
485 }
486 
487 //==========================================================================
488 //
489 //	VClass::AddState
490 //
491 //==========================================================================
492 
AddState(VState * s)493 void VClass::AddState(VState* s)
494 {
495 	guard(VClass::AddState);
496 	if (!States)
497 	{
498 		States = s;
499 	}
500 	else
501 	{
502 		VState* Prev = States;
503 		while (Prev->Next)
504 		{
505 			Prev = Prev->Next;
506 		}
507 		Prev->Next = s;
508 	}
509 	s->Next = NULL;
510 	unguard;
511 }
512 
513 //==========================================================================
514 //
515 //	VClass::AddMethod
516 //
517 //==========================================================================
518 
AddMethod(VMethod * m)519 void VClass::AddMethod(VMethod* m)
520 {
521 	guard(VClass::AddMethod);
522 	Methods.Append(m);
523 	unguard;
524 }
525 
526 //==========================================================================
527 //
528 //	VClass::FindConstant
529 //
530 //==========================================================================
531 
FindConstant(VName Name)532 VConstant* VClass::FindConstant(VName Name)
533 {
534 	guard(VClass::FindConstant);
535 	VMemberBase* m = StaticFindMember(Name, this, MEMBER_Const);
536 	if (m)
537 	{
538 		return (VConstant*)m;
539 	}
540 	if (ParentClass)
541 	{
542 		return ParentClass->FindConstant(Name);
543 	}
544 	return NULL;
545 	unguard;
546 }
547 
548 //==========================================================================
549 //
550 //	VClass::FindField
551 //
552 //==========================================================================
553 
FindField(VName Name)554 VField* VClass::FindField(VName Name)
555 {
556 	guard(VClass::FindField);
557 	if (Name == NAME_None)
558 	{
559 		return NULL;
560 	}
561 	for (VField *F = Fields; F; F = F->Next)
562 	{
563 		if (Name == F->Name)
564 		{
565 			return F;
566 		}
567 	}
568 	if (ParentClass)
569 	{
570 		return ParentClass->FindField(Name);
571 	}
572 	return NULL;
573 	unguard;
574 }
575 
576 //==========================================================================
577 //
578 //	VClass::FindField
579 //
580 //==========================================================================
581 
FindField(VName Name,TLocation l,VClass * SelfClass)582 VField* VClass::FindField(VName Name, TLocation l, VClass* SelfClass)
583 {
584 	guard(VClass::FindField);
585 	VField* F = FindField(Name);
586 	if (F && (F->Flags & FIELD_Private) && this != SelfClass)
587 	{
588 		ParseError(l, "Field %s is private", *F->Name);
589 	}
590 	return F;
591 	unguard;
592 }
593 
594 //==========================================================================
595 //
596 //	VClass::FindFieldChecked
597 //
598 //==========================================================================
599 
FindFieldChecked(VName AName)600 VField* VClass::FindFieldChecked(VName AName)
601 {
602 	guard(VClass::FindFieldChecked);
603 	VField* F = FindField(AName);
604 	if (!F)
605 	{
606 		Sys_Error("Field %s not found", *AName);
607 	}
608 	return F;
609 	unguard;
610 }
611 
612 //==========================================================================
613 //
614 //	VClass::FindProperty
615 //
616 //==========================================================================
617 
FindProperty(VName Name)618 VProperty* VClass::FindProperty(VName Name)
619 {
620 	guard(VClass::FindProperty);
621 	if (Name == NAME_None)
622 	{
623 		return NULL;
624 	}
625 	VProperty* P = (VProperty*)StaticFindMember(Name, this, MEMBER_Property);
626 	if (P)
627 	{
628 		return P;
629 	}
630 	if (ParentClass)
631 	{
632 		return ParentClass->FindProperty(Name);
633 	}
634 	return NULL;
635 	unguard;
636 }
637 
638 //==========================================================================
639 //
640 //	VClass::FindMethod
641 //
642 //==========================================================================
643 
FindMethod(VName Name,bool bRecursive)644 VMethod* VClass::FindMethod(VName Name, bool bRecursive)
645 {
646 	guard(VClass::FindMethod);
647 	if (Name == NAME_None)
648 	{
649 		return NULL;
650 	}
651 	VMethod* M = (VMethod*)StaticFindMember(Name, this, MEMBER_Method);
652 	if (M)
653 	{
654 		return M;
655 	}
656 	if (bRecursive && ParentClass)
657 	{
658 		return ParentClass->FindMethod(Name);
659 	}
660 	return NULL;
661 	unguard;
662 }
663 
664 //==========================================================================
665 //
666 //	VClass::FindMethodChecked
667 //
668 //==========================================================================
669 
FindMethodChecked(VName AName)670 VMethod *VClass::FindMethodChecked(VName AName)
671 {
672 	guard(VClass::FindMethodChecked);
673 	VMethod *func = FindMethod(AName);
674 	if (!func)
675 	{
676 		Sys_Error("Function %s not found", *AName);
677 	}
678 	return func;
679 	unguard;
680 }
681 
682 //==========================================================================
683 //
684 //	VClass::GetMethodIndex
685 //
686 //==========================================================================
687 
GetMethodIndex(VName AName)688 int VClass::GetMethodIndex(VName AName)
689 {
690 	guard(VClass::GetMethodIndex);
691 	for (int i = 0; i < ClassNumMethods; i++)
692 	{
693 		if (ClassVTable[i]->Name == AName)
694 		{
695 			return i;
696 		}
697 	}
698 	return -1;
699 	unguard;
700 }
701 
702 //==========================================================================
703 //
704 //	VClass::FindState
705 //
706 //==========================================================================
707 
FindState(VName AName)708 VState* VClass::FindState(VName AName)
709 {
710 	guard(VClass::FindState);
711 	for (VState* s = States; s; s = s->Next)
712 	{
713 		if (s->Name == AName)
714 		{
715 			return s;
716 		}
717 	}
718 	if (ParentClass)
719 	{
720 		return ParentClass->FindState(AName);
721 	}
722 	return NULL;
723 	unguard;
724 }
725 
726 //==========================================================================
727 //
728 //	VClass::FindStateChecked
729 //
730 //==========================================================================
731 
FindStateChecked(VName AName)732 VState* VClass::FindStateChecked(VName AName)
733 {
734 	guard(VClass::FindStateChecked);
735 	VState* s = FindState(AName);
736 	if (!s)
737 	{
738 		Sys_Error("State %s not found", *AName);
739 	}
740 	return s;
741 	unguard;
742 }
743 
744 //==========================================================================
745 //
746 //	VClass::FindStateLabel
747 //
748 //==========================================================================
749 
FindStateLabel(VName AName,VName SubLabel,bool Exact)750 VStateLabel* VClass::FindStateLabel(VName AName, VName SubLabel, bool Exact)
751 {
752 	guard(VClass::FindStateLabel);
753 	for (int i = 0; i < StateLabels.Num(); i++)
754 	{
755 		if (!VStr::ICmp(*StateLabels[i].Name, *AName))
756 		{
757 			if (SubLabel != NAME_None)
758 			{
759 				TArray<VStateLabel>& SubList = StateLabels[i].SubLabels;
760 				for (int j = 0; j < SubList.Num(); j++)
761 				{
762 					if (!VStr::ICmp(*SubList[j].Name, *SubLabel))
763 					{
764 						return &SubList[j];
765 					}
766 				}
767 				if (Exact)
768 				{
769 					return NULL;
770 				}
771 			}
772 			return &StateLabels[i];
773 		}
774 	}
775 	return NULL;
776 	unguard;
777 }
778 
779 //==========================================================================
780 //
781 //	VClass::FindStateLabel
782 //
783 //==========================================================================
784 
FindStateLabel(TArray<VName> & Names,bool Exact)785 VStateLabel* VClass::FindStateLabel(TArray<VName>& Names, bool Exact)
786 {
787 	guard(VClass::FindStateLabel);
788 	TArray<VStateLabel>* List = &StateLabels;
789 	VStateLabel* Best = NULL;
790 	for (int ni = 0; ni < Names.Num(); ni++)
791 	{
792 		VStateLabel* Lbl = NULL;
793 		for (int i = 0; i < List->Num(); i++)
794 		{
795 			if (!VStr::ICmp(*(*List)[i].Name, *Names[ni]))
796 			{
797 				Lbl = &(*List)[i];
798 				break;
799 			}
800 		}
801 		if (!Lbl)
802 		{
803 			if (Exact)
804 			{
805 				return NULL;
806 			}
807 			break;
808 		}
809 		else
810 		{
811 			Best = Lbl;
812 			List = &Lbl->SubLabels;
813 		}
814 	}
815 	return Best;
816 	unguard;
817 }
818 
819 //==========================================================================
820 //
821 //	VClass::FindStateLabelChecked
822 //
823 //==========================================================================
824 
FindStateLabelChecked(VName AName,VName SubLabel,bool Exact)825 VStateLabel* VClass::FindStateLabelChecked(VName AName, VName SubLabel,
826 	bool Exact)
827 {
828 	guard(VClass::FindStateLabelChecked);
829 	VStateLabel* Lbl = FindStateLabel(AName, SubLabel, Exact);
830 	if (!Lbl)
831 	{
832 		VStr FullName = *AName;
833 		if (SubLabel != NAME_None)
834 		{
835 			FullName += ".";
836 			FullName += *SubLabel;
837 		}
838 		Sys_Error("State %s not found", *FullName);
839 	}
840 	return Lbl;
841 	unguard;
842 }
843 
844 //==========================================================================
845 //
846 //	VClass::FindStateLabelChecked
847 //
848 //==========================================================================
849 
FindStateLabelChecked(TArray<VName> & Names,bool Exact)850 VStateLabel* VClass::FindStateLabelChecked(TArray<VName>& Names, bool Exact)
851 {
852 	guard(VClass::FindStateLabelChecked);
853 	VStateLabel* Lbl = FindStateLabel(Names, Exact);
854 	if (!Lbl)
855 	{
856 		VStr FullName = *Names[0];
857 		for (int i = 1; i < Names.Num(); i++)
858 		{
859 			FullName += ".";
860 			FullName += *Names[i];
861 		}
862 		Sys_Error("State %s not found", *FullName);
863 	}
864 	return Lbl;
865 	unguard;
866 }
867 
868 //==========================================================================
869 //
870 //	VClass::FindDecorateStateAction
871 //
872 //==========================================================================
873 
FindDecorateStateAction(VName ActName)874 VDecorateStateAction* VClass::FindDecorateStateAction(VName ActName)
875 {
876 	guard(VClass::FindDecorateStateAction);
877 	for (int i = 0; i < DecorateStateActions.Num(); i++)
878 	{
879 		if (DecorateStateActions[i].Name == ActName)
880 		{
881 			return &DecorateStateActions[i];
882 		}
883 	}
884 	if (ParentClass)
885 	{
886 		return ParentClass->FindDecorateStateAction(ActName);
887 	}
888 	return NULL;
889 	unguard;
890 }
891 
892 //==========================================================================
893 //
894 //	VClass::Define
895 //
896 //==========================================================================
897 
Define()898 bool VClass::Define()
899 {
900 	guard(VClass::Define);
901 	//	Check for duplicates.
902 	int HashIndex = Name.GetIndex() & 4095;
903 	for (VMemberBase* m = GMembersHash[HashIndex]; m; m = m->HashNext)
904 	{
905 		if (m->Name == Name && m->MemberType == MEMBER_Class &&
906 			((VClass*)m)->Defined)
907 		{
908 			ParseError(Loc, "Class %s already has been declared", *Name);
909 		}
910 	}
911 
912 #ifndef IN_VCC
913 	VClass* PrevParent = ParentClass;
914 #endif
915 	if (ParentClassName != NAME_None)
916 	{
917 		ParentClass = StaticFindClass(ParentClassName);
918 		if (!ParentClass)
919 		{
920 			ParseError(ParentClassLoc, "No such class %s", *ParentClassName);
921 		}
922 		else if (!ParentClass->Defined)
923 		{
924 			ParseError(ParentClassLoc, "Parent class must be defined before");
925 		}
926 	}
927 #ifndef IN_VCC
928 	if ((ObjectFlags & CLASSOF_Native) && ParentClass != PrevParent)
929 	{
930 		Sys_Error("Bad parent class, class %s, C++ %s, VavoomC %s)",
931 			GetName(), PrevParent ? PrevParent->GetName() : "(none)",
932 			ParentClass ? ParentClass->GetName() : "(none)");
933 	}
934 #endif
935 
936 	for (int i = 0; i < Structs.Num(); i++)
937 	{
938 		if (!Structs[i]->Define())
939 		{
940 			return false;
941 		}
942 	}
943 
944 	Defined = true;
945 	return true;
946 	unguard;
947 }
948 
949 //==========================================================================
950 //
951 //	VClass::DefineMembers
952 //
953 //==========================================================================
954 
DefineMembers()955 bool VClass::DefineMembers()
956 {
957 	guard(VClass::DefineMembers);
958 	bool Ret = true;
959 
960 	for (int i = 0; i < Constants.Num(); i++)
961 	{
962 		if (!Constants[i]->Define())
963 		{
964 			Ret = false;
965 		}
966 	}
967 
968 	for (int i = 0; i < Structs.Num(); i++)
969 	{
970 		Structs[i]->DefineMembers();
971 	}
972 
973 	VField* PrevBool = NULL;
974 	for (VField* fi = Fields; fi; fi = fi->Next)
975 	{
976 		if (!fi->Define())
977 		{
978 			Ret = false;
979 		}
980 		if (fi->Type.Type == TYPE_Bool && PrevBool && PrevBool->Type.BitMask != 0x80000000)
981 		{
982 			fi->Type.BitMask = PrevBool->Type.BitMask << 1;
983 		}
984 		PrevBool = fi->Type.Type == TYPE_Bool ? fi : NULL;
985 	}
986 
987 	for (int i = 0; i < Properties.Num(); i++)
988 	{
989 		if (!Properties[i]->Define())
990 		{
991 			Ret = false;
992 		}
993 	}
994 
995 	for (int i = 0; i < Methods.Num(); i++)
996 	{
997 		if (!Methods[i]->Define())
998 		{
999 			Ret = false;
1000 		}
1001 	}
1002 
1003 	if (!DefaultProperties->Define())
1004 	{
1005 		Ret = false;
1006 	}
1007 
1008 	for (VState* s = States; s; s = s->Next)
1009 	{
1010 		if (!s->Define())
1011 		{
1012 			Ret = false;
1013 		}
1014 	}
1015 
1016 	for (int ri = 0; ri < RepInfos.Num(); ri++)
1017 	{
1018 		if (!RepInfos[ri].Cond->Define())
1019 		{
1020 			Ret = false;
1021 		}
1022 		TArray<VRepField>& RepFields = RepInfos[ri].RepFields;
1023 		for (int i = 0; i < RepFields.Num(); i++)
1024 		{
1025 			VField* RepField = NULL;
1026 			for (VField* F = Fields; F; F = F->Next)
1027 			{
1028 				if (F->Name == RepFields[i].Name)
1029 				{
1030 					RepField = F;
1031 					break;
1032 				}
1033 			}
1034 			if (RepField)
1035 			{
1036 				if (RepField->Flags & FIELD_Net)
1037 				{
1038 					ParseError(RepFields[i].Loc, "Field %s has multiple replication statements",
1039 						*RepFields[i].Name);
1040 					continue;
1041 				}
1042 				RepField->Flags |= FIELD_Net;
1043 				RepField->ReplCond = RepInfos[ri].Cond;
1044 				RepFields[i].Member = RepField;
1045 				continue;
1046 			}
1047 
1048 			VMethod* RepMethod = NULL;
1049 			for (int mi = 0; mi < Methods.Num(); mi++)
1050 			{
1051 				if (Methods[mi]->Name == RepFields[i].Name)
1052 				{
1053 					RepMethod = Methods[mi];
1054 					break;
1055 				}
1056 			}
1057 			if (RepMethod)
1058 			{
1059 				if (RepMethod->SuperMethod)
1060 				{
1061 					ParseError(RepFields[i].Loc, "Method %s is overloaded in this class",
1062 						*RepFields[i].Name);
1063 					continue;
1064 				}
1065 				if (RepMethod->Flags & FUNC_Net)
1066 				{
1067 					ParseError(RepFields[i].Loc, "Method %s has multiple replication statements",
1068 						*RepFields[i].Name);
1069 					continue;
1070 				}
1071 				RepMethod->Flags |= FUNC_Net;
1072 				RepMethod->ReplCond = RepInfos[ri].Cond;
1073 				if (RepInfos[ri].Reliable)
1074 					RepMethod->Flags |= FUNC_NetReliable;
1075 				RepFields[i].Member = RepMethod;
1076 				continue;
1077 			}
1078 
1079 			ParseError(RepFields[i].Loc, "No such field or method %s", *RepFields[i].Name);
1080 		}
1081 	}
1082 
1083 	return Ret;
1084 	unguard;
1085 }
1086 
1087 //==========================================================================
1088 //
1089 //	VClass::Emit
1090 //
1091 //==========================================================================
1092 
Emit()1093 void VClass::Emit()
1094 {
1095 	guard(VClass::Emit);
1096 	int GameFilter = 0;
1097 	if (GameExpr)
1098 	{
1099 		VEmitContext ec(this);
1100 		GameExpr = GameExpr->Resolve(ec);
1101 		if (GameExpr)
1102 		{
1103 			if (!GameExpr->IsIntConst())
1104 			{
1105 				ParseError(GameExpr->Loc, "Integer constant expected");
1106 			}
1107 			else
1108 			{
1109 				GameFilter = GameExpr->GetIntConst();
1110 			}
1111 		}
1112 	}
1113 
1114 	if (MobjInfoExpr)
1115 	{
1116 		VEmitContext ec(this);
1117 		MobjInfoExpr = MobjInfoExpr->Resolve(ec);
1118 		if (MobjInfoExpr)
1119 		{
1120 			if (!MobjInfoExpr->IsIntConst())
1121 			{
1122 				ParseError(MobjInfoExpr->Loc, "Integer constant expected");
1123 			}
1124 			else
1125 			{
1126 				mobjinfo_t& mi = ec.Package->MobjInfo.Alloc();
1127 				mi.DoomEdNum = MobjInfoExpr->GetIntConst();
1128 				mi.GameFilter = GameFilter;
1129 				mi.Class = this;
1130 			}
1131 		}
1132 	}
1133 
1134 	if (ScriptIdExpr)
1135 	{
1136 		VEmitContext ec(this);
1137 		ScriptIdExpr = ScriptIdExpr->Resolve(ec);
1138 		if (ScriptIdExpr)
1139 		{
1140 			if (!ScriptIdExpr->IsIntConst())
1141 			{
1142 				ParseError(ScriptIdExpr->Loc, "Integer constant expected");
1143 			}
1144 			else
1145 			{
1146 				mobjinfo_t& mi = ec.Package->ScriptIds.Alloc();
1147 				mi.DoomEdNum = ScriptIdExpr->GetIntConst();
1148 				mi.GameFilter = GameFilter;
1149 				mi.Class = this;
1150 			}
1151 		}
1152 	}
1153 
1154 	//	Emit method code.
1155 	for (int i = 0; i < Methods.Num(); i++)
1156 	{
1157 		Methods[i]->Emit();
1158 	}
1159 
1160 	//	Build list of state labels, resolve jumps.
1161 	EmitStateLabels();
1162 
1163 	//	Emit code of the state methods.
1164 	for (VState* s = States; s; s = s->Next)
1165 	{
1166 		s->Emit();
1167 	}
1168 
1169 	//	Emit code of the network replication conditions.
1170 	for (int ri = 0; ri < RepInfos.Num(); ri++)
1171 	{
1172 		RepInfos[ri].Cond->Emit();
1173 	}
1174 
1175 	DefaultProperties->Emit();
1176 	unguard;
1177 }
1178 
1179 //==========================================================================
1180 //
1181 //	VClass::DecorateEmit
1182 //
1183 //==========================================================================
1184 
DecorateEmit()1185 void VClass::DecorateEmit()
1186 {
1187 	guard(VClass::DecorateEmit);
1188 	//	Emit method code.
1189 	for (int i = 0; i < Methods.Num(); i++)
1190 	{
1191 		Methods[i]->Emit();
1192 	}
1193 	unguard;
1194 }
1195 
1196 //==========================================================================
1197 //
1198 //	VClass::EmitStateLabels
1199 //
1200 //==========================================================================
1201 
EmitStateLabels()1202 void VClass::EmitStateLabels()
1203 {
1204 	guard(VClass::EmitStateLabels);
1205 	if (ParentClass && !(ClassFlags & CLASS_SkipSuperStateLabels))
1206 	{
1207 		StateLabels = ParentClass->StateLabels;
1208 	}
1209 
1210 	//	First add all labels.
1211 	for (int i = 0; i < StateLabelDefs.Num(); i++)
1212 	{
1213 		VStateLabelDef& Lbl = StateLabelDefs[i];
1214 		TArray<VName> Names;
1215 		StaticSplitStateLabel(Lbl.Name, Names);
1216 		SetStateLabel(Names, Lbl.State);
1217 	}
1218 
1219 	//	Then resolve state labels that do immediate jumps.
1220 	for (int i = 0; i < StateLabelDefs.Num(); i++)
1221 	{
1222 		VStateLabelDef& Lbl = StateLabelDefs[i];
1223 		if (Lbl.GotoLabel != NAME_None)
1224 		{
1225 			Lbl.State = ResolveStateLabel(Lbl.Loc, Lbl.GotoLabel, Lbl.GotoOffset);
1226 			TArray<VName> Names;
1227 			StaticSplitStateLabel(Lbl.Name, Names);
1228 			SetStateLabel(Names, Lbl.State);
1229 		}
1230 	}
1231 	unguard;
1232 }
1233 
1234 //==========================================================================
1235 //
1236 //	VClass::ResolveStateLabel
1237 //
1238 //==========================================================================
1239 
ResolveStateLabel(TLocation Loc,VName LabelName,int Offset)1240 VState* VClass::ResolveStateLabel(TLocation Loc, VName LabelName, int Offset)
1241 {
1242 	VClass* CheckClass = this;
1243 	VStr CheckName = *LabelName;
1244 
1245 	int DCol = CheckName.IndexOf("::");
1246 	if (DCol >= 0)
1247 	{
1248 		VStr ClassNameStr(CheckName, 0, DCol);
1249 		VName ClassName(*ClassNameStr);
1250 		if (ClassName == NAME_Super)
1251 		{
1252 			CheckClass = ParentClass;
1253 		}
1254 		else
1255 		{
1256 			CheckClass = StaticFindClass(ClassName);
1257 			if (!CheckClass)
1258 			{
1259 				ParseError(Loc, "No such class %s", *ClassName);
1260 				return NULL;
1261 			}
1262 		}
1263 		CheckName = VStr(CheckName, DCol + 2, CheckName.Length() - DCol - 2);
1264 	}
1265 
1266 	TArray<VName> Names;
1267 	StaticSplitStateLabel(CheckName, Names);
1268 	VStateLabel* Lbl = CheckClass->FindStateLabel(Names, true);
1269 	if (!Lbl)
1270 	{
1271 		ParseError(Loc, "No such state %s", *LabelName);
1272 		return NULL;
1273 	}
1274 
1275 	VState* State = Lbl->State;
1276 	int Count = Offset;
1277 	while (Count--)
1278 	{
1279 		if (!State || !State->Next)
1280 		{
1281 			ParseError(Loc, "Bad jump offset");
1282 			return NULL;
1283 		}
1284 		State = State->Next;
1285 	}
1286 	return State;
1287 }
1288 
1289 //==========================================================================
1290 //
1291 //	VClass::SetStateLabel
1292 //
1293 //==========================================================================
1294 
SetStateLabel(VName AName,VState * State)1295 void VClass::SetStateLabel(VName AName, VState* State)
1296 {
1297 	guard(VClass::SetStateLabel);
1298 	for (int i = 0; i < StateLabels.Num(); i++)
1299 	{
1300 		if (StateLabels[i].Name == AName)
1301 		{
1302 			StateLabels[i].State = State;
1303 			return;
1304 		}
1305 	}
1306 	VStateLabel& L = StateLabels.Alloc();
1307 	L.Name = AName;
1308 	L.State = State;
1309 	unguard;
1310 }
1311 
1312 //==========================================================================
1313 //
1314 //	VClass::SetStateLabel
1315 //
1316 //==========================================================================
1317 
SetStateLabel(const TArray<VName> & Names,VState * State)1318 void VClass::SetStateLabel(const TArray<VName>& Names, VState* State)
1319 {
1320 	guard(VClass::SetStateLabel);
1321 	if (!Names.Num())
1322 	{
1323 		return;
1324 	}
1325 	TArray<VStateLabel>* List = &StateLabels;
1326 	VStateLabel* Lbl = NULL;
1327 	for (int ni = 0; ni < Names.Num(); ni++)
1328 	{
1329 		Lbl = NULL;
1330 		for (int i = 0; i < List->Num(); i++)
1331 		{
1332 			if ((*List)[i].Name == Names[ni])
1333 			{
1334 				Lbl = &(*List)[i];
1335 				break;
1336 			}
1337 		}
1338 		if (!Lbl)
1339 		{
1340 			Lbl = &List->Alloc();
1341 			Lbl->Name = Names[ni];
1342 		}
1343 		List = &Lbl->SubLabels;
1344 	}
1345 	Lbl->State = State;
1346 	unguard;
1347 }
1348 
1349 //==========================================================================
1350 //
1351 //	VClass::PostLoad
1352 //
1353 //==========================================================================
1354 
PostLoad()1355 void VClass::PostLoad()
1356 {
1357 	if (ObjectFlags & CLASSOF_PostLoaded)
1358 	{
1359 		//	Already set up.
1360 		return;
1361 	}
1362 
1363 	//	Make sure parent class has been set up.
1364 	if (GetSuperClass())
1365 	{
1366 		GetSuperClass()->PostLoad();
1367 	}
1368 
1369 	NetStates = States;
1370 
1371 	//	Calculate field offsets and class size.
1372 	CalcFieldOffsets();
1373 
1374 	//	Initialise reference fields.
1375 	InitReferences();
1376 
1377 	//	Initialise destructor fields.
1378 	InitDestructorFields();
1379 
1380 	//	Initialise net fields.
1381 	InitNetFields();
1382 
1383 	//	Create virtual table.
1384 	CreateVTable();
1385 
1386 	//	Set up states lookup table.
1387 	InitStatesLookup();
1388 
1389 	//	Set state in-class indexes.
1390 	int CurrIndex = 0;
1391 	for (VState* S = States; S; S = S->Next)
1392 	{
1393 		S->InClassIndex = CurrIndex++;
1394 	}
1395 
1396 	ObjectFlags |= CLASSOF_PostLoaded;
1397 }
1398 
1399 //==========================================================================
1400 //
1401 //	VClass::DecoratePostLoad
1402 //
1403 //==========================================================================
1404 
DecoratePostLoad()1405 void VClass::DecoratePostLoad()
1406 {
1407 	guard(VClass::DecoratePostLoad);
1408 	//	Compile.
1409 	for (int i = 0; i < Methods.Num(); i++)
1410 	{
1411 		Methods[i]->PostLoad();
1412 	}
1413 
1414 	for (VState* S = States; S; S = S->Next)
1415 	{
1416 		S->PostLoad();
1417 	}
1418 
1419 	NetStates = States;
1420 
1421 	//	Set state in-class indexes.
1422 	int CurrIndex = 0;
1423 	for (VState* S = States; S; S = S->Next)
1424 	{
1425 		S->InClassIndex = CurrIndex++;
1426 	}
1427 
1428 	//	Calculate indexes of virtual methods.
1429 	CalcFieldOffsets();
1430 
1431 	//	Recreate virtual table.
1432 	CreateVTable();
1433 	unguard;
1434 }
1435 
1436 //==========================================================================
1437 //
1438 //	VClass::CalcFieldOffsets
1439 //
1440 //==========================================================================
1441 
CalcFieldOffsets()1442 void VClass::CalcFieldOffsets()
1443 {
1444 	guard(VClass::CalcFieldOffsets);
1445 	//	Skip this for C++ only classes.
1446 	if (!Outer && (ObjectFlags & CLASSOF_Native))
1447 	{
1448 		ClassNumMethods = ParentClass ? ParentClass->ClassNumMethods : 0;
1449 		return;
1450 	}
1451 
1452 	int PrevClassNumMethods = ClassNumMethods;
1453 	int numMethods = ParentClass ? ParentClass->ClassNumMethods : 0;
1454 	for (int i = 0; i < Methods.Num(); i++)
1455 	{
1456 		VMethod* M = (VMethod*)Methods[i];
1457 		int MOfs = -1;
1458 		if (ParentClass)
1459 		{
1460 			MOfs = ParentClass->GetMethodIndex(M->Name);
1461 		}
1462 		if (MOfs == -1 && !(M->Flags & FUNC_Final))
1463 		{
1464 			MOfs = numMethods++;
1465 		}
1466 		M->VTableIndex = MOfs;
1467 	}
1468 	if (ClassVTable && PrevClassNumMethods != ClassNumMethods)
1469 	{
1470 		delete[] ClassVTable;
1471 		ClassVTable = NULL;
1472 	}
1473 
1474 	VField* PrevField = NULL;
1475 	int PrevSize = ClassSize;
1476 	int size = 0;
1477 	if (ParentClass)
1478 	{
1479 		//	GCC has a strange behavior of starting to add fields in subclasses
1480 		// in a class that has virtual methods on unaligned parent size offset.
1481 		// In other cases and in other compilers it starts on aligned parent
1482 		// class size offset.
1483 		if (sizeof(DummyClass1) == sizeof(DummyClass2))
1484 			size = ParentClass->ClassUnalignedSize;
1485 		else
1486 			size = ParentClass->ClassSize;
1487 	}
1488 	for (VField* fi = Fields; fi; fi = fi->Next)
1489 	{
1490 		if (fi->Type.Type == TYPE_Bool && PrevField &&
1491 			PrevField->Type.Type == TYPE_Bool &&
1492 			PrevField->Type.BitMask != 0x80000000)
1493 		{
1494 			vuint32 bit_mask = PrevField->Type.BitMask << 1;
1495 			if (fi->Type.BitMask != bit_mask)
1496 				Sys_Error("Wrong bit mask");
1497 			fi->Type.BitMask = bit_mask;
1498 			fi->Ofs = PrevField->Ofs;
1499 		}
1500 		else
1501 		{
1502 			if (fi->Type.Type == TYPE_Struct ||
1503 				(fi->Type.Type == TYPE_Array && fi->Type.ArrayInnerType == TYPE_Struct))
1504 			{
1505 				//	Make sure struct size has been calculated.
1506 				fi->Type.Struct->PostLoad();
1507 			}
1508 			int FldAlign = fi->Type.GetAlignment();
1509 			size = (size + FldAlign - 1) & ~(FldAlign - 1);
1510 			fi->Ofs = size;
1511 			size += fi->Type.GetSize();
1512 		}
1513 		PrevField = fi;
1514 	}
1515 	ClassUnalignedSize = size;
1516 	size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
1517 	ClassSize = size;
1518 	ClassNumMethods = numMethods;
1519 	if ((ObjectFlags & CLASSOF_Native) && ClassSize != PrevSize)
1520 	{
1521 		Sys_Error("Bad class size, class %s, C++ %d, VavoomC %d)",
1522 			GetName(), PrevSize, ClassSize);
1523 	}
1524 	unguard;
1525 }
1526 
1527 //==========================================================================
1528 //
1529 //	VClass::InitNetFields
1530 //
1531 //==========================================================================
1532 
InitNetFields()1533 void VClass::InitNetFields()
1534 {
1535 	guard(VClass::InitNetFields);
1536 	if (ParentClass)
1537 	{
1538 		NetFields = ParentClass->NetFields;
1539 		NetMethods = ParentClass->NetMethods;
1540 		NumNetFields = ParentClass->NumNetFields;
1541 	}
1542 
1543 	for (VField* fi = Fields; fi; fi = fi->Next)
1544 	{
1545 		if (!(fi->Flags & FIELD_Net))
1546 		{
1547 			continue;
1548 		}
1549 		fi->NetIndex = NumNetFields++;
1550 		fi->NextNetField = NetFields;
1551 		NetFields = fi;
1552 	}
1553 
1554 	for (int i = 0; i < Methods.Num(); i++)
1555 	{
1556 		VMethod* M = Methods[i];
1557 		if (!(M->Flags & FUNC_Net))
1558 		{
1559 			continue;
1560 		}
1561 		VMethod* MPrev = NULL;
1562 		if (ParentClass)
1563 		{
1564 			MPrev = ParentClass->FindMethod(M->Name);
1565 		}
1566 		if (MPrev)
1567 		{
1568 			M->NetIndex = MPrev->NetIndex;
1569 		}
1570 		else
1571 		{
1572 			M->NetIndex = NumNetFields++;
1573 		}
1574 		M->NextNetMethod = NetMethods;
1575 		NetMethods = M;
1576 	}
1577 	unguard;
1578 }
1579 
1580 //==========================================================================
1581 //
1582 //	VClass::InitReferences
1583 //
1584 //==========================================================================
1585 
InitReferences()1586 void VClass::InitReferences()
1587 {
1588 	guard(VClass::InitReferences);
1589 	ReferenceFields = NULL;
1590 	if (GetSuperClass())
1591 	{
1592 		ReferenceFields = GetSuperClass()->ReferenceFields;
1593 	}
1594 
1595 	for (VField* F = Fields; F; F = F->Next)
1596 	{
1597 		switch (F->Type.Type)
1598 		{
1599 		case TYPE_Reference:
1600 		case TYPE_Delegate:
1601 			F->NextReference = ReferenceFields;
1602 			ReferenceFields = F;
1603 			break;
1604 
1605 		case TYPE_Struct:
1606 			F->Type.Struct->PostLoad();
1607 			if (F->Type.Struct->ReferenceFields)
1608 			{
1609 				F->NextReference = ReferenceFields;
1610 				ReferenceFields = F;
1611 			}
1612 			break;
1613 
1614 		case TYPE_Array:
1615 		case TYPE_DynamicArray:
1616 			if (F->Type.ArrayInnerType == TYPE_Reference)
1617 			{
1618 				F->NextReference = ReferenceFields;
1619 				ReferenceFields = F;
1620 			}
1621 			else if (F->Type.ArrayInnerType == TYPE_Struct)
1622 			{
1623 				F->Type.Struct->PostLoad();
1624 				if (F->Type.Struct->ReferenceFields)
1625 				{
1626 					F->NextReference = ReferenceFields;
1627 					ReferenceFields = F;
1628 				}
1629 			}
1630 			break;
1631 		}
1632 	}
1633 	unguard;
1634 }
1635 
1636 //==========================================================================
1637 //
1638 //	VClass::InitDestructorFields
1639 //
1640 //==========================================================================
1641 
InitDestructorFields()1642 void VClass::InitDestructorFields()
1643 {
1644 	guard(VClass::InitDestructorFields);
1645 	DestructorFields = NULL;
1646 	if (GetSuperClass())
1647 	{
1648 		DestructorFields = GetSuperClass()->DestructorFields;
1649 	}
1650 
1651 	for (VField* F = Fields; F; F = F->Next)
1652 	{
1653 		switch (F->Type.Type)
1654 		{
1655 		case TYPE_String:
1656 			F->DestructorLink = DestructorFields;
1657 			DestructorFields = F;
1658 			break;
1659 
1660 		case TYPE_Struct:
1661 			F->Type.Struct->PostLoad();
1662 			if (F->Type.Struct->DestructorFields)
1663 			{
1664 				F->DestructorLink = DestructorFields;
1665 				DestructorFields = F;
1666 			}
1667 			break;
1668 
1669 		case TYPE_Array:
1670 			if (F->Type.ArrayInnerType == TYPE_String)
1671 			{
1672 				F->DestructorLink = DestructorFields;
1673 				DestructorFields = F;
1674 			}
1675 			else if (F->Type.ArrayInnerType == TYPE_Struct)
1676 			{
1677 				F->Type.Struct->PostLoad();
1678 				if (F->Type.Struct->DestructorFields)
1679 				{
1680 					F->DestructorLink = DestructorFields;
1681 					DestructorFields = F;
1682 				}
1683 			}
1684 			break;
1685 
1686 		case TYPE_DynamicArray:
1687 			F->DestructorLink = DestructorFields;
1688 			DestructorFields = F;
1689 			break;
1690 		}
1691 	}
1692 	unguard;
1693 }
1694 
1695 //==========================================================================
1696 //
1697 //	VClass::CreateVTable
1698 //
1699 //==========================================================================
1700 
CreateVTable()1701 void VClass::CreateVTable()
1702 {
1703 	guard(VClass::CreateVTable);
1704 	if (!ClassVTable)
1705 	{
1706 		ClassVTable = new VMethod*[ClassNumMethods];
1707 	}
1708 	if (ParentClass)
1709 	{
1710 		memcpy(ClassVTable, ParentClass->ClassVTable,
1711 			ParentClass->ClassNumMethods * sizeof(VMethod*));
1712 	}
1713 	for (int i = 0; i < Methods.Num(); i++)
1714 	{
1715 		VMethod* M = Methods[i];
1716 		if (M->VTableIndex == -1)
1717 		{
1718 			continue;
1719 		}
1720 		ClassVTable[M->VTableIndex] = M;
1721 	}
1722 	unguard;
1723 }
1724 
1725 //==========================================================================
1726 //
1727 //	VClass::InitStatesLookup
1728 //
1729 //==========================================================================
1730 
InitStatesLookup()1731 void VClass::InitStatesLookup()
1732 {
1733 	guard(VClass::InitStatesLookup);
1734 	//	This is also called from dehacked parser, so we must do this check.
1735 	if (StatesLookup.Num())
1736 	{
1737 		return;
1738 	}
1739 
1740 	//	Create states lookup table.
1741 	if (GetSuperClass())
1742 	{
1743 		GetSuperClass()->InitStatesLookup();
1744 		for (int i = 0; i < GetSuperClass()->StatesLookup.Num(); i++)
1745 		{
1746 			StatesLookup.Append(GetSuperClass()->StatesLookup[i]);
1747 		}
1748 	}
1749 	for (VState* S = NetStates; S; S = S->NetNext)
1750 	{
1751 		S->NetId = StatesLookup.Num();
1752 		StatesLookup.Append(S);
1753 	}
1754 	unguard;
1755 }
1756 
1757 #ifndef IN_VCC
1758 
1759 //==========================================================================
1760 //
1761 //	VClass::CreateDefaults
1762 //
1763 //==========================================================================
1764 
CreateDefaults()1765 void VClass::CreateDefaults()
1766 {
1767 	guard(VClass::CreateDefaults);
1768 	if (Defaults)
1769 	{
1770 		return;
1771 	}
1772 
1773 	if (ParentClass && !ParentClass->Defaults)
1774 	{
1775 		ParentClass->CreateDefaults();
1776 	}
1777 
1778 	//	Allocate memory.
1779 	Defaults = new vuint8[ClassSize];
1780 	memset(Defaults, 0, ClassSize);
1781 
1782 	//	Copy default properties from the parent class.
1783 	if (ParentClass)
1784 	{
1785 		ParentClass->CopyObject(ParentClass->Defaults, Defaults);
1786 	}
1787 
1788 	//	Call default properties method.
1789 	if (DefaultProperties)
1790 	{
1791 		P_PASS_REF((VObject*)Defaults);
1792 		VObject::ExecuteFunction(DefaultProperties);
1793 	}
1794 	unguard;
1795 }
1796 
1797 //==========================================================================
1798 //
1799 //	VClass::CopyObject
1800 //
1801 //==========================================================================
1802 
CopyObject(const vuint8 * Src,vuint8 * Dst)1803 void VClass::CopyObject(const vuint8* Src, vuint8* Dst)
1804 {
1805 	guard(VClass::CopyObject);
1806 	//	Copy parent class fields.
1807 	if (GetSuperClass())
1808 	{
1809 		GetSuperClass()->CopyObject(Src, Dst);
1810 	}
1811 	//	Copy fields.
1812 	for (VField* F = Fields; F; F = F->Next)
1813 	{
1814 		VField::CopyFieldValue(Src + F->Ofs, Dst + F->Ofs, F->Type);
1815 	}
1816 	unguardf(("(%s)", GetName()));
1817 }
1818 
1819 //==========================================================================
1820 //
1821 //	VClass::SerialiseObject
1822 //
1823 //==========================================================================
1824 
SerialiseObject(VStream & Strm,VObject * Obj)1825 void VClass::SerialiseObject(VStream& Strm, VObject* Obj)
1826 {
1827 	guard(SerialiseObject);
1828 	//	Serialise parent class fields.
1829 	if (GetSuperClass())
1830 	{
1831 		GetSuperClass()->SerialiseObject(Strm, Obj);
1832 	}
1833 	//	Serialise fields.
1834 	for (VField* F = Fields; F; F = F->Next)
1835 	{
1836 		//	Skip native and transient fields.
1837 		if (F->Flags & (FIELD_Native | FIELD_Transient))
1838 		{
1839 			continue;
1840 		}
1841 		VField::SerialiseFieldValue(Strm, (vuint8*)Obj + F->Ofs, F->Type);
1842 	}
1843 	unguardf(("(%s)", GetName()));
1844 }
1845 
1846 //==========================================================================
1847 //
1848 //	VClass::CleanObject
1849 //
1850 //==========================================================================
1851 
CleanObject(VObject * Obj)1852 void VClass::CleanObject(VObject* Obj)
1853 {
1854 	guard(VClass::CleanObject);
1855 	for (VField* F = ReferenceFields; F; F = F->NextReference)
1856 	{
1857 		VField::CleanField((vuint8*)Obj + F->Ofs, F->Type);
1858 	}
1859 	unguardf(("(%s)", GetName()));
1860 }
1861 
1862 //==========================================================================
1863 //
1864 //	VClass::DestructObject
1865 //
1866 //==========================================================================
1867 
DestructObject(VObject * Obj)1868 void VClass::DestructObject(VObject* Obj)
1869 {
1870 	guard(VClass::DestructObject);
1871 	for (VField* F = DestructorFields; F; F = F->DestructorLink)
1872 	{
1873 		VField::DestructField((vuint8*)Obj + F->Ofs, F->Type);
1874 	}
1875 	unguardf(("(%s)", GetName()));
1876 }
1877 
1878 //==========================================================================
1879 //
1880 //	VClass::CreateDerivedClass
1881 //
1882 //==========================================================================
1883 
CreateDerivedClass(VName AName,VMemberBase * AOuter,TLocation ALoc)1884 VClass* VClass::CreateDerivedClass(VName AName, VMemberBase* AOuter,
1885 	TLocation ALoc)
1886 {
1887 	guard(VClass::CreateDerivedClass);
1888 	VClass* NewClass = NULL;
1889 	for (int i = 0; i < GDecorateClassImports.Num(); i++)
1890 	{
1891 		if (GDecorateClassImports[i]->Name == AName)
1892 		{
1893 			//	This class implements a decorate import class.
1894 			NewClass = GDecorateClassImports[i];
1895 			NewClass->MemberType = MEMBER_Class;
1896 			NewClass->Outer = AOuter;
1897 			NewClass->Loc = ALoc;
1898 			//	Make sure parent class is correct.
1899 			VClass* Check = FindClass(*NewClass->ParentClassName);
1900 			if (!Check)
1901 			{
1902 				Sys_Error("No such class %s", *NewClass->ParentClassName);
1903 			}
1904 			if (!IsChildOf(Check))
1905 			{
1906 				Sys_Error("%s must be a child of %s", *AName, *Check->Name);
1907 			}
1908 			GDecorateClassImports.RemoveIndex(i);
1909 			break;
1910 		}
1911 	}
1912 	if (!NewClass)
1913 	{
1914 		NewClass = new VClass(AName, AOuter, ALoc);
1915 	}
1916 	NewClass->ParentClass = this;
1917 	NewClass->PostLoad();
1918 	NewClass->CreateDefaults();
1919 	return NewClass;
1920 	unguard;
1921 }
1922 
1923 #endif
1924 
1925 //==========================================================================
1926 //
1927 //	VClass::GetReplacement
1928 //
1929 //==========================================================================
1930 
GetReplacement()1931 VClass* VClass::GetReplacement()
1932 {
1933 	guard(VClass::GetReplacement);
1934 	if (!Replacement)
1935 	{
1936 		return this;
1937 	}
1938 	//	Avoid looping recursion by temporarely NULL-ing the field
1939 	VClass* Temp = Replacement;
1940 	Replacement = NULL;
1941 	VClass* Ret = Temp->GetReplacement();
1942 	Replacement = Temp;
1943 	return Ret;
1944 	unguard;
1945 }
1946 
1947 //==========================================================================
1948 //
1949 //	VClass::GetReplacee
1950 //
1951 //==========================================================================
1952 
GetReplacee()1953 VClass* VClass::GetReplacee()
1954 {
1955 	guard(VClass::GetReplacee);
1956 	if (!Replacee)
1957 	{
1958 		return this;
1959 	}
1960 	//	Avoid looping recursion by temporarely NULL-ing the field
1961 	VClass* Temp = Replacee;
1962 	Replacee = NULL;
1963 	VClass* Ret = Temp->GetReplacee();
1964 	Replacee = Temp;
1965 	return Ret;
1966 	unguard;
1967 }
1968 
1969 //==========================================================================
1970 //
1971 //	VClass::HashLowerCased
1972 //
1973 //==========================================================================
1974 
HashLowerCased()1975 void VClass::HashLowerCased()
1976 {
1977 	guard(VClass::HashLowerCased);
1978 	LowerCaseName = *VStr(*Name).ToLower();
1979 	int HashIndex = GetTypeHash(LowerCaseName) & (LOWER_CASE_HASH_SIZE - 1);
1980 	LowerCaseHashNext = GLowerCaseHashTable[HashIndex];
1981 	GLowerCaseHashTable[HashIndex] = this;
1982 	unguard;
1983 }
1984 
1985 //==========================================================================
1986 //
1987 //	VClass::FindClassLowerCase
1988 //
1989 //==========================================================================
1990 
FindClassLowerCase(VName AName)1991 VClass* VClass::FindClassLowerCase(VName AName)
1992 {
1993 	guard(VClass::FindClassLowerCase);
1994 	int HashIndex = GetTypeHash(AName) & (LOWER_CASE_HASH_SIZE - 1);
1995 	for (VClass* Probe = GLowerCaseHashTable[HashIndex]; Probe;
1996 		Probe = Probe->LowerCaseHashNext)
1997 	{
1998 		if (Probe->LowerCaseName == AName)
1999 		{
2000 			return Probe;
2001 		}
2002 	}
2003 	return NULL;
2004 	unguard;
2005 }
2006 
2007 //==========================================================================
2008 //
2009 //	operator<<
2010 //
2011 //==========================================================================
2012 
operator <<(VStream & Strm,VStateLabel & Lbl)2013 VStream& operator<<(VStream& Strm, VStateLabel& Lbl)
2014 {
2015 	return Strm << Lbl.Name << Lbl.State << Lbl.SubLabels;
2016 }
2017