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

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

Portability patches for Windows, Linux, Darwin by Bird.

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