| 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 |  | 
|---|
| 41 | #include <glib.h> | 
|---|
| 42 | #define SOM_NO_OBJECTS  /* Otherwise som.h includes the IBM SOM classes */ | 
|---|
| 43 |  | 
|---|
| 44 | /* For somToken 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 somBuildClass() and friends */ | 
|---|
| 52 | //#define DEBUG_NOMBUILDCLASS | 
|---|
| 53 | /* Define if you want to have messages from building NOMObject */ | 
|---|
| 54 | //#define DEBUG_BUILDNOMOBJECT | 
|---|
| 55 | /* Define if you want to have messages from building NOMClass */ | 
|---|
| 56 | //#define DEBUG_BUILDNOMCLASS | 
|---|
| 57 |  | 
|---|
| 58 | #ifdef DEBUG_BUILDNOMCLASS | 
|---|
| 59 | #define BUILDNOMCLASS_ENTER nomPrintf("\n%d: *** entering %s...\n",__LINE__,  __FUNCTION__); | 
|---|
| 60 | #define BUILDNOMCLASS_LEAVE nomPrintf("%d: *** Leaving %s...\n\n",__LINE__,  __FUNCTION__); | 
|---|
| 61 | #else | 
|---|
| 62 | #define BUILDNOMCLASS_ENTER | 
|---|
| 63 | #define BUILDNOMCLASS_LEAVE | 
|---|
| 64 | #endif | 
|---|
| 65 |  | 
|---|
| 66 | /********************************************************/ | 
|---|
| 67 |  | 
|---|
| 68 | /********************************************************/ | 
|---|
| 69 |  | 
|---|
| 70 | extern PNOM_ENV pGlobalNomEnv; | 
|---|
| 71 | extern ULONG thunk[]; | 
|---|
| 72 | extern ULONG mThunkCode[]; | 
|---|
| 73 |  | 
|---|
| 74 | /********************************************************/ | 
|---|
| 75 |  | 
|---|
| 76 | /* | 
|---|
| 77 | Create the SOMClassPriv structure and fill it with info | 
|---|
| 78 | from the sci. This is a general function when building classes. | 
|---|
| 79 |  | 
|---|
| 80 | This function does | 
|---|
| 81 |  | 
|---|
| 82 | -allocate the memory for the struct depending on the sci info | 
|---|
| 83 | -creates the mtab in this memory | 
|---|
| 84 | -fills all the necessary pointers in the mtab | 
|---|
| 85 | -fills the method addresses in the mtab | 
|---|
| 86 |  | 
|---|
| 87 | It does not insert a class object pointer! | 
|---|
| 88 |  | 
|---|
| 89 | */ | 
|---|
| 90 | static NOMClassPriv *buildNOMClassPrivStruct(nomStaticClassInfo *sci, NOMClassPriv *ncpParent) | 
|---|
| 91 | { | 
|---|
| 92 | gulong gulParentDataSize=0; | 
|---|
| 93 | gulong mtabSize; | 
|---|
| 94 | gulong gulMemSize=0; | 
|---|
| 95 | NOMClassPriv *nClass; | 
|---|
| 96 |  | 
|---|
| 97 | BUILDNOMCLASS_ENTER | 
|---|
| 98 |  | 
|---|
| 99 | /* ulMemsize will be the size of our private class structure SOMClassPriv */ | 
|---|
| 100 | gulMemSize=sizeof(NOMClassPriv)-sizeof(nomMethodTab); /* start size class struct. somMethodTab will be calculated later */ | 
|---|
| 101 |  | 
|---|
| 102 | /* Calculate size of new class object */ | 
|---|
| 103 | #ifdef DEBUG_BUILDNOMCLASS | 
|---|
| 104 | nomPrintf("%d: ncParent->mtab->mtabSize: %d\n", __LINE__, ncpParent->mtab->mtabSize); | 
|---|
| 105 | #endif | 
|---|
| 106 |  | 
|---|
| 107 | mtabSize=ncpParent->mtab->mtabSize+sizeof(nomMethodProc*)*(sci->ulNumStaticMethods)+sizeof(NOMClass*);/* numStaticMethods is correct here! | 
|---|
| 108 | NOT numStaticMethods-1! | 
|---|
| 109 | entries[0] in fact contains the | 
|---|
| 110 | class pointer not a method | 
|---|
| 111 | pointer. */ | 
|---|
| 112 | gulMemSize+=mtabSize; /* add space for new procs and the new class pointer in addition to parent stuff */ | 
|---|
| 113 |  | 
|---|
| 114 | gulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size. This is the mtab pointer + instance vars */ | 
|---|
| 115 |  | 
|---|
| 116 | #ifdef DEBUG_BUILDNOMCLASS | 
|---|
| 117 | nomPrintf("%d: mtabSize is: %d, ulParentDataSize is: %d (instance vars + mtab ptr)\n", | 
|---|
| 118 | __LINE__, mtabSize, gulParentDataSize); | 
|---|
| 119 | nomPrintf("%d: sci->numStaticMethods: %d\n", __LINE__, sci->ulNumStaticMethods); | 
|---|
| 120 | #endif | 
|---|
| 121 |  | 
|---|
| 122 | /* Alloc private class struct using SOMCalloc. */ | 
|---|
| 123 | if((nClass=(NOMClassPriv*)NOMCalloc(1, gulMemSize))==NULLHANDLE) | 
|---|
| 124 | return NULLHANDLE; | 
|---|
| 125 |  | 
|---|
| 126 | /* Get mem for method thunking code */ | 
|---|
| 127 | nClass->mThunk=NOMMalloc(sizeof(nomMethodThunk)*sci->ulNumStaticMethods); | 
|---|
| 128 | if(!nClass->mThunk) { | 
|---|
| 129 | NOMFree(nClass); | 
|---|
| 130 | return NULLHANDLE; | 
|---|
| 131 | } | 
|---|
| 132 |  | 
|---|
| 133 | /* The size of each instance of this class. A NOM object has a method tab pointer | 
|---|
| 134 | at the beginning followed by the instance variables. */ | 
|---|
| 135 | nClass->ulClassSize=sci->ulInstanceDataSize+gulParentDataSize; | 
|---|
| 136 | nClass->ulPrivClassSize=gulMemSize; /* This will not be seen by any user */ | 
|---|
| 137 |  | 
|---|
| 138 | /* Add class struct of this class and the parent one. | 
|---|
| 139 | This includes resolving the method adresses of our new class | 
|---|
| 140 | (parent ones are already resolved) including adding the thunking | 
|---|
| 141 | code . This is essentially done by just copying the parents | 
|---|
| 142 | mtab-entries[] to our new one before adding our own methods. | 
|---|
| 143 | sci will be saved in nClass->sci */ | 
|---|
| 144 | #warning !!!!! Move mem alloc for thunking into this func !!!!! | 
|---|
| 145 | addMethodAndDataToThisPrivClassStruct( nClass, ncpParent, sci); | 
|---|
| 146 |  | 
|---|
| 147 | /**********************************/ | 
|---|
| 148 | /*     Fill methodtable mtab      */ | 
|---|
| 149 | /**********************************/ | 
|---|
| 150 | nClass->mtab->mtabSize=mtabSize; | 
|---|
| 151 | nClass->mtab->nomClsInfo=(nomClassInfo*)nClass;  /* Hold a pointer to the private data that is this NOMClassPriv */ | 
|---|
| 152 | #warning !!!!! Change this when nomId is a GQuark !!!!! | 
|---|
| 153 | nClass->mtab->nomClassName=*sci->nomClassId; | 
|---|
| 154 | nClass->mtab->ulInstanceSize=sci->ulInstanceDataSize+gulParentDataSize; /* Size of instance data of this class and all | 
|---|
| 155 | parent classes + size of mtab pointer. */ | 
|---|
| 156 |  | 
|---|
| 157 | //#warning !!!!!!!!! No overrride methods yet!! | 
|---|
| 158 | /* Resolve ovverrides if any */ | 
|---|
| 159 | priv_resolveOverrideMethods(nClass, sci); | 
|---|
| 160 |  | 
|---|
| 161 | BUILDNOMCLASS_LEAVE | 
|---|
| 162 | return nClass; | 
|---|
| 163 | } | 
|---|
| 164 |  | 
|---|
| 165 |  | 
|---|
| 166 | /* | 
|---|
| 167 | Build NOMClass. This function will only called once when bootstrapping the object system. | 
|---|
| 168 |  | 
|---|
| 169 | NOMClass the root of all Meta classes. This will also become the meta class of NOMObject, we | 
|---|
| 170 | already created. This is done by updating NOMObject when all the structures for NOMClass | 
|---|
| 171 | are created and filled with info. | 
|---|
| 172 | */ | 
|---|
| 173 | NOMClass * NOMLINK priv_buildNOMClass(gulong ulReserved, | 
|---|
| 174 | nomStaticClassInfo *sci, | 
|---|
| 175 | gulong majorVersion, | 
|---|
| 176 | gulong minorVersion) | 
|---|
| 177 | { | 
|---|
| 178 | NOMClassPriv *nClass; | 
|---|
| 179 | NOM_ulong ulParentDataSize=0; | 
|---|
| 180 | NOMClassPriv *ncpParent; | 
|---|
| 181 | NOMClass *nomClass; | 
|---|
| 182 |  | 
|---|
| 183 | #ifdef DEBUG_BUILDNOMCLASS | 
|---|
| 184 | nomParentMtabStructPtr pParentMtab; | 
|---|
| 185 | nomMethodTabs psmTab; | 
|---|
| 186 | nomPrintf("\n%d: Entering %s\n", __LINE__, __FUNCTION__); | 
|---|
| 187 | _dumpSci(sci); | 
|---|
| 188 | #endif | 
|---|
| 189 |  | 
|---|
| 190 | /* We don't support replacing NOMObject so we don't have to search | 
|---|
| 191 | the class list for the current parent but just take the NOMClassPriv | 
|---|
| 192 | pointer of NOMObject we saved in the NOM env. Be aware that this structure | 
|---|
| 193 | doesn't have a class object pointer yet. We won't use it but just | 
|---|
| 194 | as a remark if you want to screw this code... */ | 
|---|
| 195 | if(pGlobalNomEnv->ncpNOMObject) | 
|---|
| 196 | ncpParent=pGlobalNomEnv->ncpNOMObject; | 
|---|
| 197 | else{ | 
|---|
| 198 | g_error("No NOMObject while trying to build NOMClass."); /* This will result in a termination of the app! */ | 
|---|
| 199 | return NULLHANDLE;                                       /* NOMClass *must* have an object as parent! | 
|---|
| 200 | We won't reach this point */ | 
|---|
| 201 | } | 
|---|
| 202 |  | 
|---|
| 203 | #ifdef DEBUG_BUILDNOMCLASS | 
|---|
| 204 | pParentMtab=&ncpParent->parentMtabStruct; | 
|---|
| 205 | nomPrintf("    %d:  parent priv class: %s (%x), pParentMtab->mtab %x, next: %x\n", | 
|---|
| 206 | __LINE__, ncpParent->mtab->nomClassName, | 
|---|
| 207 | ncpParent, pParentMtab->mtab, pParentMtab->next); | 
|---|
| 208 | /* climb parent list */ | 
|---|
| 209 | psmTab=pParentMtab->next; | 
|---|
| 210 | while(psmTab) { | 
|---|
| 211 | nomPrintf("     next class: %s\n", psmTab->mtab->nomClassName); | 
|---|
| 212 | psmTab=psmTab->next; | 
|---|
| 213 | } | 
|---|
| 214 | #endif | 
|---|
| 215 |  | 
|---|
| 216 | /* Build the NOMClassPriv for NOMClass */ | 
|---|
| 217 | if((nClass=buildNOMClassPrivStruct(sci, ncpParent))==NULLHANDLE) | 
|---|
| 218 | return NULLHANDLE; | 
|---|
| 219 |  | 
|---|
| 220 | ulParentDataSize=ncpParent->mtab->ulInstanceSize; /* Parent instance size. This is the mtab pointer + instance vars */ | 
|---|
| 221 | //nomPrintf("%s line %d: SOMClassPriv: %x    ulParentDataSize  %d\n", __FILE__, __LINE__, nClass, sci->ulInstanceDataSize+ulParentDataSize); | 
|---|
| 222 |  | 
|---|
| 223 | /* And now the NOMClass struct. A NOMClass has a mTab pointer at the beginning and the instance data | 
|---|
| 224 | following (including the parent instance data).*/ | 
|---|
| 225 | if((nomClass=(NOMClass*)NOMCalloc(1, sci->ulInstanceDataSize+ulParentDataSize))==NULLHANDLE) { | 
|---|
| 226 | NOMFree(nClass->mThunk); | 
|---|
| 227 | NOMFree(nClass); | 
|---|
| 228 | return NULLHANDLE; | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | nomClass->mtab=nClass->mtab; /* Now it's an object */ | 
|---|
| 232 |  | 
|---|
| 233 | nClass->mtab->nomClassObject=nomClass; | 
|---|
| 234 | sci->nomCds->nomClassObject=nomClass; /* Put class pointer in static struct. Meta class of SOMClass is SOMClass */ | 
|---|
| 235 | *nClass->entries0=nomClass; | 
|---|
| 236 | /* Mark that we are a metaclass */ | 
|---|
| 237 | nClass->ulIsMetaClass=1; | 
|---|
| 238 |  | 
|---|
| 239 | fillCClassDataStructParentMtab(sci, nClass, nomClass); | 
|---|
| 240 |  | 
|---|
| 241 |  | 
|---|
| 242 | /* | 
|---|
| 243 | Note: | 
|---|
| 244 |  | 
|---|
| 245 | SOMClass is almost ready now. What's missing is the class object for SOMObject (which is SOMClass | 
|---|
| 246 | derived from). The class object pointer must be found in mtab->entries[0]. We have to create | 
|---|
| 247 | a class object for SOMObject now, update it properly put the pointer into our mtab and update | 
|---|
| 248 | the already built SOMObject. | 
|---|
| 249 | */ | 
|---|
| 250 |  | 
|---|
| 251 |  | 
|---|
| 252 | /* The NOMClass is built. Insert it as meta class into the NOMObject class. | 
|---|
| 253 | The instance vars must be properly setup otherwise this object won't be | 
|---|
| 254 | able to create instances. Put it as the class object into the static | 
|---|
| 255 | class data sturcture of NOMObject. Update the mtab of our just built | 
|---|
| 256 | SOMClass. */ | 
|---|
| 257 | nomClass->mtab->entries[0]= | 
|---|
| 258 | (nomMethodProc*) createNOMObjectClassObjectAndUpdateNOMObject(nomClass, nClass, | 
|---|
| 259 | sci->ulInstanceDataSize+ulParentDataSize); | 
|---|
| 260 |  | 
|---|
| 261 | pGlobalNomEnv->nomObjectMetaClass=(NOMClass*)nomClass->mtab->entries[0]; | 
|---|
| 262 |  | 
|---|
| 263 | #ifdef DEBUG_BUILDNOMCLASS | 
|---|
| 264 | nomPrintf("%d: mtab: %x New class ptr (class object SOMClass): %x (SOMClassPriv: %x) for %s\n", | 
|---|
| 265 | __LINE__, nomClass->mtab, nomClass, nClass, *sci->nomClassId); | 
|---|
| 266 | #endif | 
|---|
| 267 |  | 
|---|
| 268 | pGlobalNomEnv->defaultMetaClass=nomClass; | 
|---|
| 269 |  | 
|---|
| 270 | #warning !!!!! _nomSetInstanceSize() not called !!!!! | 
|---|
| 271 | #if 0 | 
|---|
| 272 | /* Set this class size into instance var */ | 
|---|
| 273 | _somSetInstanceSize(somClass, sClass->ulClassSize /* sci->instanceDataSize+ulParentDataSize*/ ); /* This includes exactly one mtab pointer */ | 
|---|
| 274 | #endif | 
|---|
| 275 |  | 
|---|
| 276 |  | 
|---|
| 277 | /* Run initialization code if any */ | 
|---|
| 278 | _nomInit(nomClass, NULLHANDLE); | 
|---|
| 279 | return nomClass; | 
|---|
| 280 | } | 
|---|
| 281 |  | 
|---|
| 282 |  | 
|---|
| 283 |  | 
|---|
| 284 |  | 
|---|
| 285 |  | 
|---|