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

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

Only use GLib types.

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 nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods);
150 if(!nClass->mThunk) {
151 NOMFree(nClass);
152 return NULLHANDLE;
153 }
154
155 memcpy(nClass->thunk, thunk, sizeof(thunk)); /* Copy assembler thunking code for instance data */
156
157 /* Copy class data. This goes at the address of "nomMethodProc* entries[0]".
158 Entries[] contain copies of the ClassDataStruct and thus the proc addresses of the static methods.
159 We don't use the static classDataStruct directly because subclasses will override the proc addresses. */
160 mem=(char*)&(nClass->mtab->entries[0]); /* Target address.entries[0] will contain the class pointer */
161 /* Add class struct of this class. This includes the proc adresses. */
162 if(sci->ulNumStaticMethods) {
163#ifdef DEBUG_BUILDNOMOBJECT
164 nomPrintf("copy: %d (classptr+numProcs*procpointersize) from %x (cds, classDataStruct) to %x\n",
165 sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*),
166 sci->nomCds, mem);
167#endif
168 /* Copy classDataStruct with the resolved proc addresses */
169 memcpy( mem, sci->nomCds, sizeof(NOMClass*)+sci->ulNumStaticMethods*sizeof(nomMethodProc*));
170 /* Now finally put the thunking in so the procedures are resolved correctly. */
171 for(a=0;a<sci->ulNumStaticMethods;a++) {
172 ULONG ulOffset;
173
174 memcpy(&nClass->mThunk[a], mThunkCode, sizeof(mThunkCode)); /* Copy method thunking code template */
175 ulOffset=(ULONG)((char*)(mem+sizeof(NOMClass*))-(char*)nClass->mtab); /* Skip priv class data pointer */
176 nClass->mThunk[a].thunk[2]=((ulOffset+a*sizeof(nomMethodProc*))<<8)+0xa2; /* Calculate offset for assembler code */
177#ifdef DEBUG_BUILDNOMOBJECT
178 nomPrintf(" %d: %d : Thunk offset: %d (0x%x) -> address will be: %x\n",
179 __LINE__, a, ulOffset, ulOffset, mem+ulOffset+a*sizeof(nomMethodProc*) );
180#endif
181 /* Put thunking code address into CClassStruct */
182 sci->nomCds->nomTokens[a]=(void*)&nClass->mThunk[a];
183 } /* for */
184 } /* if(ulNumStaticMethods) */
185 return nClass; /* This is not a NOMClass* but a NOMClassPriv* */
186}
187
188/*
189 Create a NOMClassPriv (which will be put into the classInfo of the mtab) for
190 NOMObject. This contains an mtab which is completely built but without
191 a pointer to the class object. This pointer will be inserted later when we have
192 a NOMClass.
193
194 !!! This function is only called once for building NOMObject !!!
195 */
196NOMClassPriv * NOMLINK priv_buildNOMObjectClassInfo(gulong ulReserved,
197 nomStaticClassInfo *sci,
198 gulong majorVersion,
199 gulong minorVersion)
200{
201 NOMClassPriv *nClassPriv; /* This struct holds our private data. A pointer will be in mtab->nomClsInfo */
202 ULONG ulParentDataSize=0;
203
204#ifdef DEBUG_BUILDNOMOBJECT
205 nomPrintf("%d: Entering %s to build the NOMClassPriv for NOMObjects\n", __LINE__, __FUNCTION__);
206 _dumpSci(sci);
207#endif
208
209 /* Note: NOMObject has no parents */
210 if((nClassPriv=buildNOMClassPrivStructForNOMObject(sci))==NULLHANDLE)
211 return NULLHANDLE;
212
213#ifdef DEBUG_BUILDNOMOBJECT
214 nomPrintf("mtab: %x nClassPriv: %x\n", nClassPriv->mtab, nClassPriv);
215#endif
216
217 sci->ccds->parentMtab=&nClassPriv->parentMtabStruct; /* Insert pointer into CClassDataStructure */
218 /* Fill somParentMtabStruct in CClassDataStructure */
219 sci->ccds->parentMtab->mtab=nClassPriv->mtab; /* This class mtab */
220 sci->ccds->parentMtab->next=NULL; /* We dont have parents because we are NOMObject */
221 sci->ccds->parentMtab->nomClassObject=NULLHANDLE; /* NOMClass* Class object. We don't have one yet */
222 sci->ccds->parentMtab->ulInstanceSize=nClassPriv->mtab->ulInstanceSize;
223 /* C Class data structure */
224
225 /* Thunking code see above. Adjust the offset to the instance data so the right
226 variables are accessed. The offset is different depending on the number of parent
227 classes (which isn't fix) and the number of parent instance vars (which isn't known
228 at compile time) */
229 nClassPriv->thunk[1]=(ulParentDataSize<<8)+0x05; //0x00000405
230 sci->ccds->instanceDataToken=&nClassPriv->thunk;
231
232
233#ifdef DEBUG_BUILDNOMOBJECT
234 nomPrintf("No class ptr (temp. class object for NOMObject) yet. (NOMClassPriv: %x) for %s\n",
235 nClassPriv, *sci->nomClassId);
236 nomPrintf("%d: Dumping the filled classdata structure:\n", __LINE__);
237 _dumpClassDataStruct(sci->nomCds, sci->ulNumStaticMethods);
238#endif
239
240
241 /* NOMObject is special because it's root of normal classes and meta classes. Because of this it
242 cannot be insert into the class list yet. We have to wait until NOMClass was built.
243 We also use this info to check if NOMObject was already built in other places. */
244 pGlobalNomEnv->ncpNOMObject=nClassPriv;
245
246 //priv_addPrivClassToGlobalClassList(pGlobalNomEnv, nClassPriv);
247
248 /*
249 FIXME: This explanantion isn't correct anymore
250
251 We don't run the somInit() method here because the SOMObject class isn't yet completely built.
252 First a SOMClass meta class must be created because SOMObject needs a SOMClass as the class object like
253 any other class. In case some code in somInit() tries to access the class object initialization would
254 fail. In the function building the root SOMClass a metaclass for SOMObject will be created and attached.
255
256 Not running somInit() here shouldn't be a problem because we know what we are doing ;-).
257 If there will ever be the need for special initialization for this very first SOMObject we think again...
258
259 In any case fiddling with somInit() in SOMObject and SOMClass is a dangerous thing because at least one of the
260 two classes won't be completely built at that point in time (because SOMClass is a subclass of SOMObject
261 and SOMObject needs a SOMClass as metaclass).
262
263 _somInit(somClass);
264 */
265
266 /* Run initialization code if any */
267 _nomInit((NOMObject*)nClassPriv, NULLHANDLE);
268 return NULLHANDLE;
269}
270
271
272
273
Note: See TracBrowser for help on using the repository browser.