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

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

Initial NOM checkin

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