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

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

Fixed of by one array access bug showing only on Darwin in release builds for some strange reason. Fixed two warnings.

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)
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=(guint8*)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=((guint8*)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 DBG_NOMBUILDCLASS(TRUE, "Find NOMClassPriv for %s %x\n", chrClassName, chrClassName);
436
437 if(NULL==NOMClassMgrObject){
438 /* If we build NOMClass or NOMClassMgr we just use the pointer we saved before. */
439 if(!strcmp(chrClassName, "NOMObject"))
440 ncpParent=pGlobalNomEnv->ncpNOMObject;
441 else
442 g_error("Asking for a parent not being NOMObject while NOMClassMgrObject is NULL. This can't be!!!");
443 }/* NULL== NOMClassMgrObject */
444 else
445 {
446 ncpParent=_nomGetClassInfoPtrFromName(NOMClassMgrObject, chrClassName,
447 NULL);
448 }
449
450 return ncpParent;
451}
452
453#if 0
454static void priv_checkForNomUnInitOverride( NOMClass *nomClass, NOMClassPriv *ncpParent)
455{
456 /* Mark the class as using nomUnInit() if any parent did that. We just have to
457 check the flag and the flag of the parent class. This information is important
458 because if this method is overriden the garbage collector has to run a finalizer
459 on the object when collecting memory so the object may do its uninit stuff. */
460 if(nomClass && !(((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN))
461 {
462 /* Flag not set. Try parent */
463 if(ncpParent && ncpParent->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN)
464 ((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags|= NOM_FLG_NOMUNINIT_OVERRIDEN;
465 }
466
467 DBG_NOMBUILDCLASS(TRUE, "nomUnInit overriden in class %s: %s\n",
468 nomClass->mtab->nomClassName,
469 (((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN ?
470 "Yes" : "No"));
471
472};
473#endif
474
475static void priv_checkForNomUnInitOverride( NOMClassPriv *nomClassPriv, NOMClassPriv *ncpParent)
476{
477 /* Mark the class as using nomUnInit() if any parent did that. We just have to
478 check the flag and the flag of the parent class. This information is important
479 because if this method is overriden the garbage collector has to run a finalizer
480 on the object when collecting memory so the object may do its uninit stuff. */
481 DBG_NOMBUILDCLASS(TRUE, " %s (%x): %x, %s (%x): %x ", nomClassPriv->mtab->nomClassName, nomClassPriv,
482 nomClassPriv->ulClassFlags,
483 ncpParent->mtab->nomClassName, ncpParent, ncpParent->ulClassFlags);
484 if(nomClassPriv && !(nomClassPriv->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN))
485 {
486 /* Flag not set. Try parent */
487 if(ncpParent && ncpParent->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN)
488 nomClassPriv->ulClassFlags|= NOM_FLG_NOMUNINIT_OVERRIDEN;
489 }
490
491 DBG_NOMBUILDCLASS(TRUE, " %x nomUnInit overriden in class %s: %s\n",
492 nomClassPriv->ulClassFlags, nomClassPriv->mtab->nomClassName,
493 (nomClassPriv->ulClassFlags & NOM_FLG_NOMUNINIT_OVERRIDEN ?
494 "Yes" : "No"));
495};
496
497
498/*
499 This function creates a private class structure for an object from the given sci with
500 correctly resolved methods which holds the mtab. This struct is kept by the metaclass
501 and holds all the information for creating objects.
502
503 nomClass: class object
504 */
505static NOMClassPriv * NOMLINK priv_buildPrivClassStruct(long inherit_vars,
506 nomStaticClassInfo *sci,
507 long majorVersion,
508 long minorVersion,
509 NOMClass* nomClass)
510{
511 gulong ulParentDataSize=0;
512 gulong mtabSize;
513 gulong ulMemSize=0;
514 NOMClassPriv *nClass, *ncpParent;
515
516 DBGBUILDNOMCLASS_ENTER
517
518 if(!nomClass||!sci)
519 return NULL;
520
521 /* The addresse of static methods in sci are already resolved. See nomBuildClass() */
522
523 /* Get parent class if any */
524 if(NULL!=sci->chrParentClassNames){
525 ncpParent=priv_getClassFromName(sci->chrParentClassNames[sci->ulNumParentsInChain-1]);
526 }/* nomIdAllParents */
527 else
528 ncpParent = NULL;
529
530 if(!ncpParent) {
531 g_warning("We are supposed to create a NOMClassPriv but there's no parent!\n");
532 /* FIXME:
533 Maybe we should panic here. */
534 return NULL; /* Only NOMObject has no parent, so we have a problem here. */
535 }
536
537 /* Calculate size of new class object */
538 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct */
539
540 DBG_NOMBUILDCLASS(TRUE, " ncpParent->mtab->mtabSize: %d. Parent is: %x (priv) %s\n",
541 ncpParent->mtab->mtabSize, ncpParent, ncpParent->mtab->nomClassName);
542
543 mtabSize=ncpParent->mtab->mtabSize+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods)+
544 sizeof(NOMObject*);/* numStaticMethods is correct here!
545 NOT numStaticMethods-1!
546 entries[0] in fact contains the
547 class pointer not a method
548 pointer. */
549 ulMemSize+=mtabSize; /* add place for new procs and the new class pointer */
550 ulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size */
551
552 DBG_NOMBUILDCLASS(TRUE, " %s: mtabSize will be: %d, ulParentDataSize is: %d\n"
553 , __FUNCTION__, mtabSize, ulParentDataSize);
554
555 /* Alloc private class struct using NOMCalloc. */
556 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULL)
557 return NULL;
558#if 0
559 //Moved to addMethodAndDataToThisPrivClassStruct()
560 /* Get mem for method thunking code */
561 if(0!=sci->ulNumStaticMethods){
562 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
563 if(!nClass->mThunk) {
564 NOMFree(nClass);
565 return NULL;
566 }
567 }
568#endif
569
570 /* Add class struct of this class.
571 This includes
572 -resolving the new method adresses
573 -add the parent mtab info to the new built mtab
574 */
575 if(!addMethodAndDataToThisPrivClassStruct( nClass, ncpParent, sci)){
576 NOMFree(nClass);
577 return NULL;
578 };
579
580 DBG_NOMBUILDCLASS(TRUE, "%s: mtab: %x\n", __FUNCTION__, nClass->mtab);
581
582 /*
583 Note: We don't create a class object here so the following isn't done:
584 sci->cds->classObject=nomClass;
585 */
586
587 /* Resolve ovverrides if any */
588 priv_resolveOverrideMethods(nClass, sci);
589
590 /**********************************/
591 /* Fill methodtable mtab */
592 /**********************************/
593 nClass->mtab->mtabSize=mtabSize;
594 nClass->mtab->nomClassObject=nomClass; /* Class object (metaclass). We build a normal class here. */
595 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass;
596#ifndef _MSC_VER
597#warning !!!!! Change this when nomId is a GQuark !!!!!
598#endif
599 nClass->mtab->nomClassName=*sci->nomClassId;
600 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+ulParentDataSize; /* Size of instance data of this class and all
601 parent classes. This isn't actually allocated for this class
602 object but the entry is used when creating the objects. */
603 fillCClassDataStructParentMtab(sci, nClass, nomClass);
604
605 DBG_NOMBUILDCLASS(TRUE, "New NOMClassPriv*: %x\n", nClass);
606
607 _nomSetObjectCreateInfo(nomClass, nClass, NULL);
608
609 /* Mark the class as using nomUnInit() if any parent did that. We just have to
610 check the flag and the flag of the parent class. This information is important
611 because if this method is overriden the garbage collector has to run a finalizer
612 on the object when collecting memory so the object may do its uninit stuff. */
613 priv_checkForNomUnInitOverride( nClass, ncpParent);
614
615 DBGBUILDNOMCLASS_LEAVE
616 return nClass;
617}
618
619
620NOMClass * NOMLINK priv_buildWithExplicitMetaClass(glong ulReserved,
621 nomStaticClassInfo *sci,
622 gulong majorVersion,
623 gulong minorVersion)
624{
625 NOMClass *nomClass, *nomClassMeta;
626
627 if(NULL==NOMClassMgrObject)
628 return NULL;
629
630 /* Search for meta class. */
631#ifndef _MSC_VER
632#warning !!!!! Change this when nomID is a GQuark !!!!!
633#endif
634 nomClassMeta=_nomFindClassFromName(NOMClassMgrObject, *sci->nomExplicitMetaId, majorVersion, minorVersion, NULL);
635
636 DBG_NOMBUILDCLASS(TRUE, "%x %s %s\n", nomClassMeta, *sci->nomClassId, *sci->nomExplicitMetaId);
637
638 if(!nomClassMeta)
639 return NULL;
640
641 /* Create a new class object. We create a copy here because we may change the mtab entries
642 through overriding or two classes may use the same meta class but have different
643 sizes, methods etc. I wonder how IBM SOM manages to use the same metaclass
644 for different classes without (apparently) copying it for different uses... */
645 if((nomClass=(NOMClass*)NOMCalloc(1, _nomGetSize(nomClassMeta, NULL)))==NULL)
646 return NULL;
647
648 /* Maybe we should just copy the whole struct here? */
649 nomClass->mtab=nomClassMeta->mtab;
650#ifndef _MSC_VER
651#warning !!!!! No call of _nomSetInstanceSize !!!!!
652#warning !!!!! No call of _nomSetObjectsSCI !!!!!
653#endif
654#if 0
655 /* Set object data */
656 _nomSetInstanceSize(nomClass, _nomGetSize(nomClassMeta));
657 /* Save objects sci pointer. We need it when we create instances */
658 _nomSetObjectsSCI(somClass, sci);
659#endif
660
661 /* Update static class data of class to be build */
662 sci->nomCds->nomClassObject=nomClass;
663
664 /* Now we have a meta class. Create the NOMClassPriv* holding the mtab for the class
665 to be built (which is not a meta class). */
666 priv_buildPrivClassStruct(ulReserved, sci,
667 majorVersion, minorVersion,
668 nomClass);
669
670 DBG_NOMBUILDCLASS(TRUE, "New class Object (child of NOMClass): %x \n", nomClass);
671
672 /* nomClassReady() is called in nomBuildClass() */
673 return nomClass;
674}
675
676/*
677 This function climbs the chain of parents and looks for a parent introducing
678 an explicit metaclass. If found, this metaclass is returned otherwise NOMClass.
679 */
680static
681NOMClass * NOMLINK priv_findExplicitMetaClassFromParents(nomStaticClassInfo *sci)
682{
683 int a;
684
685 if(1==sci->ulNumParentsInChain)
686 {
687 /* One parent only. That must be NOMObject and NOMObject has NOMClass
688 as metaclass. */
689 return pGlobalNomEnv->defaultMetaClass;;
690 }
691
692 /* Climb the list of parents... */
693
694 /* NOMClassMgrObject==NULL shouldn't ever happen here! */
695 g_assert(NOMClassMgrObject);
696
697 for(a=sci->ulNumParentsInChain-1;a>=0; a--)
698 {
699 NOMObject *nObject;
700 nObject=_nomFindClassFromName(NOMClassMgrObject, sci->chrParentClassNames[a], 0, 0, NULL);
701
702 DBG_NOMBUILDCLASS( TRUE , " Parent %d: %s, class object: %x\n" ,
703 a, sci->chrParentClassNames[a], nObject);
704 if(nObject){
705 DBG_NOMBUILDCLASS( TRUE , " Class object name: %s\n" , nObject->mtab->nomClassName);
706 if(strcmp(nObject->mtab->nomClassName, "NOMClass"))
707 return (NOMClass*)nObject; /* Not NOMClass so return */
708 } /* if(nObject) */
709 } /* for() */
710 return pGlobalNomEnv->defaultMetaClass;
711}
712
713/*
714 This function is called when a class for a given sci should be build with a parent
715 which isn't derived from NOMClass. In that case some NOMClass ccild is the class to
716 be used for the class object. We have to climb the parent list of this object class
717 to check if one parent introduced an explicit metaclass. If yes, we have to use that
718 one as the metaclass. If no parent did that we just use NOMClass.
719 This doesn't mean we reuse the found structs directly. Instead a new copy is created
720 so individula overriding is possible.
721*/
722static
723NOMClass * NOMLINK priv_buildWithNOMClassChildAsMeta(gulong ulReserved,
724 nomStaticClassInfo *sci,
725 long majorVersion,
726 long minorVersion)
727{
728 NOMClass *nomClass, *nomClassDefault;
729 NOMClassPriv *nClass;
730
731#ifdef DEBUG_NOMBUILDCLASS
732# ifndef _MSC_VER
733#warning !!!!! Change this when nomId is a GQuark !!!!!
734# endif
735 nomPrintf("\n%d: Entering %s to build %s\n", __LINE__, __FUNCTION__, *sci->nomClassId);
736#endif
737
738 /* Search parents for a an explicit metaclass. If no explicit metaclass return
739 NOMClass. */
740 nomClassDefault=priv_findExplicitMetaClassFromParents(sci);// this gives a NOMClass* not a NOMClassPriv*
741
742 /**** Create the meta class object ****/
743 //nomClassDefault=pGlobalNomEnv->defaultMetaClass; // this gives a NOMClass* not a NOMClassPriv*
744
745 if(!nomClassDefault)
746 return NULL;
747
748 /* Found NOMClass object */
749
750 //nomPrintf("_nomGetSize(): %d\n", _nomGetSize(nomClassParent, NULL));
751
752 /* Create an object */
753 if((nomClass=(NOMClass*)NOMCalloc(1, _nomGetSize(nomClassDefault, NULL)))==NULL)
754 return NULL;
755
756 nomClass->mtab=nomClassDefault->mtab;
757
758#ifndef _MSC_VER
759#warning !!!!! _nomSetInstanceSize() not called here !!!!!
760#warning !!!!! _nomSetObjectsSCI() not called here !!!!!
761#endif
762#if 0
763 /* Set object data */
764 _nomSetInstanceSize(somClass, _nomGetSize(nomClassDefault));
765 /* Save objects sci pointer. We need it when we create instances */
766 _nomSetObjectsSCI(nomClass, sci);
767#endif
768
769 /* Update static class data of the class to be built */
770 sci->nomCds->nomClassObject=nomClass;
771
772 /* Now we have a meta class. Create the NOMClassPriv* holding the mtab for the class
773 to be built. */
774 nClass=priv_buildPrivClassStruct(ulReserved, sci,
775 majorVersion, minorVersion,
776 nomClass);
777
778#ifdef DEBUG_NOMBUILDCLASS
779 DBG_NOMBUILDCLASS(TRUE, "%s: New class Object (NOMClass): %x NOMClassPriv*: %x ulClassFlags: %x\n",
780 __FUNCTION__, nomClass, nomClass->mtab->nomClsInfo,
781 ((NOMClassPriv*)nomClass->mtab->nomClsInfo)->ulClassFlags);
782 //_dumpMtab(nomClass->mtab);
783 //_dumpObjShort(nomClass);
784#endif
785
786 /* nomClassReady() is called in nomBuildClass(), so don't call it here. Same goes for _nomInit(). */
787 return nomClass;
788}
789
790
791/*
792 nomClass: NOMClass
793 nClass: NOMClassPriv for NOMClass
794 ulSize: size of a NOMClass object
795
796 This function is used to add a meta class to NOMOBject which was built before.
797*/
798NOMClass* createNOMObjectClassObjectAndUpdateNOMObject(NOMClass* nomClass, NOMClassPriv* nClass, gulong ulSize)
799{
800 NOMClassPriv *ncp;
801 NOMClass *nomObjClass;
802
803 DBGBUILDNOMCLASS_ENTER
804
805 /* The NOMClassPriv for NOMObject */
806 ncp= pGlobalNomEnv->ncpNOMObject;
807
808 /* Allocate a class object for NOMObject for creating NOMObject instances. */
809 if((nomObjClass=(NOMClass*)NOMCalloc(1, ulSize))==NULL) {
810 /* We panic here for the simple reason that without a working NOMObject the whole object system
811 will not work. */
812 g_error("No memory for building the class object _NOMObject for NOMObject.");
813 return NULL;
814 }
815
816 nomObjClass->mtab=nomClass->mtab; /* Now it's an object */
817
818 _nomSetObjectCreateInfo(nomObjClass, pGlobalNomEnv->ncpNOMObject, NULL); /* This NOMClassPriv holds all info to build
819 instances of NOMObject (not that anybody
820 should do that but... */
821#ifndef _MSC_VER
822#warning !!!!!!!!!!!!! _somSetObjectsSCI() not called!!!!!!!!!!!!!!!!
823#warning !!!!!!!!!!!!! _somSetClassData() not called!!!!!!!!!!!!!!!!
824#endif
825#if 0
826 _somSetObjectsSCI(nomObjClass, ncp->sci);
827 _somSetClassData(somObjClass, scp->sci->cds);
828#endif
829
830 /* Update NOMObject data */
831 ncp->mtab->nomClassObject=nomObjClass; /* This is the real NOMClass pointer, not a pointer to NOMClassPriv */
832 ncp->mtab->entries[0]=(void*)nomObjClass;
833
834 /* Put it into the class data of NOMObject */
835 ncp->sci->nomCds->nomClassObject=nomObjClass;
836
837#ifdef DEBUG_BUILDNOMOBJECT
838 nomPrintf("%d: metaclass for NOMObject created: %x\n",__LINE__, nomObjClass);
839#endif
840 DBGBUILDNOMCLASS_LEAVE
841 return nomObjClass;
842}
843
844/**
845 Build a class for NOM from the data generated from the IDL compiler and
846 compiled into the DLL.
847 */
848NOMEXTERN NOMClass * NOMLINK nomBuildClass(gulong ulReserved,
849 nomStaticClassInfo *sci,
850 gulong ulMajorVersion,
851 gulong ulMinorVersion)
852{
853 NOMClass *nomClass;
854 NOMClassPriv *nClass;
855 NOMClassPriv *ncpParent;
856 gulong ulParentDataSize=0;
857 gulong mtabSize;
858 gulong ulMemSize=0;
859 int a;
860
861#ifdef DEBUG_NOMBUILDCLASS
862 nomParentMtabStructPtr pParentMtab;
863 nomMethodTabs psmTab;
864 /* Print some info for debbuging */
865 nomPrintf("\n%d: Entering %s to build class %s. ---> NOMClassManagerObject: 0x%x\n",
866 __LINE__, __FUNCTION__, *sci->nomClassId, NOMClassMgrObject);
867 nomPrintf("%d: cds: 0x%x nomClassObject: 0x%x\n", __LINE__, sci->nomCds, sci->nomCds->nomClassObject);
868#endif
869
870 /* Check if already built */
871 if(sci->nomCds->nomClassObject) {
872 DBG_NOMBUILDCLASS(TRUE, "Class %s already built. returning 0x%x\n", *sci->nomClassId, sci->nomCds->nomClassObject);
873 return (sci->nomCds)->nomClassObject; /* Yes,return the object */
874 }
875
876 /* Do we want to build again NOMObject the mother of all classes?
877 This happens because every class automatically tries to build the parents
878 (which includes NOMObject somewhere). NOMObject doesn't have a class object
879 yet when created
880 so we have to check here the global pointer to the NOMObject private data.
881 */
882
883 if(!strcmp(*sci->nomClassId, "NOMObject")){
884 if(pGlobalNomEnv->ncpNOMObject!=NULL){
885 DBG_NOMBUILDCLASS(TRUE, "Class %s already built. returning 0x%x\n",
886 *sci->nomClassId, sci->nomCds->nomClassObject);
887 /* FIXME: this seems to be broken!! */
888 return NULL; /* NOMObject already built */
889 }
890 }
891
892#ifdef _DEBUG_NOMBUILDCLASS
893 DBG_NOMBUILDCLASS(TRUE, "Dumping sci:\n");
894 _dumpSci(sci);
895#endif
896
897 if(sci->ulNumStaticMethods!=0 && !sci->nomSMethods){
898 nomPrintf(" !!! %s line %d: sci->nomSMethods is NULL for %s !!!\n", __FUNCTION__, __LINE__, *sci->nomClassId);
899 return NULL;
900 }
901 /* Fill static classdata with the info from nomStaticMethodDesc array. This means
902 putting the method adresses into the classdata struct.
903 Be aware that the order of the methods in the somStaticMethod_t array is not
904 necessarily in the order as specified in the releaseorder list. But each array member
905 (which is a nomStaticMethodDesc) contains the address of the correct
906 field in the static classdata struct. */
907 /* This also resolves methods for objects not only class objects. Be careful when
908 removing here. You have to correct priv_buildObjecttemplate(). */
909 /* Insert class data structure method tokens */
910 for(a=0;a<sci->ulNumStaticMethods;a++) {
911 *sci->nomSMethods[a].nomMAddressInClassData=(void*)sci->nomSMethods[a].nomMethod; /* Address to place the resolved function address in see *.ih files. */
912#ifdef DEBUG_NOMBUILDCLASS
913 nomPrintf(" static method: %s, %lx\n", *sci->nomSMethods[a].chrMethodDescriptor, sci->nomSMethods[a].nomMethod);
914 nomPrintf("%d: %d: method: %x %s (classdata addr. %x) (Fill static class struct with procs)\n",
915 __LINE__, a, sci->nomSMethods[a].nomMethod, *sci->nomSMethods[a].nomMethodId, sci->nomSMethods[a].nomMAddressInClassData);
916#endif
917 }
918
919#ifdef DEBUG_NOMBUILDCLASS
920 nomPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
921 _dumpClassDataStruct(sci->nomCds, sci->ulNumStaticMethods);
922#endif
923
924 /* Do we want to build NOMObject the mother of all classes? */
925 if(!strcmp(*sci->nomClassId, "NOMObject")){
926
927 DBG_NOMBUILDCLASS(TRUE, "Trying to build %s\n", *sci->nomClassId);
928
929 priv_buildNOMObjectClassInfo(ulReserved, sci, /* yes */
930 ulMajorVersion, ulMinorVersion);
931 return NULL; /* We can't return a NOMClass for NOMObject because NOMClass isn't built yet. */
932 }
933
934 /* Do we want to build NOMClass? */
935 if(!strcmp(*sci->nomClassId, "NOMClass"))
936 return priv_buildNOMClass(ulReserved, sci, /* yes */
937 ulMajorVersion, ulMinorVersion);
938
939 /* Get parent class */
940 if(sci->nomIdAllParents) {
941#ifdef DEBUG_NOMBUILDCLASS
942# ifndef _MSC_VER
943#warning !!!!! Change this when nomId is a GQuark !!!!!
944# endif
945 nomPrintf("%d: About to search parent %s (%d)...\n", __LINE__, **(sci->nomIdAllParents), sci->ulNumParentsInChain);
946 nomPrintf("%d: About to search parent %s (%s)...\n", __LINE__, **(sci->nomIdAllParents),
947 sci->chrParentClassNames[0]);
948#endif
949
950 ncpParent=priv_getClassFromName(sci->chrParentClassNames[sci->ulNumParentsInChain-1]);
951
952#if 0
953 ncpParent=priv_getClassFromName(**(sci->nomIdAllParents));
954 ncpParent=priv_findPrivClassInGlobalClassListFromName(pGlobalNomEnv,
955 **(sci->nomIdAllParents)); /* This may also return a class not derived
956 from NOMClass */
957#endif
958 if(!ncpParent)
959 return NULL; /* Every class except NOMObject must have a parent!! */
960 }/* nomIdAllParents */
961 else
962 return NULL; /* Every class except NOMObject must have a parent!! */
963
964 if(!ncpParent)
965 return NULL; /* Every class except NOMObject must have a parent!! */
966
967#ifdef DEBUG_NOMBUILDCLASS
968 /* Do some debugging here... */
969 DBG_NOMBUILDCLASS(TRUE, "Found parent private class info struct. Dumping parentMTabStruct...\n", NULL);
970 pParentMtab=&ncpParent->parentMtabStruct;
971 nomPrintf(" parent class: %s (priv %x), pParentMtab: %x, pParentMtab->mtab %x, next: %x\n",
972 ncpParent->mtab->nomClassName,
973 ncpParent, pParentMtab, pParentMtab->mtab, pParentMtab->next);
974 /* climb parent list */
975 psmTab=pParentMtab->next;
976 while(psmTab) {
977 nomPrintf(" next class: %s, next: %x\n", psmTab->mtab->nomClassName, psmTab->next);
978 psmTab=psmTab->next;
979 }
980#endif /* DEBUG_NOMBUILDCLASS */
981
982
983 /* Check if parent is a class object (derived from NOMClass). */
984 if(!priv_nomIsA((NOMObject*)ncpParent, pGlobalNomEnv->defaultMetaClass)) {
985 /* No, parent of class to build is normal object so we have to use either an explicit meta class if given or
986 another NOMClass derived class for the class object. */
987
988 DBG_NOMBUILDCLASS(TRUE, "Class %x (ncpParent->mtab->nomClassName: %s) is not a NOMClass\n",
989 ncpParent, ncpParent->mtab->nomClassName);
990
991 if(sci->nomExplicitMetaId)
992 {
993 /* The explicit metaclass is created at this point. Now it will be filled
994 with the info how to create objects. */
995
996 DBG_NOMBUILDCLASS(TRUE, "sci->nomExplicitMetaId is set. Calling priv_buildWithExplicitMetaClass().\n", "");
997
998 nomClass= priv_buildWithExplicitMetaClass(ulReserved, sci,
999 ulMajorVersion, ulMinorVersion);
1000 if(nomClass){
1001 CORBA_Environment * tempEnv=nomCreateEnvNoObjectCheck();
1002
1003 DBG_NOMBUILDCLASS(TRUE, "%s: class is 0x%x\n", nomClass->mtab->nomClassName, nomClass);
1004#if 0
1005 /* Mark the class as using nomUnInit() if any parent did that. We just have to
1006 check the flag and the flag of the parent class. This information is important
1007 because if this method is overriden the garbage collector has to run a finalizer
1008 on the object when collecting memory so the object may do its uninit stuff. */
1009 priv_checkForNomUnInitOverride( (NOMClassPriv*)nomClass->mtab->nomClsInfo, ncpParent);
1010#endif
1011 /* Make sure the env is marked that we don't chek the object pointer. This would fail
1012 because the class isn't registered yet. */
1013 _nomInit((NOMObject*)nomClass, tempEnv);
1014 _nomClassReady(nomClass, tempEnv);
1015 }
1016
1017 return nomClass;
1018 }/* nomExplicitMetaId */
1019 else {
1020 /* Use NOMClass derived class as meta class. We have to climb the parent list of this object class
1021 to check if one parent introduced an explicit metaclass. If yes, we have to use that one as
1022 the metaclass. If no parent did that we just use NOMClass.
1023 The following call will create the class object and will also fill in the necessary object info for
1024 creating instances. */
1025 nomClass= priv_buildWithNOMClassChildAsMeta(ulReserved, sci,
1026 ulMajorVersion, ulMinorVersion);
1027
1028 if(nomClass){
1029 CORBA_Environment * tempEnv=nomCreateEnvNoObjectCheck();
1030 /* Make sure the env is marked that we don't chek the object pointer. This would fail
1031 because the class isn't registered yet. */
1032 _nomInit((NOMObject*)nomClass, tempEnv);
1033 _nomClassReady(nomClass, tempEnv);
1034 }
1035 return nomClass;
1036 }
1037 }/* NOMClass derived? */
1038
1039 /* Child of some NOMClass */
1040
1041 /**** From this point we are building a new class object (derived from NOMClass ****/
1042 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct */
1043
1044 /* Calculate size of new class object */
1045 DBG_NOMBUILDCLASS(TRUE, "Parent class 0x%x (ncpParent->mtab->nomClassName: %s) is a NOMClass (or derived)\n",
1046 ncpParent, ncpParent->mtab->nomClassName);
1047 DBG_NOMBUILDCLASS(TRUE, " ncParent->mtab->mtabSize: %d\n", ncpParent->mtab->mtabSize);
1048
1049 mtabSize=ncpParent->mtab->mtabSize+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods)+sizeof(NOMClass*);/* ulNumStaticMethods is correct here!
1050 NOT numStaticMethods-1!
1051 entries[0] in fact contains the
1052 class pointer not a method
1053 pointer. */
1054 ulMemSize+=mtabSize; /* add place for new procs and the new class pointer */
1055 ulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size */
1056
1057 DBG_NOMBUILDCLASS(TRUE, "%s mtabSize is: %d, ulParentDataSize is: %d\n",
1058 *sci->nomClassId, mtabSize, ulParentDataSize);
1059
1060 /* Alloc class struct using NOMCalloc. */
1061 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULL)
1062 return NULL;
1063
1064#if 0
1065 //Moved to addMethodAndDataToThisPrivClassStruct()
1066 if(0!=sci->ulNumStaticMethods){
1067 /* Get mem for method thunking code */
1068 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
1069 if(!nClass->mThunk) {
1070 NOMFree(nClass);
1071 return NULL;
1072 }
1073 }
1074#endif
1075
1076 nClass->ulClassSize=sci->ulInstanceDataSize+ulParentDataSize;
1077
1078 if((nomClass=(NOMClass*)NOMCalloc(1, sci->ulInstanceDataSize+ulParentDataSize))==NULL) {
1079 //NOMFree(nClass->mThunk);
1080 NOMFree(nClass);
1081 return NULL;
1082 }
1083
1084 nClass->ulPrivClassSize=ulMemSize;
1085
1086 /* Add class struct of this class. This includes resolving the method adresses. */
1087 if(!addMethodAndDataToThisPrivClassStruct( nClass, ncpParent, sci)){
1088 NOMFree(nClass);
1089 NOMFree(nomClass);
1090 return NULL;
1091 };
1092
1093 /* Resolve overrides if any */
1094 priv_resolveOverrideMethods(nClass, sci);
1095
1096 nomClass->mtab=nClass->mtab;
1097
1098 DBG_NOMBUILDCLASS(TRUE,"mtab: %x, nClass: 0x%x, nomClass: 0x%x\n", nClass->mtab, nClass, nomClass);
1099
1100 sci->nomCds->nomClassObject=nomClass; /* Put class pointer in static struct */
1101
1102 /**********************************/
1103 /* Fill methodtable mtab */
1104 /**********************************/
1105 nClass->mtab->mtabSize=mtabSize;
1106 nClass->mtab->nomClassObject=nomClass;
1107 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass;
1108 nClass->mtab->nomClassName=*sci->nomClassId;
1109 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+ulParentDataSize; /* Size of instance data of this class and all
1110 parent classes. This isn't actually allocated
1111 for this class object but the entry is used
1112 when creating the objects. */
1113 fillCClassDataStructParentMtab(sci, nClass, nomClass);
1114
1115 /* Thunking see above */
1116 nClass->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
1117 sci->ccds->instanceDataToken=&nClass->thunk;
1118
1119 /* Set this class size into instance var */
1120#ifndef _MSC_VER
1121#warning !!!!! No call of _nomSetInstanceSize() here !!!!!
1122#endif
1123 // _nomSetInstanceSize(nomClass, sci->ulInstanceDataSize+ulParentDataSize);
1124
1125 DBG_NOMBUILDCLASS(TRUE, "New class ptr (class object): %x (NOMClassPriv: %x) for %s\n"
1126 , nomClass, nClass, *sci->nomClassId);
1127
1128 if(nomClass){
1129 CORBA_Environment * tempEnv=nomCreateEnvNoObjectCheck();
1130
1131 /* Mark the class as using nomUnInit() if any parent did that. We just have to
1132 check the flag and the flag of the parent class. This information is important
1133 because if this method is overriden the garbage collector has to run a finalizer
1134 on the object when collecting memory so the object may do its uninit stuff. */
1135 priv_checkForNomUnInitOverride( (NOMClassPriv*)nomClass->mtab->nomClsInfo, ncpParent);
1136
1137 /* Make sure the env is marked that we don't chek the object pointer. This would fail
1138 because the class isn't registered yet. */
1139 _nomInit(nomClass, tempEnv);
1140 _nomClassReady(nomClass, tempEnv);
1141 }
1142 return nomClass;
1143};
1144
1145
1146
1147
1148
1149
1150/*********************************************************************************************************************/
1151/* Unused stuff */
1152/*********************************************************************************************************************/
1153#if 0
1154#include <cwsomcls.h>
1155#include <somclassmanager.h>
1156/********************************************************/
1157/* Toolkit functions, exported */
1158/********************************************************/
1159
1160/*
1161 Caller is responsible for freeing the returned somId with SOMFree.
1162 Note: this is not the internal id (hash) of a string!
1163
1164 FIXME:
1165 This function must be checked if it's correct.
1166 */
1167
1168somId SOMLINK somIdFromString (string aString)
1169{
1170 /* This call automatically registers the ID with the runtime */
1171 somIdItem *sid;
1172 somId sID;
1173
1174 if(!aString)
1175 return NULL;
1176
1177 /* Do we already have an ID at all? */
1178 sid=priv_findSomIdInList(pGlobalSomEnv, aString);
1179
1180 if(sid) {
1181 sID=SOMMalloc(sizeof(void*));
1182 if(!sID)
1183 return NULL;
1184
1185 *sID=(char*)sid;
1186 return sID;
1187 }
1188
1189 /* No somId registered yet, so create one */
1190 if((sid=(somIdItem*)SOMCalloc(1, sizeof(somIdItem)))==NULL)
1191 return NULL;
1192
1193 sid->idString=SOMMalloc(strlen(aString)+1);
1194 if(!sid->idString)
1195 {
1196 SOMFree(sid);
1197 return NULL;
1198 }
1199
1200 sid->id=calculateNameHash(aString);
1201
1202 strcpy(sid->idString, aString);
1203 if(!priv_addSomIdToIdList(pGlobalSomEnv, sid)) {
1204 SOMFree(sid->idString);
1205 SOMFree(sid);
1206 return NULL;
1207 }
1208
1209 sID=SOMMalloc(sizeof(void*));
1210 if(!sID)
1211 return NULL;
1212
1213 *sID=(char*)sid;
1214 return sID;
1215}
1216
1217/*
1218 FIXME: semaphores!!!!!
1219 */
1220/*
1221 This function tries to find the class introducing the method 'sid' at first.
1222 */
1223static SOMClassPriv* priv_getOverrideClass(somId *sid)
1224{
1225 char* chrPtr;
1226 SOMClassPriv *scp;
1227 gulong ulLen;
1228 char *chrMem;
1229
1230 if(!sid)
1231 return NULL;
1232
1233 if((chrPtr=strchr(**sid, ':'))==NULL)
1234 return NULL;
1235
1236 /* Create local copy */
1237 ulLen=strlen(**sid);
1238 if(ulLen>5000) /* prevent stack overflow in case of error */
1239 return NULL;
1240
1241 chrMem=alloca(ulLen);
1242 strcpy(chrMem, **sid);
1243
1244 if((chrPtr=strchr(chrMem, ':'))==NULL)
1245 return NULL; /* How should that happen, but anyway... */
1246
1247 *chrPtr=0; /* Now we have separated the class name */
1248#ifdef DEBUG_SOMBUILDCLASS
1249 somPrintf("%d: %s: searching override for %s\n", __LINE__, __FUNCTION__, chrMem);
1250#endif
1251 scp=priv_findPrivClassInGlobalClassList(pGlobalSomEnv, chrMem);
1252#ifdef DEBUG_SOMBUILDCLASS
1253 somPrintf("%d: %s: found %x\n", __LINE__, __FUNCTION__, scp);
1254#endif
1255 if(!scp)
1256 return NULL;
1257#ifdef DEBUG_SOMBUILDCLASS
1258 somPrintf("%d: %s: found %x (SOMClassPriv) ->%x (SOMClass)\n", __LINE__, __FUNCTION__, scp, scp->mtab->classObject);
1259#endif
1260 return scp;
1261}
1262
1263/*
1264 FIXME: semaphores!!!!!
1265 */
1266/*
1267 This function tries to find the class introducing the method 'sid' at first.
1268 It returns a SOMClass not a SOMClassPriv.
1269 */
1270static SOMClass* priv_getOverrideSOMClass(somId *sid)
1271{
1272 char* chrPtr;
1273 SOMClassPriv *scp;
1274 gulong ulLen;
1275 char *chrMem;
1276
1277 if(!sid)
1278 return NULL;
1279
1280 if((chrPtr=strchr(**sid, ':'))==NULL)
1281 return NULL;
1282
1283 /* Create local copy */
1284 ulLen=strlen(**sid);
1285 if(ulLen>5000) /* prevent stack overflow in case of error */
1286 return NULL;
1287
1288 chrMem=alloca(ulLen);
1289 strcpy(chrMem, **sid);
1290
1291 if((chrPtr=strchr(chrMem, ':'))==NULL)
1292 return NULL; /* How should that happen, but anyway... */
1293
1294 *chrPtr=0; /* Now we have separated the class name */
1295#ifdef DEBUG_SOMBUILDCLASS
1296 somPrintf("%d: %s: searching override for %s\n", __LINE__, __FUNCTION__, chrMem);
1297#endif
1298 scp=priv_findPrivClassInGlobalClassList(pGlobalSomEnv, chrMem);
1299 somPrintf("%d: %s: found %x (SOMClassPriv)\n", __LINE__, __FUNCTION__, scp);
1300 if(!scp)
1301 return NULL;
1302#ifdef DEBUG_SOMBUILDCLASS
1303 somPrintf("%d: %s: found %x (SOMClassPriv) ->%x\n", __LINE__, __FUNCTION__, scp, scp->mtab->classObject);
1304#endif
1305 return scp->mtab->classObject;
1306}
1307
1308/*
1309 This function finds the class which introduced the method (methodId) to be overriden. It gets the index
1310 in the mtab of that class and returns it. Using this index the correct method address is taken
1311 from the mtab of the parent class of the class which wants to override a method (sClass). By using the
1312 parent instead the original class (introducing this method in the beginning) any overriding
1313 done in a class subclassing the introducing class is automatically taken into account.
1314 */
1315/*
1316 FIXME: semaphores ????
1317 */
1318static gulong priv_getIndexOfMethodToBeOverriden(somId *methodId )
1319{
1320 return 0;
1321}
1322
1323/*
1324 Class format:
1325
1326 struct _SOMClass {
1327 struct somMethodTabStruct *mtab;
1328 struct somClassInfo;
1329 struct somMethodTabListStruct;
1330 struct somParentMtabStruct; Struct to place parent mtab pointer
1331 gulong thunk[3]; Assembler thunking code
1332 somMethodTabStruct mtabStruct; See beloe
1333 ClassDataStruct class1;
1334 ClassDataStruct class2;
1335 ClassDataStruct class3;
1336 ...
1337 };
1338
1339 -- Object Instance Structure:
1340
1341 struct somMethodTabStruct;
1342 typedef struct SOMAny_struct {
1343 struct somMethodTabStruct *mtab;
1344 integer4 body[1];
1345 } SOMAny;
1346
1347 The following struct was built by CW
1348 struct somClassInfo
1349 {
1350 SOMClass *classObject; <- This is a pointer to the SOMObject class object in SOM.
1351 }
1352
1353typedef struct somMethodTabStruct {
1354 SOMClass *classObject;
1355 somClassInfo *classInfo;
1356 char *className;
1357 long instanceSize;
1358 long dataAlignment;
1359 long mtabSize;
1360 long protectedDataOffset; / from class's introduced data
1361 somDToken protectedDataToken;
1362 somEmbeddedObjStruct *embeddedObjs;
1363 / remaining structure is opaque /
1364 somMethodProc* entries[1]; <-- I found that this isn't correct (or I misseed something in the includes). When dumping a mtab
1365 the following has this structure:
1366
1367 SOMClass *classObject; /The first class object (SOMObject)
1368 This is basically a copy -> somMethodProc* firstMethod_1;
1369 of the ClassDataStruct somMethodProc* secondMethod_1;
1370 ...
1371 SOMClass *classObject; /The second class object
1372 ClassDataStruct of 2. -> somMethodProc* firstMethod_2;
1373 class somMethodProc* secondMethod_2;
1374
1375} somMethodTab, *somMethodTabPtr;
1376*/
1377
1378/*
1379 Build a "SOMObject class" usable for building other class objects e.g. SOMClass
1380 (base for all class objects). Right after SOMObject is constructed, it will be used only
1381 for holding the created mtab structure which contains all the resolved procedure
1382 pointers. This mtab is referenced by the SOMObject and thus by SOMClass (and all classes
1383 to come).
1384 SOMObject will get a full featured class object later when SOMClass is built.
1385
1386
1387 Is this still correct???:
1388
1389 Within this function a "real" SOMObject will be created which will be used when
1390 creating normal objects derived from SOMObject but not from a class object.
1391 This is necessary because the class structure and the object structure are different
1392 so we need two different templates. The class created by this function is only used
1393 for holding data necessary for building SOMClass. This class pointer will not be used
1394 for anything else.
1395 */
1396SOMClass * SOMLINK priv_buildSOMObject(long inherit_vars,
1397 somStaticClassInfo *sci,
1398 long majorVersion,
1399 long minorVersion)
1400{
1401 guint8 * mem;
1402 SOMClassPriv *sClass; /* This struct holds our private data. A pointer will be in mtab->classInfo */
1403 SOMClass *somClass; /* A real SOMClass pointer */
1404 int a;
1405 gulong mtabSize;
1406 gulong ulMemSize=0;
1407 gulong ulParentDataSize=0;
1408
1409#ifdef DEBUG_BUILDSOMOBJECT
1410 somPrintf("%d: Entering %s to build a temporary SOMObject class object\n", __LINE__, __FUNCTION__);
1411 somPrintf("%d: Entering %s to build the mtab for SOMObjects (pEnv->mtabSOMObject)\n", __LINE__, __FUNCTION__);
1412 _dumpSci(sci);
1413#endif
1414
1415 /* Note: SOMObject has no parents */
1416 return NULL;
1417
1418 /* ulMemsize will be the size of our private class structure SOMClassPriv */
1419 ulMemSize=sizeof(SOMClassPriv)-sizeof(somMethodTab); /* start size class struct without the somMethodTab
1420 holding the method pointers. The size of this
1421 somMethodTab will be added later. */
1422
1423 /* Calculate the size of the method tab to be added to the size of the private class struct */
1424 mtabSize=sizeof(somMethodTab)+sizeof(somMethodProc*)*(sci->numStaticMethods);/* numStaticMethods is correct here! NOT
1425 numStaticMethods-1! entries[0] in fact
1426 contains the class pointer not a method
1427 pointer. */
1428 ulMemSize+=mtabSize; /* Add size of base mtab struct */
1429
1430 /* Alloc private class struct using SOMCalloc. */
1431 if((sClass=(SOMClassPriv*)SOMCalloc(1, ulMemSize))==NULL)
1432 return NULL;
1433
1434 /* Get mem for method thunking code. This assembler code is needed so the indirect
1435 jump to the methods from the object pointer which is known does work. For each class
1436 an individual thunking code must be calculated because the number of instance
1437 variables is not defined. */
1438 sClass->mThunk=SOMMalloc(sizeof(cwMethodThunk)*sci->numStaticMethods);
1439 if(!sClass->mThunk) {
1440 SOMFree(sClass);
1441 return NULL;
1442 }
1443
1444 /* The size of each instance of this class. A SOM object has a method tab pointer
1445 at the beginning followed by the instance variables. */
1446 sClass->ulClassSize=sci->instanceDataSize+sizeof(somMethodTab*);
1447
1448 sClass->sci=sci; /* Save static class info for internal use */
1449 sClass->ulPrivClassSize=ulMemSize; /* Internal housekeeping. Not needed by SOM methods */
1450 memcpy(sClass->thunk, thunk, sizeof(thunk)); /* Copy assembler thunking code for instance data */
1451
1452 /* Fill all the pointers to methodtable we need in the *private* structure */
1453 sClass->mtab=(somMethodTab*)&sClass->thisMtab; /* create the mtab pointer and store it */
1454 sClass->mtabList.mtab= (somMethodTab*)&sClass->thisMtab; /* thisMtab is the position where the mtab starts */
1455 sClass->parentMtabStruct.mtab=(somMethodTab*)&sClass->thisMtab;
1456
1457 /* And now the real SOMClass struct which will be seen by the user. A SOMClass has a mTab pointer
1458 at the beginning and the instance data following. */
1459 if((somClass=(SOMClass*)SOMCalloc(1, sci->instanceDataSize+sizeof(somMethodTab*)))==NULL) {
1460 SOMFree(sClass->mThunk);
1461 SOMFree(sClass);
1462 return NULL;
1463 }
1464 somClass->mtab=sClass->mtab;
1465
1466#ifdef DEBUG_BUILDSOMOBJECT
1467 somPrintf("mtab: %x sClass: %x, somClass: %x\n", sClass->mtab, sClass, somClass);
1468#endif
1469
1470 /*
1471 FIXME: this somClass must be deleted after updating with the real metaclass!
1472 */
1473 /*
1474 We don't have a class object yet...
1475 */
1476 // sci->cds->classObject=somClass; /* Put class pointer in static struct */
1477
1478 /* Copy class data. This goes at the address of "somMethodProc* entries[0]".
1479 Entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
1480 We don't use the static classDataStruct directly because subclasses will override the proc addresses. */
1481 mem=(char*)&(somClass->mtab->entries[0]); /* Target address.entries[0] will contain the class pointer */
1482
1483 /* Add class struct of this class. This includes the proc adresses. */
1484 if(sci->numStaticMethods) {
1485#ifdef DEBUG_BUILDSOMOBJECT
1486 somPrintf("copy: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct) to %x\n",
1487 sizeof(SOMClass*)+sci->numStaticMethods*sizeof(somMethodProc*),
1488 sci->cds, mem);
1489#endif
1490 /* Copy classDataStruct with the resolved proc addresses */
1491 memcpy( mem, sci->cds, sizeof(SOMClass*)+sci->numStaticMethods*sizeof(somMethodProc*));
1492
1493 /* Now finally put the thunking in so the procedures are resolved correctly. */
1494 for(a=0;a<sci->numStaticMethods;a++) {
1495 gulong ulOffset;
1496
1497 memcpy(&sClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy method thunking code template */
1498 ulOffset=(gulong)((char*)(mem+sizeof(SOMClass*))-(char*)somClass->mtab); /* Skip priv class data pointer */
1499 sClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(somMethodProc*))<<8)+0xa2; /* Calculate offset for assembler code */
1500#ifdef DEBUG_BUILDSOMOBJECT
1501 somPrintf(" %d: %d : Thunk offset: %d (0x%x) -> address will be: %x\n",
1502 __LINE__, a, ulOffset, ulOffset, mem+ulOffset+a*sizeof(somMethodProc*) );
1503#endif
1504 /* Put thunking code address into CClassStruct */
1505 sci->cds->tokens[a]=(void*)&sClass->mThunk[a];
1506 } /* for */
1507 } /* if(numStaticMethods) */
1508
1509 /**********************************/
1510 /* Fill methodtable mtab */
1511 /**********************************/
1512 sClass->mtab->mtabSize=mtabSize; /* This mtab is the same as the one used in the real SOMClass */
1513
1514#if 0
1515 /* We don't have a class object yet. */
1516 sClass->mtab->classObject=somClass; /* This is the real SOMClass pointer, not a pointer to SOMClassPriv */
1517#endif
1518
1519 sClass->mtab->classInfo=(somClassInfo*)sClass; /* FIXME: I think I may just use this undocumented field for the private data. */
1520 sClass->mtab->className=*sci->classId;
1521 sClass->mtab->instanceSize=sci->instanceDataSize+sizeof(somMethodTabPtr); /* sizeof(methodTabStruct*) + size of instance data of this class
1522 and all parent classes. This is SOMObject so we have no parents. */
1523 /*
1524 FIXME:
1525 The following is not yet initialized (and the previous may be buggy...) */
1526 // long dataAlignment;
1527 // long protectedDataOffset; /* from class's introduced data */
1528 // somDToken protectedDataToken;
1529 // somEmbeddedObjStruct *embeddedObjs;
1530
1531 sci->ccds->parentMtab=&sClass->parentMtabStruct; /* Insert pointer into CClassDataStructure */
1532
1533 /* Fill somParentMtabStruct in CClassDataStructure */
1534 sci->ccds->parentMtab->mtab=sClass->mtab; /* This class mtab */
1535 sci->ccds->parentMtab->next=NULL; /* We dont have parents because we are SOMObject */
1536 sci->ccds->parentMtab->classObject=somClass; /* SOMClass* Class object, this means ourself */
1537 sci->ccds->parentMtab->instanceSize=sClass->mtab->instanceSize;
1538 /* C Class data structure */
1539
1540 /* Thunking code see above. Adjust the offset to the instance data so the right
1541 variables are accessed. The offset is different depending on the number of parent
1542 classes (which isn't fix) and the number of parent instance vars (which isn't known
1543 at compile time) */
1544 sClass->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
1545 sci->ccds->instanceDataToken=&sClass->thunk;
1546
1547#ifdef DEBUG_BUILDSOMOBJECT
1548 somPrintf("New class ptr (temp. class object for SOMObject): %x (SOMClassPriv: %x) for %s\n",
1549 somClass, sClass, *sci->classId);
1550
1551 somPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
1552 _dumpClassDataStruct(sci->cds, sci->numStaticMethods);
1553#endif
1554#ifdef DEBUG_OBJECTS
1555 _dumpMTabListPrivClass(sClass);
1556#endif
1557
1558 /* SOMObject is special because it's root of normal classes and meta classes. Because of this it
1559 isn't insert into the normal private meta class list. We also use this info to check if SOMObject
1560 was already built in other places. */
1561 pGlobalSomEnv->scpSOMObject=sClass;
1562
1563 priv_addPrivClassToGlobalClassList(pGlobalSomEnv, sClass);
1564
1565#ifdef DEBUG_OBJECTS
1566 _dumpObj(somClass);
1567#endif
1568
1569 /*
1570 We don't run the somInit() method here because the SOMObject class isn't yet completely built.
1571 First a SOMClass meta class must be created because SOMObject needs a SOMClass as the class object like
1572 any other class. In case some code in somInit() tries to access the class object initialization would
1573 fail. In the function building the root SOMClass a metaclass for SOMObject will be created and attached.
1574
1575 Not running somInit() here shouldn't be a problem because we know what we are doing ;-).
1576 If there will ever be the need for special initialization for this very first SOMObject we think again...
1577
1578 In any case fiddling with somInit() in SOMObject and SOMClass is a dangerous thing because at least one of the
1579 two classes won't be completely built at that point in time (because SOMClass is a subclass of SOMObject
1580 and SOMObject needs a SOMClass as metaclass).
1581
1582 _somInit(somClass);
1583 */
1584 return somClass;
1585}
1586#endif
Note: See TracBrowser for help on using the repository browser.