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

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

Changes...

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