source: trunk/nom/src/nombuildnomobj.c

Last change on this file was 331, checked in by cinc, 17 years ago

Fixed ticket #20. Not a perfect solution, though...

File size: 12.0 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2* Version: CDDL 1.0/LGPL 2.1
3*
4* The contents of this file are subject to the COMMON DEVELOPMENT AND
5* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6* this file except in compliance with the License. You may obtain a copy of
7* the License at http://www.sun.com/cddl/
8*
9* Software distributed under the License is distributed on an "AS IS" basis,
10* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11* for the specific language governing rights and limitations under the
12* License.
13*
14* The Original Code is "NOM" Netlabs Object Model
15*
16* The Initial Developer of the Original Code is
17* netlabs.org: Chris Wohlgemuth <cinc-ml@netlabs.org>.
18* Portions created by the Initial Developer are Copyright (C) 2005-2007
19* the Initial Developer. All Rights Reserved.
20*
21* Contributor(s):
22*
23* Alternatively, the contents of this file may be used under the terms of
24* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
25* case the provisions of the LGPL are applicable instead of those above. If
26* you wish to allow use of your version of this file only under the terms of
27* the LGPL, and not to allow others to use your version of this file under
28* the terms of the CDDL, indicate your decision by deleting the provisions
29* above and replace them with the notice and other provisions required by the
30* LGPL. If you do not delete the provisions above, a recipient may use your
31* version of this file under the terms of any one of the CDDL or the LGPL.
32*
33* ***** END LICENSE BLOCK ***** */
34
35#ifdef __OS2__
36# define INCL_DOS
37# define INCL_DOSERRORS
38# include <os2.h>
39#endif /* __OS2__ */
40
41#include <stdio.h>
42#include <string.h>
43#include <glib.h>
44#define SOM_NO_OBJECTS /* Otherwise som.h includes the IBM SOM classes */
45
46/* For nomToken etc. */
47#include <nom.h>
48#include <nomtk.h>
49#include <nomobj.h>
50#include <thunk.h>
51
52/********************************************************/
53
54/* Define if you want to have messages from building NOMObject */
55//#define DEBUG_BUILDNOMOBJECT
56
57/********************************************************/
58
59/********************************************************/
60
61extern PNOM_ENV pGlobalNomEnv;
62
63
64/********************************************************/
65
66
67/*
68 Create the NOMClassPriv structure *only* for NOMObject and fill it with info
69 from the sci.
70
71 This function does
72
73 -allocate the memory for the struct depending on the sci info
74 -creates the mtab in this memory
75 -fills all the necessary pointers in the mtab
76 -fills the method addresses in the mtab
77
78 It does not insert a class object pointer!
79
80 */
81static NOMClassPriv *buildNOMClassPrivStructForNOMObject(nomStaticClassInfo *sci)
82{
83
84 NOMClassPriv *nClass; /* This struct holds our private data. A pointer will be in mtab->nomClsInfo */
85
86 gulong mtabSize;
87 gulong ulMemSize=0;
88 guint8 * mem;
89 int a;
90
91 /* ulMemsize will be the size of our private class structure NOMClassPriv */
92 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct without the nomMethodTab
93 holding the method pointers. The size of this
94 nomMethodTab will be added later. */
95
96 /* Calculate the size of the method tab to be added to the size of the private class struct */
97 mtabSize=sizeof(nomMethodTab)+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods);/* ulNumStaticMethods is correct here! NOT
98 ulNumStaticMethods-1! entries[0] in fact
99 contains the class pointer not a method
100 pointer. */
101 ulMemSize+=mtabSize; /* Add size of base mtab struct */
102
103 /* Alloc private class struct using NOMCalloc. */
104 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULL)
105 return NULL;
106
107
108 /* The size of each instance of this class. A SOM object has a method tab pointer
109 at the beginning followed by the instance variables. */
110 nClass->ulClassSize=sci->ulInstanceDataSize+sizeof(nomMethodTab*);
111 nClass->sci=sci; /* Save static class info for internal use */
112 nClass->ulPrivClassSize=ulMemSize; /* Internal housekeeping. Not needed by NOM methods */
113
114
115 /* Fill all the pointers to methodtable we need in the *private* structure */
116 nClass->mtab=(nomMethodTab*)&nClass->thisMtab; /* create the mtab pointer and store it */
117 nClass->mtabList.mtab= (nomMethodTab*)&nClass->thisMtab; /* thisMtab is the position where the mtab starts */
118 nClass->parentMtabStruct.mtab=(nomMethodTab*)&nClass->thisMtab;
119
120
121 /**********************************/
122 /* Fill methodtable mtab */
123 /**********************************/
124 nClass->mtab->mtabSize=mtabSize; /* This mtab is the same as the one used in the public NOMClass */
125 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass; /* Hold a pointer to the private data that is this NOMClassPriv */
126#ifndef _MSC_VER
127#warning !!!!! Change this when nomId is a GQuark !!!!!
128#endif
129 nClass->mtab->nomClassName=*sci->nomClassId;
130 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+sizeof(nomMethodTabPtr); /* sizeof(methodTabStruct*) + size of instance data of this class
131 and all parent classes. This is NOMObject so we have no parents. */
132
133 /* Get mem for method thunking code. This assembler code is needed so the indirect
134 jump to the methods from the object pointer which is known does work. For each class
135 an individual thunking code must be calculated because the number of instance
136 variables is not defined. */
137 if(0!=sci->ulNumStaticMethods){
138 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
139 if(!nClass->mThunk) {
140 NOMFree(nClass);
141 return NULL;
142 }
143 }
144
145 memcpy(nClass->thunk, thunk, sizeof(thunk)); /* Copy assembler thunking code for instance data */
146
147 /* Copy class data. This goes at the address of "nomMethodProc* entries[0]".
148 Entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
149 We don't use the static classDataStruct directly because subclasses will override the proc addresses. */
150 mem=(char*)&(nClass->mtab->entries[0]); /* Target address.entries[0] will contain the class pointer */
151 /* Add class struct of this class. This includes the proc adresses. */
152 if(sci->ulNumStaticMethods) {
153#ifdef DEBUG_BUILDNOMOBJECT
154 nomPrintf("copy: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct) to %x\n",
155 sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*),
156 sci->nomCds, mem);
157#endif
158 /* Copy classDataStruct with the resolved proc addresses */
159 memcpy( mem, sci->nomCds, sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*));
160 /* Now finally put the thunking in so the procedures are resolved correctly. */
161 for(a=0;a<sci->ulNumStaticMethods;a++) {
162 gulong ulOffset;
163
164 memcpy(&nClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy method thunking code template */
165 ulOffset=(gulong)((char*)(mem+sizeof(NOMClass*))-(char*)nClass->mtab); /* Skip priv class data pointer */
166 nClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(nomMethodProc*))<<8)+0xa2; /* Calculate offset for assembler code */
167#ifdef DEBUG_BUILDNOMOBJECT
168 nomPrintf(" %d: %d : Thunk offset: %d (0x%x) -> address will be: %x\n",
169 __LINE__, a, ulOffset, ulOffset, mem+ulOffset+a*sizeof(nomMethodProc*) );
170#endif
171 /* Put thunking code address into CClassStruct */
172 sci->nomCds->nomTokens[a]=(void*)&nClass->mThunk[a];
173 } /* for */
174 } /* if(ulNumStaticMethods) */
175 return nClass; /* This is not a NOMClass* but a NOMClassPriv* */
176}
177
178/*
179 Create a NOMClassPriv (which will be put into the classInfo of the mtab) for
180 NOMObject. This contains an mtab which is completely built but without
181 a pointer to the class object. This pointer will be inserted later when we have
182 a NOMClass.
183
184 !!! This function is only called once for building NOMObject !!!
185 */
186NOMClassPriv * NOMLINK priv_buildNOMObjectClassInfo(gulong ulReserved,
187 nomStaticClassInfo *sci,
188 gulong majorVersion,
189 gulong minorVersion)
190{
191 NOMClassPriv *nClassPriv; /* This struct holds our private data. A pointer will be in mtab->nomClsInfo */
192 gulong ulParentDataSize=0;
193
194#ifdef DEBUG_BUILDNOMOBJECT
195 nomPrintf("%d: Entering %s to build the NOMClassPriv for NOMObjects\n", __LINE__, __FUNCTION__);
196 _dumpSci(sci);
197#endif
198
199 /* Note: NOMObject has no parents */
200 if((nClassPriv=buildNOMClassPrivStructForNOMObject(sci))==NULL)
201 return NULL;
202
203#ifdef DEBUG_BUILDNOMOBJECT
204 nomPrintf("mtab: %x nClassPriv: %x\n", nClassPriv->mtab, nClassPriv);
205#endif
206
207 sci->ccds->parentMtab=&nClassPriv->parentMtabStruct; /* Insert pointer into CClassDataStructure */
208 /* Fill somParentMtabStruct in CClassDataStructure */
209 sci->ccds->parentMtab->mtab=nClassPriv->mtab; /* This class mtab */
210 sci->ccds->parentMtab->next=NULL; /* We dont have parents because we are NOMObject */
211 sci->ccds->parentMtab->nomClassObject=NULL; /* NOMClass* Class object. We don't have one yet */
212 sci->ccds->parentMtab->ulInstanceSize=nClassPriv->mtab->ulInstanceSize;
213 /* C Class data structure */
214
215 /* Thunking code see above. Adjust the offset to the instance data so the right
216 variables are accessed. The offset is different depending on the number of parent
217 classes (which isn't fix) and the number of parent instance vars (which isn't known
218 at compile time) */
219 nClassPriv->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
220 sci->ccds->instanceDataToken=&nClassPriv->thunk;
221
222
223#ifdef DEBUG_BUILDNOMOBJECT
224 nomPrintf("No class ptr (temp. class object for NOMObject) yet. (NOMClassPriv: %x) for %s\n",
225 nClassPriv, *sci->nomClassId);
226 nomPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
227 _dumpClassDataStruct(sci->nomCds, sci->ulNumStaticMethods);
228#endif
229
230
231 /* NOMObject is special because it's root of normal classes and meta classes. Because of this it
232 cannot be insert into the class list yet. We have to wait until NOMClass was built.
233 We also use this info to check if NOMObject was already built in other places. */
234 pGlobalNomEnv->ncpNOMObject=nClassPriv;
235
236 //priv_addPrivClassToGlobalClassList(pGlobalNomEnv, nClassPriv);
237
238 /*
239 FIXME: This explanantion isn't correct anymore
240
241 We don't run the somInit() method here because the SOMObject class isn't yet completely built.
242 First a SOMClass meta class must be created because SOMObject needs a SOMClass as the class object like
243 any other class. In case some code in somInit() tries to access the class object initialization would
244 fail. In the function building the root SOMClass a metaclass for SOMObject will be created and attached.
245
246 Not running somInit() here shouldn't be a problem because we know what we are doing ;-).
247 If there will ever be the need for special initialization for this very first SOMObject we think again...
248
249 In any case fiddling with somInit() in SOMObject and SOMClass is a dangerous thing because at least one of the
250 two classes won't be completely built at that point in time (because SOMClass is a subclass of SOMObject
251 and SOMObject needs a SOMClass as metaclass).
252
253 _somInit(somClass);
254 */
255
256 /* Run initialization code if any */
257 _nomInit((NOMObject*)nClassPriv, NULL);
258 return NULL;
259}
260
261
262
263
Note: See TracBrowser for help on using the repository browser.