source: trunk/nom/src/nombuildnomobj.c@ 221

Last change on this file since 221 was 221, checked in by cinc, 18 years ago

Changes...

File size: 12.5 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 <stdio.h>
40#include <string.h>
41#include <glib.h>
42#define SOM_NO_OBJECTS /* Otherwise som.h includes the IBM SOM classes */
43
44/* For nomToken etc. */
45#include <nom.h>
46#include <nomtk.h>
47#include <nomobj.h>
48
49/********************************************************/
50
51/* Define if you want to have messages from building NOMObject */
52//#define DEBUG_BUILDNOMOBJECT
53
54/********************************************************/
55
56/********************************************************/
57
58extern PNOM_ENV pGlobalNomEnv;
59
60/*
61 Thunking code to get the instance var address from an object pointer pushed
62 on the stack. The following translates into this assembler code:
63
64 MOV EAX,DWORD PTR [ESP+4] ;Move object ptr into EAX
65 ADD EAX, +4
66 RET
67*/
68
69static ULONG thunk[]={0x0424448b, 0x00000405, 0x0000c300};
70
71/*
72MOV ECX,DWORD PTR [ESP+4] : move object pointer from stack in ECX
73MOV EDX,DWORD PTR [ECX] : move [ECX] in EDX -> mtab in EDX
74JMP DWORD PTR [EDX+0ACh] : JMP to address pointing to by EDX+0ACh
75 */
76static ULONG mThunkCode[]={0x04244c8b, 0xff00518b, 0x0000aca2 , 0x16000000};
77
78/********************************************************/
79
80
81/*
82 Create the SOMClassPriv structure *only* for SOMObject and fill it with info
83 from the sci.
84
85 This function does
86
87 -allocate the memory for the struct depending on the sci info
88 -creates the mtab in this memory
89 -fills all the necessary pointers in the mtab
90 -fills the method addresses in the mtab
91
92 It does not insert a class object pointer!
93
94 */
95static NOMClassPriv *buildNOMClassPrivStructForNOMObject(nomStaticClassInfo *sci)
96{
97
98 NOMClassPriv *nClass; /* This struct holds our private data. A pointer will be in mtab->nomClsInfo */
99
100 gulong mtabSize;
101 gulong ulMemSize=0;
102 BYTE * mem;
103 int a;
104
105 /* ulMemsize will be the size of our private class structure NOMClassPriv */
106 ulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct without the nomMethodTab
107 holding the method pointers. The size of this
108 nomMethodTab will be added later. */
109
110 /* Calculate the size of the method tab to be added to the size of the private class struct */
111 mtabSize=sizeof(nomMethodTab)+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods);/* ulNumStaticMethods is correct here! NOT
112 ulNumStaticMethods-1! entries[0] in fact
113 contains the class pointer not a method
114 pointer. */
115 ulMemSize+=mtabSize; /* Add size of base mtab struct */
116
117 /* Alloc private class struct using NOMCalloc. */
118 if((nClass=(NOMClassPriv*)NOMCalloc(1, ulMemSize))==NULLHANDLE)
119 return NULLHANDLE;
120
121
122 /* The size of each instance of this class. A SOM object has a method tab pointer
123 at the beginning followed by the instance variables. */
124 nClass->ulClassSize=sci->ulInstanceDataSize+sizeof(nomMethodTab*);
125 nClass->sci=sci; /* Save static class info for internal use */
126 nClass->ulPrivClassSize=ulMemSize; /* Internal housekeeping. Not needed by NOM methods */
127
128
129 /* Fill all the pointers to methodtable we need in the *private* structure */
130 nClass->mtab=(nomMethodTab*)&nClass->thisMtab; /* create the mtab pointer and store it */
131 nClass->mtabList.mtab= (nomMethodTab*)&nClass->thisMtab; /* thisMtab is the position where the mtab starts */
132 nClass->parentMtabStruct.mtab=(nomMethodTab*)&nClass->thisMtab;
133
134
135 /**********************************/
136 /* Fill methodtable mtab */
137 /**********************************/
138 nClass->mtab->mtabSize=mtabSize; /* This mtab is the same as the one used in the public NOMClass */
139 nClass->mtab->nomClsInfo=(nomClassInfo*)nClass; /* Hold a pointer to the private data that is this NOMClassPriv */
140#warning !!!!! Change this when nomId is a GQuark !!!!!
141 nClass->mtab->nomClassName=*sci->nomClassId;
142 nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+sizeof(nomMethodTabPtr); /* sizeof(methodTabStruct*) + size of instance data of this class
143 and all parent classes. This is NOMObject so we have no parents. */
144
145 /* Get mem for method thunking code. This assembler code is needed so the indirect
146 jump to the methods from the object pointer which is known does work. For each class
147 an individual thunking code must be calculated because the number of instance
148 variables is not defined. */
149 if(0!=sci->ulNumStaticMethods){
150 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
151 if(!nClass->mThunk) {
152 NOMFree(nClass);
153 return NULLHANDLE;
154 }
155 }
156
157 memcpy(nClass->thunk, thunk, sizeof(thunk)); /* Copy assembler thunking code for instance data */
158
159 /* Copy class data. This goes at the address of "nomMethodProc* entries[0]".
160 Entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
161 We don't use the static classDataStruct directly because subclasses will override the proc addresses. */
162 mem=(char*)&(nClass->mtab->entries[0]); /* Target address.entries[0] will contain the class pointer */
163 /* Add class struct of this class. This includes the proc adresses. */
164 if(sci->ulNumStaticMethods) {
165#ifdef DEBUG_BUILDNOMOBJECT
166 nomPrintf("copy: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct) to %x\n",
167 sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*),
168 sci->nomCds, mem);
169#endif
170 /* Copy classDataStruct with the resolved proc addresses */
171 memcpy( mem, sci->nomCds, sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*));
172 /* Now finally put the thunking in so the procedures are resolved correctly. */
173 for(a=0;a<sci->ulNumStaticMethods;a++) {
174 ULONG ulOffset;
175
176 memcpy(&nClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy method thunking code template */
177 ulOffset=(ULONG)((char*)(mem+sizeof(NOMClass*))-(char*)nClass->mtab); /* Skip priv class data pointer */
178 nClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(nomMethodProc*))<<8)+0xa2; /* Calculate offset for assembler code */
179#ifdef DEBUG_BUILDNOMOBJECT
180 nomPrintf(" %d: %d : Thunk offset: %d (0x%x) -> address will be: %x\n",
181 __LINE__, a, ulOffset, ulOffset, mem+ulOffset+a*sizeof(nomMethodProc*) );
182#endif
183 /* Put thunking code address into CClassStruct */
184 sci->nomCds->nomTokens[a]=(void*)&nClass->mThunk[a];
185 } /* for */
186 } /* if(ulNumStaticMethods) */
187 return nClass; /* This is not a NOMClass* but a NOMClassPriv* */
188}
189
190/*
191 Create a NOMClassPriv (which will be put into the classInfo of the mtab) for
192 NOMObject. This contains an mtab which is completely built but without
193 a pointer to the class object. This pointer will be inserted later when we have
194 a NOMClass.
195
196 !!! This function is only called once for building NOMObject !!!
197 */
198NOMClassPriv * NOMLINK priv_buildNOMObjectClassInfo(gulong ulReserved,
199 nomStaticClassInfo *sci,
200 gulong majorVersion,
201 gulong minorVersion)
202{
203 NOMClassPriv *nClassPriv; /* This struct holds our private data. A pointer will be in mtab->nomClsInfo */
204 ULONG ulParentDataSize=0;
205
206#ifdef DEBUG_BUILDNOMOBJECT
207 nomPrintf("%d: Entering %s to build the NOMClassPriv for NOMObjects\n", __LINE__, __FUNCTION__);
208 _dumpSci(sci);
209#endif
210
211 /* Note: NOMObject has no parents */
212 if((nClassPriv=buildNOMClassPrivStructForNOMObject(sci))==NULLHANDLE)
213 return NULLHANDLE;
214
215#ifdef DEBUG_BUILDNOMOBJECT
216 nomPrintf("mtab: %x nClassPriv: %x\n", nClassPriv->mtab, nClassPriv);
217#endif
218
219 sci->ccds->parentMtab=&nClassPriv->parentMtabStruct; /* Insert pointer into CClassDataStructure */
220 /* Fill somParentMtabStruct in CClassDataStructure */
221 sci->ccds->parentMtab->mtab=nClassPriv->mtab; /* This class mtab */
222 sci->ccds->parentMtab->next=NULL; /* We dont have parents because we are NOMObject */
223 sci->ccds->parentMtab->nomClassObject=NULLHANDLE; /* NOMClass* Class object. We don't have one yet */
224 sci->ccds->parentMtab->ulInstanceSize=nClassPriv->mtab->ulInstanceSize;
225 /* C Class data structure */
226
227 /* Thunking code see above. Adjust the offset to the instance data so the right
228 variables are accessed. The offset is different depending on the number of parent
229 classes (which isn't fix) and the number of parent instance vars (which isn't known
230 at compile time) */
231 nClassPriv->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
232 sci->ccds->instanceDataToken=&nClassPriv->thunk;
233
234
235#ifdef DEBUG_BUILDNOMOBJECT
236 nomPrintf("No class ptr (temp. class object for NOMObject) yet. (NOMClassPriv: %x) for %s\n",
237 nClassPriv, *sci->nomClassId);
238 nomPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
239 _dumpClassDataStruct(sci->nomCds, sci->ulNumStaticMethods);
240#endif
241
242
243 /* NOMObject is special because it's root of normal classes and meta classes. Because of this it
244 cannot be insert into the class list yet. We have to wait until NOMClass was built.
245 We also use this info to check if NOMObject was already built in other places. */
246 pGlobalNomEnv->ncpNOMObject=nClassPriv;
247
248 //priv_addPrivClassToGlobalClassList(pGlobalNomEnv, nClassPriv);
249
250 /*
251 FIXME: This explanantion isn't correct anymore
252
253 We don't run the somInit() method here because the SOMObject class isn't yet completely built.
254 First a SOMClass meta class must be created because SOMObject needs a SOMClass as the class object like
255 any other class. In case some code in somInit() tries to access the class object initialization would
256 fail. In the function building the root SOMClass a metaclass for SOMObject will be created and attached.
257
258 Not running somInit() here shouldn't be a problem because we know what we are doing ;-).
259 If there will ever be the need for special initialization for this very first SOMObject we think again...
260
261 In any case fiddling with somInit() in SOMObject and SOMClass is a dangerous thing because at least one of the
262 two classes won't be completely built at that point in time (because SOMClass is a subclass of SOMObject
263 and SOMObject needs a SOMClass as metaclass).
264
265 _somInit(somClass);
266 */
267
268 /* Run initialization code if any */
269 _nomInit((NOMObject*)nClassPriv, NULLHANDLE);
270 return NULLHANDLE;
271}
272
273
274
275
Note: See TracBrowser for help on using the repository browser.