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

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

Fixed class creation crash with explicit metaclasses not having any new methods.

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