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

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

Fixes for explicit metaclass handling

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