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