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

Last change on this file since 255 was 255, checked in by cinc, 18 years ago

Parameter checking for object pointer working.

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