home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / smc / CORimp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  92.8 KB  |  3,166 lines

  1. /*****************************************************************************/
  2.  
  3. #include "smcPCH.h"
  4. #pragma hdrstop
  5.  
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8.  
  9. /*****************************************************************************
  10.  *
  11.  *  Helpers to fetch various pieces of a COM99 signature.
  12.  */
  13.  
  14. class   MDsigImport
  15. {
  16. public:
  17.  
  18.     void                MDSIinit(Compiler comp,
  19.                                  SymTab   stab, PCCOR_SIGNATURE  sigptr,
  20.                                                 size_t           sigsiz)
  21.     {
  22.         MDSIsigPtr = sigptr;
  23. #ifdef  DEBUG
  24.         MDSIsigMax = sigptr + sigsiz;
  25. #endif
  26.         MDSIcomp   = comp;
  27.         MDSIstab   = stab;
  28.     }
  29.  
  30.     Compiler            MDSIcomp;
  31.     SymTab              MDSIstab;
  32.  
  33.     PCCOR_SIGNATURE     MDSIsigPtr;
  34.  
  35. #ifdef  DEBUG
  36.     PCCOR_SIGNATURE     MDSIsigMax;
  37. #endif
  38.  
  39.     void                MDSIchkEnd()
  40.     {
  41.         assert(MDSIsigPtr == MDSIsigMax);
  42.     }
  43.  
  44.     unsigned            MDSIreadUI1()
  45.     {
  46.         assert(MDSIsigPtr < MDSIsigMax);
  47.         return*MDSIsigPtr++;
  48.     }
  49.  
  50.     unsigned            MDSIpeekUI1()
  51.     {
  52.         assert(MDSIsigPtr < MDSIsigMax);
  53.         return*MDSIsigPtr;
  54.     }
  55.  
  56.     ULONG               MDSIreadUI4()
  57.     {
  58.         ULONG           temp;
  59.         MDSIsigPtr += CorSigUncompressData(MDSIsigPtr, &temp); assert(MDSIsigPtr <= MDSIsigMax);
  60.         return temp;
  61.     }
  62.  
  63.     CorElementType      MDSIreadETP()
  64.     {
  65.         CorElementType  temp;
  66.         MDSIsigPtr += CorSigUncompressElementType(MDSIsigPtr, &temp); assert(MDSIsigPtr <= MDSIsigMax);
  67.         return temp;
  68.     }
  69.  
  70.     mdToken             MDSIreadTok()
  71.     {
  72.         mdToken         temp;
  73.         MDSIsigPtr += CorSigUncompressToken(MDSIsigPtr, &temp); assert(MDSIsigPtr <= MDSIsigMax);
  74.         return temp;
  75.     }
  76. };
  77.  
  78. /*****************************************************************************
  79.  *
  80.  *  When importing an argument list the following structure (whose address is
  81.  *  passed along) holds the state of the argument list conversion process.
  82.  */
  83.  
  84. struct MDargImport
  85. {
  86.     bool            MDaiExtArgDef;
  87.     HCORENUM        MDaiParamEnum;
  88.     mdToken         MDaiMethodTok;
  89.     mdToken         MDaiNparamTok;
  90. };
  91.  
  92. /*****************************************************************************
  93.  *
  94.  *  Import and convert a class type from COM99 metadata.
  95.  */
  96.  
  97. TypDef              metadataImp::MDimportClsr(mdTypeRef clsRef, bool isVal)
  98. {
  99.     SymDef          clsSym;
  100.     bool            clsNew;
  101.     TypDef          clsTyp;
  102.  
  103.     WCHAR           clsName[MAX_CLASS_NAME];
  104.     ULONG           lenClsName;
  105.  
  106.     symbolKinds     symKind;
  107.  
  108.     var_types       vtyp;
  109.  
  110.     /* Get the fully qualified name of the referenced type */
  111.  
  112.     if  (TypeFromToken(clsRef) == mdtTypeRef)
  113.     {
  114.         if  (FAILED(MDwmdi->GetTypeRefProps(clsRef, 0,
  115.                                             clsName, arraylen(clsName), NULL)))
  116.         {
  117.             MDcomp->cmpFatal(ERRreadMD);
  118.         }
  119.     }
  120.     else
  121.     {
  122.  
  123.         DWORD           typeFlag;
  124.  
  125.         if  (FAILED(MDwmdi->GetTypeDefProps(clsRef,
  126.                                             clsName, arraylen(clsName), &lenClsName,
  127.                                             NULL, &typeFlag, NULL)))
  128.         {
  129.             MDcomp->cmpFatal(ERRreadMD);
  130.         }
  131.  
  132.         symKind = SYM_CLASS;    // UNDONE: we don't whether we have enum or class!!!!!!
  133.  
  134.         /* Is this a nested class ? */
  135.  
  136.         if  ((typeFlag & tdVisibilityMask) >= tdNestedPublic &&
  137.              (typeFlag & tdVisibilityMask) <= tdNestedFamORAssem)
  138.         {
  139.             mdTypeDef           outerTok;
  140.             TypDef              outerCls;
  141.             SymDef              outerSym;
  142.             LPWSTR              tmpName;
  143.             Ident               clsIden;
  144.  
  145.             if  (MDwmdi->GetNestedClassProps(clsRef, &outerTok))
  146.                 MDcomp->cmpFatal(ERRreadMD);
  147.  
  148.             /* Resolve the outer class token to a class symbol */
  149.  
  150.             outerCls = MDimportClsr(outerTok, false); assert(outerCls);
  151.             outerSym = outerCls->tdClass.tdcSymbol;
  152.  
  153.             /* Lookup the nested class and declare it if it doesn't exist yet */
  154.  
  155.             tmpName = wcsrchr(clsName, '.');        // ISSUE: this is pretty awful
  156.             if (!tmpName)
  157.                 tmpName = clsName;
  158.             else
  159.                 tmpName++;
  160.  
  161.             /* Got the naked nested class name, now look for it */
  162.  
  163.             clsIden = MDhashWideName(tmpName);
  164.             clsSym  = MDstab->stLookupScpSym(clsIden, outerSym);
  165.  
  166.             if  (!clsSym)
  167.                 clsSym = MDstab->stDeclareSym(clsIden, symKind, NS_NORM, outerSym);
  168.  
  169.             goto GOT_TYPE;
  170.         }
  171.     }
  172.  
  173.     /* Is this a class or enum ref ? */
  174.  
  175.     symKind = SYM_CLASS;        // HACK!!!!!!
  176.  
  177.     /* Convert the dotted name to a symbol */
  178.  
  179.     clsNew  = false;
  180.     clsSym  = MDparseDotted(clsName, SYM_CLASS, &clsNew);
  181.  
  182.     if  (!clsSym)
  183.         return  NULL;
  184.  
  185. GOT_TYPE:
  186.  
  187.     symKind = clsSym->sdSymKindGet();        // HACK!!!!!!
  188.  
  189. //  printf("Typeref '%s'\n", clsSym->sdSpelling());
  190.  
  191.     /* We better get the right kind of a symbol back */
  192.  
  193.     assert(clsSym);
  194.     assert(clsSym->sdSymKind == symKind);
  195.  
  196.     if  (clsNew || clsSym->sdCompileState < CS_DECLSOON)
  197.     {
  198.         mdTypeRef       clsd;
  199.         WMetaDataImport*wmdi;
  200.  
  201.         /* Do we have a typedef ? */
  202.  
  203.         if  (TypeFromToken(clsRef) == mdtTypeDef)
  204.         {
  205.             clsSym = MDimportClss(clsRef, NULL, 0, false);
  206.             goto GOT_CLS;
  207.         }
  208.  
  209.         /* The class hasn't been seen yet, we'll import it later if needed */
  210.  
  211.         if  (MDwmdi->ResolveTypeRef(clsRef,
  212.                                     getIID_IMetaDataImport(),
  213.                                     &wmdi,
  214.                                     &clsd) != S_OK)
  215.         {
  216.             MDcomp->cmpFatal(ERRundefTref, clsSym);
  217.         }
  218.  
  219. #if 0
  220.  
  221.         save the scope/typeref in the symbol for later retrieval (when needed)
  222.  
  223. #else
  224.  
  225.         /* For now (to test things) we eagerly suck everything */
  226.  
  227.         MetaDataImp     cimp;
  228.  
  229.         for (cimp = MDcomp->cmpMDlist; cimp; cimp = cimp->MDnext)
  230.         {
  231.             if  (cimp->MDwmdi == wmdi)
  232.                 break;
  233.         }
  234.  
  235.         if  (!cimp)
  236.         {
  237.             cimp = MDcomp->cmpAddMDentry();
  238.             cimp->MDinit(wmdi, MDcomp, MDstab);
  239.         }
  240.  
  241.         clsSym = cimp->MDimportClss(clsd, NULL, 0, false);
  242.  
  243. #endif
  244.  
  245.     }
  246.  
  247. GOT_CLS:
  248.  
  249.     clsTyp = clsSym->sdTypeGet();
  250.  
  251.     if  (clsSym->sdSymKind == SYM_CLASS)
  252.     {
  253.         assert(clsTyp->tdTypeKind == TYP_CLASS);
  254.  
  255.         /* Check for some "known" classes */
  256.  
  257.         if  ((hashTab::getIdentFlags(clsSym->sdName) & IDF_PREDEF) &&
  258.              clsSym->sdParent == MDcomp->cmpNmSpcSystem)
  259.         {
  260.             MDcomp->cmpMarkStdType(clsSym);
  261.         }
  262.  
  263.         /* Is this an intrinsic type "in disguise" ? */
  264.  
  265.         vtyp = (var_types)clsTyp->tdClass.tdcIntrType;
  266.  
  267.         if  (vtyp != TYP_UNDEF)
  268.             clsTyp = MDstab->stIntrinsicType(vtyp);
  269.     }
  270.     else
  271.     {
  272.         // HACK!!!!!!!!!!!!!!!!!!!!
  273.  
  274.         clsTyp->tdEnum.tdeIntType = MDstab->stIntrinsicType(TYP_INT);
  275.     }
  276.  
  277.     return clsTyp;
  278. }
  279.  
  280. /*****************************************************************************
  281.  *
  282.  *  The following maps a metadata type onto our own var_types value.
  283.  */
  284.  
  285. static
  286. BYTE                CORtypeToSMCtype[] =
  287. {
  288.     TYP_UNDEF,  // ELEMENT_TYPE_END
  289.     TYP_VOID,   // ELEMENT_TYPE_VOID
  290.     TYP_BOOL,   // ELEMENT_TYPE_BOOLEAN
  291.     TYP_WCHAR,  // ELEMENT_TYPE_CHAR
  292.     TYP_CHAR,   // ELEMENT_TYPE_I1
  293.     TYP_UCHAR,  // ELEMENT_TYPE_U1
  294.     TYP_SHORT,  // ELEMENT_TYPE_I2
  295.     TYP_USHORT, // ELEMENT_TYPE_U2
  296.     TYP_INT,    // ELEMENT_TYPE_I4
  297.     TYP_UINT,   // ELEMENT_TYPE_U4
  298.     TYP_LONG,   // ELEMENT_TYPE_I8
  299.     TYP_ULONG,  // ELEMENT_TYPE_U8
  300.     TYP_FLOAT,  // ELEMENT_TYPE_R4
  301.     TYP_DOUBLE, // ELEMENT_TYPE_R8
  302. };
  303.  
  304. /*****************************************************************************
  305.  *
  306.  *  Import and convert a single type from COM99 metadata.
  307.  */
  308.  
  309. TypDef              metadataImp::MDimportType(MDsigImport *sig)
  310. {
  311.     CorElementType  etp = sig->MDSIreadETP();
  312.  
  313.     if      (etp < sizeof(CORtypeToSMCtype)/sizeof(CORtypeToSMCtype[0]))
  314.     {
  315.         return  MDstab->stIntrinsicType((var_types)CORtypeToSMCtype[etp]);
  316.     }
  317.     else if (etp & ELEMENT_TYPE_MODIFIER)
  318.     {
  319.         switch (etp)
  320.         {
  321.         case ELEMENT_TYPE_SENTINEL:
  322.             UNIMPL(!"modified type");
  323.         }
  324.     }
  325.     else
  326.     {
  327. //      printf("etp = %u\n", etp); fflush(stdout); DebugBreak();
  328.  
  329.         switch (etp)
  330.         {
  331.             TypDef          type;
  332.             DimDef          dims;
  333.  
  334.         case ELEMENT_TYPE_CLASS:
  335.             return  MDimportClsr(sig->MDSIreadTok(), false)->tdClass.tdcRefTyp;
  336.  
  337.         case ELEMENT_TYPE_VALUECLASS:
  338.             return  MDimportClsr(sig->MDSIreadTok(),  true);
  339.  
  340.         case ELEMENT_TYPE_SZARRAY:
  341.  
  342.             /* Read the element type */
  343.  
  344.             type = MDimportType(sig);
  345.  
  346.             /* Create the dimension descriptor */
  347.  
  348.             dims = MDstab->stNewDimDesc(0);
  349.  
  350.             /* Create and return the array type */
  351.  
  352.             return  MDstab->stNewArrType(dims, true, type);
  353.  
  354.         case ELEMENT_TYPE_BYREF:
  355.  
  356.             /* Read the element type */
  357.  
  358.             type = MDimportType(sig);
  359.  
  360.             /* Create and return the ref type */
  361.  
  362.             return  MDstab->stNewRefType(TYP_REF, type);
  363.  
  364.         case ELEMENT_TYPE_PTR:
  365.  
  366.             /* Read the element type */
  367.  
  368.             type = MDimportType(sig);
  369.  
  370.             /* Create and return the ptr type */
  371.  
  372.             return  MDstab->stNewRefType(TYP_PTR, type);
  373.  
  374.         case ELEMENT_TYPE_ARRAY:
  375.             UNIMPL(!"have not implemented sucking of multi-dim array metadata");
  376.  
  377.         case ELEMENT_TYPE_OBJECT:
  378.             return  MDcomp->cmpObjectRef();
  379.  
  380.         case ELEMENT_TYPE_STRING:
  381.             return  MDcomp->cmpStringRef();
  382.  
  383.         case ELEMENT_TYPE_TYPEDBYREF:
  384.             return  MDstab->stIntrinsicType(TYP_REFANY);
  385.  
  386.         case ELEMENT_TYPE_I:
  387.             return  MDstab->stIntrinsicType(TYP_NATINT);
  388.  
  389.         case ELEMENT_TYPE_U:
  390.             return  MDstab->stIntrinsicType(TYP_NATUINT);
  391.  
  392.         case ELEMENT_TYPE_CMOD_OPT:
  393.             sig->MDSIreadTok();         // ISSUE: warning???
  394.             return  MDimportType(sig);
  395.  
  396.         case ELEMENT_TYPE_CMOD_REQD:
  397.             MDundefCount++;
  398.             sig->MDSIreadTok();
  399.             return  MDimportType(sig);
  400. //          return  MDstab->stIntrinsicType(TYP_UNDEF);
  401.  
  402.         default:
  403. #ifdef  DEBUG
  404.             printf("COR type value = %u = 0x%02X\n", etp, etp);
  405. #endif
  406.             UNIMPL(!"unexpected COR type");
  407.         }
  408.     }
  409.  
  410.     return  NULL;
  411. }
  412.  
  413. /*****************************************************************************
  414.  *
  415.  *  Hash the given unicode name.
  416.  */
  417.  
  418. Ident               metadataImp::MDhashWideName(WCHAR *name)
  419. {
  420.     char            buff[256];
  421.  
  422.     assert(wcslen(name) < sizeof(buff));
  423.  
  424.     wcstombs(buff, name, sizeof(buff)-1);
  425.  
  426.     return  MDcomp->cmpGlobalHT->hashString(buff);
  427. }
  428.  
  429. /*****************************************************************************
  430.  *
  431.  *  Convert a fully qualified namespace or class name to its corresponding
  432.  *  entry in the global symbol table (adding it if it isn't already there
  433.  *  when 'add' is true, returning NULL when called with 'add' set to false).
  434.  */
  435.  
  436. SymDef              metadataImp::MDparseDotted(WCHAR *name, symbolKinds kind,
  437.                                                              bool      * added)
  438. {
  439.     symbolKinds     ckind  = SYM_NAMESPACE;
  440.     SymDef          scope  = MDcomp->cmpGlobalNS;
  441.     SymTab          symtab = MDstab;
  442.  
  443. //  printf("Declare NS sym '%ls'\n", name);
  444.  
  445.     *added = false;
  446.  
  447.     for (;;)
  448.     {
  449.         SymDef          newScp;
  450.         WCHAR   *       delim;
  451.         Ident           iden;
  452.         bool            last;
  453.  
  454.         /* Find the next delimiter (if any) */
  455.  
  456.         delim = wcschr(name, '.');
  457.         if  (delim)
  458.         {
  459.             *delim = 0;
  460.  
  461.             last = false;
  462.         }
  463.         else
  464.         {
  465.             // AWFUL HACK: nested class names are mangled!
  466.  
  467.             delim = wcschr(name, '$');
  468.  
  469.             if  (delim)
  470.             {
  471.                 *delim = 0;
  472.  
  473.                 last  = false;
  474.                 ckind = SYM_CLASS;
  475.             }
  476.             else
  477.             {
  478.                 last  = true;
  479.                 ckind = kind;
  480.             }
  481.         }
  482.  
  483.         /* Look for an existing namespace entry */
  484.  
  485.         iden = MDhashWideName(name);
  486.  
  487.         if  (scope->sdSymKind == SYM_CLASS)
  488.             newScp = symtab->stLookupScpSym(iden,          scope);
  489.         else
  490.             newScp = symtab->stLookupNspSym(iden, NS_NORM, scope);
  491.  
  492.         if  (newScp)
  493.         {
  494.             /* Symbol already exists, make sure it's the right kind */
  495.  
  496.             if  (newScp->sdSymKindGet() != ckind)
  497.             {
  498.                 if  (newScp->sdSymKind == SYM_ENUM && ckind == SYM_CLASS)
  499.                 {
  500.                     // THIS IS A HORRIBLE HACK!!!!!!!!!!!!!!!!!!!!
  501.                 }
  502.                 else
  503.                 {
  504.                     /* This is not legal, issue an error message or something? */
  505.  
  506.                     UNIMPL(!"redef of symbol in metadata, now what?");
  507.                 }
  508.             }
  509.         }
  510.         else
  511.         {
  512.             /* Symbol not known yet, define a new symbol */
  513.  
  514.             newScp = symtab->stDeclareSym(iden, ckind, NS_NORM, scope);
  515.  
  516.             /* Tell the caller about what we've done */
  517.  
  518.             *added = true;
  519.  
  520.             /* Is this a namespace symbol? */
  521.  
  522.             if      (ckind == SYM_NAMESPACE)
  523.             {
  524.                 /* Record which symbol table the namespace uses */
  525.  
  526.                 newScp->sdNS.sdnSymtab = symtab;
  527.             }
  528.             else if (ckind == SYM_CLASS)
  529.             {
  530.                 /* Well, we don't really know anything at all about this class */
  531.  
  532.                 newScp->sdCompileState = CS_NONE;
  533.             }
  534.         }
  535.  
  536.         scope = newScp;
  537.  
  538.         /* Done if no more delimiters are present */
  539.  
  540.         if  (!delim)
  541.             break;
  542.  
  543.         /* Continue with the character that follows the delimiter */
  544.  
  545.         name = delim + 1;
  546.     }
  547.  
  548.     return  scope;
  549. }
  550.  
  551. /*****************************************************************************
  552.  *
  553.  *  Map a set of MD type / member attributes to an access level.
  554.  */
  555.  
  556. accessLevels        metadataImp::MDgetAccessLvl(unsigned attrs)
  557. {
  558.     assert(fdFieldAccessMask == mdMemberAccessMask);
  559.     assert(fdPublic          == mdPublic);
  560.     assert(fdPrivate         == mdPrivate);
  561.     assert(fdFamily          == mdFamily);
  562.  
  563.     switch (attrs & fdFieldAccessMask)
  564.     {
  565.     case fdPublic : return ACL_PUBLIC;
  566.     case fdPrivate: return ACL_PRIVATE;
  567.     case fdFamily : return ACL_PROTECTED;
  568.     default:        return ACL_DEFAULT;
  569.     }
  570. }
  571.  
  572. /*****************************************************************************
  573.  *
  574.  *  Check for any custom attributes attached to the given symbol.
  575.  */
  576.  
  577. void                metadataImp::MDchk4CustomAttrs(SymDef sym, mdToken tok)
  578. {
  579.     HCORENUM        attrEnum = NULL;
  580.  
  581.     /* Are there any custom attributes at all ? */
  582.  
  583.     if  (!FAILED(MDwmdi->EnumCustomAttributes(&attrEnum, tok, 0, NULL, 0, NULL)) && attrEnum)
  584.     {
  585.         ULONG           attrCnt;
  586.  
  587.         if  (!FAILED(MDwmdi->CountEnum(attrEnum, &attrCnt)) && attrCnt)
  588.         {
  589.             /* Check for interesting custom values */
  590.  
  591.             MDwmdi->CloseEnum(attrEnum); attrEnum = NULL;
  592.  
  593.             for (;;)
  594.             {
  595.                 mdToken         attrTok;
  596.                 mdToken         attrRef;
  597.                 mdToken         methTok;
  598.  
  599.                 const void    * attrValAddr;
  600.                 ULONG           attrValSize;
  601.  
  602.                 if  (MDwmdi->EnumCustomAttributes(&attrEnum,
  603.                                                   tok,
  604.                                                   0,
  605.                                                   &attrTok,
  606.                                                   1,
  607.                                                   &attrCnt))
  608.                     break;
  609.  
  610.                 if  (!attrCnt)
  611.                     break;
  612.  
  613.                 if  (MDwmdi->GetCustomAttributeProps(attrTok,
  614.                                                      NULL,
  615.                                                      &attrRef,
  616.                                                      &attrValAddr,
  617.                                                      &attrValSize))
  618.                     break;
  619.  
  620.                 /* Check for an attribute we've seen before */
  621.  
  622.                 methTok = 0;
  623.  
  624.             AGAIN:
  625.  
  626.                 switch (TypeFromToken(attrRef))
  627.                 {
  628.                     DWORD           typeFlag;
  629.                     mdToken         scope;
  630.  
  631.                     WCHAR           symName[MAX_PACKAGE_NAME];
  632.  
  633.                 case mdtTypeRef:
  634.  
  635.                     if  (attrRef == MDclsRefObsolete)
  636.                     {
  637.                         sym->sdIsDeprecated = true;
  638.                         break;
  639.                     }
  640.  
  641.                     if  (attrRef == MDclsRefAttribute)
  642.                         goto GOT_ATTR;
  643.  
  644.                     if  (FAILED(MDwmdi->GetTypeRefProps(attrRef, 0,
  645.                                                         symName, arraylen(symName), NULL)))
  646.                     {
  647.                         break;
  648.                     }
  649.  
  650. #if 0
  651.                     if  (methTok)
  652.                         printf("Custom attribute (mem): '%ls::ctor'\n", symName);
  653.                     else
  654.                         printf("Custom attribute (ref): '%ls'\n"      , symName);
  655. #endif
  656.  
  657.                     goto GOT_NAME;
  658.  
  659.                 case mdtTypeDef:
  660.  
  661.                     if  (attrRef == MDclsDefObsolete)
  662.                     {
  663.                         sym->sdIsDeprecated = true;
  664.                         break;
  665.                     }
  666.  
  667.                     if  (attrRef == MDclsDefAttribute)
  668.                         goto GOT_ATTR;
  669.  
  670.                     if  (FAILED(MDwmdi->GetTypeDefProps(attrRef,
  671.                                                         symName, arraylen(symName), NULL,
  672.                                                         NULL, &typeFlag, NULL)))
  673.                     {
  674.                         MDcomp->cmpFatal(ERRreadMD);
  675.                     }
  676.  
  677.                     /* Forget it if the type is a nested class */
  678.  
  679.                     if  ((typeFlag & tdVisibilityMask) >= tdNestedPublic &&
  680.                          (typeFlag & tdVisibilityMask) <= tdNestedFamORAssem)
  681.                     {
  682.                         break;
  683.                     }
  684.  
  685. #if 0
  686.                     if  (methTok)
  687.                         printf("Custom attribute (mem): '%ls::ctor'\n", symName);
  688.                     else
  689.                         printf("Custom attribute (def): '%ls'\n"      , symName);
  690. #endif
  691.  
  692.                 GOT_NAME:
  693.  
  694.                     if  (wcsncmp(symName, L"System.Reflection.", 18))
  695.                         break;
  696.  
  697.                     if  (wcscmp(symName+18, L"ObsoleteAttribute") == 0)
  698.                     {
  699.                         sym->sdIsDeprecated = true;
  700.  
  701.                         if  (TypeFromToken(attrRef) == mdtTypeRef)
  702.                             MDclsDefObsolete  = attrRef;
  703.                         else
  704.                             MDclsDefObsolete  = attrRef;
  705.  
  706.                         break;
  707.                     }
  708.  
  709.                     if  (wcscmp(symName+18, L"Attribute") == 0)
  710.                     {
  711.                         const void *    blobAddr;
  712.                         ULONG           blobSize;
  713.  
  714.                         if  (TypeFromToken(attrRef) == mdtTypeRef)
  715.                             MDclsDefAttribute = attrRef;
  716.                         else
  717.                             MDclsDefAttribute = attrRef;
  718.  
  719.                     GOT_ATTR:
  720.  
  721. //                      printf("Class '%s' has Attribute [%08X]\n", sym->sdSpelling());
  722.  
  723.                         /* Ignore if it's not a ctor-ref or we don't have a class */
  724.  
  725.                         if  (!methTok)
  726.                             break;
  727.  
  728.                         if  (sym->sdSymKind != SYM_CLASS)
  729.                             break;
  730.  
  731.                         /* HACK: Figure argument count based on blob size */
  732.  
  733.                         if  (MDwmdi->GetCustomAttributeProps(attrTok, NULL, NULL, &blobAddr,
  734.                                                                                   &blobSize))
  735.                             break;
  736.  
  737.                         sym->sdClass.sdcAttribute = true;
  738.  
  739.                         switch (blobSize)
  740.                         {
  741.                         case 6:
  742.  
  743.                             /* No argument at all, this must be "Attribute" itself */
  744.  
  745.                             break;
  746.  
  747.                         case 8:
  748.  
  749.                             if  (TypeFromToken(methTok) == mdtMemberRef)
  750.                                 MDctrRefAttribute1 = methTok;
  751.                             else
  752.                                 MDctrDefAttribute1 = methTok;
  753.  
  754.                             break;
  755.  
  756.                         case 9:
  757.  
  758.                             if  (TypeFromToken(methTok) == mdtMemberRef)
  759.                                 MDctrRefAttribute2 = methTok;
  760.                             else
  761.                                 MDctrDefAttribute2 = methTok;
  762.  
  763.                             if  (((BYTE*)blobAddr)[6] != 0)
  764.                                 sym->sdClass.sdcAttrDupOK = true;
  765.  
  766.                             break;
  767.  
  768.                         case 10:
  769.  
  770.                             if  (TypeFromToken(methTok) == mdtMemberRef)
  771.                                 MDctrRefAttribute3 = methTok;
  772.                             else
  773.                                 MDctrDefAttribute3 = methTok;
  774.  
  775.                             if  (((BYTE*)blobAddr)[6] != 0)
  776.                                 sym->sdClass.sdcAttrDupOK = true;
  777.  
  778.                             break;
  779.  
  780.                         default:
  781.                             printf("WARNING: unexpected custom attribute blob size %u\n", blobSize);
  782.                             break;
  783.                         }
  784.                         break;
  785.                     }
  786.  
  787.                     break;
  788.  
  789.                 case mdtMemberRef:
  790.  
  791.                                         methTok = attrRef;
  792.  
  793.                     if  (attrRef == MDctrRefAttribute1)
  794.                         goto GOT_ATTR;
  795.                     if  (attrRef == MDctrRefAttribute2)
  796.                         goto GOT_ATTR;
  797.                     if  (attrRef == MDctrRefAttribute3)
  798.                         goto GOT_ATTR;
  799.  
  800.                     if  (FAILED(MDwmdi->GetMemberRefProps(attrRef,
  801.                                                          &scope,
  802.                                                           symName, arraylen(symName), NULL,
  803.                                                           NULL, NULL)))
  804.                     {
  805.                         break;
  806.                     }
  807.  
  808.                 GOT_METH:
  809.  
  810.                     /* The method better be a constructor */
  811.  
  812.                     if  (wcscmp(symName, L".ctor"))     // NOTE: s/b OVOP_STR_CTOR_INST
  813.                         break;
  814.  
  815.                     attrRef = scope;
  816.                     goto AGAIN;
  817.  
  818.                 case mdtMethodDef:
  819.  
  820.                                         methTok = attrRef;
  821.  
  822.                     if  (attrRef == MDctrDefAttribute1)
  823.                         goto GOT_ATTR;
  824.                     if  (attrRef == MDctrDefAttribute2)
  825.                         goto GOT_ATTR;
  826.                     if  (attrRef == MDctrDefAttribute3)
  827.                         goto GOT_ATTR;
  828.  
  829.                     if  (FAILED(MDwmdi->GetMethodProps   (attrRef,
  830.                                                          &scope,
  831.                                                           symName, arraylen(symName), NULL,
  832.                                                           NULL,
  833.                                                           NULL, NULL,
  834.                                                           NULL,
  835.                                                           NULL)))
  836.                     {
  837.                         break;
  838.                     }
  839.  
  840.                     goto GOT_METH;
  841.  
  842.                 default:
  843.                     printf("Found custom attribute: ?token? = %08X\n", attrRef);
  844.                     break;
  845.                 }
  846.             }
  847.         }
  848.  
  849.         MDwmdi->CloseEnum(attrEnum);
  850.     }
  851. }
  852.  
  853. /*****************************************************************************
  854.  *
  855.  *  Import and convert an argument list from COM99 metadata.
  856.  */
  857.  
  858. ArgDef              metadataImp::MDimportArgs(MDsigImport * sig,
  859.                                               unsigned      cnt,
  860.                                               MDargImport  *state)
  861. {
  862.     TypDef          argType;
  863.     Ident           argName;
  864.     ArgDef          argDesc;
  865.     ArgDef          argNext;
  866.     size_t          argDsiz;
  867.  
  868.     unsigned        argFlags = 0;
  869. //  constVal        argDef;
  870.  
  871.     /* Is this a "byref" argument? */
  872.  
  873.     if  (sig->MDSIpeekUI1() == ELEMENT_TYPE_BYREF)
  874.     {
  875.          sig->MDSIreadUI1();
  876.  
  877.         argFlags = ARGF_MODE_INOUT;
  878.  
  879.         state->MDaiExtArgDef = true;
  880.     }
  881.  
  882.     /* Do we have a functioning parameter enumerator? */
  883.  
  884.     if  (state->MDaiParamEnum)
  885.     {
  886.         const   char *  paramName;
  887.         ULONG           paramNlen;
  888.         ULONG           paramAttr;
  889.         ULONG           cppFlags;
  890.  
  891.         const   void *  defVal;
  892.         ULONG           cbDefVal;
  893. //      VARIANT         defValue;
  894.  
  895.         ULONG           paramCnt = 0;
  896.  
  897.         /* Get the info about the current parameter */
  898.  
  899.         if  (MDwmdi->GetNameFromToken(state->MDaiNparamTok,
  900.                                       ¶mName)
  901.                          ||
  902.              MDwmdi->GetParamProps   (state->MDaiNparamTok,
  903.                                       NULL,
  904.                                       NULL,
  905. //                                    paramName, sizeof(paramName)/sizeof(paramName[0]),
  906.                                       NULL, 0,
  907.                                       ¶mNlen,
  908.                                       ¶mAttr,
  909.                                       &cppFlags,
  910.                                       &defVal,
  911.                                       &cbDefVal))
  912.         {
  913.             /* Couldn't get parameter info for some reason ... */
  914.  
  915.             MDwmdi->CloseEnum(state->MDaiParamEnum); state->MDaiParamEnum = NULL;
  916.         }
  917.  
  918.         /* Hash the argument name */
  919.  
  920.         argName = MDcomp->cmpGlobalHT->hashString(paramName);
  921.  
  922.         /* Is this an "out" argument? */
  923.  
  924. #if 0
  925.  
  926.         if  (paramAttr & pdOut)
  927.         {
  928.             argFlags |= (paramAttr & pdIn) ? ARGF_MODE_INOUT
  929.                                            : ARGF_MODE_OUT;
  930.  
  931.             state->MDaiExtArgDef = true;
  932.         }
  933.  
  934. #endif
  935.  
  936.         // UNDONE: Grab argument default value, and whatever else we need ....
  937.  
  938.         /* Advance to the next argument */
  939.  
  940.         if  (MDwmdi->EnumParams(&state->MDaiParamEnum,
  941.                                  state->MDaiMethodTok,
  942.                                 &state->MDaiNparamTok,
  943.                                 1,
  944.                                 ¶mCnt) || paramCnt != 1)
  945.         {
  946.             /* Couldn't get parameter info for some reason ... */
  947.  
  948.             MDwmdi->CloseEnum(state->MDaiParamEnum); state->MDaiParamEnum = NULL;
  949.         }
  950.     }
  951.     else
  952.     {
  953.         argName = NULL; assert(sig->MDSIpeekUI1() != ELEMENT_TYPE_BYREF);
  954.     }
  955.  
  956.     /* Extract the argument type from the signature */
  957.  
  958.     argType = MDimportType(sig);
  959.  
  960.     /* Is this the last argument? */
  961.  
  962.     if  (cnt > 1)
  963.     {
  964.         /* Recursively import the rest of the arguments */
  965.  
  966.         argNext = MDimportArgs(sig, cnt - 1, state);
  967.     }
  968.     else
  969.     {
  970.         /* No more arguments to import */
  971.  
  972.         argNext = NULL;
  973.     }
  974.  
  975.     /* Allocate an argument entry */
  976.  
  977.     argDsiz = state->MDaiExtArgDef ? sizeof(ArgExtRec)
  978.                                    : sizeof(ArgDefRec);
  979.  
  980. #if MGDDATA
  981.     argDesc = new ArgDef;
  982. #else
  983.     argDesc =    (ArgDef)MDcomp->cmpAllocPerm.nraAlloc(argDsiz);
  984. #endif
  985.  
  986.     /* Record the argument type and name */
  987.  
  988.     argDesc->adType  = argType;
  989.     argDesc->adName  = argName;
  990.     argDesc->adNext  = argNext;
  991.  
  992. #ifdef  DEBUG
  993.     argDesc->adIsExt = state->MDaiExtArgDef;
  994. #endif
  995.  
  996.     /* Fill in any extra info if we're creating extended descriptors */
  997.  
  998.     if  (state->MDaiExtArgDef)
  999.     {
  1000.         ArgExt          argXdsc = (ArgExt)argDesc;
  1001.  
  1002. //      argXdsc->adDefVal = argDef;
  1003.         argXdsc->adFlags  = argFlags;
  1004.     }
  1005.     else
  1006.     {
  1007.         assert(argFlags == 0);
  1008.     }
  1009.  
  1010.     return  argDesc;
  1011. }
  1012.  
  1013. /*****************************************************************************
  1014.  *
  1015.  *  Import and convert information about a field/method from COM99 metadata.
  1016.  */
  1017.  
  1018. SymDef              metadataImp::MDimportMem(SymDef          scope,
  1019.                                              Ident           memName,
  1020.                                              mdToken         memTok,
  1021.                                              unsigned        attrs,
  1022.                                              bool            isProp,
  1023.                                              bool            fileScope,
  1024.                                              PCCOR_SIGNATURE sigAddr,
  1025.                                              size_t          sigSize)
  1026. {
  1027.     SymDef          memSym;
  1028.     MDsigImport     memSig;
  1029.     TypDef          memType;
  1030.  
  1031.     unsigned        sdfCtor;
  1032.     bool            sdfProp;
  1033.  
  1034.     BYTE            call;
  1035.  
  1036.     unsigned        MDundefStart;
  1037.  
  1038.     /* Start reading from the signature string */
  1039.  
  1040.     memSig.MDSIinit(MDcomp, MDstab, sigAddr, sigSize);
  1041.  
  1042.     /* Track constructor/property accessor state for methods */
  1043.  
  1044.     sdfCtor = sdfProp = false;
  1045.  
  1046. #if 0
  1047.  
  1048.     printf("Importing member [%04X] '%s.%s'\n", attrs, scope->sdSpelling(), memName->idSpelling());
  1049.  
  1050. #if 0
  1051.     if  (sigAddr)
  1052.     {
  1053.         BYTE    *       sig = (BYTE*)sigAddr;
  1054.  
  1055.         printf("    Signature:");
  1056.  
  1057.         while (sig < sigAddr+sigSize)
  1058.             printf(" 0x%02X", *sig++);
  1059.  
  1060.         printf("\n");
  1061.  
  1062.         fflush(stdout);
  1063.     }
  1064. #endif
  1065.  
  1066. #endif
  1067.  
  1068.     /* Get the calling convention byte */
  1069.  
  1070.     call = memSig.MDSIreadUI1();
  1071.  
  1072.     /* We need to notice members that references unrecognized metadata */
  1073.  
  1074.     MDundefStart = MDundefCount;
  1075.  
  1076.     /* Do we have a field or a method? */
  1077.  
  1078.     if  ((call & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD)
  1079.     {
  1080.         /* Import/convert the member's type */
  1081.  
  1082.         memType = MDimportType(&memSig);
  1083.  
  1084.         /* Declare the member symbol */
  1085.  
  1086.         if  (scope->sdSymKind == SYM_ENUM)
  1087.         {
  1088.             if  (!(attrs & fdStatic))
  1089.             {
  1090.                 /* This must be the fake enum type instance member */
  1091.  
  1092.                 scope->sdType->tdEnum.tdeIntType = memType;
  1093.  
  1094.                 return  NULL;
  1095.             }
  1096.  
  1097.             memSym  = MDstab->stDeclareSym(memName,          SYM_ENUMVAL       , NS_NORM, scope);
  1098.         }
  1099.         else
  1100.         {
  1101.             memSym  = MDstab->stDeclareSym(memName, isProp ? SYM_PROP : SYM_VAR, NS_NORM, scope);
  1102.  
  1103.             /* Record any other interesting attributes */
  1104.  
  1105.             if  (attrs & fdInitOnly    ) memSym->sdIsSealed     = true;
  1106. //          if  (attrs & fdVolatile    ) memSym->memIsVolatile  = true;
  1107. //          if  (attrs & fdTransient   ) memSym->memIsTransient = true;
  1108.  
  1109.             /* Record the member's token */
  1110.  
  1111.             memSym->sdVar.sdvMDtoken = memTok;
  1112.         }
  1113.  
  1114.         /* For globals we record the importer index */
  1115.  
  1116.         if  (fileScope)
  1117.         {
  1118.             memSym->sdVar.sdvImpIndex = MDnum;
  1119.  
  1120. //          printf("Importer %2u originated '%s'\n", MDnum, MDstab->stTypeName(NULL, memSym, NULL, NULL, true));
  1121.  
  1122.             /* Make sure the index fit in the [bit]field */
  1123.  
  1124.             assert(memSym->sdVar.sdvImpIndex == MDnum);
  1125.         }
  1126.     }
  1127.     else
  1128.     {
  1129.         ULONG           argCnt;
  1130.         TypDef          retType;
  1131.         ArgDscRec       argDesc;
  1132.         SymDef          oldSym;
  1133.  
  1134.         ovlOpFlavors    ovlop  = OVOP_NONE;
  1135.  
  1136.         bool            argExt = false;
  1137.  
  1138.         /* Get the argument count */
  1139.  
  1140.         argCnt  = memSig.MDSIreadUI4();
  1141.  
  1142.         /* Get the return type */
  1143.  
  1144.         retType = MDimportType(&memSig);
  1145.  
  1146.         /* Munge the name if it's a ctor or operator */
  1147.  
  1148.         if  ((attrs & mdSpecialName) && !isProp)
  1149.         {
  1150.             stringBuff      memNstr = memName->idSpelling();
  1151.  
  1152.             /* Is this an instance or static constructor? */
  1153.  
  1154.             if  (!strcmp(memNstr, OVOP_STR_CTOR_INST))
  1155.             {
  1156.                 assert((attrs & mdStatic) == 0);
  1157.                 ovlop   = OVOP_CTOR_INST;
  1158.                 sdfCtor = true;
  1159.                 goto DONE_OVLOP;
  1160.             }
  1161.  
  1162.             if  (!strcmp(memNstr, OVOP_STR_CTOR_STAT))
  1163.             {
  1164.                 assert((attrs & mdStatic) != 0);
  1165.                 ovlop   = OVOP_CTOR_STAT;
  1166.                 sdfCtor = true;
  1167.                 goto DONE_OVLOP;
  1168.             }
  1169.  
  1170.             assert(MDcomp->cmpConfig.ccNewMDnames);
  1171.  
  1172.             ovlop = MDname2ovop(memNstr);
  1173.  
  1174.             if  (ovlop == OVOP_NONE)
  1175.             {
  1176.                 /* This better be a property accessor method, right? */
  1177.  
  1178.                 if  (memcmp(memNstr, "get_", 4) && memcmp(memNstr, "set_", 4))
  1179.                 {
  1180. #ifdef  DEBUG
  1181.                     if  (!strchr(memNstr, '.'))
  1182.                         printf("WARNING: Strange 'specialname' method '%s' found in '%s'\n", memNstr, scope->sdSpelling());
  1183. #endif
  1184.                 }
  1185.                 else
  1186.                 {
  1187.                     sdfProp = true;
  1188.                 }
  1189.             }
  1190.         }
  1191.  
  1192.     DONE_OVLOP:
  1193.  
  1194.         /* Get the argument list, if present */
  1195.  
  1196. #if MGDDATA
  1197.         argDesc = new ArgDscRec;
  1198. #else
  1199.         memset(&argDesc, 0, sizeof(argDesc));
  1200. #endif
  1201.  
  1202.         if  (argCnt)
  1203.         {
  1204.             MDargImport     paramState;
  1205.             ULONG           paramCnt  = 0;
  1206.  
  1207.             /* Start the parameter enumerator */
  1208.  
  1209.             paramState.MDaiParamEnum = NULL;
  1210.             paramState.MDaiExtArgDef = argExt;
  1211.             paramState.MDaiMethodTok = memTok;
  1212.  
  1213.             if  (MDwmdi->EnumParams(¶mState.MDaiParamEnum,
  1214.                                     memTok,
  1215.                                     ¶mState.MDaiNparamTok,
  1216.                                     1,
  1217.                                     ¶mCnt) || paramCnt != 1)
  1218.             {
  1219.                 /* Couldn't get parameter info for some reason ... */
  1220.  
  1221.                 MDwmdi->CloseEnum(paramState.MDaiParamEnum); paramState.MDaiParamEnum = NULL;
  1222.             }
  1223.  
  1224.             /* Recursively import the argument list */
  1225.  
  1226.             argDesc.adCount  = argCnt;
  1227.             argDesc.adArgs   = MDimportArgs(&memSig, argCnt, ¶mState);
  1228.  
  1229.             /* Close the argument enumerator */
  1230.  
  1231.             MDwmdi->CloseEnum(paramState.MDaiParamEnum);
  1232.  
  1233.             /* Remember whether we have extended argument descriptors */
  1234.  
  1235.             argExt = paramState.MDaiExtArgDef;
  1236.         }
  1237.         else
  1238.             argDesc.adArgs   = NULL;
  1239.  
  1240.         /* Fill in the argument descriptor */
  1241.  
  1242.         argDesc.adCount   = argCnt;
  1243.         argDesc.adExtRec  = argExt;
  1244.         argDesc.adVarArgs = false;
  1245.  
  1246.         /* Figure out the calling convention */
  1247.  
  1248.         switch (call & IMAGE_CEE_CS_CALLCONV_MASK)
  1249.         {
  1250.         case IMAGE_CEE_CS_CALLCONV_DEFAULT:
  1251.         case IMAGE_CEE_CS_CALLCONV_STDCALL:
  1252.         case IMAGE_CEE_CS_CALLCONV_THISCALL:
  1253.         case IMAGE_CEE_CS_CALLCONV_FASTCALL:
  1254.             break;
  1255.  
  1256.         case IMAGE_CEE_CS_CALLCONV_VARARG:
  1257.             argDesc.adVarArgs = true;
  1258.         case IMAGE_CEE_CS_CALLCONV_C:
  1259.             break;
  1260.         }
  1261.  
  1262.         /* Create the function type */
  1263.  
  1264.         memType = MDstab->stNewFncType(argDesc, retType);
  1265.  
  1266.         /* Look for an existing symbol with a matching name */
  1267.  
  1268.         if (isProp)
  1269.         {
  1270.             oldSym = MDstab->stLookupProp(memName, scope);
  1271.             if  (oldSym)
  1272.             {
  1273.                 /* Check for a redefinition of an earlier property */
  1274.  
  1275.                 memSym = MDstab->stFindSameProp(oldSym, memType);
  1276.                 if  (memSym)
  1277.                 {
  1278.                     UNIMPL(!"redefined property in metadata - now what?");
  1279.                 }
  1280.  
  1281.                 /* The new property is a new overload */
  1282.  
  1283.                 memSym = MDstab->stDeclareOvl(oldSym);
  1284.             }
  1285.             else
  1286.             {
  1287.                 memSym = MDstab->stDeclareSym(memName, SYM_PROP, NS_NORM, scope);
  1288.             }
  1289.  
  1290.             memSym->sdCompileState = CS_DECLARED;
  1291.  
  1292.             /* Record any other interesting attributes */
  1293.  
  1294. //          if  (attrs & prFinal   ) memSym->sdIsSealed   = true;
  1295. //          if  (attrs & prAbstract) memSym->sdIsAbstract = true;
  1296.  
  1297.             memSym->sdAccessLevel = ACL_PUBLIC;
  1298.  
  1299.             /* The property is static if there is no "this" pointer */
  1300.  
  1301.             if  (!(call & IMAGE_CEE_CS_CALLCONV_HASTHIS))
  1302.                 memSym->sdIsStatic = true;
  1303.  
  1304.             goto DONE_SIG;
  1305.         }
  1306.  
  1307.         if  (fileScope)
  1308.         {
  1309.             assert(ovlop == OVOP_NONE);
  1310.  
  1311.             oldSym = MDstab->stLookupNspSym(memName, NS_NORM, scope);
  1312.         }
  1313.         else if (ovlop == OVOP_NONE)
  1314.         {
  1315.             oldSym = MDstab->stLookupClsSym(memName,          scope);
  1316.         }
  1317.         else
  1318.         {
  1319.             oldSym = MDstab->stLookupOper  (ovlop,            scope);
  1320.         }
  1321.  
  1322.         /* Is this an overload of an existing method? */
  1323.  
  1324.         if  (oldSym)
  1325.         {
  1326.             if  (oldSym->sdSymKind != SYM_FNC)
  1327.             {
  1328.                 UNIMPL(!"fncs and vars can't overload, right?");
  1329.             }
  1330.  
  1331.             /* Look for a function with a matching arglist */
  1332.  
  1333.             memSym = MDstab->stFindOvlFnc(oldSym, memType);
  1334.  
  1335.             if  (memSym)
  1336.             {
  1337. #ifdef  DEBUG
  1338.                 SymDef newSym = MDstab->stDeclareOvl(memSym); newSym->sdType = memType;
  1339.                 printf("Old overload: '%s'\n", MDstab->stTypeName(NULL, memSym, NULL, NULL, true));
  1340.                 printf("New overload: '%s'\n", MDstab->stTypeName(NULL, newSym, NULL, NULL, true));
  1341. #endif
  1342.                 UNIMPL(!"duplicate method found, what to do?");
  1343.             }
  1344.  
  1345.             /* It's a new overload, declare a symbol for it */
  1346.  
  1347.             memSym = MDstab->stDeclareOvl(oldSym);
  1348.         }
  1349.         else
  1350.         {
  1351.             /* This is a brand new function */
  1352.  
  1353.             if  (ovlop == OVOP_NONE)
  1354.                 memSym = MDstab->stDeclareSym (memName, SYM_FNC, NS_NORM, scope);
  1355.             else
  1356.                 memSym = MDstab->stDeclareOper(ovlop, scope);
  1357.         }
  1358.  
  1359.         /* Record the member's token */
  1360.  
  1361.         memSym->sdFnc.sdfMDtoken = memTok;
  1362.         memSym->sdFnc.sdfMDfnref = 0;
  1363.  
  1364.         /* Record whether the method is a constructor */
  1365.  
  1366.         memSym->sdFnc.sdfCtor     = sdfCtor;
  1367.  
  1368.         /* Record whether the method is a property accessor */
  1369.  
  1370.         memSym->sdFnc.sdfProperty = sdfProp;
  1371.  
  1372.         /* Record any other interesting attributes */
  1373.  
  1374.         if  (attrs & mdFinal       ) memSym->sdIsSealed         = true;
  1375.         if  (attrs & mdAbstract    ) memSym->sdIsAbstract       = true;
  1376.  
  1377. //      if  (attrs & mdAgile       ) memSym->                   = true;
  1378. //      if  (attrs & mdNotRemotable) memSym->                   = true;
  1379. //      if  (attrs & mdSynchronized) memSym->sdFnc.sdfExclusive = true;
  1380.  
  1381.         /* Some crazy compilers mark ctors as virtual */
  1382.  
  1383.         if  (attrs & mdVirtual)
  1384.             if  (!sdfCtor)           memSym->sdFnc.sdfVirtual = true;
  1385.  
  1386.         /* For globals we record the importer index */
  1387.  
  1388.         if  (fileScope)
  1389.         {
  1390.             memSym->sdFnc.sdfImpIndex = MDnum;
  1391.  
  1392. //          printf("Importer %2u originated '%s'\n", MDnum, MDstab->stTypeName(NULL, memSym, NULL, NULL, true));
  1393.  
  1394.             /* Make sure the index fit in the [bit]field */
  1395.  
  1396.             assert(memSym->sdFnc.sdfImpIndex == MDnum);
  1397.         }
  1398.     }
  1399.  
  1400.     /* Figure out and record the member's access level */
  1401.  
  1402.     memSym->sdAccessLevel = MDgetAccessLvl(attrs);
  1403.  
  1404. DONE_SIG:
  1405.  
  1406.     /* The member signature should have been consumed by now */
  1407.  
  1408.     memSig.MDSIchkEnd();
  1409.  
  1410.     /* Remember that the member is an import */
  1411.  
  1412.     memSym->sdIsImport = true;
  1413.  
  1414.     /* Remember whether this is a member or a global variable/function */
  1415.  
  1416.     memSym->sdIsMember = !fileScope;
  1417.  
  1418.     /* Record the member's type */
  1419.  
  1420.     memSym->sdType     = memType;
  1421.  
  1422.     /* Record other tidbits of information about the member */
  1423.  
  1424.     assert(fdStatic == mdStatic);
  1425.  
  1426.     if  (attrs & fdStatic)
  1427.         memSym->sdIsStatic = true;
  1428.  
  1429. //  if  (MDwmdi->GetCustomAttributeByName(memTok,                   L"Deprecated", NULL, NULL) == S_OK)
  1430. //      memSym->sdIsDeprecated = true;
  1431. //  if  (MDwmdi->GetCustomAttributeByName(memTok, L"System.Attributes.Deprecated", NULL, NULL) == S_OK)
  1432. //      memSym->sdIsDeprecated = true;
  1433. //  if  (MDwmdi->GetCustomAttributeByName(memTok,     L"System.ObsoleteAttribute", NULL, NULL) == S_OK)
  1434. //      memSym->sdIsDeprecated = true;
  1435.  
  1436.     MDchk4CustomAttrs(memSym, memTok);
  1437.  
  1438.     /* Did the member use unrecognized metadata? */
  1439.  
  1440.     if  (MDundefStart != MDundefCount)
  1441.     {
  1442. #if 0
  1443.         memSym->sdNameSpace = (name_space)(memSym->sdNameSpace & ~(NS_NORM|NS_TYPE));
  1444. #else
  1445.         MDcomp->cmpErrorQnm(ERRunknownMD, memSym);
  1446.         memSym->sdType      = MDstab->stIntrinsicType(TYP_UNDEF);
  1447. #endif
  1448.  
  1449.         MDundefCount = MDundefStart;
  1450.     }
  1451.  
  1452.     return memSym;
  1453. }
  1454.  
  1455. /*****************************************************************************
  1456.  *
  1457.  *  Find the property accessor method that corresponds to the given property.
  1458.  */
  1459.  
  1460. SymDef              metadataImp::MDfindPropMF(SymDef    propSym,
  1461.                                               mdToken   methTok,
  1462.                                               bool      getter)
  1463. {
  1464.     Ident           mfnName = MDcomp->cmpPropertyName(propSym->sdName, getter);
  1465.     SymDef          mfnSym  = MDstab->stLookupClsSym(mfnName, propSym->sdParent);
  1466.  
  1467.     if  (mfnSym)
  1468.     {
  1469.         do
  1470.         {
  1471.             if  (mfnSym->sdFnc.sdfMDtoken == methTok)
  1472.                 return  mfnSym;
  1473.  
  1474.             mfnSym = mfnSym->sdFnc.sdfNextOvl;
  1475.         }
  1476.         while (mfnSym);
  1477.     }
  1478.  
  1479.     /* The creator of this DLL probably used different naming conventions */
  1480.  
  1481.     for (mfnSym = propSym->sdParent->sdScope.sdScope.sdsChildList;
  1482.          mfnSym;
  1483.          mfnSym = mfnSym->sdNextInScope)
  1484.     {
  1485.         SymDef          ovlSym;
  1486.  
  1487.         if (mfnSym->sdSymKind != SYM_FNC)
  1488.             continue;
  1489.  
  1490.         ovlSym = mfnSym;
  1491.         do
  1492.         {
  1493.             if  (ovlSym->sdFnc.sdfMDtoken == methTok)
  1494.                 return  ovlSym;
  1495.  
  1496.             ovlSym = ovlSym->sdFnc.sdfNextOvl;
  1497.         }
  1498.         while (ovlSym);
  1499.     }
  1500. #ifdef  DEBUG
  1501.     printf("Could not find accessor for %s [%08X]\n", propSym->sdSpelling(), methTok);
  1502. #endif
  1503.  
  1504.     return  NULL;
  1505. }
  1506.  
  1507. /*****************************************************************************
  1508.  *
  1509.  *  Import metadata for a single class.
  1510.  */
  1511.  
  1512. SymDef              metadataImp::MDimportClss(mdTypeDef td,
  1513.                                               SymDef    clsSym,
  1514.                                               unsigned  assx, bool deep)
  1515. {
  1516.     WMetaDataImport*wmdi = MDwmdi;
  1517.  
  1518.     bool            fileScope;
  1519.  
  1520.     TypDef          clsTyp;
  1521.     str_flavors     clsKind;
  1522.     Ident           clsIden;
  1523.  
  1524.     WCHAR           scpName[MAX_CLASS_NAME];
  1525. //  WCHAR           clsName[MAX_CLASS_NAME];
  1526.     CLASSVERSION    ver;
  1527.  
  1528.     DWORD           typeFlg;
  1529.  
  1530.     mdTypeRef       baseTok;
  1531.  
  1532.     /* Do we already have a class symbol? */
  1533.  
  1534.     if  (clsSym)
  1535.     {
  1536.         /* Presumably we're importing the members of the class/enum */
  1537.  
  1538.         assert(td == 0);
  1539.         assert(clsSym->sdSymKind == SYM_ENUM ||
  1540.                clsSym->sdSymKind == SYM_CLASS);
  1541.         assert(clsSym->sdIsImport);
  1542.         assert(clsSym->sdCompileState < CS_DECLARED);
  1543.  
  1544.         /* Get hold of the token for the class */
  1545.  
  1546.         td = (clsSym->sdSymKind == SYM_CLASS) ? clsSym->sdClass.sdcMDtypedef
  1547.                                               : clsSym->sdEnum .sdeMDtypedef;
  1548.     }
  1549.  
  1550.     if  (!td)
  1551.     {
  1552.         /* We're importing the global scope */
  1553.  
  1554.         fileScope = true;
  1555.  
  1556. #ifdef  DEBUG
  1557.         if  (MDcomp->cmpConfig.ccVerbose >= 4) printf("Import Filescope\n");
  1558. #endif
  1559.  
  1560.         /* We'll enter any symbols we find in the global namespace */
  1561.  
  1562.         clsSym = MDcomp->cmpGlobalNS;
  1563.     }
  1564.     else
  1565.     {
  1566.         unsigned        typContextVal;
  1567.         bool            typIsDelegate;
  1568.         bool            typIsStruct;
  1569.         bool            typIsEnum;
  1570.  
  1571.         char            nameTemp[MAX_CLASS_NAME];
  1572.  
  1573.         const   char *  clsName;
  1574.         SymDef          scopeSym;
  1575.         symbolKinds     symKind;
  1576.         accessLevels    clsAcc;
  1577.  
  1578.         fileScope = false;
  1579.  
  1580.         /* Ask for the details for the current typedef */
  1581.  
  1582.         if  (wmdi->GetNameFromToken(td, &clsName))
  1583.             MDcomp->cmpFatal(ERRreadMD);
  1584.  
  1585.         if  (wmdi->GetTypeDefProps(td,
  1586.                                    scpName, sizeof(scpName)/sizeof(scpName[0])-1, NULL,
  1587.                                    &ver,
  1588.                                    &typeFlg,
  1589.                                    &baseTok))
  1590.         {
  1591.             MDcomp->cmpFatal(ERRreadMD);
  1592.         }
  1593.  
  1594.         /*
  1595.             Sad thing: we have to resolve the base class (if any) to detect
  1596.             things such as structs and enums (no, I'm not making this up).
  1597.          */
  1598.  
  1599.         typContextVal = 0;
  1600.         typIsDelegate = false;
  1601.         typIsStruct   = false;
  1602.         typIsEnum     = false;
  1603.  
  1604. #if 1   // check for old-style flags [this will disappear soon]
  1605.         if  (typeFlg & tdEnum     ) typIsEnum   = true;
  1606.         if  (typeFlg & tdValueType) typIsStruct = true;
  1607. #endif
  1608.  
  1609.         if  (baseTok && baseTok != mdTypeRefNil)
  1610.         {
  1611.             char            nameBuff[MAX_CLASS_NAME];
  1612.             const   char *  typeName;
  1613.  
  1614.             if  (TypeFromToken(baseTok) == mdtTypeRef)
  1615.             {
  1616.                 WCHAR           clsTypeName[MAX_CLASS_NAME];
  1617.  
  1618.                 /* Get hold of the base class name */
  1619.  
  1620.                 if  (MDwmdi->GetTypeRefProps(baseTok,
  1621.                                              0,
  1622.                                              clsTypeName,
  1623.                                              arraylen(clsTypeName),
  1624.                                              NULL))
  1625.                     goto NOT_HW_BASE;
  1626.  
  1627.                 if  (wcsncmp(clsTypeName, L"System.", 7))
  1628.                     goto NOT_HW_BASE;
  1629.  
  1630.                 /* Convert the class name to normal characters */
  1631.  
  1632.                 wcstombs(nameBuff, clsTypeName+7, sizeof(nameBuff)-1);
  1633.  
  1634.                 typeName = nameBuff;
  1635.             }
  1636.             else
  1637.             {
  1638.                 SymDef          baseSym;
  1639.  
  1640.                 /* Get hold the base class type */
  1641.  
  1642.                 baseSym = MDimportClss(baseTok, NULL, 0, false);
  1643.                 assert(baseSym && baseSym->sdSymKind == SYM_CLASS);
  1644.  
  1645.                 /* Does the class belong to "System" ? */
  1646.  
  1647.                 if  (baseSym->sdParent != MDcomp->cmpNmSpcSystem)
  1648.                     goto NOT_HW_BASE;
  1649.  
  1650.                 /* Get hold of the class name */
  1651.  
  1652.                 typeName = baseSym->sdSpelling();
  1653.             }
  1654.  
  1655.             if      (!strcmp(typeName,          "Delegate") ||
  1656.                      !strcmp(typeName, "MulticastDelegate"))
  1657.             {
  1658.                 typIsDelegate = true;
  1659.             }
  1660.             else if (!strcmp(typeName, "ValueType"))
  1661.             {
  1662.                 typIsStruct   = true;
  1663.             }
  1664.             else if (!strcmp(typeName, "Enum"))
  1665.             {
  1666.                 typIsEnum     = true;
  1667.             }
  1668.             else if (!strcmp(typeName, "MarshalByRefObject"))
  1669.             {
  1670.                 typContextVal = 1;
  1671.             }
  1672.             else if (!strcmp(typeName, "ContextBoundObject"))
  1673.             {
  1674.                 typContextVal = 2;
  1675.             }
  1676.         }
  1677.  
  1678.     NOT_HW_BASE:
  1679.  
  1680.         // ISSUE: The following is a nasty hack
  1681.  
  1682.         WCHAR       *   scpNameTmp = wcsrchr(scpName, '.');
  1683.  
  1684.         if  (scpNameTmp)
  1685.             *scpNameTmp = 0;
  1686.         else
  1687.             scpName[0] = 0;
  1688.  
  1689. #ifdef  DEBUG
  1690.  
  1691.         if  (MDcomp->cmpConfig.ccVerbose >= 4)
  1692.         {
  1693.             printf("Import [%08X] ", assx);
  1694.  
  1695.             if      (typIsEnum)
  1696.                 printf("Enum      ");
  1697.             else if (typeFlg & tdInterface)
  1698.                 printf("Interface ");
  1699.             else
  1700.                 printf("Class     ");
  1701.  
  1702.             if  (scpName[0])
  1703.                 printf("%ls.", scpName);
  1704.  
  1705.             printf("%s'\n", clsName);
  1706.         }
  1707.  
  1708. #endif
  1709.  
  1710. //      if  (!strcmp(clsName, "AttributeTargets")) printf("Import class '%s'\n", clsName);
  1711.  
  1712.         /* Is this a nested class ? */
  1713.  
  1714.         assert(tdNotPublic < tdPublic);
  1715.  
  1716.         if  ((typeFlg & tdVisibilityMask) > tdPublic)
  1717.         {
  1718.             mdTypeDef           outerTok;
  1719.             TypDef              outerCls;
  1720.  
  1721.             if  (wmdi->GetNestedClassProps(td, &outerTok))
  1722.                 MDcomp->cmpFatal(ERRreadMD);
  1723.  
  1724.             // TEMP HACK: Ignore nesting if name is mangled !!!!!!!
  1725.  
  1726.             if  (!strchr(clsName, '$'))
  1727.             {
  1728.                 /* Resolve the outer class token to a class symbol */
  1729.  
  1730.                 outerCls = MDimportClsr(outerTok, false); assert(outerCls);
  1731.                 scopeSym = outerCls->tdClass.tdcSymbol;
  1732.  
  1733.                 goto GOT_SCP;
  1734.             }
  1735.         }
  1736.  
  1737.         /* Enter this class/interface in the global symbol table */
  1738.  
  1739.         if  (*scpName)
  1740.         {
  1741.             if  (wcscmp(MDprevNam, scpName))
  1742.             {
  1743.                 bool            toss;
  1744.  
  1745.                 /* The namespace has changed, enter it in the symbol table */
  1746.  
  1747.                 wcscpy(MDprevNam, scpName);
  1748.  
  1749.                 MDprevSym = MDparseDotted(scpName, SYM_NAMESPACE, &toss);
  1750.             }
  1751.  
  1752.             scopeSym = MDprevSym;
  1753.         }
  1754.         else
  1755.         {
  1756.             scopeSym = MDcomp->cmpGlobalNS;
  1757.         }
  1758.  
  1759.     GOT_SCP:
  1760.  
  1761.         /* Remember that the namespace contains import members */
  1762.  
  1763.         scopeSym->sdIsImport = true;
  1764.  
  1765.         /* Figure out what kind of a symbol we're dealing with */
  1766.  
  1767.         if  (typIsEnum)
  1768.         {
  1769.             symKind = SYM_ENUM;
  1770.         }
  1771.         else
  1772.         {
  1773.             symKind = SYM_CLASS;
  1774.  
  1775.             if      (typIsStruct)
  1776.                 clsKind = STF_STRUCT;
  1777.             else if (typeFlg & tdInterface)
  1778.                 clsKind = STF_INTF;
  1779.             else
  1780.                 clsKind = STF_CLASS;
  1781.         }
  1782.  
  1783.         /* Figure out the access level of the class */
  1784.  
  1785.         switch (typeFlg & tdVisibilityMask)
  1786.         {
  1787.         case tdPublic:
  1788.         case tdNestedPublic:        clsAcc = ACL_PUBLIC   ; break;
  1789.         case tdNestedFamily:        clsAcc = ACL_PROTECTED; break;
  1790.         case tdNestedPrivate:       clsAcc = ACL_PRIVATE  ; break;
  1791.  
  1792. //      case tdNotPublic:
  1793. //      case tdNestedAssembly:
  1794. //      case tdNestedFamANDAssem:
  1795. //      case tdNestedFamORAssem:
  1796.         default:                    clsAcc = ACL_DEFAULT  ; break;
  1797.         }
  1798.  
  1799.         /* Awful hack - check for mangled nested class name */
  1800.  
  1801.         if  (strchr(clsName, '$') && *clsName != '$')
  1802.         {
  1803.             strcpy(nameTemp, clsName);
  1804.  
  1805.             for (clsName = nameTemp;;)
  1806.             {
  1807.                 char *          dollar;
  1808.                 SymDef          scpSym;
  1809.  
  1810.                 dollar = strchr(clsName, '$');
  1811.                 if  (!dollar)
  1812.                     break;
  1813.  
  1814.                 *dollar = 0;
  1815.  
  1816. //              printf("Outer class name: '%s'\n", clsName);
  1817.  
  1818.                 assert(*clsName);
  1819.  
  1820.                 clsIden = MDcomp->cmpGlobalHT->hashString(clsName);
  1821.  
  1822.                 if  (scopeSym->sdSymKind == SYM_CLASS)
  1823.                     scpSym  = MDstab->stLookupScpSym(clsIden,          scopeSym);
  1824.                 else
  1825.                     scpSym  = MDstab->stLookupNspSym(clsIden, NS_NORM, scopeSym);
  1826.  
  1827.                 if  (!scpSym)
  1828.                 {
  1829.                     /* Outer class doesn't exist, declare it now */
  1830.  
  1831.                     scpSym = MDstab->stDeclareSym(clsIden, SYM_CLASS, NS_NORM, scopeSym);
  1832.  
  1833.                     /* Well, we don't really know anything at all about this class */
  1834.  
  1835.                     scpSym->sdCompileState = CS_NONE;
  1836.                 }
  1837.  
  1838.                 scopeSym = scpSym;
  1839.                 clsName  = dollar + 1;
  1840.             }
  1841.  
  1842. //          printf("Final class name: '%s'\n", clsName);
  1843.         }
  1844.  
  1845.         clsIden = MDcomp->cmpGlobalHT->hashString(clsName);
  1846.  
  1847.         /* Note that the caller may have supplied the symbol */
  1848.  
  1849.         if  (!clsSym)
  1850.         {
  1851.             if  (scopeSym->sdSymKind == SYM_CLASS)
  1852.                 clsSym = MDstab->stLookupScpSym(clsIden,          scopeSym);
  1853.             else
  1854.                 clsSym = MDstab->stLookupNspSym(clsIden, NS_NORM, scopeSym);
  1855.         }
  1856.  
  1857.         if  (clsSym)
  1858.         {
  1859.             /* Symbol already exists, make sure it's the right kind */
  1860.  
  1861.             if  (clsSym->sdSymKindGet() != symKind)
  1862.             {
  1863.                 /* Issue an error message or something? */
  1864.  
  1865.                 UNIMPL(!"unexpected redef of class/enum symbol, now what?");
  1866.             }
  1867.  
  1868.             // ISSUE: We also need to check that (BYTE)clsSym->sdClass.sdcFlavor != (BYTE)clsKind), right?
  1869.  
  1870.             /* Bail if this type has already been imported */
  1871.  
  1872.             if  (clsSym->sdCompileState >= CS_DECLARED)
  1873.                 return clsSym;
  1874.  
  1875.             clsTyp = clsSym->sdType;
  1876.             if  (clsTyp == NULL)
  1877.                 goto DCL_CLS;
  1878.  
  1879.             if  (clsSym->sdCompileState == CS_NONE)
  1880.             {
  1881.                 assert(clsTyp == NULL);
  1882.                 goto DCL_CLS;
  1883.             }
  1884.  
  1885.             /* The access level of the type should agree, right? */
  1886.  
  1887.             assert(clsSym->sdAccessLevel == clsAcc || scopeSym->sdSymKind == SYM_CLASS);
  1888.         }
  1889.         else
  1890.         {
  1891.             /* Class not known yet, declare it */
  1892.  
  1893.             clsSym = MDstab->stDeclareSym(clsIden, symKind, NS_NORM, scopeSym);
  1894.  
  1895.         DCL_CLS:
  1896.  
  1897.             /* Assume everything is managed until proven otherwise */
  1898.  
  1899.             clsSym->sdIsManaged   = true;
  1900.  
  1901.             /* Check for any custom attributes on the type */
  1902.  
  1903. //          if  (MDwmdi->GetCustomAttributeByName(td,                   L"Deprecated", NULL, NULL) == S_OK)
  1904. //              clsSym->sdIsDeprecated = true;
  1905. //          if  (MDwmdi->GetCustomAttributeByName(td, L"System.Attributes.Deprecated", NULL, NULL) == S_OK)
  1906. //              clsSym->sdIsDeprecated = true;
  1907. //          if  (MDwmdi->GetCustomAttributeByName(td,     L"System.ObsoleteAttribute", NULL, NULL) == S_OK)
  1908. //              clsSym->sdIsDeprecated = true;
  1909.  
  1910.             MDchk4CustomAttrs(clsSym, td);
  1911.  
  1912.             /* Record the access level of the type */
  1913.  
  1914.             clsSym->sdAccessLevel = clsAcc;
  1915.  
  1916.             /* Create the class/enum type */
  1917.  
  1918.             if  (symKind == SYM_CLASS)
  1919.             {
  1920.                 /* Record the "flavor" (i.e. class/struct/union) */
  1921.  
  1922.                 clsSym->sdClass.sdcFlavor = clsKind;
  1923.  
  1924.                 /* We can now create the class type */
  1925.  
  1926.                 clsTyp = MDstab->stNewClsType(clsSym);
  1927.  
  1928.                 /* Has explicit layout been specified for the class ? */
  1929.  
  1930.                 if  ((typeFlg & tdLayoutMask) == tdExplicitLayout)
  1931.                 {
  1932.                     DWORD           al;
  1933.                     ULONG           fc;
  1934.                     ULONG           sz;
  1935.  
  1936. //                  clsSym->sdIsManaged = false;
  1937.  
  1938.                     if  (wmdi->GetClassLayout(td, &al, NULL, 0, &fc, &sz))
  1939.                         MDcomp->cmpFatal(ERRreadMD);
  1940.  
  1941. //                  printf("Layout info [%u,%u] for class '%s'\n", sz, al, clsSym->sdSpelling());
  1942.  
  1943.                     clsTyp->tdClass.tdcSize       = sz;
  1944.                     clsTyp->tdClass.tdcAlignment  = MDcomp->cmpEncodeAlign(al);
  1945.                     clsTyp->tdClass.tdcLayoutDone = true;
  1946.  
  1947. #if 0
  1948.  
  1949.                     if  (fc)
  1950.                     {
  1951.                         COR_FIELD_OFFSET *  fldOffs;
  1952.  
  1953.                         COR_FIELD_OFFSET *  fldPtr;
  1954.                         unsigned            fldCnt;
  1955.  
  1956.                         printf("%3u field offset records for '%s'\n", fc, clsSym->sdSpelling());
  1957.  
  1958.                         fldOffs = new COR_FIELD_OFFSET[fc];
  1959.  
  1960.                         if  (wmdi->GetClassLayout(td, &al, fldOffs, fc, &fc, &sz))
  1961.                             MDcomp->cmpFatal(ERRreadMD);
  1962.  
  1963.                         for (fldCnt = fc, fldPtr = fldOffs;
  1964.                              fldCnt;
  1965.                              fldCnt--   , fldPtr++)
  1966.                         {
  1967.                             printf("    Field [rid=%08X,%s=%04X]\n", fldPtr->ridOfField,
  1968.                                                                      (typeFlg & tdExplicitLayout) ? "offs" : "seq#",
  1969.                                                                      fldPtr->ulOffset);
  1970.                         }
  1971.  
  1972.                         printf("\n");
  1973.  
  1974.                         delete [] fldOffs;
  1975.                     }
  1976.  
  1977. #endif
  1978.  
  1979.                 }
  1980.  
  1981.                 /* Remember whether this is a value type */
  1982.  
  1983.                 if  (typIsStruct)
  1984.                 {
  1985.                     clsTyp->tdClass.tdcValueType = true;
  1986.  
  1987.                     if  ((typeFlg & tdUnmanagedValueType) == tdUnmanagedValueType)
  1988.                     {
  1989.                         clsSym->sdIsManaged = false;
  1990.                         clsTyp->tdIsManaged = false;
  1991.                     }
  1992.                 }
  1993.  
  1994.                 /* Check for a "known" class name */
  1995.  
  1996.                 if  ((hashTab::getIdentFlags(clsIden) & IDF_PREDEF) &&
  1997.                      scopeSym == MDcomp->cmpNmSpcSystem)
  1998.                 {
  1999.                     MDcomp->cmpMarkStdType(clsSym);
  2000.                 }
  2001.             }
  2002.             else
  2003.             {
  2004.                 clsSym->sdType = clsTyp = MDstab->stNewEnumType(clsSym);
  2005.  
  2006.                 // HACK!!!!!!!!!!!!!!!!!!!!
  2007.  
  2008.                 clsTyp->tdEnum.tdeIntType = MDstab->stIntrinsicType(TYP_INT);
  2009.             }
  2010.  
  2011.             /* The class/enum is now in a slightly better shape now */
  2012.  
  2013.             clsSym->sdCompileState = CS_KNOWN;
  2014.         }
  2015.  
  2016. #if 0
  2017.         if  (!strcmp(clsSym->sdSpelling(), "SystemException"))
  2018.             printf("Import type '%s'\n", clsSym->sdSpelling());
  2019. #endif
  2020.  
  2021.         /* Mark the type symbol as a metadata import */
  2022.  
  2023.         clsSym->sdIsImport            = true;
  2024.         clsSym->sdCompileState        = CS_KNOWN;
  2025.  
  2026.         /* Are we importing a class or emum ? */
  2027.  
  2028.         if  (symKind == SYM_CLASS)
  2029.         {
  2030.             /* Remember where the class type came from */
  2031.  
  2032.             clsSym->sdClass.sdcMDtypedef  = td;
  2033.             clsSym->sdClass.sdcMDtypeImp  = 0;
  2034.             clsSym->sdClass.sdcMDimporter = this;
  2035.  
  2036.             if  (typeFlg & tdAbstract)
  2037.                 clsSym->sdIsAbstract = true;
  2038.             if  (typeFlg & tdSealed)
  2039.                 clsSym->sdIsSealed   = true;
  2040.  
  2041.             /* Record the owning assembly (if we don't have one already) */
  2042.  
  2043.             if  (clsSym->sdClass.sdcAssemIndx == 0)
  2044.                  clsSym->sdClass.sdcAssemIndx = assx;
  2045.  
  2046.             /* Is the class a delegate ? */
  2047.  
  2048.             if  (typIsDelegate)
  2049.             {
  2050.                 clsTyp = clsSym->sdType;
  2051.  
  2052.                 assert(clsTyp && clsTyp->tdTypeKind == TYP_CLASS);
  2053.  
  2054.                 clsTyp->tdClass.tdcFnPtrWrap = true;
  2055.                 clsTyp->tdClass.tdcFlavor    =
  2056.                 clsSym->sdClass.sdcFlavor    = STF_DELEGATE;
  2057.             }
  2058.         }
  2059.         else
  2060.         {
  2061.             clsSym->sdEnum .sdeMDtypedef  = td;
  2062.             clsSym->sdEnum .sdeMDtypeImp  = 0;
  2063.             clsSym->sdEnum .sdeMDimporter = this;
  2064.  
  2065.             /* Record the owning assembly (if we don't have one already) */
  2066.  
  2067.             if  (clsSym->sdEnum .sdeAssemIndx == 0)
  2068.                  clsSym->sdEnum .sdeAssemIndx = assx;
  2069.         }
  2070.  
  2071.         /* Are we supposed to suck the members of the class/enum ? */
  2072.  
  2073.         if  (!deep)
  2074.             return  clsSym;
  2075.  
  2076.         /* The class/enum type will be 'declared' shortly */
  2077.  
  2078.         clsSym->sdCompileState = CS_DECLARED;
  2079.         clsSym->sdIsDefined    = true;
  2080.  
  2081.         /* Skip the next part if we have an enum type */
  2082.  
  2083.         if  (symKind == SYM_ENUM)
  2084.         {
  2085.             clsSym->sdCompileState = CS_CNSEVALD;
  2086.  
  2087.             assert(clsTyp);
  2088.             assert(clsTyp->tdTypeKind == TYP_ENUM);
  2089.  
  2090.             goto SUCK_MEMS;
  2091.         }
  2092.  
  2093.         assert(symKind == SYM_CLASS);
  2094.  
  2095.         /* Get hold of the class type */
  2096.  
  2097.         clsTyp = clsSym->sdType; assert(clsTyp && clsTyp->tdTypeKind == TYP_CLASS);
  2098.  
  2099.         /* Recursively import the base class, if one is present */
  2100.  
  2101.         if  (baseTok && baseTok != mdTypeRefNil)
  2102.         {
  2103.             TypDef          baseTyp;
  2104.  
  2105.             if  (TypeFromToken(baseTok) == mdtTypeRef)
  2106.                 baseTyp = MDimportClsr(baseTok, false);
  2107.             else
  2108.                 baseTyp = MDimportClss(baseTok, NULL, 0, deep)->sdType;
  2109.  
  2110.             /* Record the base class */
  2111.  
  2112.             clsTyp->tdClass.tdcBase      = baseTyp;
  2113.             clsTyp->tdClass.tdcFnPtrWrap = baseTyp->tdClass.tdcFnPtrWrap;
  2114.  
  2115.             /* If the base class is "Delegate", so is this class */
  2116.  
  2117.             if  (baseTyp->tdClass.tdcFlavor == STF_DELEGATE)
  2118.             {
  2119.                 clsTyp->tdClass.tdcFlavor =
  2120.                 clsSym->sdClass.sdcFlavor = STF_DELEGATE;
  2121.             }
  2122.         }
  2123.         else
  2124.         {
  2125.             /* We set the base of all interfaces to "Object" */
  2126.  
  2127.             if  (clsTyp->tdClass.tdcFlavor == STF_INTF)
  2128.                 clsTyp->tdClass.tdcBase = MDcomp->cmpClassObject->sdType;
  2129.         }
  2130.  
  2131.         /* Is this a value type with an explicit layout? */
  2132.  
  2133.         if  (typeFlg & tdExplicitLayout)
  2134.         {
  2135.             assert(clsTyp->tdClass.tdcLayoutDone);
  2136.         }
  2137.         else
  2138.         {
  2139.             clsTyp->tdClass.tdcAlignment  = 0;
  2140.             clsTyp->tdClass.tdcSize       = 0;
  2141.         }
  2142.  
  2143.         /* Ask for any interfaces the class includes */
  2144.  
  2145.         const unsigned  intfMax  = 8;
  2146.         HCORENUM        intfEnum = NULL;
  2147.         mdInterfaceImpl intfToks[intfMax];
  2148.         ULONG           intfCnt;
  2149.  
  2150.         TypList         intfList = NULL;
  2151.         TypList         intfLast = NULL;
  2152.  
  2153.         for (;;)
  2154.         {
  2155.             unsigned        intfNum;
  2156.  
  2157.             if  (MDwmdi->EnumInterfaceImpls(&intfEnum,
  2158.                                             td,
  2159.                                             intfToks,
  2160.                                             intfMax,
  2161.                                             &intfCnt))
  2162.             {
  2163.                 break;
  2164.             }
  2165.  
  2166.             if  (!intfCnt)
  2167.                 break;
  2168.  
  2169.             for (intfNum = 0; intfNum < intfCnt; intfNum++)
  2170.             {
  2171.                 mdTypeDef       intfClass;
  2172.                 mdTypeRef       intfIntf;
  2173.                 TypDef          intfType;
  2174.  
  2175.                 if  (MDwmdi->GetInterfaceImplProps(intfToks[intfNum],
  2176.                                                    &intfClass,
  2177.                                                    &intfIntf))
  2178.                 {
  2179.                     MDcomp->cmpFatal(ERRreadMD);
  2180.                 }
  2181.  
  2182.                 if  (TypeFromToken(intfIntf) == mdtTypeRef)
  2183.                     intfType = MDimportClsr(intfIntf, false);
  2184.                 else
  2185.                     intfType = MDimportClss(intfIntf, NULL, 0, deep)->sdType;
  2186.  
  2187.                 /* Add an entry to the interface list */
  2188.  
  2189.                 intfList = MDstab->stAddIntfList(intfType, intfList, &intfLast);
  2190.             }
  2191.         }
  2192.  
  2193.         clsSym->sdType->tdClass.tdcIntf = intfList;
  2194.     }
  2195.  
  2196. SUCK_MEMS:
  2197.  
  2198.     /* Iterate over all members (fields and methods) */
  2199.  
  2200.     HCORENUM        memEnum;
  2201.     unsigned        memNum;
  2202.  
  2203.     for (memEnum = NULL, memNum = 0;; memNum++)
  2204.     {
  2205.         unsigned        memInd;
  2206.         mdMemberRef     memDsc[32];
  2207.         ULONG           memCnt;
  2208.  
  2209.         /* Get the next batch of members */
  2210.  
  2211.         if  (wmdi->EnumMembers(&memEnum,
  2212.                                td,
  2213.                                memDsc,
  2214.                                sizeof(memDsc)/sizeof(memDsc[0]),
  2215.                                &memCnt) != S_OK)
  2216.             break;
  2217.  
  2218.         /* If we got no members we must be done */
  2219.  
  2220.         if  (!memCnt)
  2221.             break;
  2222.  
  2223.         for (memInd=0; memInd < memCnt; ++memInd)
  2224.         {
  2225.             Ident           memIden;
  2226.             SymDef          memSym;
  2227.  
  2228. //          WCHAR           memName[255];   // ISSUE: fixed-size buffer?????
  2229.             const   char *  memName;
  2230.  
  2231.             PCCOR_SIGNATURE sigAddr;
  2232.             ULONG           sigSize;
  2233.  
  2234.             ULONG           memFlag;
  2235.             ULONG           cnsType;
  2236.             const   void *  cnsAddr;
  2237.             ULONG           cbValue;
  2238.  
  2239.             DWORD           attrs;
  2240.  
  2241.             /* Get the scoop on this member */
  2242.  
  2243.             if  (wmdi->GetNameFromToken(memDsc[memInd], &memName))
  2244.             {
  2245.                 MDcomp->cmpFatal(ERRreadMD);
  2246.             }
  2247.  
  2248.             if  (wmdi->GetMemberProps(memDsc[memInd],
  2249.                                       NULL,
  2250. //                                    memName, sizeof(memName)/sizeof(memName[0])-1, 0,
  2251.                                       NULL, 0, NULL,
  2252.                                       &attrs,
  2253.                                       &sigAddr, &sigSize,
  2254.                                       NULL,
  2255.                                       &memFlag,
  2256.                                       &cnsType, &cnsAddr, &cbValue))
  2257.             {
  2258.                 MDcomp->cmpFatal(ERRreadMD);
  2259.             }
  2260.  
  2261.             /* Hash the member name into our hash table */
  2262.  
  2263.             memIden = MDcomp->cmpGlobalHT->hashString(memName);
  2264. //          memIden = MDhashWideName(memName);
  2265.  
  2266.             /* Import/convert the member */
  2267.  
  2268.             memSym  = MDimportMem(clsSym,
  2269.                                   memIden,
  2270.                                   memDsc[memInd],
  2271.                                   attrs,
  2272.                                   false,
  2273.                                   fileScope,
  2274.                                   sigAddr,
  2275.                                   sigSize);
  2276.             if  (!memSym)
  2277.                 continue;
  2278.  
  2279.             memSym->sdIsManaged = clsSym->sdIsManaged;
  2280.  
  2281.             /* Is this a data or function or enum member? */
  2282.  
  2283.             if  (memSym->sdSymKind == SYM_FNC)
  2284.             {
  2285.                 if  (memFlag & mdPinvokeImpl)
  2286.                     memSym->sdFnc.sdfNative = true;
  2287.             }
  2288.             else
  2289.             {
  2290.                 assert(memSym->sdSymKind == SYM_VAR ||
  2291.                        memSym->sdSymKind == SYM_ENUMVAL);
  2292.  
  2293.                 /* Is this a constant? */
  2294.  
  2295.                 if  (cnsAddr)
  2296.                 {
  2297.                     var_types       vtyp;
  2298.                     ConstVal        cptr;
  2299.  
  2300.                     /* Allocate space for the constant value, if this is a variable */
  2301.  
  2302.                     if  (memSym->sdSymKind == SYM_VAR)
  2303.                     {
  2304. #if MGDDATA
  2305.                         cptr = new ConstVal;
  2306. #else
  2307.                         cptr =    (ConstVal)MDcomp->cmpAllocPerm.nraAlloc(sizeof(*cptr));
  2308. #endif
  2309.                     }
  2310.  
  2311.                     switch (cnsType)
  2312.                     {
  2313.                         __int32         ival;
  2314.  
  2315.                     case ELEMENT_TYPE_BOOLEAN:
  2316.                     case ELEMENT_TYPE_U1:
  2317.                         ival = *(unsigned char  *)cnsAddr;
  2318.                         goto INT_CNS;
  2319.  
  2320.                     case ELEMENT_TYPE_I1:
  2321.                         ival = *(  signed char  *)cnsAddr;
  2322.                         goto INT_CNS;
  2323.  
  2324.                     case ELEMENT_TYPE_I2:
  2325.                         ival = *(  signed short *)cnsAddr;
  2326.                         goto INT_CNS;
  2327.  
  2328.                     case ELEMENT_TYPE_U2:
  2329.                     case ELEMENT_TYPE_CHAR:
  2330.                         ival = *(unsigned short *)cnsAddr;
  2331.                         goto INT_CNS;
  2332.  
  2333.                     case ELEMENT_TYPE_I4:
  2334.                     case ELEMENT_TYPE_U4:
  2335.                         ival = *(           int *)cnsAddr;
  2336.  
  2337.                     INT_CNS:
  2338.  
  2339.                         /* Special case: enum member */
  2340.  
  2341.                         if  (memSym->sdSymKind == SYM_ENUMVAL)
  2342.                         {
  2343.                             memSym->sdEnumVal.sdEV.sdevIval = ival;
  2344.  
  2345.                         DONE_EMV:
  2346.  
  2347.                             assert(clsTyp);
  2348.                             assert(clsTyp->tdTypeKind == TYP_ENUM);
  2349.  
  2350.                             memSym->sdType = clsTyp;
  2351.  
  2352.                             goto DONE_INI;
  2353.                         }
  2354.                         cptr->cvValue.cvIval = ival;
  2355.                         break;
  2356.  
  2357.                     case ELEMENT_TYPE_I8:
  2358.                     case ELEMENT_TYPE_U8:
  2359.                         if  (memSym->sdSymKind == SYM_ENUMVAL)
  2360.                         {
  2361.                             UNIMPL(!"record 64-bit enum value");
  2362.                             goto DONE_EMV;
  2363.                         }
  2364.                         cptr->cvValue.cvLval = *(__int64*)cnsAddr;
  2365.                         break;
  2366.  
  2367.                     case ELEMENT_TYPE_R4:
  2368.                         assert(memSym->sdSymKind == SYM_VAR);
  2369.                         cptr->cvValue.cvFval = *(float  *)cnsAddr;
  2370.                         break;
  2371.  
  2372.                     case ELEMENT_TYPE_R8:
  2373.                         assert(memSym->sdSymKind == SYM_VAR);
  2374.                         cptr->cvValue.cvDval = *(double *)cnsAddr;
  2375.                         break;
  2376.  
  2377.                     case ELEMENT_TYPE_STRING:
  2378.                         assert(memSym->sdSymKind == SYM_VAR);
  2379.                         cptr->cvValue.cvSval = MDcomp->cmpSaveStringCns((wchar*)cnsAddr,
  2380.                                                                  wcslen((wchar*)cnsAddr));
  2381.                         cptr->cvType  = memSym->sdType;
  2382.                         cptr->cvVtyp  = memSym->sdType->tdTypeKindGet();
  2383.                         cptr->cvHasLC = false;
  2384.                         goto DONE_CNS;
  2385.  
  2386.                     default:
  2387.                         NO_WAY(!"Unexpected const type in metadata");
  2388.                         break;
  2389.                     }
  2390.  
  2391.                     /* Record the type of the constant */
  2392.  
  2393.                     assert(cnsType < arraylen(CORtypeToSMCtype));
  2394.  
  2395.                     cptr->cvVtyp = vtyp = (var_types)CORtypeToSMCtype[cnsType];
  2396.                     cptr->cvType = MDstab->stIntrinsicType(vtyp);
  2397.  
  2398.                 DONE_CNS:
  2399.  
  2400.                     /* Remember the fact that this is a constant variable */
  2401.  
  2402.                     memSym->sdVar.sdvConst  = true;
  2403.                     memSym->sdVar.sdvCnsVal = cptr;
  2404.  
  2405.                 DONE_INI:
  2406.  
  2407.                     memSym->sdCompileState  = CS_CNSEVALD;
  2408.                 }
  2409.             }
  2410.  
  2411. #ifdef  DEBUG
  2412.  
  2413.             if  (MDcomp->cmpConfig.ccVerbose >= 4)
  2414.             {
  2415.                 if  (fileScope)
  2416.                 {
  2417.                     printf("       %-10s", (memSym->sdSymKind == SYM_FNC) ? "Function" : "Variable");
  2418.                 }
  2419.                 else
  2420.                 {
  2421.                     printf("       %-10s", (memSym->sdSymKind == SYM_FNC) ? "Method" : "Field");
  2422.                 }
  2423.  
  2424.                 printf("'%s'\n", MDstab->stTypeName(NULL, memSym, NULL, NULL));
  2425.             }
  2426.  
  2427. #endif
  2428.  
  2429.             /* This member is now fully declared */
  2430.  
  2431.             memSym->sdCompileState = CS_DECLARED;
  2432.         }
  2433.     }
  2434.  
  2435.     wmdi->CloseEnum(memEnum);
  2436.  
  2437.     /* Iterate over all properties */
  2438.  
  2439.     HCORENUM        propEnum;
  2440.     unsigned        propNum;
  2441.  
  2442.     for (propEnum = NULL, propNum = 0;; propNum++)
  2443.     {
  2444.         unsigned        propInd;
  2445.         mdProperty      propDsc[32];
  2446.         ULONG           propCnt;
  2447.  
  2448.         /* Get the next batch of properties */
  2449.  
  2450.         if  (wmdi->EnumProperties(&propEnum,
  2451.                                   td,
  2452.                                   propDsc,
  2453.                                   sizeof(propDsc)/sizeof(propDsc[0]),
  2454.                                   &propCnt) != S_OK)
  2455.             break;
  2456.  
  2457.         /* If we got no properties we must be done */
  2458.  
  2459.         if  (!propCnt)
  2460.             break;
  2461.  
  2462.         for (propInd=0; propInd < propCnt; ++propInd)
  2463.         {
  2464.             Ident           propIden;
  2465.             const   char *  propName;
  2466.             TypDef          propType;
  2467.             SymDef          propSym;
  2468.  
  2469.             PCCOR_SIGNATURE sigAddr;
  2470.             ULONG           sigSize;
  2471.  
  2472.             mdMethodDef     propGet;
  2473.             mdMethodDef     propSet;
  2474.  
  2475.             DWORD           flags;
  2476.             SymDef          sym;
  2477.  
  2478.             /* Get the scoop on this property */
  2479.  
  2480.             if  (wmdi->GetNameFromToken(propDsc[propInd], &propName))
  2481.                 MDcomp->cmpFatal(ERRreadMD);
  2482.  
  2483.             if  (wmdi->GetPropertyProps(propDsc[propInd],
  2484.                                         NULL,
  2485.                                         NULL, 0, NULL,
  2486.                                         &flags,
  2487.                                         &sigAddr, &sigSize,
  2488.                                         NULL, NULL, NULL,
  2489.                                         &propSet,
  2490.                                         &propGet,
  2491.                                         NULL, 0, NULL,
  2492.                                         NULL))
  2493.             {
  2494.                 MDcomp->cmpFatal(ERRreadMD);
  2495.             }
  2496.  
  2497.             /* Hash the property name into our hash table */
  2498.  
  2499.             propIden = MDcomp->cmpGlobalHT->hashString(propName);
  2500.  
  2501.             /* Import/convert the member */
  2502.  
  2503.             propSym  = MDimportMem(clsSym,
  2504.                                    propIden,
  2505.                                    propDsc[propInd],
  2506.                                    flags,
  2507.                                    true,
  2508.                                    false,
  2509.                                    sigAddr,
  2510.                                    sigSize);
  2511.  
  2512.             propSym->sdIsManaged = true;
  2513.  
  2514.             /* Is this an indexed property? */
  2515.  
  2516.             propType = propSym->sdType;
  2517.  
  2518.             if  (propType->tdTypeKind == TYP_FNC && !propType->tdFnc.tdfArgs.adCount)
  2519.             {
  2520.                 /* Not an indexed property, just use the return type */
  2521.  
  2522.                 propSym->sdType = propType->tdFnc.tdfRett;
  2523.             }
  2524.  
  2525. //          printf("Property: '%s'\n", MDstab->stTypeName(propSym->sdType, propSym, NULL, NULL, true));
  2526.  
  2527.             /* Locate the corresponding accessor methods */
  2528.  
  2529.             if  (propGet != mdMethodDefNil)
  2530.             {
  2531.                 sym = MDfindPropMF(propSym, propGet,  true);
  2532.                 if  (sym)
  2533.                 {
  2534.                     propSym->sdProp.sdpGetMeth = sym;
  2535. //                  printf("Prop get = '%s'\n", sym->sdSpelling());
  2536.                     propSym->sdIsVirtProp     |= sym->sdFnc.sdfVirtual;
  2537.                 }
  2538.             }
  2539.  
  2540.             if  (propSet != mdMethodDefNil)
  2541.             {
  2542.                 sym = MDfindPropMF(propSym, propSet, false);
  2543.                 if  (sym)
  2544.                 {
  2545.                     propSym->sdProp.sdpSetMeth = sym;
  2546. //                  printf("Prop set = '%s'\n", sym->sdSpelling());
  2547.                     propSym->sdIsVirtProp     |= sym->sdFnc.sdfVirtual;
  2548.                 }
  2549.             }
  2550.         }
  2551.     }
  2552.  
  2553.     wmdi->CloseEnum(propEnum);
  2554.  
  2555.     assert(clsSym->sdSymKind != SYM_ENUM || (clsTyp->tdEnum.tdeIntType != NULL &&
  2556.                                              clsTyp->tdEnum.tdeIntType->tdTypeKind <= TYP_UINT));
  2557.  
  2558.     return  clsSym;
  2559. }
  2560.  
  2561. /*****************************************************************************
  2562.  *
  2563.  *  Locate a given custom attribute attached to the specified token.
  2564.  */
  2565.  
  2566. bool                metadataImp::MDfindAttr(mdToken token,
  2567.                                             wideStr name, const void * *blobAddr,
  2568.                                                           ULONG        *blobSize)
  2569. {
  2570.     int             ret;
  2571.  
  2572.     *blobAddr = NULL;
  2573.     *blobSize = 0;
  2574.  
  2575.     cycleCounterPause();
  2576.     ret = MDwmdi->GetCustomAttributeByName(token, name, blobAddr, blobSize);
  2577.     cycleCounterResume();
  2578.  
  2579.     return  (ret != S_OK);
  2580. }
  2581.  
  2582. /*****************************************************************************
  2583.  *
  2584.  *  Add a manifest definition for the given input type.
  2585.  */
  2586.  
  2587. void                metadataImp::MDimportCTyp(mdTypeDef td, mdToken ft)
  2588. {
  2589.     WCHAR           typName[MAX_CLASS_NAME  ];
  2590.  
  2591.     DWORD           typeFlg;
  2592.  
  2593.     if  (FAILED(MDwmdi->GetTypeDefProps(td,
  2594.                                         typName, sizeof(typName)/sizeof(typName[0])-1, NULL,
  2595.                                         NULL,
  2596.                                         &typeFlg,
  2597.                                         NULL)))
  2598.     {
  2599.         MDcomp->cmpFatal(ERRreadMD);
  2600.     }
  2601.  
  2602. #if 0
  2603.  
  2604.     printf("%s type = '", ((typeFlg & tdVisibilityMask) == tdPublic) ? "Public  "
  2605.                                                                      : "Non-pub ");
  2606.  
  2607.     printf("%ls'\n", typName);
  2608.  
  2609. #endif
  2610.  
  2611.     /* Is this a public type ? */
  2612.  
  2613.     if  ((typeFlg & tdVisibilityMask) == tdPublic)
  2614.     {
  2615.         /* Add a type definition to the manifest */
  2616.  
  2617.         MDcomp->cmpAssemblyAddType(typName, td, ft, tdPublic);
  2618.     }
  2619. }
  2620.  
  2621. /*****************************************************************************
  2622.  *
  2623.  *  Locate the metadata importer interface value for the given global symbol.
  2624.  */
  2625.  
  2626. IMetaDataImport   * compiler::cmpFindImporter(SymDef globSym)
  2627. {
  2628.     MetaDataImp     cimp;
  2629.     unsigned        index;
  2630.  
  2631.     assert(globSym->sdSymKind == SYM_FNC ||
  2632.            globSym->sdSymKind == SYM_VAR);
  2633.  
  2634.     index = (globSym->sdSymKind == SYM_FNC) ? globSym->sdFnc.sdfImpIndex
  2635.                                             : globSym->sdVar.sdvImpIndex;
  2636.  
  2637.     for (cimp = cmpMDlist; cimp; cimp = cimp->MDnext)
  2638.     {
  2639.         if  (cimp->MDnum == index)
  2640.         {
  2641. //          if  (cimp->MDnum > 1)   // s/b something like "!cmpAssemblyIsBCL(assx)"
  2642. //              cimp->MDrecordFile();
  2643.  
  2644.             return  uwrpIMDIwrapper(cimp->MDwmdi);
  2645.         }
  2646.     }
  2647.  
  2648.     return  NULL;
  2649. }
  2650.  
  2651. /*****************************************************************************
  2652.  *
  2653.  *  Import metadata from the given file.
  2654.  */
  2655.  
  2656. void                metadataImp::MDimportStab(const char *  filename,
  2657.                                               unsigned      assx,
  2658.                                               bool          asmOnly,
  2659.                                               bool          isBCL)
  2660. {
  2661.     HCORENUM        typeEnum;
  2662.     unsigned        typeNum;
  2663.  
  2664.     SymTab          symtab = MDstab;
  2665.  
  2666.     WMetaDataImport*wmdi;
  2667.  
  2668.     WCHAR           wfname[255];
  2669.     WCHAR   *       wfnptr;
  2670.  
  2671.     mdToken         fileTok;
  2672.  
  2673.     assert(MDcomp->cmpWmdd);
  2674.  
  2675.     /* Create the input file name */
  2676.  
  2677.     wfnptr = wcscpy(wfname, L"file:") + 5;
  2678.     mbstowcs(wfnptr, filename, sizeof(wfname)-1-(wfnptr-wfname));
  2679.  
  2680.     /* See if the file is an assembly */
  2681.  
  2682.     if  (!assx && MDcomp->cmpConfig.ccAssembly && !asmOnly)
  2683.     {
  2684.         WAssemblyImport*wasi;
  2685.         BYTE    *       cookie;
  2686.         mdAssembly      assTok;
  2687.  
  2688.         /* Try to create an assembly importer against the file */
  2689.  
  2690.         if  (MDcomp->cmpWmdd->OpenAssem(wfname,
  2691.                                         0,
  2692.                                         getIID_IMetaDataAssemblyImport(),
  2693.                                         filename,
  2694.                                         &assTok,
  2695.                                         &cookie,
  2696.                                         &wasi) >= 0)
  2697.         {
  2698.             /* Add the assembly to the assembly table */
  2699.  
  2700.             assx = MDcomp->cmpAssemblyRefAdd(assTok, wasi, cookie);
  2701.  
  2702.             /* Remember the BCL assembly token */
  2703.  
  2704.             if  (isBCL)
  2705.                 MDcomp->cmpAssemblyTkBCL(assx);
  2706.         }
  2707.     }
  2708.  
  2709.     /* Open the metadata in the file */
  2710.  
  2711.     if  (MDcomp->cmpWmdd->OpenScope(wfname,
  2712.                                     0,
  2713.                                     getIID_IMetaDataImport(),
  2714.                                     &wmdi))
  2715.     {
  2716.         MDcomp->cmpGenFatal(ERRopenMDbad, filename);
  2717.     }
  2718.  
  2719.     /* Do we need to create a file entry in our own assembly for this guy? */
  2720.  
  2721.     if  (asmOnly)
  2722.         fileTok = MDcomp->cmpAssemblyAddFile(wfnptr, true);
  2723.  
  2724.     /* Make the import interface available to the rest of the class */
  2725.  
  2726.     MDwmdi = wmdi;
  2727.  
  2728.     /* Pass 1: enumerate top-level typedefs and enter them in the symbol table */
  2729.  
  2730.     for (typeEnum = NULL, typeNum = 0; ; typeNum++)
  2731.     {
  2732.         mdTypeDef       typeRef;
  2733.         ULONG           count;
  2734.  
  2735.         /* Ask for the next typedef */
  2736.  
  2737.         if  (wmdi->EnumTypeDefs(&typeEnum, &typeRef, 1, &count) != S_OK)
  2738.             break;
  2739.         if  (!count)
  2740.             break;
  2741.  
  2742.         if  (asmOnly)
  2743.             MDimportCTyp(typeRef, fileTok);
  2744.         else
  2745.             MDimportClss(typeRef, NULL, assx, false);
  2746.     }
  2747.  
  2748.     wmdi->CloseEnum(typeEnum);
  2749.  
  2750.     /* Import any names declared at file scope */
  2751.  
  2752.     MDimportClss(0, NULL, assx, false);
  2753.  
  2754.     /* Everything has been imported, release the metadata importer */
  2755.  
  2756.     wmdi->Release();
  2757. }
  2758.  
  2759. void                metadataImp::MDcreateFileTok()
  2760. {
  2761.     if  (!MDfileTok)
  2762.     {
  2763.         WCHAR           name[128];
  2764.  
  2765.         if  (FAILED(MDwmdi->GetScopeProps(name, arraylen(name), NULL, NULL)))
  2766.             MDcomp->cmpFatal(ERRmetadata);
  2767.  
  2768.         MDfileTok = MDcomp->cmpAssemblyAddFile(name, false);
  2769.     }
  2770. }
  2771.  
  2772. /*****************************************************************************
  2773.  *
  2774.  *  Initialize metadata importing stuff.
  2775.  */
  2776.  
  2777. void                compiler::cmpInitMDimp()
  2778. {
  2779.     cmpInitMD(); assert(cmpWmdd);
  2780. }
  2781.  
  2782. /*****************************************************************************
  2783.  *
  2784.  *  Initialize metadata importing stuff.
  2785.  */
  2786.  
  2787. void                compiler::cmpDoneMDimp()
  2788. {
  2789.     // UNDONE: release all importer instances as well!!!
  2790. }
  2791.  
  2792. /*****************************************************************************
  2793.  *
  2794.  *  Create a metadata importer and add it to the global importer list.
  2795.  */
  2796.  
  2797. MetaDataImp         compiler::cmpAddMDentry()
  2798. {
  2799.     MetaDataImp     cimp;
  2800.  
  2801. #if MGDDATA
  2802.     cimp = new MetaDataImp;
  2803. #else
  2804.     cimp =    (MetaDataImp)cmpAllocTemp.baAlloc(sizeof(*cimp));
  2805. #endif
  2806.  
  2807.     cimp->MDnum  = ++cmpMDcount;
  2808.  
  2809.     /* Append the importer to the global list */
  2810.  
  2811.     cimp->MDnext = NULL;
  2812.  
  2813.     if  (cmpMDlist)
  2814.         cmpMDlast->MDnext = cimp;
  2815.     else
  2816.         cmpMDlist         = cimp;
  2817.  
  2818.     cmpMDlast = cimp;
  2819.  
  2820.     return  cimp;
  2821. }
  2822.  
  2823. /*****************************************************************************
  2824.  *
  2825.  *  Import the metadata from the given file (pass NULL to import MSCORLIB).
  2826.  */
  2827.  
  2828. void                compiler::cmpImportMDfile(const char *  fname,
  2829.                                               bool          asmOnly,
  2830.                                               bool          isBCL)
  2831. {
  2832.     MetaDataImp     cimp;
  2833.     char            buff[_MAX_PATH];
  2834.  
  2835.     /* Create the importer and initialize it [ISSUE: need to trap errors?] */
  2836.  
  2837.     cimp = cmpAddMDentry();
  2838.  
  2839.     cycleCounterPause();
  2840.     cimp->MDinit(this, cmpGlobalST);
  2841.     cycleCounterResume();
  2842.  
  2843.     /* Make sure we have a valid filename to import */
  2844.  
  2845.     if  (!fname || !*fname)
  2846.         fname = "MSCORLIB.DLL";
  2847.  
  2848.     /* Find the specified file on the search path */
  2849.  
  2850.     if  (!SearchPathA(NULL, fname, NULL, sizeof(buff), buff, NULL))
  2851.     {
  2852.         StrList         path;
  2853.  
  2854.         /* Try any additional path that may have been specified */
  2855.  
  2856.         for (path = cmpConfig.ccPathList; path; path = path->slNext)
  2857.         {
  2858.             _Fstat          fileInfo;
  2859.  
  2860.             strcpy(buff, path->slString);
  2861.             strcat(buff, "\\");
  2862.             strcat(buff, fname);
  2863.  
  2864.             /* See if the file exists */
  2865.  
  2866.             if  (!_stat(buff, &fileInfo))
  2867.                 goto GOTIT;
  2868.         }
  2869.  
  2870.         cmpGenFatal(ERRopenMDerr, fname);
  2871.     }
  2872.  
  2873. GOTIT:
  2874.  
  2875. //  printf("Found metadata file '%s'\n", buff);
  2876.  
  2877.     /* We're ready to import the file */
  2878.  
  2879.     cycleCounterPause();
  2880.     cimp->MDimportStab(buff, 0, asmOnly, isBCL);
  2881.     cycleCounterResume();
  2882. }
  2883.  
  2884. /*****************************************************************************
  2885.  *
  2886.  *  Get hold of all the various interfaces we need to pass to the metadata
  2887.  *  API's to create import references.
  2888.  */
  2889.  
  2890. void                compiler::cmpFindMDimpAPIs(SymDef                   typSym,
  2891.                                                IMetaDataImport        **imdiPtr,
  2892.                                                IMetaDataAssemblyEmit  **iasePtr,
  2893.                                                IMetaDataAssemblyImport**iasiPtr)
  2894. {
  2895.     unsigned        assx;
  2896.  
  2897.     MetaDataImp     imp;
  2898.  
  2899.     assert(typSym->sdIsImport);
  2900.  
  2901.     if  (typSym->sdSymKind == SYM_CLASS)
  2902.     {
  2903.         assert(typSym->sdClass.sdcMDtypedef);
  2904.  
  2905.         imp  = typSym->sdClass.sdcMDimporter;
  2906.         assx = typSym->sdClass.sdcAssemIndx;
  2907.     }
  2908.     else
  2909.     {
  2910.         assert(typSym->sdSymKind == SYM_ENUM);
  2911.  
  2912.         assert(typSym->sdEnum .sdeMDtypedef);
  2913.  
  2914.         imp  = typSym->sdEnum .sdeMDimporter;
  2915.         assx = typSym->sdEnum .sdeAssemIndx;
  2916.     }
  2917.  
  2918.     assert(imp);
  2919.  
  2920.     *imdiPtr = uwrpIMDIwrapper(imp->MDwmdi);
  2921.     *iasePtr = cmpWase ? uwrpIASEwrapper(cmpWase) : NULL;
  2922.     *iasiPtr = NULL;
  2923.  
  2924.     if  (assx == 0)
  2925.     {
  2926.         *iasePtr = NULL;
  2927.     }
  2928.     else if (!cmpAssemblyIsBCL(assx))
  2929.     {
  2930.         *iasiPtr = uwrpIASIwrapper(cmpAssemblyGetImp(assx));
  2931.  
  2932. //      imp->MDrecordFile();
  2933.     }
  2934. }
  2935.  
  2936. /*****************************************************************************
  2937.  *
  2938.  *  Create a typeref for the specified import class.
  2939.  */
  2940.  
  2941. void                compiler::cmpMakeMDimpTref(SymDef clsSym)
  2942. {
  2943.     IMetaDataImport        *imdi;
  2944.     IMetaDataAssemblyEmit  *iase;
  2945.     IMetaDataAssemblyImport*iasi;
  2946.  
  2947.     mdTypeRef               clsr;
  2948.  
  2949.     assert(clsSym->sdIsImport);
  2950.     assert(clsSym->sdSymKind == SYM_CLASS);
  2951.     assert(clsSym->sdClass.sdcMDtypedef);
  2952.     assert(clsSym->sdClass.sdcMDtypeImp == 0);
  2953.  
  2954.     cmpFindMDimpAPIs(clsSym, &imdi, &iase, &iasi);
  2955.  
  2956.     cycleCounterPause();
  2957.  
  2958.     if  (FAILED(cmpWmde->DefineImportType(iasi,
  2959.                                           NULL,
  2960.                                           0,
  2961.                                           mdTokenNil,
  2962.                                           imdi,
  2963.                                           clsSym->sdClass.sdcMDtypedef,
  2964.                                           iase,
  2965.                                           &clsr)))
  2966.     {
  2967.         cmpFatal(ERRmetadata);
  2968.     }
  2969.  
  2970.     cycleCounterResume();
  2971.  
  2972.     clsSym->sdClass.sdcMDtypeImp = clsr;
  2973.  
  2974.     if  (cmpConfig.ccAssembly && clsSym->sdClass.sdcAssemIndx)
  2975.         cmpAssemblySymDef(clsSym);
  2976. }
  2977.  
  2978. /*****************************************************************************
  2979.  *
  2980.  *  Create a typeref for the specified import enum.
  2981.  */
  2982.  
  2983. void                compiler::cmpMakeMDimpEref(SymDef etpSym)
  2984. {
  2985.     IMetaDataImport        *imdi;
  2986.     IMetaDataAssemblyEmit  *iase;
  2987.     IMetaDataAssemblyImport*iasi;
  2988.  
  2989.     mdTypeRef               etpr;
  2990.  
  2991.     assert(etpSym->sdIsImport);
  2992.     assert(etpSym->sdSymKind == SYM_ENUM);
  2993.     assert(etpSym->sdEnum.sdeMDtypedef);
  2994.     assert(etpSym->sdEnum.sdeMDtypeImp == 0);
  2995.  
  2996.     cmpFindMDimpAPIs(etpSym, &imdi, &iase, &iasi);
  2997.  
  2998.     cycleCounterPause();
  2999.  
  3000.     if  (FAILED(cmpWmde->DefineImportType(iasi,
  3001.                                           NULL,
  3002.                                           0,
  3003.                                           mdTokenNil,
  3004.                                           imdi,
  3005.                                           etpSym->sdEnum.sdeMDtypedef,
  3006.                                           iase,
  3007.                                           &etpr)))
  3008.     {
  3009.         cmpFatal(ERRmetadata);
  3010.     }
  3011.  
  3012.     cycleCounterResume();
  3013.  
  3014.     etpSym->sdEnum.sdeMDtypeImp = etpr;
  3015. }
  3016.  
  3017. /*****************************************************************************
  3018.  *
  3019.  *  Create a methodref for the specified import method.
  3020.  */
  3021.  
  3022. void                compiler::cmpMakeMDimpFref(SymDef fncSym)
  3023. {
  3024.     mdMemberRef     fncr;
  3025.  
  3026.     assert(fncSym->sdIsImport);
  3027.     assert(fncSym->sdFnc.sdfMDtoken != 0);
  3028.     assert(fncSym->sdFnc.sdfMDfnref == 0);
  3029.  
  3030.     cycleCounterPause();
  3031.  
  3032.     if  (fncSym->sdIsMember)
  3033.     {
  3034.         IMetaDataImport        *imdi;
  3035.         IMetaDataAssemblyEmit  *iase;
  3036.         IMetaDataAssemblyImport*iasi;
  3037.  
  3038.         SymDef                  clsSym = fncSym->sdParent;
  3039.         mdTypeRef               clsRef = clsSym->sdClass.sdcMDtypeImp;
  3040.  
  3041.         assert(clsSym->sdSymKind == SYM_CLASS);
  3042.         assert(clsSym->sdIsImport);
  3043.  
  3044.         /* Make sure the class has an import typeref */
  3045.  
  3046.         if  (!clsRef)
  3047.         {
  3048.             cmpMakeMDimpTref(clsSym);
  3049.             clsRef = clsSym->sdClass.sdcMDtypeImp;
  3050.         }
  3051.  
  3052.         cmpFindMDimpAPIs(clsSym, &imdi, &iase, &iasi);
  3053.  
  3054.         /* Now create the methodref */
  3055.  
  3056.         if  (FAILED(cmpWmde->DefineImportMember(iasi,
  3057.                                                 NULL,
  3058.                                                 0,
  3059.                                                 mdTokenNil,
  3060.                                                 imdi,
  3061.                                                 fncSym->sdFnc.sdfMDtoken,
  3062.                                                 iase,
  3063.                                                 clsRef,
  3064.                                                 &fncr)))
  3065.         {
  3066.             cmpFatal(ERRmetadata);
  3067.         }
  3068.     }
  3069.     else
  3070.     {
  3071.         if  (FAILED(cmpWmde->DefineImportMember(NULL, // iasi,
  3072.                                                 NULL,
  3073.                                                 0,
  3074.                                                 mdTokenNil,
  3075.                                                 cmpFindImporter(fncSym),
  3076.                                                 fncSym->sdFnc.sdfMDtoken,
  3077.                                                 NULL, // iase,
  3078.                                                 mdTokenNil,
  3079.                                                 &fncr)))
  3080.         {
  3081.             cmpFatal(ERRmetadata);
  3082.         }
  3083.     }
  3084.  
  3085.     cycleCounterResume();
  3086.  
  3087. //  printf("Imp func ref: %04X = '%s'\n", fncr, fncSym->sdSpelling());
  3088.  
  3089.     fncSym->sdFnc.sdfMDfnref = fncr;
  3090. }
  3091.  
  3092. /*****************************************************************************
  3093.  *
  3094.  *  Create a memberref for the specified import global var / static data member.
  3095.  */
  3096.  
  3097. void                compiler::cmpMakeMDimpDref(SymDef fldSym)
  3098. {
  3099.     mdMemberRef     fldr;
  3100.  
  3101.     assert(fldSym->sdIsImport);
  3102.     assert(fldSym->sdVar.sdvMDtoken != 0);
  3103.     assert(fldSym->sdVar.sdvMDsdref == 0);
  3104.  
  3105.     cycleCounterPause();
  3106.  
  3107.     if  (fldSym->sdIsMember)
  3108.     {
  3109.         IMetaDataImport        *imdi;
  3110.         IMetaDataAssemblyEmit  *iase;
  3111.         IMetaDataAssemblyImport*iasi;
  3112.  
  3113.         SymDef                  clsSym = fldSym->sdParent;
  3114.         mdTypeRef               clsRef = clsSym->sdClass.sdcMDtypeImp;
  3115.  
  3116.         assert(clsSym->sdSymKind == SYM_CLASS);
  3117.         assert(clsSym->sdIsImport);
  3118.  
  3119.         /* Make sure the class has an import typeref */
  3120.  
  3121.         if  (!clsRef)
  3122.         {
  3123.             cmpMakeMDimpTref(clsSym);
  3124.             clsRef = clsSym->sdClass.sdcMDtypeImp;
  3125.         }
  3126.  
  3127.         cmpFindMDimpAPIs(clsSym, &imdi, &iase, &iasi);
  3128.  
  3129.         /* Now create the memberref */
  3130.  
  3131.         if  (FAILED(cmpWmde->DefineImportMember(iasi,
  3132.                                                 NULL,
  3133.                                                 0,
  3134.                                                 mdTokenNil,
  3135.                                                 imdi,
  3136.                                                 fldSym->sdVar.sdvMDtoken,
  3137.                                                 iase,
  3138.                                                 clsRef,
  3139.                                                 &fldr)))
  3140.         {
  3141.             cmpFatal(ERRmetadata);
  3142.         }
  3143.     }
  3144.     else
  3145.     {
  3146.         if  (FAILED(cmpWmde->DefineImportMember(NULL, // iasi,
  3147.                                                 NULL,
  3148.                                                 0,
  3149.                                                 mdTokenNil,
  3150.                                                 cmpFindImporter(fldSym),
  3151.                                                 fldSym->sdVar.sdvMDtoken,
  3152.                                                 NULL, // iase,
  3153.                                                 mdTokenNil,
  3154.                                                 &fldr)))
  3155.         {
  3156.             cmpFatal(ERRmetadata);
  3157.         }
  3158.     }
  3159.  
  3160.     cycleCounterResume();
  3161.  
  3162.     fldSym->sdVar.sdvMDsdref = fldr;
  3163. }
  3164.  
  3165. /*****************************************************************************/
  3166.