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

Last change on this file since 326 was 326, checked in by cinc, 17 years ago

Portability patches for Windows, Linux, Darwin by Bird.

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