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

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

Disabled a ton of debug messages.

File size: 57.2 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. Same goes for _nomInit(). */
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(gulong ulReserved,
699 nomStaticClassInfo *sci,
700 gulong ulMajorVersion,
701 gulong 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 _nomInit(nomClass, NULLHANDLE);
861 _nomClassReady(nomClass, NULLHANDLE);
862 }
863
864 return nomClass;
865 }/* nomExplicitMetaId */
866 else {
867 /* Use NOMClass as meta class. The following call will create the
868 class object and will also fill in the necessary object info for
869 creating instances. */
870 nomClass= priv_buildWithNOMClassAsMeta(ulReserved, sci,
871 ulMajorVersion, ulMinorVersion);
872
873 if(nomClass){
874 //#warning !!!!! No call of _nomClassReady() here !!!!!
875 //#if 0
876 _nomInit(nomClass, NULLHANDLE);
877 _nomClassReady(nomClass, NULLHANDLE);
878 //#endif
879 }
880 return nomClass;
881 }
882 }/* NOMClass derived? */
883
884 /* Child of some NOMClass */
885
886
887 /**** From this point we are building a new class object (derived from NOMClass ****/
888 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct */
889
890 /* Calculate size of new class object */
891#ifdef DEBUG_NOMBUILDCLASS
892 nomPrintf("Parent class %x (ncpParent->mtab->nomClassName: %s) is a NOMClass (or derived)\n",
893 ncpParent, ncpParent->mtab->nomClassName);
894 nomPrintf("ncParent->mtab->mtabSize: %d\n", ncpParent->mtab->mtabSize);
895#endif
896 mtabSize=ncpParent->mtab->mtabSize+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods)+sizeof(NOMClass*);/* ulNumStaticMethods is correct here!
897 NOT numStaticMethods-1!
898 entries[0] in fact contains the
899 class pointer not a method
900 pointer. */
901 ulMemSize+=mtabSize; /* add place for new procs and the new class pointer */
902 ulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size */
903
904#ifdef DEBUG_NOMBUILDCLASS
905 nomPrintf("%s mtabSize is: %d, ulParentDataSize is: %d\n", *sci->nomClassId, mtabSize, ulParentDataSize);
906#endif
907
908
909 /* Alloc class struct using SOMCalloc. This means the struct is allocated in shared mem */
910 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULLHANDLE)
911 return NULLHANDLE;
912
913 /* Get mem for method thunking code */
914 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
915 if(!nClass->mThunk) {
916 NOMFree(nClass);
917 return NULLHANDLE;
918 }
919
920 nClass->ulClassSize=sci->ulInstanceDataSize+ulParentDataSize;
921
922 if((nomClass=(NOMClass*)NOMCalloc(1, sci->ulInstanceDataSize+ulParentDataSize))==NULLHANDLE) {
923 NOMFree(nClass->mThunk);
924 NOMFree(nClass);
925 return NULLHANDLE;
926 }
927
928 nClass->ulPrivClassSize=ulMemSize;
929
930
931 /* Add class struct of this class. This includes resolving the method adresses. */
932 addMethodAndDataToThisPrivClassStruct( nClass, ncpParent, sci) ;
933
934 /* Resolve ovverrides if any */
935 //#warning !!!!! no resolving of overriden methods here !!!!!
936 priv_resolveOverrideMethods(nClass, sci);
937
938 nomClass->mtab=nClass->mtab;
939#ifdef DEBUG_nOMBUILDCLASS
940 nomPrintf("mtab: %x\n", nClass->mtab);
941#endif
942 sci->nomCds->nomClassObject=nomClass; /* Put class pointer in static struct */
943
944 /**********************************/
945 /* Fill methodtable mtab */
946 /**********************************/
947 nClass->mtab->mtabSize=mtabSize;
948 nClass->mtab->nomClassObject=nomClass;
949 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass;
950 nClass->mtab->nomClassName=*sci->nomClassId;
951 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+ulParentDataSize; /* Size of instance data of this class and all
952 parent classes. This isn't actually allocated for this class
953 object but the entry is used when creating the objects. */
954 fillCClassDataStructParentMtab(sci, nClass, nomClass);
955
956 /* Thunking see above */
957 nClass->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
958 sci->ccds->instanceDataToken=&nClass->thunk;
959
960 /* Set this class size into instance var */
961#warning !!!!! No call of _nomSetInstanceSize() here !!!!!
962 // _nomSetInstanceSize(nomClass, sci->ulInstanceDataSize+ulParentDataSize);
963
964#ifdef DEBUG_NOMBUILDCLASS
965 nomPrintf("New class ptr (class object): %x (NOMClassPriv: %x) for %s\n", nomClass, nClass, *sci->nomClassId);
966#endif
967
968 //priv_addPrivClassToGlobalClassList(pGlobalNomEnv, nClass);
969 _nomInit(nomClass, NULLHANDLE);
970 _nomClassReady(nomClass, NULLHANDLE);
971 return nomClass;
972};
973
974
975/*********************************************************************************************************************/
976/* Unused stuff */
977/*********************************************************************************************************************/
978
979
980
981#if 0
982#include <cwsomcls.h>
983#include <somclassmanager.h>
984/********************************************************/
985/* Internal functions */
986/********************************************************/
987
988/* String manager functions */
989static BOOL priv_addSomIdToIdList(PSOM_ENV pEnv, somIdItem * sid)
990{
991 somIdItem *tmpList;
992
993 if(!sid || !pEnv)
994 return FALSE;
995
996 if(NO_ERROR != priv_requestSomEnvMutex(pEnv))
997 return FALSE;
998
999 if(!pEnv->livingSomIds)
1000 {
1001 /* Add first class */
1002 pEnv->livingSomIds=sid;
1003 priv_releaseSomEnvMutex(pEnv);
1004 return TRUE;
1005 }
1006 tmpList=sid;
1007
1008 tmpList->next=(somIdItem*)pEnv->livingSomIds;
1009 pEnv->livingSomIds=tmpList;
1010 pEnv->ulNumRegIds++;
1011
1012 priv_releaseSomEnvMutex(pEnv);
1013 return TRUE;
1014}
1015
1016/* This returns the ID of a string, this means the hash of this string if
1017 already registered. */
1018static somIdItem* priv_findSomIdInList(PSOM_ENV pEnv, string aString)
1019{
1020 somIdItem *tmpItem;
1021 ULONG ulHash;
1022
1023 if(!pEnv|| aString)
1024 return 0;
1025
1026 ulHash=calculateNameHash(aString);
1027
1028 if(NO_ERROR != priv_requestSomEnvMutex(pEnv))
1029 return NULL;
1030
1031 tmpItem=pEnv->livingSomIds;
1032 while(tmpItem)
1033 {
1034 if(tmpItem->id == ulHash) {
1035 priv_releaseSomEnvMutex(pEnv);
1036 return tmpItem; /* We have found the string return somId */
1037 }
1038 tmpItem=tmpItem->next;
1039 };
1040 priv_releaseSomEnvMutex(pEnv);
1041
1042 return NULL; /* No id yet. */
1043}
1044
1045/********************************************************/
1046/* Toolkit functions, exported */
1047/********************************************************/
1048
1049/*
1050 Caller is responsible for freeing the returned somId with SOMFree.
1051 Note: this is not the internal id (hash) of a string!
1052
1053 FIXME:
1054 This function must be checked if it's correct.
1055 */
1056
1057somId SOMLINK somIdFromString (string aString)
1058{
1059 /* This call automatically registers the ID with the runtime */
1060 somIdItem *sid;
1061 somId sID;
1062
1063 if(!aString)
1064 return NULL;
1065
1066 /* Do we already have an ID at all? */
1067 sid=priv_findSomIdInList(pGlobalSomEnv, aString);
1068
1069 if(sid) {
1070 sID=SOMMalloc(sizeof(void*));
1071 if(!sID)
1072 return NULLHANDLE;
1073
1074 *sID=(char*)sid;
1075 return sID;
1076 }
1077
1078 /* No somId registered yet, so create one */
1079 if((sid=(somIdItem*)SOMCalloc(1, sizeof(somIdItem)))==NULLHANDLE)
1080 return NULLHANDLE;
1081
1082 sid->idString=SOMMalloc(strlen(aString)+1);
1083 if(!sid->idString)
1084 {
1085 SOMFree(sid);
1086 return NULLHANDLE;
1087 }
1088
1089 sid->id=calculateNameHash(aString);
1090
1091 strcpy(sid->idString, aString);
1092 if(!priv_addSomIdToIdList(pGlobalSomEnv, sid)) {
1093 SOMFree(sid->idString);
1094 SOMFree(sid);
1095 return NULLHANDLE;
1096 }
1097
1098 sID=SOMMalloc(sizeof(void*));
1099 if(!sID)
1100 return NULLHANDLE;
1101
1102 *sID=(char*)sid;
1103 return sID;
1104}
1105
1106/* Returns the total number of ids that have been registered so far, */
1107unsigned long SOMLINK somTotalRegIds(void)
1108{
1109 long numIds;
1110
1111 if(NO_ERROR != priv_requestSomEnvMutex(pGlobalSomEnv))
1112 return 0;
1113
1114 numIds=pGlobalSomEnv->ulNumRegIds;
1115 priv_releaseSomEnvMutex(pGlobalSomEnv);
1116
1117 return numIds;
1118}
1119
1120/*
1121 FIXME: semaphores!!!!!
1122 */
1123/*
1124 This function tries to find the class introducing the method 'sid' at first.
1125 */
1126static SOMClassPriv* priv_getOverrideClass(somId *sid)
1127{
1128 char* chrPtr;
1129 SOMClassPriv *scp;
1130 ULONG ulLen;
1131 char *chrMem;
1132
1133 if(!sid)
1134 return NULLHANDLE;
1135
1136 if((chrPtr=strchr(**sid, ':'))==NULLHANDLE)
1137 return NULLHANDLE;
1138
1139 /* Create local copy */
1140 ulLen=strlen(**sid);
1141 if(ulLen>5000) /* prevent stack overflow in case of error */
1142 return NULLHANDLE;
1143
1144 chrMem=alloca(ulLen);
1145 strcpy(chrMem, **sid);
1146
1147 if((chrPtr=strchr(chrMem, ':'))==NULLHANDLE)
1148 return NULLHANDLE; /* How should that happen, but anyway... */
1149
1150 *chrPtr=0; /* Now we have separated the class name */
1151#ifdef DEBUG_SOMBUILDCLASS
1152 somPrintf("%d: %s: searching override for %s\n", __LINE__, __FUNCTION__, chrMem);
1153#endif
1154 scp=priv_findPrivClassInGlobalClassList(pGlobalSomEnv, chrMem);
1155#ifdef DEBUG_SOMBUILDCLASS
1156 somPrintf("%d: %s: found %x\n", __LINE__, __FUNCTION__, scp);
1157#endif
1158 if(!scp)
1159 return NULLHANDLE;
1160#ifdef DEBUG_SOMBUILDCLASS
1161 somPrintf("%d: %s: found %x (SOMClassPriv) ->%x (SOMClass)\n", __LINE__, __FUNCTION__, scp, scp->mtab->classObject);
1162#endif
1163 return scp;
1164}
1165
1166/*
1167 FIXME: semaphores!!!!!
1168 */
1169/*
1170 This function tries to find the class introducing the method 'sid' at first.
1171 It returns a SOMClass not a SOMClassPriv.
1172 */
1173static SOMClass* priv_getOverrideSOMClass(somId *sid)
1174{
1175 char* chrPtr;
1176 SOMClassPriv *scp;
1177 ULONG ulLen;
1178 char *chrMem;
1179
1180 if(!sid)
1181 return NULLHANDLE;
1182
1183 if((chrPtr=strchr(**sid, ':'))==NULLHANDLE)
1184 return NULLHANDLE;
1185
1186 /* Create local copy */
1187 ulLen=strlen(**sid);
1188 if(ulLen>5000) /* prevent stack overflow in case of error */
1189 return NULLHANDLE;
1190
1191 chrMem=alloca(ulLen);
1192 strcpy(chrMem, **sid);
1193
1194 if((chrPtr=strchr(chrMem, ':'))==NULLHANDLE)
1195 return NULLHANDLE; /* How should that happen, but anyway... */
1196
1197 *chrPtr=0; /* Now we have separated the class name */
1198#ifdef DEBUG_SOMBUILDCLASS
1199 somPrintf("%d: %s: searching override for %s\n", __LINE__, __FUNCTION__, chrMem);
1200#endif
1201 scp=priv_findPrivClassInGlobalClassList(pGlobalSomEnv, chrMem);
1202 somPrintf("%d: %s: found %x (SOMClassPriv)\n", __LINE__, __FUNCTION__, scp);
1203 if(!scp)
1204 return NULLHANDLE;
1205#ifdef DEBUG_SOMBUILDCLASS
1206 somPrintf("%d: %s: found %x (SOMClassPriv) ->%x\n", __LINE__, __FUNCTION__, scp, scp->mtab->classObject);
1207#endif
1208 return scp->mtab->classObject;
1209}
1210
1211/*
1212 This function finds the class which introduced the method (methodId) to be overriden. It gets the index
1213 in the mtab of that class and returns it. Using this index the correct method address is taken
1214 from the mtab of the parent class of the class which wants to override a method (sClass). By using the
1215 parent instead the original class (introducing this method in the beginning) any overriding
1216 done in a class subclassing the introducing class is automatically taken into account.
1217 */
1218/*
1219 FIXME: semaphores ????
1220 */
1221static ULONG priv_getIndexOfMethodToBeOverriden(somId *methodId )
1222{
1223 return 0;
1224}
1225
1226/*
1227 Class format:
1228
1229 struct _SOMClass {
1230 struct somMethodTabStruct *mtab;
1231 struct somClassInfo;
1232 struct somMethodTabListStruct;
1233 struct somParentMtabStruct; Struct to place parent mtab pointer
1234 ULONG thunk[3]; Assembler thunking code
1235 somMethodTabStruct mtabStruct; See beloe
1236 ClassDataStruct class1;
1237 ClassDataStruct class2;
1238 ClassDataStruct class3;
1239 ...
1240 };
1241
1242 -- Object Instance Structure:
1243
1244 struct somMethodTabStruct;
1245 typedef struct SOMAny_struct {
1246 struct somMethodTabStruct *mtab;
1247 integer4 body[1];
1248 } SOMAny;
1249
1250 The following struct was built by CW
1251 struct somClassInfo
1252 {
1253 SOMClass *classObject; <- This is a pointer to the SOMObject class object in SOM.
1254 }
1255
1256typedef struct somMethodTabStruct {
1257 SOMClass *classObject;
1258 somClassInfo *classInfo;
1259 char *className;
1260 long instanceSize;
1261 long dataAlignment;
1262 long mtabSize;
1263 long protectedDataOffset; / from class's introduced data
1264 somDToken protectedDataToken;
1265 somEmbeddedObjStruct *embeddedObjs;
1266 / remaining structure is opaque /
1267 somMethodProc* entries[1]; <-- I found that this isn't correct (or I misseed something in the includes). When dumping a mtab
1268 the following has this structure:
1269
1270 SOMClass *classObject; /The first class object (SOMObject)
1271 This is basically a copy -> somMethodProc* firstMethod_1;
1272 of the ClassDataStruct somMethodProc* secondMethod_1;
1273 ...
1274 SOMClass *classObject; /The second class object
1275 ClassDataStruct of 2. -> somMethodProc* firstMethod_2;
1276 class somMethodProc* secondMethod_2;
1277
1278} somMethodTab, *somMethodTabPtr;
1279*/
1280
1281/*
1282 Build a "SOMObject class" usable for building other class objects e.g. SOMClass
1283 (base for all class objects). Right after SOMObject is constructed, it will be used only
1284 for holding the created mtab structure which contains all the resolved procedure
1285 pointers. This mtab is referenced by the SOMObject and thus by SOMClass (and all classes
1286 to come).
1287 SOMObject will get a full featured class object later when SOMClass is built.
1288
1289
1290 Is this still correct???:
1291
1292 Within this function a "real" SOMObject will be created which will be used when
1293 creating normal objects derived from SOMObject but not from a class object.
1294 This is necessary because the class structure and the object structure are different
1295 so we need two different templates. The class created by this function is only used
1296 for holding data necessary for building SOMClass. This class pointer will not be used
1297 for anything else.
1298 */
1299SOMClass * SOMLINK priv_buildSOMObject(long inherit_vars,
1300 somStaticClassInfo *sci,
1301 long majorVersion,
1302 long minorVersion)
1303{
1304 BYTE * mem;
1305 SOMClassPriv *sClass; /* This struct holds our private data. A pointer will be in mtab->classInfo */
1306 SOMClass *somClass; /* A real SOMClass pointer */
1307 int a;
1308 ULONG mtabSize;
1309 ULONG ulMemSize=0;
1310 ULONG ulParentDataSize=0;
1311
1312#ifdef DEBUG_BUILDSOMOBJECT
1313 somPrintf("%d: Entering %s to build a temporary SOMObject class object\n", __LINE__, __FUNCTION__);
1314 somPrintf("%d: Entering %s to build the mtab for SOMObjects (pEnv->mtabSOMObject)\n", __LINE__, __FUNCTION__);
1315 _dumpSci(sci);
1316#endif
1317
1318 /* Note: SOMObject has no parents */
1319 return NULLHANDLE;
1320
1321 /* ulMemsize will be the size of our private class structure SOMClassPriv */
1322 ulMemSize=sizeof(SOMClassPriv)-sizeof(somMethodTab); /* start size class struct without the somMethodTab
1323 holding the method pointers. The size of this
1324 somMethodTab will be added later. */
1325
1326 /* Calculate the size of the method tab to be added to the size of the private class struct */
1327 mtabSize=sizeof(somMethodTab)+sizeof(somMethodProc*)*(sci->numStaticMethods);/* numStaticMethods is correct here! NOT
1328 numStaticMethods-1! entries[0] in fact
1329 contains the class pointer not a method
1330 pointer. */
1331 ulMemSize+=mtabSize; /* Add size of base mtab struct */
1332
1333 /* Alloc private class struct using SOMCalloc. */
1334 if((sClass=(SOMClassPriv*)SOMCalloc(1, ulMemSize))==NULLHANDLE)
1335 return NULLHANDLE;
1336
1337 /* Get mem for method thunking code. This assembler code is needed so the indirect
1338 jump to the methods from the object pointer which is known does work. For each class
1339 an individual thunking code must be calculated because the number of instance
1340 variables is not defined. */
1341 sClass->mThunk=SOMMalloc(sizeof(cwMethodThunk)*sci->numStaticMethods);
1342 if(!sClass->mThunk) {
1343 SOMFree(sClass);
1344 return NULLHANDLE;
1345 }
1346
1347 /* The size of each instance of this class. A SOM object has a method tab pointer
1348 at the beginning followed by the instance variables. */
1349 sClass->ulClassSize=sci->instanceDataSize+sizeof(somMethodTab*);
1350
1351 sClass->sci=sci; /* Save static class info for internal use */
1352 sClass->ulPrivClassSize=ulMemSize; /* Internal housekeeping. Not needed by SOM methods */
1353 memcpy(sClass->thunk, thunk, sizeof(thunk)); /* Copy assembler thunking code for instance data */
1354
1355 /* Fill all the pointers to methodtable we need in the *private* structure */
1356 sClass->mtab=(somMethodTab*)&sClass->thisMtab; /* create the mtab pointer and store it */
1357 sClass->mtabList.mtab= (somMethodTab*)&sClass->thisMtab; /* thisMtab is the position where the mtab starts */
1358 sClass->parentMtabStruct.mtab=(somMethodTab*)&sClass->thisMtab;
1359
1360 /* And now the real SOMClass struct which will be seen by the user. A SOMClass has a mTab pointer
1361 at the beginning and the instance data following. */
1362 if((somClass=(SOMClass*)SOMCalloc(1, sci->instanceDataSize+sizeof(somMethodTab*)))==NULLHANDLE) {
1363 SOMFree(sClass->mThunk);
1364 SOMFree(sClass);
1365 return NULLHANDLE;
1366 }
1367 somClass->mtab=sClass->mtab;
1368
1369#ifdef DEBUG_BUILDSOMOBJECT
1370 somPrintf("mtab: %x sClass: %x, somClass: %x\n", sClass->mtab, sClass, somClass);
1371#endif
1372
1373 /*
1374 FIXME: this somClass must be deleted after updating with the real metaclass!
1375 */
1376 /*
1377 We don't have a class object yet...
1378 */
1379 // sci->cds->classObject=somClass; /* Put class pointer in static struct */
1380
1381 /* Copy class data. This goes at the address of "somMethodProc* entries[0]".
1382 Entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
1383 We don't use the static classDataStruct directly because subclasses will override the proc addresses. */
1384 mem=(char*)&(somClass->mtab->entries[0]); /* Target address.entries[0] will contain the class pointer */
1385
1386 /* Add class struct of this class. This includes the proc adresses. */
1387 if(sci->numStaticMethods) {
1388#ifdef DEBUG_BUILDSOMOBJECT
1389 somPrintf("copy: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct) to %x\n",
1390 sizeof(SOMClass*)+sci->numStaticMethods*sizeof(somMethodProc*),
1391 sci->cds, mem);
1392#endif
1393 /* Copy classDataStruct with the resolved proc addresses */
1394 memcpy( mem, sci->cds, sizeof(SOMClass*)+sci->numStaticMethods*sizeof(somMethodProc*));
1395
1396 /* Now finally put the thunking in so the procedures are resolved correctly. */
1397 for(a=0;a<sci->numStaticMethods;a++) {
1398 ULONG ulOffset;
1399
1400 memcpy(&sClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy method thunking code template */
1401 ulOffset=(ULONG)((char*)(mem+sizeof(SOMClass*))-(char*)somClass->mtab); /* Skip priv class data pointer */
1402 sClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(somMethodProc*))<<8)+0xa2; /* Calculate offset for assembler code */
1403#ifdef DEBUG_BUILDSOMOBJECT
1404 somPrintf(" %d: %d : Thunk offset: %d (0x%x) -> address will be: %x\n",
1405 __LINE__, a, ulOffset, ulOffset, mem+ulOffset+a*sizeof(somMethodProc*) );
1406#endif
1407 /* Put thunking code address into CClassStruct */
1408 sci->cds->tokens[a]=(void*)&sClass->mThunk[a];
1409 } /* for */
1410 } /* if(numStaticMethods) */
1411
1412 /**********************************/
1413 /* Fill methodtable mtab */
1414 /**********************************/
1415 sClass->mtab->mtabSize=mtabSize; /* This mtab is the same as the one used in the real SOMClass */
1416
1417#if 0
1418 /* We don't have a class object yet. */
1419 sClass->mtab->classObject=somClass; /* This is the real SOMClass pointer, not a pointer to SOMClassPriv */
1420#endif
1421
1422 sClass->mtab->classInfo=(somClassInfo*)sClass; /* FIXME: I think I may just use this undocumented field for the private data. */
1423 sClass->mtab->className=*sci->classId;
1424 sClass->mtab->instanceSize=sci->instanceDataSize+sizeof(somMethodTabPtr); /* sizeof(methodTabStruct*) + size of instance data of this class
1425 and all parent classes. This is SOMObject so we have no parents. */
1426 /*
1427 FIXME:
1428 The following is not yet initialized (and the previous may be buggy...) */
1429 // long dataAlignment;
1430 // long protectedDataOffset; /* from class's introduced data */
1431 // somDToken protectedDataToken;
1432 // somEmbeddedObjStruct *embeddedObjs;
1433
1434 sci->ccds->parentMtab=&sClass->parentMtabStruct; /* Insert pointer into CClassDataStructure */
1435
1436 /* Fill somParentMtabStruct in CClassDataStructure */
1437 sci->ccds->parentMtab->mtab=sClass->mtab; /* This class mtab */
1438 sci->ccds->parentMtab->next=NULL; /* We dont have parents because we are SOMObject */
1439 sci->ccds->parentMtab->classObject=somClass; /* SOMClass* Class object, this means ourself */
1440 sci->ccds->parentMtab->instanceSize=sClass->mtab->instanceSize;
1441 /* C Class data structure */
1442
1443 /* Thunking code see above. Adjust the offset to the instance data so the right
1444 variables are accessed. The offset is different depending on the number of parent
1445 classes (which isn't fix) and the number of parent instance vars (which isn't known
1446 at compile time) */
1447 sClass->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
1448 sci->ccds->instanceDataToken=&sClass->thunk;
1449
1450#ifdef DEBUG_BUILDSOMOBJECT
1451 somPrintf("New class ptr (temp. class object for SOMObject): %x (SOMClassPriv: %x) for %s\n",
1452 somClass, sClass, *sci->classId);
1453
1454 somPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
1455 _dumpClassDataStruct(sci->cds, sci->numStaticMethods);
1456#endif
1457#ifdef DEBUG_OBJECTS
1458 _dumpMTabListPrivClass(sClass);
1459#endif
1460
1461 /* SOMObject is special because it's root of normal classes and meta classes. Because of this it
1462 isn't insert into the normal private meta class list. We also use this info to check if SOMObject
1463 was already built in other places. */
1464 pGlobalSomEnv->scpSOMObject=sClass;
1465
1466 priv_addPrivClassToGlobalClassList(pGlobalSomEnv, sClass);
1467
1468#ifdef DEBUG_OBJECTS
1469 _dumpObj(somClass);
1470#endif
1471
1472 /*
1473 We don't run the somInit() method here because the SOMObject class isn't yet completely built.
1474 First a SOMClass meta class must be created because SOMObject needs a SOMClass as the class object like
1475 any other class. In case some code in somInit() tries to access the class object initialization would
1476 fail. In the function building the root SOMClass a metaclass for SOMObject will be created and attached.
1477
1478 Not running somInit() here shouldn't be a problem because we know what we are doing ;-).
1479 If there will ever be the need for special initialization for this very first SOMObject we think again...
1480
1481 In any case fiddling with somInit() in SOMObject and SOMClass is a dangerous thing because at least one of the
1482 two classes won't be completely built at that point in time (because SOMClass is a subclass of SOMObject
1483 and SOMObject needs a SOMClass as metaclass).
1484
1485 _somInit(somClass);
1486 */
1487 return somClass;
1488}
1489#endif
Note: See TracBrowser for help on using the repository browser.