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

  1. /*****************************************************************************/
  2.  
  3. #include "smcPCH.h"
  4. #pragma hdrstop
  5.  
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8.  
  9. #include "comp.h"
  10.  
  11. /*****************************************************************************/
  12. #ifdef  ASYNCH_INPUT_READ
  13.  
  14. #define MAX_SIMULTANEOUS_ASYNC_IOS  3       // NT limit (is this really true?)
  15.  
  16. #define DISP_ASYNC_PROGRESS         0       // set to "1" to see the following:
  17.  
  18. //  RDIRRRDDDDPEPEPREPERRDDDPEPEPERRDDPEPERRDDPEPERRDDPEPRERRDDDPEPE
  19. //  PERRDDPEPERRDDPEPERRDDPEPERRDDPRDRDEPREPEPERRDDDPEPREPRERDDDPEPE
  20. //  PRERRDDDPEPREPRERDDDPEPREPERRDDDPEPREPERRDDDPEPEPEC
  21.  
  22. #endif
  23. /*****************************************************************************/
  24.  
  25. #ifndef __SMC__
  26. extern  "C"
  27. const   char *      COMPILER_VERSION;
  28. #endif
  29.  
  30. /*****************************************************************************/
  31.  
  32. #ifdef  __IL__
  33. #ifdef  _MSC_VER
  34.  
  35. // The following is a horrendous temp hack.
  36.  
  37. #undef  isspace
  38. #define isspace IsSpace
  39.  
  40. inline
  41. int     isspace(int c)
  42. {
  43.     return  (c == ' ') || (c == '\t');
  44. }
  45.  
  46. #endif
  47. #endif
  48.  
  49. /*****************************************************************************/
  50.  
  51. const   char *      SMCregKey = "Software\\Microsoft\\SMC";
  52.  
  53. /*****************************************************************************/
  54.  
  55. static
  56. char                  firstFileName[_MAX_PATH];
  57.  
  58. static
  59. char                outfileNameBuff[_MAX_PATH];
  60.  
  61. /*****************************************************************************/
  62.  
  63. static
  64. bool                startedCompiling;
  65.  
  66. /*****************************************************************************/
  67.  
  68. static
  69. StrList             addToStrList(const char *str, StrList  list,
  70.                                                   StrList *lastPtr);
  71.  
  72. static
  73. bool                processDLLbaseFile(const char *fname, Compiler comp);
  74.  
  75. /*****************************************************************************
  76.  *
  77.  *  Display the help screen with short descriptions of command-line options.
  78.  */
  79.  
  80. void                dispHelpScreen(Compiler comp, const char *optStr = NULL)
  81. {
  82.     if  (optStr)
  83.         printf("ERROR: Invalid compiler option '%s'\n\n", optStr);
  84.  
  85.     printf("Usage: SMC [options] source-filename-list\n");
  86.     printf("\n");
  87.  
  88.     printf("  -q                quiet mode\n");
  89.     printf("\n");
  90.     printf("  -d                create a DLL (default is EXE)\n");
  91.     printf("  -b<base>          set the image base (value in decimal for now)\n");
  92.     printf("  -b@filename,key   set the image base/size from the given file\n");
  93.     printf("  -CG{IID}          set the GUID attribute of the PE file\n");
  94.     printf("  -CM<name>         name of entry point class\n");
  95.     printf("  -CN<name>         set the name attribute of the PE file\n");
  96.     printf("  -CR<name>         add .RES file to the image\n");
  97.     printf("  -CS               ignore '@' COM interop comments\n");
  98.     printf("  -O<filename>      set the name of the output file name\n");
  99.     printf("  -R                recurse into subdirs for source files\n");
  100.     printf("  -Wc             * set subsystem to character mode\n");
  101.     printf("  -Wg               set subsystem to GUI\n");
  102.     printf("  -s[filename]    * specify MSCORLIB.DLL location (default: MSCORLIB.DLL in path)\n");
  103.     printf("  -m[filename]      import additional metadata from the given EXE/DLL\n");
  104.     printf("  -p[pathlist]      search additional path(s) for metadata\n");
  105.     printf("  -z              * import and emit assembly goo\n");
  106.     printf("  -zm<name>         add module   to assembly manifest\n");
  107.     printf("  -zr<file>         add resource to assembly manifest\n");
  108.     printf("  -zt               exclude types from manifest (use for mscorlib.dll)\n");
  109.     printf("  -zn               mark assembly as non-CLS compliant\n");
  110. #ifdef  ASYNCH_INPUT_READ
  111.     printf("  -i                overlapped (asynch) file input\n");
  112. #endif
  113.     printf("\n");
  114.     printf("  -w                 enable all warnings\n");
  115.     printf("  -w-               disable all warnings\n");
  116.     printf("  -w####             enable one warning\n");
  117.     printf("  -w-####           disable one warning\n");
  118.     printf("  -wx               treat warnings as errors\n");
  119.     printf("  -e<count>         set max. number of errors\n");
  120.     printf("\n");
  121.     printf("  -N                use new-style metadata names\n");
  122.     printf("\n");
  123.     printf("  -Zi               generate full debug info (implies -Zn)\n");
  124.     printf("  -Zl               generate only line# info\n");
  125.     printf("  -Zn               include parameter names in metadata\n");
  126.     printf("\n");
  127.     printf("  -A                enable asserts\n");
  128.     printf("  -AS               enable asserts with source info\n");
  129.     printf("\n");
  130.     printf("  -Dname[=value]    define a macro\n");
  131.     printf("\n");
  132.     printf("  -a<size>          set default struct alignment (1,2,4,8 or 16)\n");
  133.     printf("  -c                default to C-style declarations\n");
  134.     printf("  -S                typesafe mode\n");
  135.     printf("  -P                pedantic mode\n");
  136.     printf("  -U              * flag uninitialized local variable use\n");
  137.     printf("  -X                pick class for ambiguous lookups in multiple usings\n");
  138.     printf("  -r                relation operators compare string values\n");
  139.     printf("  -6                64-bit target\n");
  140.     printf("  -E                map enums to ints\n");
  141. #ifdef  DEBUG
  142.     printf("\n");
  143.     printf(" Debug build switches (for debugging of the compiler):\n");
  144.     printf("  -v[level]         verbose mode\n");
  145.     printf("  -g                display generated IL code\n");
  146.     printf("  -gd               display generated IL code (detailed)\n");
  147.     printf("  -R                display RVA's of methods\n");
  148. #endif
  149.     printf("\n");
  150.     printf("NOTE: Following a toggle flag with '-' turns it\n");
  151.     printf("off, options marked '*' are enabled by default.\n");
  152.     printf("\n");
  153.     printf("The list of source file names may contain wildcards\n");
  154.     printf("as well as response files (of the form '@file.lst');\n");
  155.     printf("note that only new-style command-line options will be\n");
  156.     printf("recognized within response files.\n");
  157.     printf("\n");
  158.     printf("A leading -o indicates that old-style command-line\n");
  159.     printf("option syntax is desired (it also implies -L -Zn).\n");
  160.     printf("\n");
  161. }
  162.  
  163. const
  164. char    *           saveOptionString(const char *str)
  165. {
  166.     char    *       save = (char *)malloc(strlen(str)+1);
  167.     strcpy(save, str);
  168.     return  save;
  169. }
  170.  
  171. /*****************************************************************************
  172.  *
  173.  *  Process a command-line option. Returns true if there is a problem.
  174.  */
  175.  
  176. bool                processOption(const char *optStr, Compiler comp)
  177. {
  178.     bool       *    flagPtr;
  179.     const char *    cmdPtr;
  180.  
  181.     cmdPtr = optStr + 2;
  182.  
  183.     switch  (cmdPtr[-1])
  184.     {
  185.         int             temp;
  186.         unsigned        val;
  187.  
  188.     case '6':
  189.         flagPtr = &comp->cmpConfig.ccTgt64bit;
  190.         goto TOGGLE_FLAG;
  191.  
  192.     case 'A':
  193.         switch (*cmdPtr)
  194.         {
  195.         case '-':
  196.             comp->cmpConfig.ccAsserts = 0;
  197.             break;
  198.  
  199.         case 0:
  200.             comp->cmpConfig.ccAsserts = 1;
  201.             break;
  202.  
  203.         case 'S':
  204.             comp->cmpConfig.ccAsserts = 2;
  205.             break;
  206.  
  207.         default:
  208.             return  true;
  209.         }
  210.         break;
  211.  
  212.     case 'a':
  213.         temp = atoi(cmdPtr);
  214.         switch (temp)
  215.         {
  216.         case 1:
  217.         case 2:
  218.         case 4:
  219.         case 8:
  220.         case 16:
  221.             comp->cmpConfig.ccAlignVal = temp;
  222.             break;
  223.  
  224.         default:
  225.             return  true;
  226.         }
  227.  
  228.     case 'b':
  229.  
  230.         if  (*cmdPtr == '@')
  231.             return  processDLLbaseFile(cmdPtr+1, comp);
  232.  
  233.         comp->cmpConfig.ccOutBase = atoi(cmdPtr);
  234.         break;
  235.  
  236.     case 'c':
  237.         flagPtr = &comp->cmpConfig.ccOldStyle;
  238.         goto TOGGLE_FLAG;
  239.  
  240.     case 'E':
  241.         flagPtr = &comp->cmpConfig.ccIntEnums;
  242.         goto TOGGLE_FLAG;
  243.  
  244.     case 'C':
  245.         switch (*cmdPtr++)
  246.         {
  247.         case 'G':
  248.             if  (parseGUID(cmdPtr, &comp->cmpConfig.ccOutGUID, true))
  249.                 return  true;
  250.             break;
  251.  
  252.         case 'M':
  253.             comp->cmpConfig.ccMainCls = saveOptionString(cmdPtr);
  254.             break;
  255.  
  256.         case 'N':
  257.             comp->cmpConfig.ccOutName = saveOptionString(cmdPtr);
  258.             break;
  259.  
  260.         case 'R':
  261.             comp->cmpConfig.ccRCfile  = saveOptionString(cmdPtr);
  262.             break;
  263.  
  264.         case 'S':
  265.             flagPtr = &comp->cmpConfig.ccSkipATC;
  266.             goto TOGGLE_FLAG;
  267.  
  268.         default:
  269.             return  true;
  270.         }
  271.         break;
  272.  
  273.     case 'd':
  274.         flagPtr = &comp->cmpConfig.ccOutDLL;
  275.         goto TOGGLE_FLAG;
  276.  
  277.     case 'W':
  278.         switch (*cmdPtr++)
  279.         {
  280.         case 'c':
  281.             comp->cmpConfig.ccSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
  282.             break;
  283.  
  284.         case 'g':
  285.             comp->cmpConfig.ccSubsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
  286.             break;
  287.  
  288.         default:
  289.             return  true;
  290.         }
  291.         break;
  292.  
  293.     case 'D':
  294.         comp->cmpConfig.ccMacList = addToStrList(cmdPtr, comp->cmpConfig.ccMacList, &comp->cmpConfig.ccMacLast);
  295.         break;
  296.  
  297.     case 'e':
  298.         comp->cmpConfig.ccMaxErrs = atoi(cmdPtr);
  299.         break;
  300.  
  301.     case 'i':
  302. #ifdef  ASYNCH_INPUT_READ
  303.         flagPtr = &comp->cmpConfig.ccAsynchIO;
  304.         goto TOGGLE_FLAG;
  305. #else
  306.         break;
  307. #endif
  308.  
  309.     case 'm':
  310.         comp->cmpConfig.ccSuckList = addToStrList(cmdPtr, comp->cmpConfig.ccSuckList, &comp->cmpConfig.ccSuckLast);
  311.         break;
  312.  
  313.     case 'N':
  314.         flagPtr = &comp->cmpConfig.ccNewMDnames;
  315.         goto TOGGLE_FLAG;
  316.  
  317. #ifdef  OLD_IL
  318.  
  319.     case 'G':
  320.         switch (*cmdPtr++)
  321.         {
  322.         case 0:
  323.             comp->cmpConfig.ccOILgen = true;
  324.             break;
  325.  
  326.         case '-':
  327.             comp->cmpConfig.ccOILgen = false;
  328.             break;
  329.  
  330.         case 'g':
  331.             comp->cmpConfig.ccOILcgen = saveOptionString(cmdPtr);
  332.             break;
  333.  
  334.         case 'l':
  335.             flagPtr = &comp->cmpConfig.ccOILlink;
  336.             goto TOGGLE_FLAG;
  337.  
  338.         case 'k':
  339.             flagPtr = &comp->cmpConfig.ccOILkeep;
  340.             goto TOGGLE_FLAG;
  341.  
  342.         case 'x':
  343.             flagPtr = &comp->cmpConfig.ccOILopt;
  344.             goto TOGGLE_FLAG;
  345.  
  346.         case 's':
  347.             flagPtr = &comp->cmpConfig.ccOILopts;
  348.             goto TOGGLE_FLAG;
  349.  
  350.         case 'a':
  351.             flagPtr = &comp->cmpConfig.ccOILasm;
  352.             goto TOGGLE_FLAG;
  353.  
  354.         case 'c':
  355.             flagPtr = &comp->cmpConfig.ccOILcod;
  356.             goto TOGGLE_FLAG;
  357.  
  358.         default:
  359.             return  true;
  360.         }
  361.         break;
  362.  
  363. #endif
  364.  
  365.     case 'O':
  366.         strcpy(outfileNameBuff, cmdPtr); comp->cmpConfig.ccOutFileName = outfileNameBuff;
  367.         break;
  368.  
  369.     case 'p':
  370.         comp->cmpConfig.ccPathList = addToStrList(cmdPtr, comp->cmpConfig.ccPathList, &comp->cmpConfig.ccPathLast);
  371.         break;
  372.  
  373.     case 'P':
  374.         flagPtr = &comp->cmpConfig.ccPedantic;
  375.         goto TOGGLE_FLAG;
  376.  
  377.     case 'q':
  378.         flagPtr = &comp->cmpConfig.ccQuiet;
  379.         goto TOGGLE_FLAG;
  380.  
  381.     case 'r':
  382.         flagPtr = &comp->cmpConfig.ccStrValCmp;
  383.         goto TOGGLE_FLAG;
  384.  
  385.     case 'R':
  386.         flagPtr = &comp->cmpConfig.ccRecDir;
  387.         goto TOGGLE_FLAG;
  388.  
  389.     case 's':
  390.         switch (*cmdPtr)
  391.         {
  392.         case 0:
  393.             comp->cmpConfig.ccBaseLibs = "";
  394.             break;
  395.  
  396.         case '-':
  397.             comp->cmpConfig.ccBaseLibs = NULL;
  398.             break;
  399.  
  400.         default:
  401.             comp->cmpConfig.ccBaseLibs = saveOptionString(cmdPtr);
  402.         }
  403.         break;
  404.  
  405.     case 'S':
  406.         flagPtr = &comp->cmpConfig.ccSafeMode;
  407.         goto TOGGLE_FLAG;
  408.  
  409.     case 'T':
  410.         comp->cmpConfig.ccTestMask = atoi(cmdPtr);
  411.         printf("NOTE: Using test mask of 0x%X\n", comp->cmpConfig.ccTestMask);
  412.         break;
  413.  
  414.     case 'U':
  415.         flagPtr = &comp->cmpConfig.ccChkUseDef;
  416.         goto TOGGLE_FLAG;
  417.  
  418.     case 'u':
  419.         flagPtr = &comp->cmpConfig.ccNoDefines;
  420.         goto TOGGLE_FLAG;
  421.  
  422. #ifdef  DEBUG
  423.  
  424.     case 'g':
  425.         switch (*cmdPtr)
  426.         {
  427.         case 0:
  428.             comp->cmpConfig.ccDispCode = true;
  429.             break;
  430.  
  431.         case '-':
  432.             comp->cmpConfig.ccDispCode = false;
  433.             break;
  434.  
  435.         case 'd':
  436.             cmdPtr++;
  437.             comp->cmpConfig.ccDispCode = true;
  438.             flagPtr = &comp->cmpConfig.ccDispILcd;
  439.             goto TOGGLE_FLAG;
  440.  
  441.         default:
  442.             return  true;
  443.         }
  444.         break;
  445.  
  446.     case 'v':
  447.         switch (*cmdPtr)
  448.         {
  449.         case 0:
  450.             comp->cmpConfig.ccVerbose = 1;
  451.             break;
  452.  
  453.         case '-':
  454.             comp->cmpConfig.ccVerbose = 0;
  455.             break;
  456.  
  457.         case '0':
  458.         case '1':
  459.         case '2':
  460.         case '3':
  461.         case '4':
  462.         case '5':
  463.         case '6':
  464.         case '7':
  465.         case '8':
  466.         case '9':
  467.             comp->cmpConfig.ccVerbose = atoi(cmdPtr);
  468.             break;
  469.  
  470.         default:
  471.             return  true;
  472.         }
  473.         break;
  474.  
  475. #endif
  476.  
  477.     case 'V':
  478.         // Temp hack: just ignore the darn thing
  479.         printf("Please stop using the -V flag, it's no longer meaningful!!!!!!!!!\n");
  480.         break;
  481.  
  482.     case 'w':
  483.         switch (*cmdPtr++)
  484.         {
  485.         case 0:
  486.             memset(comp->cmpConfig.ccWarning, 1, sizeof(comp->cmpConfig.ccWarning));
  487.             return  false;
  488.  
  489.         case '-':
  490.             if  (*cmdPtr == 0)
  491.             {
  492.                 unsigned        w;
  493.  
  494.                 for (w = 0; w < sizeof(comp->cmpConfig.ccWarning); w++)
  495.                 {
  496.                     if  (comp->cmpConfig.ccWarning[w] != 9)
  497.                          comp->cmpConfig.ccWarning[w]  = 0;
  498.                 }
  499.                 return  false;
  500.             }
  501.             val = 0;
  502.             break;
  503.  
  504.         case 'x':
  505.             flagPtr = &comp->cmpConfig.ccWarnErr;
  506.             goto TOGGLE_FLAG;
  507.  
  508.         default:
  509.             val = 1; cmdPtr--;
  510.             break;
  511.         }
  512.  
  513.         /* We better have a warning number here */
  514.  
  515.         temp = atoi(cmdPtr);
  516.         if  (temp < 4000 || temp >= 4000 + WRNcountWarn)
  517.             return  true;
  518.  
  519.         comp->cmpConfig.ccWarning[temp - 4000] = val;
  520.         break;
  521.  
  522.     case 'X':
  523.         flagPtr = &comp->cmpConfig.ccAmbigHack;
  524.         goto TOGGLE_FLAG;
  525.  
  526.     case 'z':
  527.         switch (*cmdPtr++)
  528.         {
  529.         case 0:
  530.             comp->cmpConfig.ccAssembly = true;
  531.             break;
  532.  
  533.         case '-':
  534.             comp->cmpConfig.ccAssembly = false;
  535.             break;
  536.  
  537.         case 't':
  538.             flagPtr = &comp->cmpConfig.ccAsmNoPubTp;
  539.             comp->cmpConfig.ccAssembly = true;
  540.             goto TOGGLE_FLAG;
  541.  
  542.         case 'n':
  543.             flagPtr = &comp->cmpConfig.ccAsmNonCLS;
  544.             comp->cmpConfig.ccAssembly = true;
  545.             goto TOGGLE_FLAG;
  546.  
  547.         case 'm':
  548.             comp->cmpConfig.ccModList = addToStrList(cmdPtr, comp->cmpConfig.ccModList, &comp->cmpConfig.ccModLast);
  549.             comp->cmpConfig.ccAssembly = true;
  550.             break;
  551.  
  552.         case 'r':
  553.             comp->cmpConfig.ccMRIlist = addToStrList(cmdPtr, comp->cmpConfig.ccMRIlist, &comp->cmpConfig.ccMRIlast);
  554.             comp->cmpConfig.ccAssembly = true;
  555.             break;
  556.  
  557.         default:
  558.             return  true;
  559.         }
  560.         break;
  561.  
  562.     case 'Z':
  563.         switch (*cmdPtr++)
  564.         {
  565.         case 'i':
  566.             flagPtr = &comp->cmpConfig.ccGenDebug;
  567.             goto TOGGLE_FLAG;
  568.  
  569.         case 'l':
  570.             flagPtr = &comp->cmpConfig.ccLineNums;
  571.             goto TOGGLE_FLAG;
  572.  
  573.         case 'n':
  574.             flagPtr = &comp->cmpConfig.ccParamNames;
  575.             goto TOGGLE_FLAG;
  576.  
  577.         default:
  578.             return  true;
  579.         }
  580.  
  581.     TOGGLE_FLAG:
  582.  
  583.         switch  (*cmdPtr)
  584.         {
  585.         case 0:
  586.             *flagPtr = true;
  587.             break;
  588.         case '-':
  589.             *flagPtr = false;
  590.             break;
  591.         default:
  592.             return  true;
  593.         }
  594.         break;
  595.  
  596.     default:
  597.         return  true;
  598.     }
  599.  
  600.     return  false;
  601. }
  602.  
  603. /*****************************************************************************
  604.  *
  605.  *  The following is used to map a managed String instance to a raw C-style
  606.  *  unmanaged string when running on top of the COM+ runtime.
  607.  */
  608.  
  609. #ifdef  __COMRT__
  610.  
  611. char    *           makeRawString(String s)
  612. {
  613.     size_t          strLen = s.Length;
  614.     char    *       strPtr = (char *)malloc(strLen + 1);
  615.  
  616.     unsigned        i;
  617.  
  618.     for (i = 0; i < strLen; i++)
  619.         strPtr[i] = (char)s.Chars[i];
  620.  
  621.     strPtr[strLen] = 0;
  622.  
  623.     return  strPtr;
  624. }
  625.  
  626. String              makeMgdString(char * s)
  627. {
  628. #ifdef  __64BIT__
  629. #pragma message("temp hack: all managed code disabled for 64 bits")
  630.     return  NULL;
  631. #else
  632.     size_t              strLen = strlen(s);
  633.     Text::StringBuilder strBuf = new Text::StringBuilder(strLen);
  634.  
  635.     unsigned        i;
  636.  
  637.     for (i = 0; i < strLen; i++)
  638.         strBuf.Append((wchar)s[i]);
  639.  
  640.     return  strBuf.ToString();
  641. #endif
  642. }
  643.  
  644. #endif
  645.  
  646. /*****************************************************************************
  647.  *
  648.  *  Convert a GUID string to a - surprise - GUID!
  649.  */
  650.  
  651. static
  652. int                 convertHC(int ch)
  653. {
  654.     if  (ch >= '0' && ch <= '9')
  655.         return  ch - '0';
  656.     if  (ch >= 'A' && ch <= 'Z')
  657.         return  ch - 'A' + 10;
  658.     if  (ch >= 'a' && ch <= 'z')
  659.         return  ch - 'a' + 10;
  660.  
  661.     return  -1;
  662. }
  663.  
  664. static
  665. const   char *      parseHexD(const char *str, void *dest, unsigned cnt, bool fwd, bool end)
  666. {
  667.     size_t          size;
  668.     unsigned char   buff[6];
  669.     unsigned char * next;
  670.  
  671.     assert(cnt && (cnt & 2) == 0);
  672.  
  673.     size = cnt = cnt / 2; assert(size <= arraylen(buff));
  674.  
  675.     if  (fwd)
  676.         next = buff;
  677.     else
  678.         next = buff + size;
  679.  
  680.     do
  681.     {
  682.         int             nb1;
  683.         int             nb2;
  684.  
  685.         nb1 = convertHC(*str++); if (nb1 == -1) return NULL;
  686.         nb2 = convertHC(*str++); if (nb2 == -1) return NULL;
  687.  
  688.         next -= (int)(fwd == false);
  689.  
  690.         assert(next >= buff);
  691.         assert(next <  buff + sizeof(buff));
  692.  
  693.         *next = nb1 << 4 | nb2;
  694.  
  695.         next += (int)(fwd != false);
  696.     }
  697.     while (--cnt);
  698.  
  699.     assert((fwd == false && next == buff) || (fwd != false && next == buff + size));
  700.  
  701.     if  (!end)
  702.     {
  703.         if  (*str++ != '-') return NULL;
  704.     }
  705.  
  706.     memcpy(dest, buff, size);
  707.  
  708.     return  str;
  709. }
  710.  
  711. bool                parseGUID(const char *str, GUID *guidPtr, bool curlied)
  712. {
  713.     if  (curlied && *str++ != '{')
  714.     {
  715.     ERR:
  716. //      printf("ERROR: GUID's use the format 'HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH'\n");
  717.         return  true;
  718.     }
  719.  
  720.     str = parseHexD(str, &guidPtr->Data1   , 8, false, false);
  721.     if  (str == NULL)
  722.         goto ERR;
  723.     str = parseHexD(str, &guidPtr->Data2   , 4, false, false);
  724.     if  (str == NULL)
  725.         goto ERR;
  726.     str = parseHexD(str, &guidPtr->Data3   , 4, false, false);
  727.     if  (str == NULL)
  728.         goto ERR;
  729.     str = parseHexD(str,  guidPtr->Data4   , 4,  true, false);
  730.     if  (str == NULL)
  731.         goto ERR;
  732.     str = parseHexD(str,  guidPtr->Data4+2 ,12,  true,  true);
  733.     if  (str == NULL)
  734.         goto ERR;
  735.  
  736.     if  (curlied && *str++ != '}')
  737.         goto ERR;
  738.     if  (*str)
  739.         goto ERR;
  740.  
  741.     return  false;
  742. }
  743.  
  744. /*****************************************************************************
  745.  *
  746.  *  Process a DLL base file option.
  747.  */
  748.  
  749. static
  750. bool                parseHexNum(const char **nextPtr, unsigned *valPtr)
  751. {
  752.     const   char *  next = *nextPtr;
  753.     unsigned        val  = 0;
  754.  
  755.     /* Skip over any whitespace */
  756.  
  757.     while (isspace(*next)) next++;
  758.  
  759.     /* We should have "0x" next */
  760.  
  761.     if  (*next++ != '0')
  762.         return  true;
  763.     if  (*next++ != 'x')
  764.         return  true;
  765.  
  766.     /* Now collect a hex number */
  767.  
  768.     while (*next)
  769.     {
  770.         int             add;
  771.  
  772.         add = convertHC(*next);
  773.  
  774.         if  (add == -1)
  775.             break;
  776.  
  777.         val <<= 4;
  778.         val  += add;
  779.  
  780.         next++;
  781.     }
  782.  
  783.     /* Everything went fine, return everything to the caller */
  784.  
  785.     *nextPtr = next;
  786.     * valPtr = val;
  787.  
  788.     return  false;
  789. }
  790.  
  791. static
  792. bool                processDLLbaseFile(const char *fname, Compiler comp)
  793. {
  794.     const   char *  comma;
  795.     char            nbuff[_MAX_PATH];
  796.     FILE    *       filep;
  797.     bool            found;
  798.  
  799.     const   char *  nmstr;
  800.     unsigned        nmlen;
  801.  
  802. //  printf("DLL file = '%s'\n", fname);
  803.  
  804.     /* There better be a filename followed by name seperated by comma */
  805.  
  806.     comma = strchr(fname, ',');
  807.     if  (!comma || comma == fname || comma[1] == 0)
  808.         return  true;
  809.  
  810.     memcpy(nbuff, fname, comma-fname); nbuff[comma-fname] = 0;
  811.     nmstr = comma + 1;
  812.     nmlen = strlen(nmstr);
  813.  
  814. //  printf("File = '%s'\n", nbuff);
  815. //  printf("Name = '%s'\n", nmstr);
  816.  
  817.     filep = fopen(nbuff, "rt");
  818.     if  (!filep)
  819.     {
  820.         printf("WARNING: Could not open DLL base file '%s'\n", nbuff);
  821.         return  false;
  822.     }
  823.  
  824.     for (found = false;;)
  825.     {
  826.         char            line[256];
  827.         const   char *  next;
  828.  
  829.         if  (!fgets(line, sizeof(line), filep))
  830.             break;
  831.  
  832.         for (next = line; *next; next++)
  833.         {
  834.             if  (isalpha(*next))
  835.             {
  836.                 const   char *  nsbeg = next;
  837.  
  838.                 do
  839.                 {
  840.                     next++;
  841.                 }
  842.                 while (isalpha(*next));
  843.  
  844.                 if  ((int)nmlen == next - nsbeg && !memcmp(nsbeg, nmstr, nmlen))
  845.                 {
  846.                     unsigned            base;
  847.                     unsigned            size;
  848.  
  849.                     found = true;
  850.  
  851.                     /* We better have two hex numbers here */
  852.  
  853.                     if  (parseHexNum(&next, &base))
  854.                     {
  855.                         printf("WARNING: Didn't find size for DLL entry '%s' in '%s'\n", nmstr, nbuff);
  856.                         goto DONE;
  857.                     }
  858.  
  859.                     if  (parseHexNum(&next, &size))
  860.                     {
  861.                         printf("WARNING: Didn't find size for DLL entry '%s' in '%s'\n", nmstr, nbuff);
  862.                         goto DONE;
  863.                     }
  864.  
  865.                     comp->cmpConfig.ccOutBase = base;
  866.                     comp->cmpConfig.ccOutSize = size;
  867.  
  868. //                  printf("Found DLL entry [base=%08X,size=%08X]\n", base, size);
  869.  
  870.                     goto DONE;
  871.                 }
  872.             }
  873.         }
  874.     }
  875.  
  876.     fclose(filep);
  877.  
  878. DONE:
  879.  
  880.     if  (!found)
  881.     {
  882.         printf("WARNING: Didn't find entry for '%s' in DLL base file '%s'\n", nmstr, nbuff);
  883.         return  false;
  884.     }
  885.  
  886.     return  false;
  887. }
  888.  
  889. static
  890. StrList             addToStrList(const char *str, StrList  list,
  891.                                                   StrList *lastPtr)
  892. {
  893.     StrList         next;
  894.     char    *       save;
  895.  
  896. #if MGDDATA
  897.  
  898.     UNIMPL(!"save str");
  899.  
  900. #else
  901.  
  902.     next = (StrList)malloc(sizeof(*next));
  903.     save = (char  *)malloc(strlen(str)+1);
  904.  
  905.     strcpy(save, str);
  906.  
  907. #endif
  908.  
  909.     next->slString = save;
  910.     next->slNext   = NULL;
  911.  
  912.     if  (*lastPtr)
  913.         (*lastPtr)->slNext = next;
  914.     else
  915.         list               = next;
  916.  
  917.     *lastPtr = next;
  918.  
  919.     return  list;
  920. }
  921.  
  922. /*****************************************************************************/
  923. #if COUNT_CYCLES
  924. /*****************************************************************************/
  925.  
  926. #pragma warning(disable:4035)
  927.  
  928. #define CCNT_OVERHEAD64 13
  929.  
  930. __int64         GetCycleCount64()
  931. {
  932. __asm   _emit   0x0F
  933. __asm   _emit   0x31
  934. };
  935.  
  936. #define CCNT_OVERHEAD32 13
  937.  
  938. unsigned        GetCycleCount32()        // enough for about 40 seconds
  939. {
  940. __asm   push    EDX
  941. __asm   _emit   0x0F
  942. __asm   _emit   0x31
  943. __asm   pop     EDX
  944. };
  945.  
  946. #pragma warning(default:4035)
  947.  
  948. /*****************************************************************************/
  949.  
  950. static
  951. __int64         cycleBegin;
  952.  
  953. static
  954. __int64         cycleTotal;
  955.  
  956. static
  957. __int64         cycleStart;
  958.  
  959. static
  960. unsigned        cyclePause;
  961.  
  962. unsigned        cycleExtra;
  963.  
  964. static
  965. void            cycleCounterInit()
  966. {
  967.     cycleBegin = GetCycleCount64();
  968.     cycleTotal = 0;
  969.     cycleStart = 0;
  970.     cyclePause = 0;
  971. }
  972.  
  973. static
  974. __int64         cycleCounterDone(__int64 *realPtr)
  975. {
  976.     assert(cyclePause == 0);
  977.  
  978.     *realPtr = GetCycleCount64() - cycleBegin;
  979.  
  980.     return cycleTotal;
  981. }
  982.  
  983. void            cycleCounterBeg()
  984. {
  985.     assert(cyclePause == 0);
  986.  
  987.     cycleStart = GetCycleCount64();
  988. }
  989.  
  990. void            cycleCounterEnd()
  991. {
  992.     assert(cycleStart != 0);
  993.     assert(cyclePause == 0);
  994.  
  995.     cycleTotal += GetCycleCount64() - cycleStart;
  996.  
  997.     cycleStart  = 0;
  998. }
  999.  
  1000. void            cycleCounterPause()
  1001. {
  1002.     assert(cycleStart != 0);
  1003.  
  1004.     if  (!cyclePause)
  1005.         cycleTotal += GetCycleCount64() - cycleStart;
  1006.  
  1007.     cyclePause++;
  1008. }
  1009.  
  1010. void            cycleCounterResume()
  1011. {
  1012.     assert(cycleStart != 0);
  1013.     assert(cyclePause != 0);
  1014.  
  1015.     if  (--cyclePause)
  1016.         return;
  1017.  
  1018.     cycleStart = GetCycleCount64();
  1019. }
  1020.  
  1021. /*****************************************************************************/
  1022. #endif//COUNT_CYCLES
  1023. /*****************************************************************************
  1024.  *
  1025.  *  Recursively process the given file list, calling the given function pointer
  1026.  *  for each file found.
  1027.  */
  1028.  
  1029. static
  1030. bool                processFiles(Compiler    comp,
  1031.                                  unsigned    argb,
  1032.                                  unsigned    argc,
  1033.                                  stringArr_t argv,
  1034.                                  const char *subdir,
  1035.                                  bool      (*processOneFileFN)(genericRef, stringBuff, QueuedFile, stringBuff),
  1036.                                  genericRef  cookie,
  1037.                                  bool        asynch,
  1038.                                  const char *defaultFileExt)
  1039. {
  1040.     const   char *  file;
  1041.  
  1042.     int             more;
  1043.  
  1044.     __int32         ffHandle;
  1045.     _finddata_t     ffData;
  1046.  
  1047.     char            path[_MAX_PATH ];
  1048.     char            fnam[_MAX_FNAME];
  1049.     char            fdrv[_MAX_DRIVE];
  1050.     char            fdir[_MAX_DIR  ];
  1051.     char            fext[_MAX_EXT  ];
  1052.  
  1053.     bool            status = false;
  1054.  
  1055.     while (argb < argc)
  1056.     {
  1057.         /* Pull the next file name from the list */
  1058.  
  1059.         file = makeRawString(argv[argb++]);
  1060.  
  1061.         /* Is this a response file? */
  1062.  
  1063.         if  (*file == '@')
  1064.         {
  1065.             FILE    *       fp;
  1066.             bool            err;
  1067.  
  1068.             cycleCounterPause();
  1069.             fp = fopen(file+1, "rt");
  1070.             cycleCounterResume();
  1071.  
  1072.             if  (!fp)
  1073.             {
  1074.                 printf("ERROR: response file '%s' could not be opened.\n", file+1);
  1075.                 forceDebugBreak();
  1076.                 return 1;
  1077.             }
  1078.  
  1079.             for (err = false;;)
  1080.             {
  1081.                 char            line[256];
  1082.                 size_t          llen;
  1083.  
  1084.                 if  (!fgets(line, sizeof(line), fp))
  1085.                     break;
  1086.  
  1087.                 llen = strlen(line);
  1088.  
  1089.                 if  (llen && line[llen-1] == '\n')
  1090.                 {
  1091.                     llen--;
  1092.                     line[llen] = 0;
  1093.                 }
  1094.  
  1095.                 if  (line[0] && line[0] != ';')
  1096.                 {
  1097.                     if  (line[0] == '-' ||
  1098.                          line[0] == '/')
  1099.                     {
  1100.                         if  (startedCompiling)
  1101.                         {
  1102.                             printf("ERROR: All command-line options must precede source files\n");
  1103.                             return  true;
  1104.                         }
  1105.  
  1106.                         if  (processOption(line, comp))
  1107.                         {
  1108.                             dispHelpScreen(comp, line);
  1109.                             return  true;
  1110.                         }
  1111.                     }
  1112.                     else
  1113.                     {
  1114.                         char    *   name = line;
  1115.  
  1116. #ifdef  __COMRT__
  1117.                         stringArr_t nameArr   = new managed String[1]; nameArr[0] = makeMgdString(name);
  1118. #else
  1119.                         const char *nameArr[] = { name };
  1120. #endif
  1121.  
  1122.                         /* Recursive call */
  1123.  
  1124.                         err = processFiles(comp, 0, 1, nameArr,
  1125.                                                        NULL,
  1126.                                                        processOneFileFN,
  1127.                                                        cookie,
  1128.                                                        asynch,
  1129.                                                        defaultFileExt);
  1130.  
  1131.                         if  (err)
  1132.                             break;
  1133.                     }
  1134.                 }
  1135.             }
  1136.  
  1137.             fclose(fp);
  1138.  
  1139.             if  (err)
  1140.                 return err;
  1141.  
  1142.             continue;
  1143.         }
  1144.  
  1145.         /* Split the filename */
  1146.  
  1147.         _splitpath(file, fdrv, fdir, fnam, fext);
  1148.  
  1149.         /* Make sure we set the extension appropriately */
  1150.  
  1151.         if  (!fext[0])
  1152.             strcpy(fext, defaultFileExt);
  1153.  
  1154.         /* Append the subdirectory path if non-null */
  1155.  
  1156.         if  (subdir && *subdir)
  1157.             strcat(fdir, subdir);
  1158.         else
  1159.             subdir = "";
  1160.  
  1161.         /* Form a filename with the appropriate extension */
  1162.  
  1163.         _makepath(path, fdrv, fdir, fnam, fext);
  1164.  
  1165.         /* Look for the first match for the file pattern */
  1166.  
  1167.         cycleCounterPause();
  1168.         ffHandle = _findfirst(path, &ffData);
  1169.         cycleCounterResume();
  1170.  
  1171.         if  (ffHandle == -1)
  1172.         {
  1173.             if  (comp->cmpConfig.ccRecDir)
  1174.                 goto SUBDIRS;
  1175.  
  1176.             printf("ERROR: source file '%s' not found.\n", file);
  1177.             return 1;
  1178.         }
  1179.  
  1180.         do
  1181.         {
  1182.             // WARNING: Don't call cmpInit() in this thread if doing asynch I/O !!!!
  1183.  
  1184.             if  (!startedCompiling && !asynch)
  1185.             {
  1186.                 /* Initialize the compiler */
  1187.  
  1188.                 if  (comp->cmpInit())
  1189.                     return  true;
  1190.  
  1191.                 startedCompiling = true;
  1192.             }
  1193.  
  1194.             /* Make the matching file name into a complete path */
  1195.  
  1196.             _splitpath(ffData.name, NULL, NULL, fnam, fext);
  1197.             _makepath(path,         fdrv, fdir, fnam, fext);
  1198.  
  1199.             /* Remember the first name we encounter for the output file */
  1200.  
  1201.             if  (!firstFileName[0] && !comp->cmpConfig.ccRecDir)
  1202.                 _makepath(firstFileName, fdrv, fdir, fnam, NULL);
  1203.  
  1204.             /* Process the file by calling via the provided function pointer */
  1205.  
  1206.             status |= processOneFileFN(cookie, path, NULL, NULL);
  1207.             if  (status)
  1208.                 break;
  1209.  
  1210.             cycleCounterPause();
  1211.             more = _findnext(ffHandle, &ffData);
  1212.             cycleCounterResume();
  1213.         }
  1214.         while (more != -1);
  1215.  
  1216.         _findclose(ffHandle);
  1217.  
  1218.         if  (status)
  1219.             return  status;
  1220.  
  1221.     SUBDIRS:
  1222.  
  1223.         if  (comp->cmpConfig.ccRecDir)
  1224.         {
  1225.             /* Form a "*.*" filename */
  1226.  
  1227.             _makepath(path, fdrv, fdir, "*", "*");
  1228.  
  1229.             /* Walk the directory again */
  1230.  
  1231.             cycleCounterPause();
  1232.             ffHandle = _findfirst(path, &ffData);
  1233.             cycleCounterResume();
  1234.  
  1235.             if  (ffHandle == -1)
  1236.                 goto NEXT;
  1237.  
  1238.             do
  1239.             {
  1240.                 char            temp[_MAX_DIR  ];
  1241.  
  1242.                 if  (!(ffData.attrib & _A_SUBDIR))
  1243.                     continue;
  1244.  
  1245.                 /* Special case: skip "." and ".." */
  1246.  
  1247.                 if  (ffData.name[0] == '.')
  1248.                 {
  1249.                     switch (ffData.name[1])
  1250.                     {
  1251.                     case '.':
  1252.                         if  (ffData.name[2] == 0)
  1253.                             continue;
  1254.                         break;
  1255.  
  1256.                     case 0:
  1257.                         continue;
  1258.                     }
  1259.                 }
  1260.  
  1261.                 /* Append this subdirectory to the subdir path */
  1262.  
  1263.                 strcpy(temp, subdir);
  1264.                 if  (*temp) strcat(temp, "\\");
  1265.                 strcat(temp, ffData.name);
  1266.  
  1267.                 /* Recursively process the sub-directory */
  1268.  
  1269.                 status = processFiles(comp,
  1270.                                       argb-1,
  1271.                                       argb,
  1272.                                       argv, temp,
  1273.                                             processOneFileFN,
  1274.                                             cookie,
  1275.                                             asynch,
  1276.                                             defaultFileExt);
  1277.             }
  1278.             while (!status && _findnext(ffHandle, &ffData) != -1);
  1279.  
  1280.             _findclose(ffHandle);
  1281.         }
  1282.  
  1283.     NEXT:;
  1284.     }
  1285.  
  1286.     return  status;
  1287. }
  1288.  
  1289. /*****************************************************************************/
  1290. #ifdef  ASYNCH_INPUT_READ
  1291. /*****************************************************************************
  1292.  *
  1293.  *  The overlapped (asynch) file input logic follows.
  1294.  */
  1295.  
  1296. static
  1297. QueuedFile          fileQueueHead;
  1298. static
  1299. QueuedFile          fileQueueTail;
  1300.  
  1301. static
  1302. LONG    volatile    fileQueueSize;
  1303. static
  1304. LONG    volatile    fileQueueOpen;
  1305. static
  1306. LONG    volatile    fileQueueReading;
  1307. static
  1308. LONG    volatile    fileQueueRead;
  1309. static
  1310. LONG    volatile    fileQueueParsed;
  1311.  
  1312. static
  1313. CRITICAL_SECTION    fileQueueCritSect;
  1314.  
  1315. static
  1316. HANDLE              fileQueueListCnt;       // semaphore
  1317. static
  1318. HANDLE              fileQueueReadCnt;       // semaphore
  1319.  
  1320. static
  1321. HANDLE              fileQueueEndEvt0;     // event
  1322. static
  1323. HANDLE              fileQueueEndEvt1;     // event
  1324. static
  1325. HANDLE              fileQueueEndEvt2;     // event
  1326. static
  1327. HANDLE              fileQueueEndEvt3;     // event
  1328.  
  1329. struct  fileListDsc
  1330. {
  1331.     Compiler        comp;
  1332.     unsigned        argb;
  1333.     unsigned        argc;
  1334.     stringArr_t     argv;
  1335.     bool          (*func)(genericRef, stringBuff, QueuedFile, stringBuff);
  1336.     const char *    defx;
  1337.     void    *       cptr;
  1338. };
  1339.  
  1340. static
  1341. void    __stdcall   fileReadCallBack(DWORD error,
  1342.                                      DWORD count, OVERLAPPED *optr)
  1343. {
  1344.     QueuedFile      file = (QueuedFile)optr->hEvent;
  1345.  
  1346.     assert(file->qfSelf == file);
  1347.  
  1348.     if  (error || count != file->qfSize)
  1349.         file->qfComp->cmpGenFatal(ERRreadErr, file->qfName);
  1350.  
  1351. //  printf("Asynch I/O done: %6u bytes from '%s'\n", count, file->qfName);
  1352.  
  1353. #if DISP_ASYNC_PROGRESS
  1354.     printf("D");
  1355. #endif
  1356.  
  1357.     /* Append the EOF character */
  1358.  
  1359.     ((BYTE*)file->qfBuff)[file->qfSize] = 0x1A;
  1360.  
  1361.     /* Close the file */
  1362.  
  1363.     CloseHandle(file->qfHandle); file->qfHandle = 0;
  1364.  
  1365.     /* Mark the entry as "done" */
  1366.  
  1367.     file->qfDone = true; fileQueueRead++;
  1368.  
  1369.     /* Decrement the number of pending files */
  1370.  
  1371.     InterlockedDecrement((LONG*)&fileQueueReading);
  1372.  
  1373.     /* Signal the reader thread that another file has finished reading */
  1374.  
  1375.     if  (!ReleaseSemaphore(fileQueueReadCnt, 1, NULL))
  1376.     {
  1377.         printf("FATAL ERROR: Couldn't signal semaphore (error=%08X)\n", GetLastError());
  1378.         _flushall();
  1379.         exit(-1);
  1380.     }
  1381.  
  1382.     /* Signal the file event itself */
  1383.  
  1384.     SetEvent(file->qfEvent);
  1385. }
  1386.  
  1387. static
  1388. DWORD   __stdcall   fileReadWorker(LPVOID cookie)
  1389. {
  1390.     fileListDsc *   desc = (fileListDsc *)cookie;
  1391.  
  1392.     QueuedFile      list = fileQueueHead;
  1393.     bool            more = true;
  1394.  
  1395.     HANDLE          etab[3];
  1396.  
  1397. //  printf("Beg reader thread.\n");
  1398.  
  1399.     etab[0] = fileQueueListCnt;
  1400.     etab[1] = fileQueueEndEvt0;
  1401.     etab[2] = fileQueueEndEvt1;
  1402.  
  1403.     while (more || fileQueueSize != fileQueueOpen)
  1404.     {
  1405.         _Fstat          fileInfo;
  1406.  
  1407.         size_t          size;
  1408.         void    *       buff;
  1409.         size_t          read;
  1410.  
  1411.         unsigned        wait;
  1412.  
  1413.         /* Do we have a file ready to read? */
  1414.  
  1415.         if  (list && !list->qfOpen)
  1416.         {
  1417.             /* Make sure that we don't have too many files in play already */
  1418.  
  1419.             if  (fileQueueReading < MAX_SIMULTANEOUS_ASYNC_IOS)
  1420.                 goto NEXT;
  1421.         }
  1422.  
  1423.     WAIT:
  1424.  
  1425.         /* Wait for a file to be added to the queue or the end of the file list */
  1426.  
  1427. //      printf("Start wait [%u]\n", __LINE__);
  1428.  
  1429.         wait = WaitForMultipleObjectsEx(arraylen(etab),
  1430.                                         etab,
  1431.                                         FALSE,
  1432.                                         0, // INFINITE,
  1433.                                         true);
  1434.  
  1435. //      printf("End   wait [%u]\n", __LINE__);
  1436.  
  1437. #if 0
  1438.         if  (wait != WAIT_OBJECT_0 &&
  1439.              wait != WAIT_TIMEOUT  &&
  1440.              wait != WAIT_IO_COMPLETION)
  1441.         {
  1442.             printf("Wait -> 0x%04X\n", wait);
  1443. //          static int x; if (++x == 50) exit(-1);
  1444.         }
  1445. #endif
  1446.  
  1447.         switch (wait)
  1448.         {
  1449.         case WAIT_FAILED:
  1450.             printf("[1] Wait failed, huh?\n");
  1451.             return  1;
  1452.  
  1453.         case WAIT_TIMEOUT:
  1454.             continue;
  1455.  
  1456.         case WAIT_IO_COMPLETION:
  1457.             break;
  1458.  
  1459.         case WAIT_OBJECT_0:
  1460.  
  1461.             /* A new file has been added to the queue, let's go process it */
  1462.  
  1463.             break;
  1464.  
  1465.         case WAIT_OBJECT_0+1:
  1466.  
  1467.             /* Queue has been drained, let's go look for some more work */
  1468.  
  1469.             ResetEvent(fileQueueEndEvt0);
  1470.             break;
  1471.  
  1472.         case WAIT_OBJECT_0+2:
  1473.  
  1474.             /* No more files will be added to the input queue */
  1475.  
  1476.             more = false;
  1477.             ResetEvent(fileQueueEndEvt1);
  1478.             continue;
  1479.  
  1480.         default:
  1481.             printf("[1] Wait returned %08X, what the heck does that mean?\n", wait);
  1482.             return  1;
  1483.         }
  1484.  
  1485.         /* At least one file has been added to our queue, start reading it */
  1486.  
  1487.         if  (list == NULL)
  1488.              list = fileQueueHead;
  1489.  
  1490.         for (;;)
  1491.         {
  1492.             assert(list);
  1493.  
  1494.             if  (!list->qfReady)
  1495.                 goto WAIT;
  1496.  
  1497.             if  (!list->qfOpen)
  1498.                 break;
  1499.  
  1500.             if  (!list->qfNext)
  1501.                 goto WAIT;
  1502.  
  1503.             list = list->qfNext;
  1504.         }
  1505.  
  1506.         /* Make sure we don't start reading too many files at once */
  1507.  
  1508.         if  (fileQueueReading >= MAX_SIMULTANEOUS_ASYNC_IOS)
  1509.             continue;
  1510.  
  1511.     NEXT:
  1512.  
  1513. //      printf("Start asynch read from source file '%s'\n", list->qfName);
  1514.  
  1515.         /* See if the source file exists */
  1516.  
  1517.         if  (_stat(list->qfName, &fileInfo))
  1518.         {
  1519.         ERR_OPEN:
  1520.             printf("ERROR: source file '%s' not found.\n", list->qfName);
  1521.             UNIMPL(!"need to pretend the file has finished reading");
  1522.             continue;
  1523.         }
  1524.  
  1525.         /* Get hold of the file size */
  1526.  
  1527.         list->qfSize   = size = fileInfo.st_size;
  1528.  
  1529.         /* Open a read handle onto the file */
  1530.  
  1531.         list->qfHandle = CreateFileA(list->qfName,
  1532.                                      GENERIC_READ,
  1533.                                      FILE_SHARE_READ|FILE_SHARE_WRITE,
  1534.                                      NULL,
  1535.                                      OPEN_EXISTING,
  1536.                                      FILE_FLAG_SEQUENTIAL_SCAN,
  1537. //                                   FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING|FILE_FLAG_OVERLAPPED,
  1538.                                      NULL);
  1539.  
  1540.         if  (list->qfHandle == INVALID_HANDLE_VALUE)
  1541.             goto ERR_OPEN;
  1542.  
  1543.         /* Create the "read finished" event */
  1544.  
  1545.         list->qfEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  1546.  
  1547.         /* Mark the file as open and increment the open file count */
  1548.  
  1549.         list->qfOpen = true;
  1550.  
  1551.         /* Increment the number of open and pending files */
  1552.  
  1553.         InterlockedIncrement((LONG*)&fileQueueOpen);
  1554.         InterlockedIncrement((LONG*)&fileQueueReading);
  1555.  
  1556.         /* Allocate a buffer for the file contents */
  1557.  
  1558.         list->qfBuff = buff = malloc(size+1);
  1559.         if  (!buff)
  1560.             desc->comp->cmpGenFatal(ERRnoMemory);
  1561.  
  1562.         /* Clear the overlapped struct and stash the file pointer in it */
  1563.  
  1564.         memset(&list->qfOdsc, 0, sizeof(list->qfOdsc));
  1565.  
  1566.         list->qfOdsc.hEvent = (HANDLE)list;
  1567.  
  1568.         /* We're ready to issue the read request */
  1569.  
  1570.         read = ReadFileEx(list->qfHandle,
  1571.                           list->qfBuff,
  1572.                           list->qfSize,
  1573.                          &list->qfOdsc,
  1574.                           fileReadCallBack);
  1575.  
  1576. #if     DISP_ASYNC_PROGRESS
  1577.         printf("R");
  1578. #endif
  1579.  
  1580.         if  (!read)
  1581.         {
  1582.             /* Error - call the callback manually (the OS won't call it) */
  1583.  
  1584.             fileReadCallBack(GetLastError(), 0, &list->qfOdsc);
  1585.         }
  1586.     }
  1587.  
  1588.     SetEvent(fileQueueEndEvt2);
  1589.  
  1590.     while (fileQueueRead != fileQueueSize)
  1591.         SleepEx(1000, TRUE);
  1592.  
  1593. //  printf("End reader thread.\n");
  1594.  
  1595.     return  0;
  1596. }
  1597.  
  1598. static
  1599. bool                fileReadAppend(genericRef cookie, stringBuff filename, QueuedFile, stringBuff)
  1600. {
  1601.     fileListDsc *   desc = (fileListDsc *)cookie;
  1602.     Compiler        comp = desc->comp;
  1603.     char    *       name;
  1604.  
  1605.     QueuedFile      qfile;
  1606.  
  1607. //  printf("Adding file to input queue: '%s'\n", filename);
  1608.  
  1609.     /* Make a durable copy of the input file name */
  1610.  
  1611.     name  = new char[strlen(filename)+1]; strcpy(name, filename);
  1612.  
  1613.     /* Create a new file queue entry */
  1614.  
  1615.     qfile = new queuedFile;
  1616.  
  1617.     qfile->qfComp    = comp;
  1618.     qfile->qfName    = name;
  1619.     qfile->qfSize    = 0;
  1620.     qfile->qfBuff    = NULL;
  1621.     qfile->qfHandle  = 0;
  1622.     qfile->qfOpen    = false;
  1623.     qfile->qfDone    = false;
  1624.     qfile->qfParsing = false;
  1625.     qfile->qfEvent   = NULL;
  1626.     qfile->qfNext    = NULL;
  1627.  
  1628. #ifdef  DEBUG
  1629.     qfile->qfSelf    = qfile;
  1630. #endif
  1631.  
  1632.     /* Append the new file entry to the queue */
  1633.  
  1634.     EnterCriticalSection(&fileQueueCritSect);
  1635.  
  1636.     if  (fileQueueHead)
  1637.          fileQueueTail->qfNext = qfile;
  1638.     else
  1639.          fileQueueHead         = qfile;
  1640.  
  1641.     fileQueueTail = qfile;
  1642.  
  1643.     fileQueueSize++;
  1644.  
  1645.     LeaveCriticalSection(&fileQueueCritSect);
  1646.  
  1647.     /* The file is ready to be processed now */
  1648.  
  1649.     qfile->qfReady = true;
  1650.  
  1651.     /* Signal the reader thread that there is more work to be done */
  1652.  
  1653.     if  (!ReleaseSemaphore(fileQueueListCnt, 1, NULL))
  1654.     {
  1655.         printf("FATAL ERROR: Couldn't signal semaphore (error=%08X)\n", GetLastError());
  1656.         _flushall();
  1657.         exit(-1);
  1658.     }
  1659.  
  1660.     SleepEx(0, TRUE);
  1661.  
  1662.     return  false;
  1663. }
  1664.  
  1665. static
  1666. DWORD   __stdcall   fileListWorker(LPVOID cookie)
  1667. {
  1668.     bool            result;
  1669.  
  1670.     fileListDsc *   desc = (fileListDsc *)cookie;
  1671.  
  1672.     result = processFiles(desc->comp,
  1673.                           desc->argb,
  1674.                           desc->argc,
  1675.                           desc->argv,
  1676.                           NULL,
  1677.                           &fileReadAppend,
  1678.                           desc,
  1679.                           true,
  1680.                           desc->defx);
  1681.  
  1682.     SetEvent(fileQueueEndEvt1);
  1683.  
  1684.     return  result;
  1685. }
  1686.  
  1687. static
  1688. bool                processFileList(Compiler    comp,
  1689.                                     unsigned    argb,
  1690.                                     unsigned    argc,
  1691.                                     stringArr_t argv,
  1692.                                     bool      (*processOneFileFN)(genericRef, stringBuff, QueuedFile, stringBuff),
  1693.                                     genericRef  cookie,
  1694.                                     bool        asynch,
  1695.                                     const char *defaultFileExt)
  1696. {
  1697.     bool            err = false;
  1698.  
  1699.     fileListDsc     desc;
  1700.  
  1701.     bool            more;
  1702.     bool            done;
  1703.  
  1704.     HANDLE          etab[3];
  1705.  
  1706.     QueuedFile      nextFile;
  1707.     unsigned        waitCnt;
  1708.  
  1709.     DWORD           listerThrdID;
  1710.     HANDLE          listerThrdHN;
  1711.  
  1712.     DWORD           readerThrdID;
  1713.     HANDLE          readerThrdHN;
  1714.  
  1715.     if  (!asynch)
  1716.     {
  1717.         return  processFiles(comp,
  1718.                              argb,
  1719.                              argc,
  1720.                              argv,
  1721.                              NULL,
  1722.                              processOneFileFN,
  1723.                              cookie,
  1724.                              asynch,
  1725.                              defaultFileExt);
  1726.     }
  1727.  
  1728.     /* Clear the queue of input files */
  1729.  
  1730.     fileQueueHead =
  1731.     fileQueueTail = NULL;
  1732.  
  1733.     InitializeCriticalSection(&fileQueueCritSect);
  1734.  
  1735.     /* Create the necessary event objects */
  1736.  
  1737.     fileQueueListCnt = CreateSemaphore(NULL, 0, INT_MAX, NULL);
  1738.     fileQueueReadCnt = CreateSemaphore(NULL, 0, INT_MAX, NULL);
  1739.  
  1740.     fileQueueEndEvt0 = CreateEvent    (NULL, TRUE, FALSE, NULL);
  1741.     fileQueueEndEvt1 = CreateEvent    (NULL, TRUE, FALSE, NULL);
  1742.     fileQueueEndEvt2 = CreateEvent    (NULL, TRUE, FALSE, NULL);
  1743.     fileQueueEndEvt3 = CreateEvent    (NULL, TRUE, FALSE, NULL);
  1744.  
  1745.     /* Create a thread that will look for files to compile */
  1746.  
  1747.     desc.comp = comp;
  1748.     desc.argb = argb;
  1749.     desc.argc = argc;
  1750.     desc.argv = argv;
  1751.     desc.func = processOneFileFN;
  1752.     desc.defx = defaultFileExt;
  1753.     desc.cptr = cookie;
  1754.  
  1755.     listerThrdHN = CreateThread(NULL, 0, fileListWorker, &desc, 0, &listerThrdID);
  1756.     if  (listerThrdHN == NULL)
  1757.     {
  1758.         printf("FATAL ERROR: Couldn't create file list worker thread (error=%08X)\n", GetLastError());
  1759.         return  true;
  1760.     }
  1761.  
  1762.     readerThrdHN = CreateThread(NULL, 0, fileReadWorker, &desc, 0, &readerThrdID);
  1763.     if  (readerThrdHN == NULL)
  1764.     {
  1765.         printf("FATAL ERROR: Couldn't create file read worker thread (error=%08X)\n", GetLastError());
  1766.         return  true;
  1767.     }
  1768.  
  1769.     /* Wait until files start arriving */
  1770.  
  1771.     etab[0]  = fileQueueReadCnt;
  1772.     etab[1]  = fileQueueEndEvt2;
  1773.     etab[2]  = fileQueueEndEvt3;
  1774.  
  1775.     for (more = true, done = false, nextFile = NULL, waitCnt = 0;;)
  1776.     {
  1777.         unsigned        wait;
  1778.  
  1779. //      printf("[2] Pending = %u\n", fileQueueReading);
  1780.  
  1781.         /* Are any files waiting to be processed? */
  1782.  
  1783.         while (waitCnt)
  1784.         {
  1785.             if  (nextFile == NULL)
  1786.             {
  1787.                 /* This is the very first time here */
  1788.  
  1789.                 nextFile = fileQueueHead;
  1790.  
  1791.                 /* Initialize the compiler */
  1792.  
  1793.                 assert(startedCompiling == false);
  1794.  
  1795. #ifdef  ASYNCH_INPUT_READ
  1796. #if     DISP_ASYNC_PROGRESS
  1797.                 printf("I");
  1798. #endif
  1799.                 cycleCounterResume();
  1800. #endif
  1801.  
  1802.                 if  (comp->cmpInit())
  1803.                     return  true;
  1804.  
  1805. #ifdef  ASYNCH_INPUT_READ
  1806.                 cycleCounterPause();
  1807. #endif
  1808.  
  1809.                 startedCompiling = true;
  1810.  
  1811.                 SetEvent(fileQueueEndEvt3);
  1812.             }
  1813.  
  1814.             assert(nextFile);
  1815.  
  1816.             /* Skip over any files we may have processed last time */
  1817.  
  1818.             for (;;)
  1819.             {
  1820.                 if  (!nextFile->qfParsing)
  1821.                     break;
  1822.  
  1823.                 if  (!nextFile->qfNext)
  1824.                     goto WAIT;
  1825.  
  1826.                 nextFile = nextFile->qfNext;
  1827.             }
  1828.  
  1829.             if  (!nextFile->qfDone)
  1830.             {
  1831.                 /* Wait for this file to finish loading */
  1832.  
  1833.                 UNIMPL(!"wait");
  1834.             }
  1835.  
  1836.             if  (nextFile->qfEvent)
  1837.             {
  1838.                 CloseHandle(nextFile->qfEvent);
  1839.                             nextFile->qfEvent = 0;
  1840.             }
  1841.  
  1842.             nextFile->qfParsing = true;
  1843.             waitCnt--;
  1844.  
  1845.             InterlockedIncrement((LONG*)&fileQueueParsed);
  1846.  
  1847.             assert(nextFile->qfDone);
  1848.  
  1849. #ifdef  ASYNCH_INPUT_READ
  1850. #if     DISP_ASYNC_PROGRESS
  1851.             printf("P");
  1852. #endif
  1853.             cycleCounterResume();
  1854. #endif
  1855.  
  1856.             err |= processOneFileFN(comp, (char *)nextFile->qfName, nextFile, NULL);
  1857.  
  1858. #ifdef  ASYNCH_INPUT_READ
  1859.             cycleCounterPause();
  1860. #if     DISP_ASYNC_PROGRESS
  1861.             printf("E");
  1862. #endif
  1863. #endif
  1864.  
  1865.             /* Throw away the file contents */
  1866.  
  1867.             assert(nextFile->qfBuff == NULL);       // temp hack!!!!
  1868.  
  1869.             if  (nextFile->qfBuff)
  1870.             {
  1871.                 free(nextFile->qfBuff);
  1872.                      nextFile->qfBuff = NULL;
  1873.             }
  1874.  
  1875.             /* If any files might be backed up, push the queue */
  1876.  
  1877.             if  (fileQueueReading)
  1878.                 SetEvent(fileQueueEndEvt0);
  1879.  
  1880. //          printf("[3] Pending = %u\n", fileQueueReading);
  1881.  
  1882.             SleepEx(0, TRUE);
  1883.         }
  1884.  
  1885.     WAIT:
  1886.  
  1887. //      printf("Waitcnt = %u, more = %u, counts = %u/%u\n", waitCnt, more, fileQueueSize, fileQueueRead);
  1888.  
  1889.         if  (!more && done && fileQueueSize == fileQueueRead)
  1890.             break;
  1891.  
  1892.         /* Wait for a file to be added to the queue or the end of the file list */
  1893.  
  1894. //      printf("Start wait [%u]\n", __LINE__);
  1895.  
  1896.         wait = WaitForMultipleObjectsEx(arraylen(etab),
  1897.                                         etab,
  1898.                                         FALSE,
  1899.                                         0, // INFINITE,
  1900.                                         true);
  1901.  
  1902. //      printf("End   wait [%u]\n", __LINE__);
  1903.  
  1904.         switch (wait)
  1905.         {
  1906.         case WAIT_OBJECT_0:
  1907.  
  1908.             /* Another file has finished reading */
  1909.  
  1910.             waitCnt++;
  1911.             break;
  1912.  
  1913.         case WAIT_OBJECT_0+1:
  1914.  
  1915.             /* All files have been added to the file list */
  1916.  
  1917.             more = false; ResetEvent(fileQueueEndEvt2);
  1918.             break;
  1919.  
  1920.         case WAIT_OBJECT_0+2:
  1921.  
  1922.             /* At least one file has been read and started parsing */
  1923.  
  1924.             done = true;
  1925.             break;
  1926.  
  1927.         case WAIT_TIMEOUT:
  1928.             SleepEx(0, TRUE);
  1929.             break;
  1930.  
  1931.         default:
  1932.             printf("[2] Wait returned %08X, what the heck does that mean?\n", wait);
  1933.             err = true;
  1934.             goto DONE;
  1935.         }
  1936.     }
  1937.  
  1938. DONE:
  1939.  
  1940.     DeleteCriticalSection(&fileQueueCritSect);
  1941.  
  1942.     CloseHandle(fileQueueListCnt);
  1943.     CloseHandle(fileQueueReadCnt);
  1944.  
  1945.     CloseHandle(fileQueueEndEvt0);
  1946.     CloseHandle(fileQueueEndEvt1);
  1947.     CloseHandle(fileQueueEndEvt2);
  1948.     CloseHandle(fileQueueEndEvt3);
  1949.  
  1950.     assert(fileQueueReading == 0);
  1951.  
  1952.     assert(fileQueueSize    == fileQueueOpen);
  1953.     assert(fileQueueSize    == fileQueueRead);
  1954.  
  1955.     return  err;
  1956. }
  1957.  
  1958. /*****************************************************************************/
  1959. #else //ASYNCH_INPUT_READ
  1960. /*****************************************************************************/
  1961.  
  1962. static
  1963. bool                processFileList(Compiler    comp,
  1964.                                     unsigned    argb,
  1965.                                     unsigned    argc,
  1966.                                     stringArr_t argv,
  1967.                                     bool      (*processOneFileFN)(genericRef, stringBuff, QueuedFile, stringBuff),
  1968.                                     genericRef  cookie,
  1969.                                     bool        asynch,
  1970.                                     const char *defaultFileExt)
  1971. {
  1972.     return  processFiles(comp,
  1973.                          argb,
  1974.                          argc,
  1975.                          argv,
  1976.                          NULL,
  1977.                          processOneFileFN,
  1978.                          cookie,
  1979.                          asynch,
  1980.                          defaultFileExt);
  1981. }
  1982.  
  1983. /*****************************************************************************/
  1984. #endif//ASYNCH_INPUT_READ
  1985. /*****************************************************************************/
  1986.  
  1987. int                 getRegIntVal(const char *name, int defVal)
  1988. {
  1989.     assert(name);
  1990.  
  1991. #ifndef __IL__      // the following crashes as managed code, don't know why ....
  1992.  
  1993.     HKEY            subKey;
  1994.  
  1995.     if  (!RegOpenKeyExA(HKEY_CURRENT_USER, SMCregKey, 0, KEY_QUERY_VALUE, &subKey))
  1996.     {
  1997.         DWORD           value;
  1998.         DWORD           valType;
  1999.         DWORD           valSize = sizeof(value);
  2000.  
  2001.         if  (!RegQueryValueExA(subKey, name, NULL, &valType, (PBYTE)&value, &valSize))
  2002.         {
  2003.             if  (valType == REG_DWORD && valSize == sizeof(DWORD))
  2004.                 defVal = value;
  2005.         }
  2006.  
  2007.         RegCloseKey(subKey);
  2008.     }
  2009.  
  2010. #endif
  2011.  
  2012.     return defVal;
  2013. }
  2014.  
  2015. /*****************************************************************************
  2016.  *
  2017.  *  Filter expression - return 1 to handle an exception.
  2018.  */
  2019.  
  2020. int                 EHfilter(unsigned code)
  2021. {
  2022. //  printf("Error code = %08X\n", code); _flushall();
  2023.     return  (code != 0x80000003);
  2024. }
  2025.  
  2026. /*****************************************************************************
  2027.  *
  2028.  *  The main generic entry point of the compiler.
  2029.  */
  2030.  
  2031. #ifdef  DLL
  2032. int                 compileAll(int argc, stringArr_t argv, Compiler comp)
  2033. #else
  2034. int                 compileAll(int argc, stringArr_t argv)
  2035. #endif
  2036. {
  2037.     unsigned        EHcode;
  2038.  
  2039. #ifdef  DLL
  2040.  
  2041. #else
  2042.  
  2043.     Compiler        comp = (Compiler)malloc(sizeof(*comp));
  2044.  
  2045. #endif
  2046.  
  2047.     int             err  = 0;
  2048.  
  2049.     unsigned        argx = 0;
  2050.  
  2051.     /* Clear the compile state */
  2052.  
  2053. #if!MGDDATA
  2054.     memset(comp, 0, sizeof(*comp));
  2055. #endif
  2056.  
  2057.     /* Catch any exceptions and report them as "internal errors" */
  2058.  
  2059.     __try
  2060.     {
  2061.         unsigned        optNum;
  2062.         optionDesc  *   optTab;
  2063.  
  2064.         /* Create the default config value */
  2065.  
  2066.         for (optNum = 0, optTab = optionInfo;
  2067.              optNum < CC_COUNT;
  2068.              optNum++  , optTab++)
  2069.         {
  2070.             if  (optTab->odValueSize <= sizeof(int))
  2071.             {
  2072.                 memcpy( optTab->odValueOffs + (char*)(&comp->cmpConfig),
  2073.                        &optTab->odDefault,
  2074.                         optTab->odValueSize);
  2075.             }
  2076.         }
  2077.  
  2078.         /* Copy over the default warning settings */
  2079.  
  2080.         comp->cmpErrorInit();
  2081.  
  2082.         /* Process any command-line switches */
  2083.  
  2084.         while (argx < (unsigned)argc)
  2085.         {
  2086.             const   char *  argn;
  2087.  
  2088.             /* Grab the next command-line argument and stop if not an option */
  2089.  
  2090.             argn = makeRawString(argv[argx]);
  2091.             if  (argn[0] != '-' && argn[0] != '/')
  2092.                 break;
  2093.  
  2094.             if  (processOption(argn, comp))
  2095.             {
  2096.                 dispHelpScreen(comp, argn);
  2097.                 goto EXIT;
  2098.             }
  2099.  
  2100.             argx++;
  2101.         }
  2102.  
  2103.         if  (argc == (int)argx)
  2104.         {
  2105. #ifndef DLL
  2106.             printf("ERROR: No source files to be compiled have been specified\n\n");
  2107.             dispHelpScreen(comp);
  2108. #endif
  2109.             goto EXIT;
  2110.         }
  2111.  
  2112. #if COUNT_CYCLES
  2113.  
  2114.         /* Reset the cycle counter */
  2115.  
  2116.         cycleCounterInit();
  2117.         assert(cycleTotal == 0);
  2118.         cycleCounterBeg();
  2119.  
  2120. #ifdef  ASYNCH_INPUT_READ
  2121.         if  (comp->cmpConfig.ccAsynchIO)
  2122.             cycleCounterPause();
  2123. #endif
  2124.  
  2125. #endif
  2126.  
  2127.         /* Display the signon banner */
  2128.  
  2129.         if  (!comp->cmpConfig.ccQuiet)
  2130.         {
  2131.             printf("Microsoft (R) Visual SMC Compiler Version %s\n", COMPILER_VERSION);
  2132.             printf("Copyright (C) Microsoft Corp 1999. All rights reserved.\n");
  2133.             printf("\n");
  2134.         }
  2135.  
  2136.         /* Prepare all the source files given to us */
  2137.  
  2138.         err = processFileList(comp, argx, argc, argv, compiler::cmpPrepSrc, comp, comp->cmpConfig.ccAsynchIO, ".smc");
  2139.         if  (err)
  2140.             goto EXIT;
  2141.  
  2142.         /* Bail if there was a fatal error */
  2143.  
  2144.         if  (comp->cmpFatalCount)
  2145.             goto DONE;
  2146.  
  2147. #ifdef  DEBUG
  2148. //      if  (comp->cmpConfig.ccVerbose) comp->cmpDumpSymbolTable();
  2149. #endif
  2150.  
  2151. #ifdef  ASYNCH_INPUT_READ
  2152. #if     DISP_ASYNC_PROGRESS
  2153.         printf("C\n");
  2154. #endif
  2155.         if  (comp->cmpConfig.ccAsynchIO)
  2156.             cycleCounterResume();
  2157. #endif
  2158.  
  2159.         /* Prepare for the real thing */
  2160.  
  2161.         err = comp->cmpStart(firstFileName);
  2162.         if  (err)
  2163.             goto EXIT;
  2164.  
  2165.         /* Compile everything [CONSIDER: only compile one class if desired] */
  2166.  
  2167.         err = comp->cmpClass();
  2168.         if  (err)
  2169.             goto EXIT;
  2170.  
  2171. #if COUNT_CYCLES
  2172.  
  2173.         __int64         cycleTotal;
  2174.         __int64         cycleSpent;
  2175.  
  2176.         cycleSpent = cycleCounterDone(&cycleTotal);
  2177.  
  2178.         if  (cycleTotal)
  2179.             printf("Gross time (est): P2-450 / %4.2f sec, P2-500 / %4.2f, P2-650 / %4.2f\n", (float)cycleTotal/450000000, (float)cycleTotal/500000000, (float)cycleTotal/650000000);
  2180.         if  (cycleSpent)
  2181.             printf("Net   time (est): P2-450 / %4.2f sec, P2-500 / %4.2f, P2-650 / %4.2f\n", (float)cycleSpent/450000000, (float)cycleSpent/500000000, (float)cycleSpent/650000000);
  2182.  
  2183.         if  (cycleExtra)
  2184.             printf("Extra time (est): P2-450 / %4.2f sec, P2-500 / %4.2f, P2-650 / %4.2f\n", (float)cycleExtra/450000000, (float)cycleExtra/500000000, (float)cycleExtra/650000000);
  2185.  
  2186.         printf("\n");
  2187.  
  2188. #endif
  2189.  
  2190. #ifdef  SMC_MD_PERF
  2191.  
  2192.         __int64         cycCnt;
  2193.         __int64         totCyc;
  2194.  
  2195.         MetaDataImp     cimp;
  2196.         unsigned        i;
  2197.  
  2198.         printf("\nMetadata Import:\n");
  2199.  
  2200.         for (cimp = comp->cmpMDlist, i = 1, totCyc = 0;
  2201.              cimp;
  2202.              cimp = cimp->MDnext   , i++)
  2203.         {
  2204.             cycCnt  = cimp->MDwmdi->getTotalCycles();
  2205.             totCyc += cycCnt;
  2206.  
  2207.             printf("\tFile [%02u] cycles = %8.0f, time = %6.5f sec (est. on P2-450)\n", i, (float)cycCnt, (float)cycCnt/450000000);
  2208.         }
  2209.  
  2210.         cycCnt  = comp->cmpPEwriter->WPEwmde->getTotalCycles();
  2211.         totCyc += cycCnt;
  2212.  
  2213.         printf("Metadata Emit:\n");
  2214.         printf("\t          cycles = %8.0f, time = %6.5f sec (est. on P2-450)\n", (float)cycCnt, (float)cycCnt/450000000);
  2215.  
  2216.         printf("Metadata Total:\n");
  2217.         printf("\t          cycles = %8.0f, time = %6.5f sec (est. on P2-450)\n", (float)totCyc, (float)totCyc/450000000);
  2218.  
  2219. #endif
  2220.  
  2221. #ifdef  DEBUG
  2222.         if  (comp->cmpConfig.ccVerbose >= 4) comp->cmpDumpSymbolTable();
  2223. #endif
  2224.  
  2225.     DONE:
  2226.  
  2227.         /* Wrap up the compilation process */
  2228.  
  2229.         err = comp->cmpDone(err != 0);
  2230.     }
  2231. //  __except(EHcode = 0)
  2232.     __except(EHfilter(EHcode = _exception_code()))
  2233.     {
  2234.         printf("fatal error: Compiler writer error [EC=0x%08X]", EHcode);
  2235.  
  2236.         switch (EHcode)
  2237.         {
  2238.         case STATUS_STACK_OVERFLOW:
  2239.             printf(" -- stack overflow");
  2240.             break;
  2241.  
  2242. #ifdef  __IL__
  2243.         case 0x80131522:
  2244.             printf(" -- load failed (bad CORwrap.DLL?)");
  2245.             break;
  2246. #endif
  2247.  
  2248.         }
  2249.  
  2250. #ifdef  DEBUG_____DISABLED_FOR_NOW
  2251.         printf(" [compiler command line='");
  2252.         for (int i = 0; i < argc; i++)
  2253.         {
  2254.             printf("%s", makeRawString(argv[i]));
  2255.             if  (i < argc-1)
  2256.                 printf(" ");
  2257.         }
  2258.         printf("]'");
  2259.         forceDebugBreak();
  2260. #endif
  2261.  
  2262.         printf("\n");
  2263.         err = -1;
  2264.     }
  2265.  
  2266. EXIT:
  2267.  
  2268. #if 0
  2269.     printf("Total array types created: %u\n", arrTypeCnt);
  2270.     printf("Total array types  reused: %u\n", arrTypeHit);
  2271. #endif
  2272.  
  2273. #if 0
  2274.     void    dispMemAllocStats();
  2275.             dispMemAllocStats();
  2276. #endif
  2277.  
  2278. #if 0
  2279.     void    dispSymTabAllocStats();
  2280.             dispSymTabAllocStats();
  2281. #endif
  2282.  
  2283. #if 0
  2284.     void    dispHashTabStats();
  2285.             dispHashTabStats();
  2286. #endif
  2287.  
  2288. #if 0
  2289.     void    dispScannerStats();
  2290.             dispScannerStats();
  2291. #endif
  2292.  
  2293.     return  err;
  2294. }
  2295.  
  2296. /*****************************************************************************
  2297.  *
  2298.  *  Main platform-specific entry point of compiler.
  2299.  */
  2300.  
  2301. #ifdef  DLL
  2302.  
  2303. __declspec(dllexport)
  2304. int __stdcall       DllMain(HINSTANCE instance, DWORD reason, LPVOID foobar)
  2305. {
  2306.     if  (reason == DLL_PROCESS_ATTACH)
  2307.         printf("SMC compiler DLL   loaded.\n");
  2308.     if  (reason == DLL_PROCESS_DETACH)
  2309.         printf("SMC compiler DLL unloaded.\n");
  2310.  
  2311.     return  TRUE;
  2312. }
  2313.  
  2314. extern  "C"
  2315. __declspec(dllexport)
  2316. int __cdecl         compileInit(unsigned optCnt, const char *optTab[], void **cookiePtr)
  2317. {
  2318.     Compiler        comp = (Compiler)malloc(sizeof(*comp));
  2319.     int             err;
  2320.  
  2321.     /* Process the command-line options */
  2322.  
  2323.     err = compileAll(optCnt, optTab, comp);
  2324.     if  (err)
  2325.         return  err;
  2326.  
  2327.     /* Make sure we set the output file name properly */
  2328.  
  2329.     cfg.ccOutFileName = ":memory:";
  2330.  
  2331.     /* Save the option settings */
  2332.  
  2333.     comp->cmpConfig = cfg;
  2334.  
  2335.     /* Return the compiler instance to the caller */
  2336.  
  2337.     *cookiePtr = comp;
  2338.  
  2339.     return  0;
  2340. }
  2341.  
  2342. extern  "C"
  2343. __declspec(dllexport)
  2344. int __cdecl         compileText(void *cookie, const char *srcText)
  2345. {
  2346.     int             err;
  2347.     Compiler        comp = (Compiler)cookie;
  2348.  
  2349.     __try
  2350.     {
  2351.         /* Start up the compiler */
  2352.  
  2353.         comp->cmpInit();
  2354.  
  2355.         /* Prepare the source text given to us */
  2356.  
  2357.         err = comp->cmpPrepSrc(comp, NULL, "<memory>", (stringBuff)srcText);
  2358.         if  (err)
  2359.             goto EXIT;
  2360.  
  2361.         /* Bail if there was a fatal error */
  2362.  
  2363.         if  (comp->cmpFatalCount)
  2364.             goto DONE;
  2365.  
  2366.         /* Prepare for the real thing */
  2367.  
  2368.         err = comp->cmpStart(NULL);
  2369.         if  (err)
  2370.             goto EXIT;
  2371.  
  2372.         /* Compile the source text */
  2373.  
  2374.         err = comp->cmpClass();
  2375.         if  (err)
  2376.             goto EXIT;
  2377.  
  2378.     DONE:
  2379.  
  2380.         /* Wrap up the compilation process */
  2381.  
  2382.         err = comp->cmpDone(err != 0);
  2383.     }
  2384.     __except(EHfilter(_exception_code()))
  2385.     {
  2386.         printf("fatal error: Compiler writer error\n");
  2387.         err = -1;
  2388.     }
  2389.  
  2390. EXIT:
  2391.  
  2392.     return  err;
  2393. }
  2394.  
  2395. #else
  2396.  
  2397. #ifdef  __SMC__
  2398.  
  2399. int                 main(String managed [] args)
  2400. {
  2401. //  printf("Made it to %s(%u)\n", __FILE__, __LINE__); _flushall();
  2402.  
  2403.     return  compileAll(args.Length, args);
  2404. }
  2405.  
  2406. #else
  2407.  
  2408. int     _cdecl      main(int argc, stringArr_t argv)
  2409. {
  2410.  
  2411.     return  compileAll(argc - 1, argv + 1);
  2412.  
  2413. }
  2414.  
  2415. #endif
  2416.  
  2417. #endif
  2418.  
  2419. /*****************************************************************************/
  2420.