source: trunk/nom/src/nombuildclass.c@ 210

Last change on this file since 210 was 210, checked in by cinc, 19 years ago

Integration of nomUnInit() with the garbage collector using finalizers.

File size: 61.5 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2* Version: CDDL 1.0/LGPL 2.1
3*
4* The contents of this file are subject to the COMMON DEVELOPMENT AND
5* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6* this file except in compliance with the License. You may obtain a copy of
7* the License at http://www.sun.com/cddl/
8*
9* Software distributed under the License is distributed on an "AS IS" basis,
10* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11* for the specific language governing rights and limitations under the
12* License.
13*
14* The Original Code is "NOM" Netlabs Object Model
15*
16* The Initial Developer of the Original Code is
17* netlabs.org: Chris Wohlgemuth <cinc-ml@netlabs.org>.
18* Portions created by the Initial Developer are Copyright (C) 2005-2006
19* the Initial Developer. All Rights Reserved.
20*
21* Contributor(s):
22*
23* Alternatively, the contents of this file may be used under the terms of
24* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
25* case the provisions of the LGPL are applicable instead of those above. If
26* you wish to allow use of your version of this file only under the terms of
27* the LGPL, and not to allow others to use your version of this file under
28* the terms of the CDDL, indicate your decision by deleting the provisions
29* above and replace them with the notice and other provisions required by the
30* LGPL. If you do not delete the provisions above, a recipient may use your
31* version of this file under the terms of any one of the CDDL or the LGPL.
32*
33* ***** END LICENSE BLOCK ***** */
34
35#define INCL_DOS
36#define INCL_DOSERRORS
37
38#include <os2.h>
39#include <stdarg.h>
40#include <stdio.h>
41#include <string.h>
42#include <alloca.h>
43#include <glib.h>
44#define SOM_NO_OBJECTS /* Otherwise som.h includes the IBM SOM classes */
45
46/* For somToken etc. */
47#include <nom.h>
48#include <nomtk.h>
49#include <nomobj.h>
50#include <nomcls.h>
51#include <nomclassmanager.h>
52
53/* Define if you want to have messages from nomBuildClass() and friends */
54//#define DEBUG_NOMBUILDCLASS
55/* Define if you want to have messages from building NOMObject */
56//#define DEBUG_BUILDNOMOBJECT
57/* Define if you want to have messages from building NOMClass */
58//#define DEBUG_BUILDNOMCLASS
59
60#ifdef DEBUG_BUILDNOMCLASS
61 #define BUILDNOMCLASS_ENTER nomPrintf("\n%s line %d: *** entering %s...\n",__FILE__, __LINE__, __FUNCTION__);
62 #define BUILDNOMCLASS_LEAVE nomPrintf("%s line %d: *** Leaving %s...\n\n",__FILE__, __LINE__, __FUNCTION__);
63#else
64 #define BUILDNOMCLASS_ENTER
65 #define BUILDNOMCLASS_LEAVE
66#endif
67
68#ifdef DEBUG_NOMBUILDCLASS
69#define DBG_BUILD_LINE(a)
70#define DBG_NOMBUILDCLASS(a, b,...) if(a) nomPrintf("%d: " b , __LINE__, __VA_ARGS__);
71#else
72#define DBG_NOMBUILDCLASS(a, b,...)
73#endif
74
75#define DBGBUILDNOMCLASS_ENTER BUILDNOMCLASS_ENTER
76#define DBGBUILDNOMCLASS_LEAVE BUILDNOMCLASS_LEAVE
77
78/********************************************************/
79extern NOMClassMgr* NOMClassMgrObject;
80
81extern PNOM_ENV pGlobalNomEnv;
82
83/******************* somBuildClass **********************/
84
85/*
86 Thunking code to get the instance var address from an object pointer pushed
87 on the stack. The following translates into this assembler code:
88
89 MOV EAX,DWORD PTR [ESP+4] ;Move object ptr into EAX
90 ADD EAX, +4
91 RET
92*/
93
94static ULONG thunk[]={0x0424448b, 0x00000405, 0x0000c300};
95
96/*
97MOV ECX,DWORD PTR [ESP+4] : move object pointer from stack in ECX
98MOV EDX,DWORD PTR [ECX] : move [ECX] in EDX -> mtab in EDX
99JMP DWORD PTR [EDX+0ACh] : JMP to address pointing to by EDX+0ACh
100 */
101static ULONG mThunkCode[]={0x04244c8b, 0xff00518b, 0x0000aca2 , 0x16000000};
102
103
104/***********************************************************************************/
105/***********************************************************************************/
106/***********************************************************************************/
107/***********************************************************************************/
108/*
109 FIXME:
110
111 This is similar to nomIsA() of NOMObject so better use that later.
112
113 */
114
115static BOOL priv_nomIsA(NOMObject *nomSelf, NOMClass* aClassObj)
116{
117 nomParentMtabStructPtr pParentMtab=&((NOMClassPriv * )nomSelf)->parentMtabStruct;
118 nomMethodTabs psmTab;
119
120 if(!nomSelf||!aClassObj)
121 return FALSE;
122
123 /*
124 FIXME: use nomIsObj here!!
125 if(!nomIsObj(nomSelf)||!nomIsObj(aClassObj))
126 return FALSE
127 */
128
129 if(!strcmp(nomSelf->mtab->nomClassName, aClassObj->mtab->nomClassName))
130 return TRUE;
131
132 psmTab=pParentMtab->next;
133 while(psmTab) {
134 if(!strcmp(psmTab->mtab->nomClassName, aClassObj->mtab->nomClassName))
135 return TRUE;
136
137 psmTab=psmTab->next;
138 }
139
140 /* Return statement to be customized: */
141 return FALSE;
142}
143
144/*
145 Helper function
146 */
147static
148gulong nomGetNumIntroducedMethods(NOMClassPriv* ncPriv)
149{
150 return ncPriv->sci->ulNumStaticMethods;
151}
152
153/*
154 This function should be reworked later to just get the class object from the quark list
155 instead of iterating over all parents.
156 */
157static
158gulong priv_getIndexOfMethodInEntries(NOMClassPriv* nClass, nomStaticClassInfo *sci, gchar* chrMethodDescriptor)
159{
160 int a;
161 gulong idx=0;
162 gboolean bFound=FALSE;
163 char* chrMethodName;
164
165 /* We need the full info here, method name and class introducing it */
166 if((chrMethodName=strchr(chrMethodDescriptor, ':'))==NULL)
167 return 0;
168
169 chrMethodName++;
170
171 /* chrMethodName is like "ClassName:MethodName". */
172 for(a=0; a<sci->ulNumParentsInChain; a++)
173 {
174 GString *gstr;
175
176 gstr=g_string_new(sci->chrParentClassNames[a]);
177 g_string_append_printf(gstr, ":%s", chrMethodName);
178
179 // nomPrintf("Checking %s for %s\n",
180 // sci->chrParentClassNames[a], gstr->str);
181 if(g_quark_try_string(gstr->str))
182 {
183 int b;
184 NOMClassPriv *ncPriv;
185 gulong ulNumMethods;
186
187 /* Found class introducing the method */
188 //nomPrintf(" %s, %d: Found %s in %s\n", __FUNCTION__, __LINE__,
189 // gstr->str, sci->chrParentClassNames[a]);
190 if(NULL==NOMClassMgrObject)
191 g_error("%s line %d: No overriding for base classes yet (%s)!\n",
192 __FUNCTION__, __LINE__, gstr->str);
193 idx++; /* This is the position for the class pointer */
194 ncPriv=_nomGetClassInfoPtrFromName(NOMClassMgrObject, sci->chrParentClassNames[a], NULLHANDLE);
195 /* now find the index */
196 ulNumMethods=nomGetNumIntroducedMethods(ncPriv);
197 for(b=0;b<ulNumMethods;b++)
198 {
199 // nomPrintf("%d, checking %s\n", b, *ncPriv->sci->nomSMethods[b].nomMethodId);
200 if(!strcmp(chrMethodName,*ncPriv->sci->nomSMethods[b].nomMethodId ))
201 {
202 // nomPrintf(" %s, %d: Found %s in %s, index: %d\n", __FUNCTION__, __LINE__,
203 // gstr->str, sci->chrParentClassNames[a], b);
204 idx+=b;
205 bFound=TRUE;
206 break;
207 }
208 }/* for(b) */
209 }
210 else
211 {
212 /* Class not yet found... */
213 NOMClassPriv *ncPriv;
214
215 if(NULL==NOMClassMgrObject){
216 /* Things are getting dirty now. Someone tries overriding while we are
217 bootstrapping. That may be either NOMClass or NOMClassMgr. Let's climb
218 the list by hand now... */
219 gulong aLoop, numMethods;
220
221 /* We only support overriding of NOMObject for now when no manager is
222 available. a is the index into the array of class names. a=0 is the
223 first name which is always NOMObject. */
224 if(0!=a)
225 g_error("%s line %d: No Quark. No class manager and attempt to override a class which is not NOMObject\n(method: %s, current class: %s)!\n",
226 __FUNCTION__, __LINE__, gstr->str, sci->chrParentClassNames[a]);
227 ncPriv=pGlobalNomEnv->ncpNOMObject;
228
229 numMethods=nomGetNumIntroducedMethods(ncPriv);
230 for(aLoop=0;aLoop<numMethods;aLoop++)
231 {
232 //nomPrintf("%d, checking %s\n", aLoop, *ncPriv->sci->nomSMethods[aLoop].nomMethodId);
233 if(!strcmp(chrMethodName,*ncPriv->sci->nomSMethods[aLoop].nomMethodId ))
234 {
235 //nomPrintf(" %s, %d: Found %s in %s (hand search), index: %d\n", __FUNCTION__, __LINE__,
236 // gstr->str, sci->chrParentClassNames[a], aLoop);
237 idx=aLoop+1;
238 bFound=TRUE;
239 break;
240 }
241 }/* for(aLoop) */
242 }
243 else{
244 ncPriv=_nomGetClassInfoPtrFromName(NOMClassMgrObject, sci->chrParentClassNames[a], NULLHANDLE);
245 //nomPrintf(" %s did not introduce the method. Adding %d to index\n",
246 // sci->chrParentClassNames[a], nomGetNumIntroducedMethods(ncPriv)+1);
247 idx+=nomGetNumIntroducedMethods(ncPriv)+1; /* classObject pointer */
248 }/* NOMClassMgrObject */
249 }
250 g_string_free(gstr, TRUE);
251 if(bFound)
252 break;
253 }/* for(a) */
254
255 if(bFound)
256 return idx;
257 else
258 return 0;
259}
260
261/*
262
263 */
264void priv_resolveOverrideMethods(NOMClassPriv *nClass, nomStaticClassInfo *sci)
265{
266 if(sci->ulNumStaticOverrides) {
267 int b;
268
269 DBG_NOMBUILDCLASS(TRUE, "%d method(s) to override\n", sci->ulNumStaticOverrides);
270
271 /* There're some methods to override */
272 for(b=0;b<sci->ulNumStaticOverrides;b++) {/* For every overriden method do */
273 nomMethodProc** entries;
274 ULONG index;
275
276 entries=&nClass->mtab->entries[0]; /* Adress of array where we enter our resoved method */
277
278 DBG_NOMBUILDCLASS(TRUE,"Going to override \"%s\"\n", *sci->nomOverridenMethods[b].nomMethodId);
279
280 index=priv_getIndexOfMethodInEntries(nClass, sci, *sci->nomOverridenMethods[b].nomMethodId);
281 if(0==index){
282 g_warning("%s line %d:\n We are supposed to override \"%s\" but the method can't be found!",
283 __FUNCTION__, __LINE__, *sci->nomOverridenMethods[b].nomMethodId);
284 return;
285 }
286 /* This is the parent method adress which will be used by the overriding class */
287 *sci->nomOverridenMethods[b].nomParentMethod=entries[index];
288 /* Using the found index we insert our new method address into the mtab. */
289 entries[index]=sci->nomOverridenMethods[b].nomMethod;
290 /* Do we just overrid nomUnInit()? Mark it because we need this info for the
291 grabage collecting. */
292 if(strstr(*sci->nomOverridenMethods[b].nomMethodId, ":nomUnInit"))
293 {
294 DBG_NOMBUILDCLASS(TRUE, " nomUnInit() overriden.\n", "");
295 nClass->ulClassFlags|=NOM_FLG_NOMUNINIT_OVERRIDEN; /* This flag has to be propagated down to
296 each child class. */
297 }
298 } /* for(b) */
299 }/* if(sci->numStaticOverrides) */
300
301#ifdef DEBUG_NOMBUILDCLASS
302 else
303 nomPrintf(" No methods to override\n");
304#endif
305}
306
307
308void fillCClassDataStructParentMtab(nomStaticClassInfo *sci, NOMClassPriv *nClass, NOMClass *nomClass)
309{
310 /* Insert pointer into CClassDataStructure */
311 sci->ccds->parentMtab=&nClass->parentMtabStruct; /* Insert pointer into CClassDataStructure */
312
313 /* Fill somParentMtabStruct in CClassDataStructure */
314 sci->ccds->parentMtab->mtab=nClass->mtab; /* This class mtab */
315 sci->ccds->parentMtab->next=nClass->mtabList.next;
316 sci->ccds->parentMtab->nomClassObject=nomClass; /* Class object */
317 sci->ccds->parentMtab->ulInstanceSize=nClass->mtab->ulInstanceSize;
318 /* C Class data structure */
319}
320
321
322/*
323 - This function builds the nomMethodTab of class nClass.
324 - Calculates the method thunks
325 - Calculates the instance variable thunks using the parent class info
326
327 It takes a parent class ncpParent which may also have introduced instance variables and
328 methods.
329 */
330void addMethodAndDataToThisPrivClassStruct(NOMClassPriv* nClass, NOMClassPriv* ncpParent, nomStaticClassInfo *sci)
331{
332 BYTE * mem;
333 int a;
334
335BUILDNOMCLASS_ENTER
336
337 nClass->sci=sci; /* Save static class info for internal use */
338
339 /* Copy assembler thunking code for instance data */
340 memcpy(nClass->thunk, thunk, sizeof(thunk));
341 /* Link parent mtab in */
342 nClass->mtabList.next=&ncpParent->mtabList;
343
344 /* Fill all the pointers to the methodtable we need */
345 nClass->mtab=(nomMethodTab*)&nClass->thisMtab; /* thisMtab is the address where our mtab starts */
346 nClass->mtabList.mtab= (nomMethodTab*)&nClass->thisMtab;
347 nClass->parentMtabStruct.mtab=(nomMethodTab*)&nClass->thisMtab;
348
349#ifdef DEBUG_NOMBUILDCLASS
350 nomPrintf("nClass->mtabList.next: %x\n", nClass->mtabList.next);
351#endif
352
353 /* There're some parents. Copy parent mtab data into new mtab. */
354 /* Copy object data. This all goes at the address of "nomMethodProc* entries[0]"
355 entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
356 */
357 mem=(char*)nClass->mtab; /* Target address */
358 memcpy(mem, ncpParent->mtab, ncpParent->mtab->mtabSize); /* copy parent mtab with all proc addresses */
359#ifdef DEBUG_NOMBUILDCLASS
360 nomPrintf("copy parent data: %d (mtabSize) from %x (mtab of %s, taken from NOMClassPriv) to %x (mtab to build)\n",
361 ncpParent->mtab->mtabSize,
362 sci->nomCds, ncpParent->mtab->nomClassName, mem);
363#endif
364
365 mem=((char*)nClass->mtab) + ncpParent->mtab->mtabSize; /* points right after the parent mtab now in
366 our private struct */
367 /* Add class struct of this class. This includes the proc adresses. */
368 if(sci->ulNumStaticMethods) {
369#ifdef DEBUG_NOMBUILDCLASS
370 nomPrintf("copy own data: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct of %x) to %x (our mtab part)\n",
371 sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*),
372 sci->nomCds, sci->nomCds->nomClassObject, mem);
373#endif
374 nClass->entries0=(NOMClass**)mem; /* Our part in the mtab starts here. We need this position to insert the class object pointer
375 later. */
376 memcpy( mem, sci->nomCds, sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*));
377
378 /* Now finally put the thunking in so the procedures are resolved correctly. */
379 for(a=0;a<sci->ulNumStaticMethods;a++) {
380 ULONG ulOffset;
381
382 memcpy(&nClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy thunking code */
383
384 ulOffset=(ULONG)((char*)(mem+sizeof(NOMClass*))-(char*)nClass->mtab); /* Skip class object pointer */
385 nClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(nomMethodProc*))<<8)+0xa2;
386 /* Put thunking code address into CClassStruct */
387 sci->nomCds->nomTokens[a]=(void*)&nClass->mThunk[a];
388 }
389 }
390 /* Thunking code see above. Adjust the offset to the instance data so the right
391 variables are accessed. The offset is different depending on the number of parent
392 classes (which isn't fix) and the number of parent instance vars (which isn't known
393 at compile time) */
394 nClass->thunk[1]=(ncpParent->mtab->ulInstanceSize<<8)+0x05; //0x00000405
395
396 sci->ccds->instanceDataToken=&nClass->thunk;
397
398 BUILDNOMCLASS_LEAVE
399}
400
401/*
402 This function is called when asking for information about the parent of a class.
403 It checks if NOMClassMgrObject is already built and if yes asks it for the class.
404 If it's not yet built we are still in the bootstrapping stage and the only parent
405 we may search is NOMObject. Replacing of NOMObject is not supported by NOM.
406 */
407static NOMClassPriv* priv_getClassFromName(gchar* chrClassName)
408{
409 NOMClassPriv *ncpParent=NULL;
410
411 if(NULL==NOMClassMgrObject){
412 /* If we build NOMClass or NOMClassMgr we just use the pointer we saved before. */
413 if(!strcmp(chrClassName, "NOMObject"))
414 ncpParent=pGlobalNomEnv->ncpNOMObject;
415 else
416 g_error("Asking for a parent not being NOMObject while NOMClassMgrObject is NULL. This can't be!!!");
417 }/* NULL== NOMClassMgrObject */
418 else
419 {
420 ncpParent=_nomGetClassInfoPtrFromName(NOMClassMgrObject, chrClassName,
421 NULLHANDLE);
422 }
423
424 return ncpParent;
425}
426
427#if 0
428static void priv_checkForNomUnInitOverride( NOMClass *nomClass, NOMClassPriv *ncpParent)
429{
430 /* Mark the class as using nomUnInit() if any parent did that. We just have to
431 check the flag and the flag of the parent class. This information is important
432 because if this method is overriden the garbage collector has to run a finalizer
433 on the object when collecting memory so the object may do its uninit stuff. */
434 if(nomClass && !(((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN))
435 {
436 /* Flag not set. Try parent */
437 if(ncpParent && ncpParent->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN)
438 ((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags|= NOM_FLG_NOMUNINIT_OVERRIDEN;
439 }
440
441 DBG_NOMBUILDCLASS(TRUE, "nomUnInit overriden in class %s: %s\n",
442 nomClass->mtab->nomClassName,
443 (((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN ?
444 "Yes" : "No"));
445
446};
447#endif
448
449static void priv_checkForNomUnInitOverride( NOMClassPriv *nomClassPriv, NOMClassPriv *ncpParent)
450{
451 /* Mark the class as using nomUnInit() if any parent did that. We just have to
452 check the flag and the flag of the parent class. This information is important
453 because if this method is overriden the garbage collector has to run a finalizer
454 on the object when collecting memory so the object may do its uninit stuff. */
455 DBG_NOMBUILDCLASS(TRUE, " %s (%x): %x, %s (%x): %x ", nomClassPriv->mtab->nomClassName, nomClassPriv,
456 nomClassPriv->ulClassFlags,
457 ncpParent->mtab->nomClassName, ncpParent, ncpParent->ulClassFlags);
458 if(nomClassPriv && !(nomClassPriv->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN))
459 {
460 /* Flag not set. Try parent */
461 if(ncpParent && ncpParent->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN)
462 nomClassPriv->ulClassFlags|= NOM_FLG_NOMUNINIT_OVERRIDEN;
463 }
464
465 DBG_NOMBUILDCLASS(TRUE, " %x nomUnInit overriden in class %s: %s\n",
466 nomClassPriv->ulClassFlags, nomClassPriv->mtab->nomClassName,
467 (nomClassPriv->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN ?
468 "Yes" : "No"));
469};
470
471
472/*
473 This function creates a private class structure for an object from the given sci with
474 correctly resolved methods which holds the mtab. This struct is kept by the metaclass
475 and holds all the information for creating objects.
476
477 nomClass: class object
478 */
479static NOMClassPriv * NOMLINK priv_buildPrivClassStruct(long inherit_vars,
480 nomStaticClassInfo *sci,
481 long majorVersion,
482 long minorVersion,
483 NOMClass* nomClass)
484{
485 ULONG ulParentDataSize=0;
486 ULONG mtabSize;
487 ULONG ulMemSize=0;
488 NOMClassPriv *nClass, *ncpParent;
489
490 DBGBUILDNOMCLASS_ENTER
491
492 if(!nomClass||!sci)
493 return NULLHANDLE;
494
495 /* The addresse of static methods in sci are already resolved. See nomBuildClass() */
496
497 /* Get parent class if any */
498 if(NULL!=sci->chrParentClassNames){
499 ncpParent=priv_getClassFromName(sci->chrParentClassNames[sci->ulNumParentsInChain]);
500 }/* nomIdAllParents */
501 else
502 ncpParent = NULLHANDLE;
503
504 if(!ncpParent) {
505 g_warning("We are supposed to create a NOMClassPriv but there's no parent!\n");
506 /* FIXME:
507 Maybe we should panic here. */
508 return NULLHANDLE; /* Only NOMObject has no parent, so we have a problem here. */
509 }
510
511 /* Calculate size of new class object */
512 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct */
513
514 DBG_NOMBUILDCLASS(TRUE, " ncpParent->mtab->mtabSize: %d. Parent is: %x (priv) %s\n",
515 ncpParent->mtab->mtabSize, ncpParent, ncpParent->mtab->nomClassName);
516
517 mtabSize=ncpParent->mtab->mtabSize+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods)+
518 sizeof(NOMObject*);/* numStaticMethods is correct here!
519 NOT numStaticMethods-1!
520 entries[0] in fact contains the
521 class pointer not a method
522 pointer. */
523 ulMemSize+=mtabSize; /* add place for new procs and the new class pointer */
524 ulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size */
525
526 DBG_NOMBUILDCLASS(TRUE, " %s: mtabSize will be: %d, ulParentDataSize is: %d\n"
527 , __FUNCTION__, mtabSize, ulParentDataSize);
528
529 /* Alloc private class struct using NOMCalloc. */
530 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULLHANDLE)
531 return NULLHANDLE;
532
533 /* Get mem for method thunking code */
534 if(0!=sci->ulNumStaticMethods){
535 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
536 if(!nClass->mThunk) {
537 NOMFree(nClass);
538 return NULLHANDLE;
539 }
540 }
541 /* Add class struct of this class.
542 This includes
543 -resolving the new method adresses
544 -add the parent mtab info to the new built mtab
545 */
546 addMethodAndDataToThisPrivClassStruct( nClass, ncpParent, sci) ;
547
548 DBG_NOMBUILDCLASS(TRUE, "%s: mtab: %x\n", __FUNCTION__, nClass->mtab);
549
550 /*
551 Note: We don't create a class object here so the following isn't done:
552 sci->cds->classObject=nomClass;
553 */
554
555 /* Resolve ovverrides if any */
556 priv_resolveOverrideMethods(nClass, sci);
557
558 /**********************************/
559 /* Fill methodtable mtab */
560 /**********************************/
561 nClass->mtab->mtabSize=mtabSize;
562 nClass->mtab->nomClassObject=nomClass; /* Class object (metaclass). We build a normal class here. */
563 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass;
564#warning !!!!! Change this when nomId is a GQuark !!!!!
565 nClass->mtab->nomClassName=*sci->nomClassId;
566 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+ulParentDataSize; /* Size of instance data of this class and all
567 parent classes. This isn't actually allocated for this class
568 object but the entry is used when creating the objects. */
569 fillCClassDataStructParentMtab(sci, nClass, nomClass);
570
571 DBG_NOMBUILDCLASS(TRUE, "New NOMClassPriv*: %x\n", nClass);
572
573 _nomSetObjectCreateInfo(nomClass, nClass, NULLHANDLE);
574
575 /* Mark the class as using nomUnInit() if any parent did that. We just have to
576 check the flag and the flag of the parent class. This information is important
577 because if this method is overriden the garbage collector has to run a finalizer
578 on the object when collecting memory so the object may do its uninit stuff. */
579 priv_checkForNomUnInitOverride( nClass, ncpParent);
580
581 DBGBUILDNOMCLASS_LEAVE
582 return nClass;
583}
584
585
586NOMClass * NOMLINK priv_buildWithExplicitMetaClass(glong ulReserved,
587 nomStaticClassInfo *sci,
588 gulong majorVersion,
589 gulong minorVersion)
590{
591 NOMClass *nomClass, *nomClassMeta;
592
593 if(NULL==NOMClassMgrObject)
594 return NULLHANDLE;
595
596 /* Search for meta class. */
597#warning !!!!! Change this when nomID is a GQuark !!!!!
598 nomClassMeta=_nomFindClassFromName(NOMClassMgrObject, *sci->nomExplicitMetaId, majorVersion, minorVersion, NULLHANDLE);
599
600#ifdef DEBUG_NOMBUILDCLASS
601 nomPrintf("%d: %x %s %s\n", __LINE__, nomClassMeta, *sci->nomClassId, *sci->nomExplicitMetaId);
602#endif
603
604 if(!nomClassMeta)
605 return NULLHANDLE;
606
607 /* Create a new class object. We create a copy here because we may change the mtab entries
608 through overriding or two classes may use the same meta class but have different
609 sizes, methods etc. I wonder how IBM SOM manages to use the same metaclass
610 for different classes without (apparently) copying it for different uses... */
611 if((nomClass=(NOMClass*)NOMCalloc(1, _nomGetSize(nomClassMeta, NULLHANDLE)))==NULLHANDLE)
612 return NULLHANDLE;
613
614 /* Maybe we should just copy the whole struct here? */
615 nomClass->mtab=nomClassMeta->mtab;
616#warning !!!!! No call of _nomSetInstanceSize !!!!!
617#warning !!!!! No call of _nomSetObjectsSCI !!!!!
618#if 0
619 /* Set object data */
620 _nomSetInstanceSize(nomClass, _nomGetSize(nomClassMeta));
621 /* Save objects sci pointer. We need it when we create instances */
622 _nomSetObjectsSCI(somClass, sci);
623#endif
624
625 /* Update static class data of class to be build */
626 sci->nomCds->nomClassObject=nomClass;
627
628 /* Now we have a meta class. Create the NOMClassPriv* holding the mtab for the class
629 to be built (which is not a meta class). */
630 priv_buildPrivClassStruct(ulReserved, sci,
631 majorVersion, minorVersion,
632 nomClass);
633
634#ifdef DEBUG_NOMBUILDCLASS
635 nomPrintf("%d: New class Object (child of NOMClass): %x \n", __LINE__, nomClass);
636#endif
637
638 /* nomClassReady() is called in nomBuildClass() */
639 return nomClass;
640}
641
642/*
643 This function climbs the chain of parents and looks for a parent introducing
644 an explicit metaclass. If found, this metaclass is returned otherwise NOMClass.
645 */
646static
647NOMClass * NOMLINK priv_findExplicitMetaClassFromParents(nomStaticClassInfo *sci)
648{
649 int a;
650
651 if(1==sci->ulNumParentsInChain)
652 {
653 /* One parent only. That must be NOMObject and NOMObject has NOMClass
654 as metaclass. */
655 return pGlobalNomEnv->defaultMetaClass;;
656 }
657
658 /* Climb the list of parents... */
659
660 /* NOMClassMgrObject==NULL shouldn't ever happen here! */
661 g_assert(NOMClassMgrObject);
662
663 for(a=sci->ulNumParentsInChain-1;a>=0; a--)
664 {
665 NOMObject *nObject;
666 nObject=_nomFindClassFromName(NOMClassMgrObject, sci->chrParentClassNames[a], 0, 0, NULLHANDLE);
667
668 DBG_NOMBUILDCLASS( TRUE , " Parent %d: %s, class object: %x\n" ,
669 a, sci->chrParentClassNames[a], nObject);
670 if(nObject){
671 DBG_NOMBUILDCLASS( TRUE , " Class object name: %s\n" , nObject->mtab->nomClassName);
672 if(strcmp(nObject->mtab->nomClassName, "NOMClass"))
673 return (NOMClass*)nObject; /* Not NOMClass so return */
674 } /* if(nObject) */
675 } /* for() */
676 return pGlobalNomEnv->defaultMetaClass;
677}
678
679/*
680 This function is called when a class for a given sci should be build with a parent
681 which isn't derived from NOMClass. In that case some NOMClass ccild is the class to
682 be used for the class object. We have to climb the parent list of this object class
683 to check if one parent introduced an explicit metaclass. If yes, we have to use that
684 one as the metaclass. If no parent did that we just use NOMClass.
685 This doesn't mean we reuse the found structs directly. Instead a new copy is created
686 so individula overriding is possible.
687*/
688static
689NOMClass * NOMLINK priv_buildWithNOMClassChildAsMeta(gulong ulReserved,
690 nomStaticClassInfo *sci,
691 long majorVersion,
692 long minorVersion)
693{
694 NOMClass *nomClass, *nomClassDefault;
695 NOMClassPriv *nClass;
696
697#ifdef DEBUG_NOMBUILDCLASS
698#warning !!!!! Change this when nomId is a GQuark !!!!!
699 nomPrintf("\n%d: Entering %s to build %s\n", __LINE__, __FUNCTION__, *sci->nomClassId);
700#endif
701
702 /* Search parents for a an explicit metaclass. If no explicit metaclass return
703 NOMClass. */
704 nomClassDefault=priv_findExplicitMetaClassFromParents(sci);// this gives a NOMClass* not a NOMClassPriv*
705
706 /**** Create the meta class object ****/
707 //nomClassDefault=pGlobalNomEnv->defaultMetaClass; // this gives a NOMClass* not a NOMClassPriv*
708
709 if(!nomClassDefault)
710 return NULLHANDLE;
711
712 /* Found NOMClass object */
713
714 //nomPrintf("_nomGetSize(): %d\n", _nomGetSize(nomClassParent, NULLHANDLE));
715
716 /* Create an object */
717 if((nomClass=(NOMClass*)NOMCalloc(1, _nomGetSize(nomClassDefault, NULLHANDLE)))==NULLHANDLE)
718 return NULLHANDLE;
719
720 nomClass->mtab=nomClassDefault->mtab;
721
722#warning !!!!! _nomSetInstanceSize() not called here !!!!!
723#warning !!!!! _nomSetObjectsSCI() not called here !!!!!
724#if 0
725 /* Set object data */
726 _nomSetInstanceSize(somClass, _nomGetSize(nomClassDefault));
727 /* Save objects sci pointer. We need it when we create instances */
728 _nomSetObjectsSCI(nomClass, sci);
729#endif
730
731 /* Update static class data of the class to be built */
732 sci->nomCds->nomClassObject=nomClass;
733
734 /* Now we have a meta class. Create the NOMClassPriv* holding the mtab for the class
735 to be built. */
736 nClass=priv_buildPrivClassStruct(ulReserved, sci,
737 majorVersion, minorVersion,
738 nomClass);
739
740#ifdef DEBUG_NOMBUILDCLASS
741 DBG_NOMBUILDCLASS(TRUE, "%s: New class Object (NOMClass): %x NOMClassPriv*: %x ulClassFlags: %x\n",
742 __FUNCTION__, nomClass, nomClass->mtab->nomClsInfo,
743 ((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags);
744 //_dumpMtab(nomClass->mtab);
745 //_dumpObjShort(nomClass);
746#endif
747
748 /* nomClassReady() is called in nomBuildClass(), so don't call it here. Same goes for _nomInit(). */
749 return nomClass;
750}
751
752
753/*
754 nomClass: NOMClass
755 nClass: NOMClassPriv for NOMClass
756 ulSize: size of a NOMClass object
757
758 This function is used to add a meta class to NOMOBject which was built before.
759*/
760NOMClass* createNOMObjectClassObjectAndUpdateNOMObject(NOMClass* nomClass, NOMClassPriv* nClass, gulong ulSize)
761{
762 NOMClassPriv *ncp;
763 NOMClass *nomObjClass;
764
765 DBGBUILDNOMCLASS_ENTER
766
767 /* The NOMClassPriv for NOMObject */
768 ncp= pGlobalNomEnv->ncpNOMObject;
769
770 /* Allocate a class object for NOMObject for creating NOMObject instances. */
771 if((nomObjClass=(NOMClass*)NOMCalloc(1, ulSize))==NULLHANDLE) {
772 /* We panic here for the simple reason that without a working NOMObject the whole object system
773 will not work. */
774 g_error("No memory for building the class object _NOMObject for NOMObject.");
775 return NULLHANDLE;
776 }
777
778 nomObjClass->mtab=nomClass->mtab; /* Now it's an object */
779
780 _nomSetObjectCreateInfo(nomObjClass, pGlobalNomEnv->ncpNOMObject, NULLHANDLE); /* This NOMClassPriv holds all info to build
781 instances of NOMObject (not that anybody
782 should do that but... */
783#warning !!!!!!!!!!!!! _somSetObjectsSCI() not called!!!!!!!!!!!!!!!!
784#warning !!!!!!!!!!!!! _somSetClassData() not called!!!!!!!!!!!!!!!!
785#if 0
786 _somSetObjectsSCI(nomObjClass, ncp->sci);
787 _somSetClassData(somObjClass, scp->sci->cds);
788#endif
789
790 /* Update NOMObject data */
791 ncp->mtab->nomClassObject=nomObjClass; /* This is the real NOMClass pointer, not a pointer to NOMClassPriv */
792 ncp->mtab->entries[0]=(void*)nomObjClass;
793
794 /* Put it into the class data of NOMObject */
795 ncp->sci->nomCds->nomClassObject=nomObjClass;
796
797#ifdef DEBUG_BUILDNOMOBJECT
798 nomPrintf("%d: metaclass for NOMObject created: %x\n",__LINE__, nomObjClass);
799#endif
800 DBGBUILDNOMCLASS_LEAVE
801 return nomObjClass;
802}
803
804
805NOMEXTERN NOMClass * NOMLINK nomBuildClass(gulong ulReserved,
806 nomStaticClassInfo *sci,
807 gulong ulMajorVersion,
808 gulong ulMinorVersion)
809{
810 NOMClass *nomClass;
811 NOMClassPriv *nClass;
812 NOMClassPriv *ncpParent;
813 ULONG ulParentDataSize=0;
814 ULONG mtabSize;
815 ULONG ulMemSize=0;
816 int a;
817
818#ifdef DEBUG_NOMBUILDCLASS
819 nomParentMtabStructPtr pParentMtab;
820 nomMethodTabs psmTab;
821 /* Print some info for debbuging */
822 nomPrintf("\n%d: Entering %s to build class %s. ---> NOMClassManagerObject: 0x%x\n",
823 __LINE__, __FUNCTION__, *sci->nomClassId, NOMClassMgrObject);
824 nomPrintf("%d: cds: 0x%x nomClassObject: 0x%x\n", __LINE__, sci->nomCds, sci->nomCds->nomClassObject);
825#endif
826
827 /* Check if already built */
828 if(sci->nomCds->nomClassObject) {
829 DBG_NOMBUILDCLASS(TRUE, "Class %s already built. returning 0x%x\n", *sci->nomClassId, sci->nomCds->nomClassObject);
830 return (sci->nomCds)->nomClassObject; /* Yes,return the object */
831 }
832
833 /* Do we want to build again NOMObject the mother of all classes?
834 This happens because every class automatically tries to build the parents
835 (which includes NOMObject somewhere). NOMObject doesn't have a class object
836 yet when created
837 so we have to check here the global pointer to the NOMObject private data.
838 */
839
840 if(!strcmp(*sci->nomClassId, "NOMObject")){
841 if(pGlobalNomEnv->ncpNOMObject!=NULLHANDLE){
842 DBG_NOMBUILDCLASS(TRUE, "Class %s already built. returning 0x%x\n",
843 *sci->nomClassId, sci->nomCds->nomClassObject);
844 /* FIXME: this seems to be broken!! */
845 return NULLHANDLE; /* NOMObject already built */
846 }
847 }
848
849#ifdef _DEBUG_NOMBUILDCLASS
850 DBG_NOMBUILDCLASS(TRUE, "Dumping sci:\n");
851 _dumpSci(sci);
852#endif
853
854 if(sci->ulNumStaticMethods!=0 && !sci->nomSMethods){
855 nomPrintf(" !!! %s line %d: sci->nomSMethods is NULL for %s !!!\n", __FUNCTION__, __LINE__, *sci->nomClassId);
856 return NULLHANDLE;
857 }
858 /* Fill static classdata with the info from nomStaticMethodDesc array. This means
859 putting the method adresses into the classdata struct.
860 Be aware that the order of the methods in the somStaticMethod_t array is not
861 necessarily in the order as specified in the releaseorder list. But each array member
862 (which is a nomStaticMethodDesc) contains the address of the correct
863 field in the static classdata struct. */
864 /* This also resolves methods for objects not only class objects. Be careful when
865 removing here. You have to correct priv_buildObjecttemplate(). */
866 /* Insert class data structure method tokens */
867 for(a=0;a<sci->ulNumStaticMethods;a++) {
868 *sci->nomSMethods[a].nomMAddressInClassData=(void*)sci->nomSMethods[a].nomMethod; /* Address to place the resolved function address in see *.ih files. */
869#ifdef _DEBUG_NOMBUILDCLASS
870 nomPrintf(" static method: %s, %lx\n", *sci->nomSMethods[a].chrMethodDescriptor, sci->nomSMethods[a].nomMethod);
871 nomPrintf("%d: %d: method: %x %s (classdata addr. %x) (Fill static class struct with procs)\n",
872 __LINE__, a, sci->nomSMethods[a].nomMethod, *sci->nomSMethods[a].nomMethodId, sci->nomSMethods[a].nomMAddressInClassData);
873#endif
874 }
875
876#ifdef _DEBUG_NOMBUILDCLASS
877 nomPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
878 _dumpClassDataStruct(sci->nomCds, sci->ulNumStaticMethods);
879#endif
880
881 /* Do we want to build NOMObject the mother of all classes? */
882 if(!strcmp(*sci->nomClassId, "NOMObject")){
883
884 DBG_NOMBUILDCLASS(TRUE, "Trying to build %s\n", *sci->nomClassId);
885
886 priv_buildNOMObjectClassInfo(ulReserved, sci, /* yes */
887 ulMajorVersion, ulMinorVersion);
888 return NULLHANDLE; /* We can't return a SOMClass for SOMObject because SOMClass isn't built yet. */
889 }
890
891 /* Do we want to build NOMClass? */
892 if(!strcmp(*sci->nomClassId, "NOMClass"))
893 return priv_buildNOMClass(ulReserved, sci, /* yes */
894 ulMajorVersion, ulMinorVersion);
895
896 /* Get parent class */
897 if(sci->nomIdAllParents) {
898#ifdef DEBUG_NOMBUILDCLASS
899#warning !!!!! Change this when nomId is a GQuark !!!!!
900 nomPrintf("%d: About to search parent %s...\n", __LINE__, **(sci->nomIdAllParents));
901#endif
902
903 ncpParent=priv_getClassFromName(sci->chrParentClassNames[sci->ulNumParentsInChain]);
904
905#if 0
906 ncpParent=priv_getClassFromName(**(sci->nomIdAllParents));
907 ncpParent=priv_findPrivClassInGlobalClassListFromName(pGlobalNomEnv,
908 **(sci->nomIdAllParents)); /* This may also return a class not derived
909 from SOMClass */
910#endif
911 if(!ncpParent)
912 return NULLHANDLE; /* Every class except NOMObject must have a parent!! */
913 }/* nomIdAllParents */
914 else
915 return NULLHANDLE; /* Every class except NOMObject must have a parent!! */
916
917 if(!ncpParent)
918 return NULLHANDLE; /* Every class except NOMObject must have a parent!! */
919
920#ifdef DEBUG_NOMBUILDCLASS
921 /* Do some debugging here... */
922 DBG_NOMBUILDCLASS(TRUE, "Found parent private class info struct. Dumping parentMTabStruct...\n", NULL);
923 pParentMtab=&ncpParent->parentMtabStruct;
924 nomPrintf(" parent class: %s (priv %x), pParentMtab: %x, pParentMtab->mtab %x, next: %x\n",
925 ncpParent->mtab->nomClassName,
926 ncpParent, pParentMtab, pParentMtab->mtab, pParentMtab->next);
927 /* climb parent list */
928 psmTab=pParentMtab->next;
929 while(psmTab) {
930 nomPrintf(" next class: %s, next: %x\n", psmTab->mtab->nomClassName, psmTab->next);
931 psmTab=psmTab->next;
932 }
933#endif /* DEBUG_NOMBUILDCLASS */
934
935
936 /* Check if parent is a class object (derived from NOMClass). */
937 if(!priv_nomIsA((NOMObject*)ncpParent, pGlobalNomEnv->defaultMetaClass)) {
938 /* No, parent of class to build is normal object so we have to use either an explicit meta class if given or
939 another NOMClass derived class for the class object. */
940
941 DBG_NOMBUILDCLASS(TRUE, "Class %x (ncpParent->mtab->nomClassName: %s) is not a NOMClass\n",
942 ncpParent, ncpParent->mtab->nomClassName);
943
944 if(sci->nomExplicitMetaId)
945 {
946 /* The explicit metaclass is created at this point. Now it will be filled
947 with the info how to create objects. */
948
949 DBG_NOMBUILDCLASS(TRUE, "sci->nomExplicitMetaId is set. Calling priv_buildWithExplicitMetaClass().\n", "");
950
951 nomClass= priv_buildWithExplicitMetaClass(ulReserved, sci,
952 ulMajorVersion, ulMinorVersion);
953 if(nomClass){
954 DBG_NOMBUILDCLASS(TRUE, "%s: class is 0x%x\n", nomClass->mtab->nomClassName, nomClass);
955#if 0
956 /* Mark the class as using nomUnInit() if any parent did that. We just have to
957 check the flag and the flag of the parent class. This information is important
958 because if this method is overriden the garbage collector has to run a finalizer
959 on the object when collecting memory so the object may do its uninit stuff. */
960 priv_checkForNomUnInitOverride( (NOMClassPriv*)nomClass->mtab->nomClsInfo, ncpParent);
961#endif
962 _nomInit((NOMObject*)nomClass, NULLHANDLE);
963 _nomClassReady(nomClass, NULLHANDLE);
964 }
965
966 return nomClass;
967 }/* nomExplicitMetaId */
968 else {
969 /* Use NOMClass derived class as meta class. We have to climb the parent list of this object class
970 to check if one parent introduced an explicit metaclass. If yes, we have to use that one as
971 the metaclass. If no parent did that we just use NOMClass.
972 The following call will create the class object and will also fill in the necessary object info for
973 creating instances. */
974 nomClass= priv_buildWithNOMClassChildAsMeta(ulReserved, sci,
975 ulMajorVersion, ulMinorVersion);
976
977 if(nomClass){
978 _nomInit((NOMObject*)nomClass, NULLHANDLE);
979 _nomClassReady(nomClass, NULLHANDLE);
980 }
981 return nomClass;
982 }
983 }/* NOMClass derived? */
984
985 /* Child of some NOMClass */
986
987 /**** From this point we are building a new class object (derived from NOMClass ****/
988 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct */
989
990 /* Calculate size of new class object */
991 DBG_NOMBUILDCLASS(TRUE, "Parent class 0x%x (ncpParent->mtab->nomClassName: %s) is a NOMClass (or derived)\n",
992 ncpParent, ncpParent->mtab->nomClassName);
993 DBG_NOMBUILDCLASS(TRUE, " ncParent->mtab->mtabSize: %d\n", ncpParent->mtab->mtabSize);
994
995 mtabSize=ncpParent->mtab->mtabSize+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods)+sizeof(NOMClass*);/* ulNumStaticMethods is correct here!
996 NOT numStaticMethods-1!
997 entries[0] in fact contains the
998 class pointer not a method
999 pointer. */
1000 ulMemSize+=mtabSize; /* add place for new procs and the new class pointer */
1001 ulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size */
1002
1003 DBG_NOMBUILDCLASS(TRUE, "%s mtabSize is: %d, ulParentDataSize is: %d\n",
1004 *sci->nomClassId, mtabSize, ulParentDataSize);
1005
1006 /* Alloc class struct using NOMCalloc. */
1007 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULLHANDLE)
1008 return NULLHANDLE;
1009
1010 if(0!=sci->ulNumStaticMethods){
1011 /* Get mem for method thunking code */
1012 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
1013 if(!nClass->mThunk) {
1014 NOMFree(nClass);
1015 return NULLHANDLE;
1016 }
1017 }
1018
1019 nClass->ulClassSize=sci->ulInstanceDataSize+ulParentDataSize;
1020
1021 if((nomClass=(NOMClass*)NOMCalloc(1, sci->ulInstanceDataSize+ulParentDataSize))==NULLHANDLE) {
1022 NOMFree(nClass->mThunk);
1023 NOMFree(nClass);
1024 return NULLHANDLE;
1025 }
1026
1027 nClass->ulPrivClassSize=ulMemSize;
1028
1029 /* Add class struct of this class. This includes resolving the method adresses. */
1030 addMethodAndDataToThisPrivClassStruct( nClass, ncpParent, sci) ;
1031
1032 /* Resolve overrides if any */
1033 priv_resolveOverrideMethods(nClass, sci);
1034
1035 nomClass->mtab=nClass->mtab;
1036
1037 DBG_NOMBUILDCLASS(TRUE,"mtab: %x, nClass: 0x%x, nomClass: 0x%x\n", nClass->mtab, nClass, nomClass);
1038
1039 sci->nomCds->nomClassObject=nomClass; /* Put class pointer in static struct */
1040
1041 /**********************************/
1042 /* Fill methodtable mtab */
1043 /**********************************/
1044 nClass->mtab->mtabSize=mtabSize;
1045 nClass->mtab->nomClassObject=nomClass;
1046 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass;
1047 nClass->mtab->nomClassName=*sci->nomClassId;
1048 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+ulParentDataSize; /* Size of instance data of this class and all
1049 parent classes. This isn't actually allocated for this class
1050 object but the entry is used when creating the objects. */
1051 fillCClassDataStructParentMtab(sci, nClass, nomClass);
1052
1053 /* Thunking see above */
1054 nClass->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
1055 sci->ccds->instanceDataToken=&nClass->thunk;
1056
1057 /* Set this class size into instance var */
1058#warning !!!!! No call of _nomSetInstanceSize() here !!!!!
1059 // _nomSetInstanceSize(nomClass, sci->ulInstanceDataSize+ulParentDataSize);
1060
1061 DBG_NOMBUILDCLASS(TRUE, "New class ptr (class object): %x (NOMClassPriv: %x) for %s\n"
1062 , nomClass, nClass, *sci->nomClassId);
1063
1064 if(nomClass){
1065 /* Mark the class as using nomUnInit() if any parent did that. We just have to
1066 check the flag and the flag of the parent class. This information is important
1067 because if this method is overriden the garbage collector has to run a finalizer
1068 on the object when collecting memory so the object may do its uninit stuff. */
1069 priv_checkForNomUnInitOverride( (NOMClassPriv*)nomClass->mtab->nomClsInfo, ncpParent);
1070
1071 _nomInit(nomClass, NULLHANDLE);
1072 _nomClassReady(nomClass, NULLHANDLE);
1073 }
1074 return nomClass;
1075};
1076
1077
1078
1079
1080
1081
1082/*********************************************************************************************************************/
1083/* Unused stuff */
1084/*********************************************************************************************************************/
1085#if 0
1086#include <cwsomcls.h>
1087#include <somclassmanager.h>
1088/********************************************************/
1089/* Toolkit functions, exported */
1090/********************************************************/
1091
1092/*
1093 Caller is responsible for freeing the returned somId with SOMFree.
1094 Note: this is not the internal id (hash) of a string!
1095
1096 FIXME:
1097 This function must be checked if it's correct.
1098 */
1099
1100somId SOMLINK somIdFromString (string aString)
1101{
1102 /* This call automatically registers the ID with the runtime */
1103 somIdItem *sid;
1104 somId sID;
1105
1106 if(!aString)
1107 return NULL;
1108
1109 /* Do we already have an ID at all? */
1110 sid=priv_findSomIdInList(pGlobalSomEnv, aString);
1111
1112 if(sid) {
1113 sID=SOMMalloc(sizeof(void*));
1114 if(!sID)
1115 return NULLHANDLE;
1116
1117 *sID=(char*)sid;
1118 return sID;
1119 }
1120
1121 /* No somId registered yet, so create one */
1122 if((sid=(somIdItem*)SOMCalloc(1, sizeof(somIdItem)))==NULLHANDLE)
1123 return NULLHANDLE;
1124
1125 sid->idString=SOMMalloc(strlen(aString)+1);
1126 if(!sid->idString)
1127 {
1128 SOMFree(sid);
1129 return NULLHANDLE;
1130 }
1131
1132 sid->id=calculateNameHash(aString);
1133
1134 strcpy(sid->idString, aString);
1135 if(!priv_addSomIdToIdList(pGlobalSomEnv, sid)) {
1136 SOMFree(sid->idString);
1137 SOMFree(sid);
1138 return NULLHANDLE;
1139 }
1140
1141 sID=SOMMalloc(sizeof(void*));
1142 if(!sID)
1143 return NULLHANDLE;
1144
1145 *sID=(char*)sid;
1146 return sID;
1147}
1148
1149/*
1150 FIXME: semaphores!!!!!
1151 */
1152/*
1153 This function tries to find the class introducing the method 'sid' at first.
1154 */
1155static SOMClassPriv* priv_getOverrideClass(somId *sid)
1156{
1157 char* chrPtr;
1158 SOMClassPriv *scp;
1159 ULONG ulLen;
1160 char *chrMem;
1161
1162 if(!sid)
1163 return NULLHANDLE;
1164
1165 if((chrPtr=strchr(**sid, ':'))==NULLHANDLE)
1166 return NULLHANDLE;
1167
1168 /* Create local copy */
1169 ulLen=strlen(**sid);
1170 if(ulLen>5000) /* prevent stack overflow in case of error */
1171 return NULLHANDLE;
1172
1173 chrMem=alloca(ulLen);
1174 strcpy(chrMem, **sid);
1175
1176 if((chrPtr=strchr(chrMem, ':'))==NULLHANDLE)
1177 return NULLHANDLE; /* How should that happen, but anyway... */
1178
1179 *chrPtr=0; /* Now we have separated the class name */
1180#ifdef DEBUG_SOMBUILDCLASS
1181 somPrintf("%d: %s: searching override for %s\n", __LINE__, __FUNCTION__, chrMem);
1182#endif
1183 scp=priv_findPrivClassInGlobalClassList(pGlobalSomEnv, chrMem);
1184#ifdef DEBUG_SOMBUILDCLASS
1185 somPrintf("%d: %s: found %x\n", __LINE__, __FUNCTION__, scp);
1186#endif
1187 if(!scp)
1188 return NULLHANDLE;
1189#ifdef DEBUG_SOMBUILDCLASS
1190 somPrintf("%d: %s: found %x (SOMClassPriv) ->%x (SOMClass)\n", __LINE__, __FUNCTION__, scp, scp->mtab->classObject);
1191#endif
1192 return scp;
1193}
1194
1195/*
1196 FIXME: semaphores!!!!!
1197 */
1198/*
1199 This function tries to find the class introducing the method 'sid' at first.
1200 It returns a SOMClass not a SOMClassPriv.
1201 */
1202static SOMClass* priv_getOverrideSOMClass(somId *sid)
1203{
1204 char* chrPtr;
1205 SOMClassPriv *scp;
1206 ULONG ulLen;
1207 char *chrMem;
1208
1209 if(!sid)
1210 return NULLHANDLE;
1211
1212 if((chrPtr=strchr(**sid, ':'))==NULLHANDLE)
1213 return NULLHANDLE;
1214
1215 /* Create local copy */
1216 ulLen=strlen(**sid);
1217 if(ulLen>5000) /* prevent stack overflow in case of error */
1218 return NULLHANDLE;
1219
1220 chrMem=alloca(ulLen);
1221 strcpy(chrMem, **sid);
1222
1223 if((chrPtr=strchr(chrMem, ':'))==NULLHANDLE)
1224 return NULLHANDLE; /* How should that happen, but anyway... */
1225
1226 *chrPtr=0; /* Now we have separated the class name */
1227#ifdef DEBUG_SOMBUILDCLASS
1228 somPrintf("%d: %s: searching override for %s\n", __LINE__, __FUNCTION__, chrMem);
1229#endif
1230 scp=priv_findPrivClassInGlobalClassList(pGlobalSomEnv, chrMem);
1231 somPrintf("%d: %s: found %x (SOMClassPriv)\n", __LINE__, __FUNCTION__, scp);
1232 if(!scp)
1233 return NULLHANDLE;
1234#ifdef DEBUG_SOMBUILDCLASS
1235 somPrintf("%d: %s: found %x (SOMClassPriv) ->%x\n", __LINE__, __FUNCTION__, scp, scp->mtab->classObject);
1236#endif
1237 return scp->mtab->classObject;
1238}
1239
1240/*
1241 This function finds the class which introduced the method (methodId) to be overriden. It gets the index
1242 in the mtab of that class and returns it. Using this index the correct method address is taken
1243 from the mtab of the parent class of the class which wants to override a method (sClass). By using the
1244 parent instead the original class (introducing this method in the beginning) any overriding
1245 done in a class subclassing the introducing class is automatically taken into account.
1246 */
1247/*
1248 FIXME: semaphores ????
1249 */
1250static ULONG priv_getIndexOfMethodToBeOverriden(somId *methodId )
1251{
1252 return 0;
1253}
1254
1255/*
1256 Class format:
1257
1258 struct _SOMClass {
1259 struct somMethodTabStruct *mtab;
1260 struct somClassInfo;
1261 struct somMethodTabListStruct;
1262 struct somParentMtabStruct; Struct to place parent mtab pointer
1263 ULONG thunk[3]; Assembler thunking code
1264 somMethodTabStruct mtabStruct; See beloe
1265 ClassDataStruct class1;
1266 ClassDataStruct class2;
1267 ClassDataStruct class3;
1268 ...
1269 };
1270
1271 -- Object Instance Structure:
1272
1273 struct somMethodTabStruct;
1274 typedef struct SOMAny_struct {
1275 struct somMethodTabStruct *mtab;
1276 integer4 body[1];
1277 } SOMAny;
1278
1279 The following struct was built by CW
1280 struct somClassInfo
1281 {
1282 SOMClass *classObject; <- This is a pointer to the SOMObject class object in SOM.
1283 }
1284
1285typedef struct somMethodTabStruct {
1286 SOMClass *classObject;
1287 somClassInfo *classInfo;
1288 char *className;
1289 long instanceSize;
1290 long dataAlignment;
1291 long mtabSize;
1292 long protectedDataOffset; / from class's introduced data
1293 somDToken protectedDataToken;
1294 somEmbeddedObjStruct *embeddedObjs;
1295 / remaining structure is opaque /
1296 somMethodProc* entries[1]; <-- I found that this isn't correct (or I misseed something in the includes). When dumping a mtab
1297 the following has this structure:
1298
1299 SOMClass *classObject; /The first class object (SOMObject)
1300 This is basically a copy -> somMethodProc* firstMethod_1;
1301 of the ClassDataStruct somMethodProc* secondMethod_1;
1302 ...
1303 SOMClass *classObject; /The second class object
1304 ClassDataStruct of 2. -> somMethodProc* firstMethod_2;
1305 class somMethodProc* secondMethod_2;
1306
1307} somMethodTab, *somMethodTabPtr;
1308*/
1309
1310/*
1311 Build a "SOMObject class" usable for building other class objects e.g. SOMClass
1312 (base for all class objects). Right after SOMObject is constructed, it will be used only
1313 for holding the created mtab structure which contains all the resolved procedure
1314 pointers. This mtab is referenced by the SOMObject and thus by SOMClass (and all classes
1315 to come).
1316 SOMObject will get a full featured class object later when SOMClass is built.
1317
1318
1319 Is this still correct???:
1320
1321 Within this function a "real" SOMObject will be created which will be used when
1322 creating normal objects derived from SOMObject but not from a class object.
1323 This is necessary because the class structure and the object structure are different
1324 so we need two different templates. The class created by this function is only used
1325 for holding data necessary for building SOMClass. This class pointer will not be used
1326 for anything else.
1327 */
1328SOMClass * SOMLINK priv_buildSOMObject(long inherit_vars,
1329 somStaticClassInfo *sci,
1330 long majorVersion,
1331 long minorVersion)
1332{
1333 BYTE * mem;
1334 SOMClassPriv *sClass; /* This struct holds our private data. A pointer will be in mtab->classInfo */
1335 SOMClass *somClass; /* A real SOMClass pointer */
1336 int a;
1337 ULONG mtabSize;
1338 ULONG ulMemSize=0;
1339 ULONG ulParentDataSize=0;
1340
1341#ifdef DEBUG_BUILDSOMOBJECT
1342 somPrintf("%d: Entering %s to build a temporary SOMObject class object\n", __LINE__, __FUNCTION__);
1343 somPrintf("%d: Entering %s to build the mtab for SOMObjects (pEnv->mtabSOMObject)\n", __LINE__, __FUNCTION__);
1344 _dumpSci(sci);
1345#endif
1346
1347 /* Note: SOMObject has no parents */
1348 return NULLHANDLE;
1349
1350 /* ulMemsize will be the size of our private class structure SOMClassPriv */
1351 ulMemSize=sizeof(SOMClassPriv)-sizeof(somMethodTab); /* start size class struct without the somMethodTab
1352 holding the method pointers. The size of this
1353 somMethodTab will be added later. */
1354
1355 /* Calculate the size of the method tab to be added to the size of the private class struct */
1356 mtabSize=sizeof(somMethodTab)+sizeof(somMethodProc*)*(sci->numStaticMethods);/* numStaticMethods is correct here! NOT
1357 numStaticMethods-1! entries[0] in fact
1358 contains the class pointer not a method
1359 pointer. */
1360 ulMemSize+=mtabSize; /* Add size of base mtab struct */
1361
1362 /* Alloc private class struct using SOMCalloc. */
1363 if((sClass=(SOMClassPriv*)SOMCalloc(1, ulMemSize))==NULLHANDLE)
1364 return NULLHANDLE;
1365
1366 /* Get mem for method thunking code. This assembler code is needed so the indirect
1367 jump to the methods from the object pointer which is known does work. For each class
1368 an individual thunking code must be calculated because the number of instance
1369 variables is not defined. */
1370 sClass->mThunk=SOMMalloc(sizeof(cwMethodThunk)*sci->numStaticMethods);
1371 if(!sClass->mThunk) {
1372 SOMFree(sClass);
1373 return NULLHANDLE;
1374 }
1375
1376 /* The size of each instance of this class. A SOM object has a method tab pointer
1377 at the beginning followed by the instance variables. */
1378 sClass->ulClassSize=sci->instanceDataSize+sizeof(somMethodTab*);
1379
1380 sClass->sci=sci; /* Save static class info for internal use */
1381 sClass->ulPrivClassSize=ulMemSize; /* Internal housekeeping. Not needed by SOM methods */
1382 memcpy(sClass->thunk, thunk, sizeof(thunk)); /* Copy assembler thunking code for instance data */
1383
1384 /* Fill all the pointers to methodtable we need in the *private* structure */
1385 sClass->mtab=(somMethodTab*)&sClass->thisMtab; /* create the mtab pointer and store it */
1386 sClass->mtabList.mtab= (somMethodTab*)&sClass->thisMtab; /* thisMtab is the position where the mtab starts */
1387 sClass->parentMtabStruct.mtab=(somMethodTab*)&sClass->thisMtab;
1388
1389 /* And now the real SOMClass struct which will be seen by the user. A SOMClass has a mTab pointer
1390 at the beginning and the instance data following. */
1391 if((somClass=(SOMClass*)SOMCalloc(1, sci->instanceDataSize+sizeof(somMethodTab*)))==NULLHANDLE) {
1392 SOMFree(sClass->mThunk);
1393 SOMFree(sClass);
1394 return NULLHANDLE;
1395 }
1396 somClass->mtab=sClass->mtab;
1397
1398#ifdef DEBUG_BUILDSOMOBJECT
1399 somPrintf("mtab: %x sClass: %x, somClass: %x\n", sClass->mtab, sClass, somClass);
1400#endif
1401
1402 /*
1403 FIXME: this somClass must be deleted after updating with the real metaclass!
1404 */
1405 /*
1406 We don't have a class object yet...
1407 */
1408 // sci->cds->classObject=somClass; /* Put class pointer in static struct */
1409
1410 /* Copy class data. This goes at the address of "somMethodProc* entries[0]".
1411 Entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
1412 We don't use the static classDataStruct directly because subclasses will override the proc addresses. */
1413 mem=(char*)&(somClass->mtab->entries[0]); /* Target address.entries[0] will contain the class pointer */
1414
1415 /* Add class struct of this class. This includes the proc adresses. */
1416 if(sci->numStaticMethods) {
1417#ifdef DEBUG_BUILDSOMOBJECT
1418 somPrintf("copy: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct) to %x\n",
1419 sizeof(SOMClass*)+sci->numStaticMethods*sizeof(somMethodProc*),
1420 sci->cds, mem);
1421#endif
1422 /* Copy classDataStruct with the resolved proc addresses */
1423 memcpy( mem, sci->cds, sizeof(SOMClass*)+sci->numStaticMethods*sizeof(somMethodProc*));
1424
1425 /* Now finally put the thunking in so the procedures are resolved correctly. */
1426 for(a=0;a<sci->numStaticMethods;a++) {
1427 ULONG ulOffset;
1428
1429 memcpy(&sClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy method thunking code template */
1430 ulOffset=(ULONG)((char*)(mem+sizeof(SOMClass*))-(char*)somClass->mtab); /* Skip priv class data pointer */
1431 sClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(somMethodProc*))<<8)+0xa2; /* Calculate offset for assembler code */
1432#ifdef DEBUG_BUILDSOMOBJECT
1433 somPrintf(" %d: %d : Thunk offset: %d (0x%x) -> address will be: %x\n",
1434 __LINE__, a, ulOffset, ulOffset, mem+ulOffset+a*sizeof(somMethodProc*) );
1435#endif
1436 /* Put thunking code address into CClassStruct */
1437 sci->cds->tokens[a]=(void*)&sClass->mThunk[a];
1438 } /* for */
1439 } /* if(numStaticMethods) */
1440
1441 /**********************************/
1442 /* Fill methodtable mtab */
1443 /**********************************/
1444 sClass->mtab->mtabSize=mtabSize; /* This mtab is the same as the one used in the real SOMClass */
1445
1446#if 0
1447 /* We don't have a class object yet. */
1448 sClass->mtab->classObject=somClass; /* This is the real SOMClass pointer, not a pointer to SOMClassPriv */
1449#endif
1450
1451 sClass->mtab->classInfo=(somClassInfo*)sClass; /* FIXME: I think I may just use this undocumented field for the private data. */
1452 sClass->mtab->className=*sci->classId;
1453 sClass->mtab->instanceSize=sci->instanceDataSize+sizeof(somMethodTabPtr); /* sizeof(methodTabStruct*) + size of instance data of this class
1454 and all parent classes. This is SOMObject so we have no parents. */
1455 /*
1456 FIXME:
1457 The following is not yet initialized (and the previous may be buggy...) */
1458 // long dataAlignment;
1459 // long protectedDataOffset; /* from class's introduced data */
1460 // somDToken protectedDataToken;
1461 // somEmbeddedObjStruct *embeddedObjs;
1462
1463 sci->ccds->parentMtab=&sClass->parentMtabStruct; /* Insert pointer into CClassDataStructure */
1464
1465 /* Fill somParentMtabStruct in CClassDataStructure */
1466 sci->ccds->parentMtab->mtab=sClass->mtab; /* This class mtab */
1467 sci->ccds->parentMtab->next=NULL; /* We dont have parents because we are SOMObject */
1468 sci->ccds->parentMtab->classObject=somClass; /* SOMClass* Class object, this means ourself */
1469 sci->ccds->parentMtab->instanceSize=sClass->mtab->instanceSize;
1470 /* C Class data structure */
1471
1472 /* Thunking code see above. Adjust the offset to the instance data so the right
1473 variables are accessed. The offset is different depending on the number of parent
1474 classes (which isn't fix) and the number of parent instance vars (which isn't known
1475 at compile time) */
1476 sClass->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
1477 sci->ccds->instanceDataToken=&sClass->thunk;
1478
1479#ifdef DEBUG_BUILDSOMOBJECT
1480 somPrintf("New class ptr (temp. class object for SOMObject): %x (SOMClassPriv: %x) for %s\n",
1481 somClass, sClass, *sci->classId);
1482
1483 somPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
1484 _dumpClassDataStruct(sci->cds, sci->numStaticMethods);
1485#endif
1486#ifdef DEBUG_OBJECTS
1487 _dumpMTabListPrivClass(sClass);
1488#endif
1489
1490 /* SOMObject is special because it's root of normal classes and meta classes. Because of this it
1491 isn't insert into the normal private meta class list. We also use this info to check if SOMObject
1492 was already built in other places. */
1493 pGlobalSomEnv->scpSOMObject=sClass;
1494
1495 priv_addPrivClassToGlobalClassList(pGlobalSomEnv, sClass);
1496
1497#ifdef DEBUG_OBJECTS
1498 _dumpObj(somClass);
1499#endif
1500
1501 /*
1502 We don't run the somInit() method here because the SOMObject class isn't yet completely built.
1503 First a SOMClass meta class must be created because SOMObject needs a SOMClass as the class object like
1504 any other class. In case some code in somInit() tries to access the class object initialization would
1505 fail. In the function building the root SOMClass a metaclass for SOMObject will be created and attached.
1506
1507 Not running somInit() here shouldn't be a problem because we know what we are doing ;-).
1508 If there will ever be the need for special initialization for this very first SOMObject we think again...
1509
1510 In any case fiddling with somInit() in SOMObject and SOMClass is a dangerous thing because at least one of the
1511 two classes won't be completely built at that point in time (because SOMClass is a subclass of SOMObject
1512 and SOMObject needs a SOMClass as metaclass).
1513
1514 _somInit(somClass);
1515 */
1516 return somClass;
1517}
1518#endif
Note: See TracBrowser for help on using the repository browser.