source: trunk/nom/src/nombuildclass.c

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

NOM compiles now on FreeBSD. The fame goes to gahr for the patches.

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