/** cvpack - types compactor for codeview debug information. /** The purpose of this program is to remove referenced types * information from the $$types section of each module, and to * remove duplicate type strings across modules. The result is a * compacted global types section (as opposed to a type section for * each module) which are all referenced by symbols and contains no * duplicates. Duplicate global symbols are compacted into a global * symbol table. All of the public symbol tables are compacted into * a single global publics table. */ #include "compact.h" #include "version.h" #include #include #ifdef WINDOWS #include "winstuff.h" /* * Externals and forwards */ void ProcessWinArgs(char *pszCmdLine, char *pszExeFile); #endif #if defined (OS2) #define INCL_DOS #define INCL_SUB #define INCL_DOSERRORS #include #endif void _CRTAPI1 main (int, char **); LOCAL void ProcessArgs (int, char **); LOCAL void OpenExe (char *); extern int _fDosExt; #define SwapSize 11000 int exefile; // the exefile we're working on bool_t verifyDebug = FALSE; // verify debug data correctness bool_t logo = TRUE; // suppress logo and compression numbers bool_t delete = FALSE; // delete symbols and types bool_t runMpc = FALSE; bool_t NeedsBanner = TRUE; // false if banner displayed bool_t fVerbose = FALSE; // TRUE if verbose output is desired bool_t FDebug = FALSE; #ifndef WINDOWS void _CRTAPI1 main(int argc, char **argv) #else int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) #endif { ushort i; ushort nMod = 0; #if !defined (WINDOWS) // print startup microsoft banner and process the arguments ProcessArgs (argc, argv); if ((logo == TRUE) && (NeedsBanner == TRUE)) { Banner (); } OpenExe (argv[argc-1]); #if defined (OS2) DosError (HARDERROR_ENABLE | EXCEPTION_DISABLE); #endif #else char szExeFile[_MAX_PATH]; char szMsg[128]; ProcessWinArgs (lpCmdLine, szExeFile ); // report version number sprintf (szMsg, "Microsoft Debugging Information Compactor Version %d.%02d.%02d", rmj, rmm, rup); ReportVersion (szMsg, "Copyright\xa9 1987-1992 Microsoft Corporation", rmj, rmm, rup); if ((exefile = open (szExeFile, O_RDWR | O_BINARY)) == -1) { if ((exefile = open (szExeFile, O_RDONLY | O_BINARY)) == -1) { ErrorExit (ERR_EXEOPEN, NULL, NULL); } else { ErrorExit (ERR_READONLY, NULL, NULL); } } #endif // initialize virtual memory manager and compaction tables InitializeTables (); if (VmStart (0, SwapSize, _VM_ALLSWAP) == FALSE) { ErrorExit (ERR_NOMEM, NULL, NULL); } // verify exe file and read subsection directory table ReadDir (); // do the compaction of files in packorder for (i = 0; i < cMod; i++) { if (fVerbose) printf("%d\n", i); CompactOneModule (i); #if defined (WINDOWS) sprintf (szMsg, "%% Complete: %d", (int)((i*100)/cMod)); ReportProgress (szMsg); #endif #if DBG if (FDebug) { extern void UniqueType(void); UniqueType(); } #endif } free (pSSTMOD); free (pTypes); free (pPublics); free (pSymbols); free (pSrcLn); CleanUpTables (); // fixup the publics and symbols with the newly assigned type indices, // and write new global types section to file FixupExeFile (); VmEnd (); close (exefile); #if defined (WINDOWS) ComputeChecksum( szExeFile ); #else ComputeChecksum( argv[argc-1] ); #endif #ifndef WIN32 #if !defined (WINDOWS) if (runMpc) { #if !defined (OS2) && !defined (DOSX32) if (_fDosExt == FALSE) { execlp("mpc", "mpc", argv[argc - 1], NULL); // If we returned from the execlp(), something is wrong. ErrorExit (ERR_NOMPC, NULL, NULL); } else { spawnlp (P_WAIT, "mpc", "mpc", argv[argc - 1], NULL); } #else execlp("mpc", "mpc", argv[argc - 1], NULL); // If we returned from the execlp(), something is wrong. ErrorExit (ERR_NOMPC, NULL, NULL); #endif } exit(0); #else AppExit(0); return 0; #endif #else exit(0); #endif } #if !defined (WINDOWS) /** ProcessArgs - process command line arguments * * ProcessArgs (arc, argv) * * Entry argc = argument count * argv = pointer to argument list * * Exit * * Returns none */ LOCAL void ProcessArgs (int argc, char **argv) { int iRet; // skip program name argc--; ++argv; while (argc && (**argv == '/' || **argv == '-')) { switch (toupper (*++*argv)) { case 'D': FDebug = TRUE; break; case 'N': logo = FALSE; break; case 'P': runMpc = TRUE; // pcode break; case 'H': iRet = spawnlp (P_WAIT, "qh.exe", "qh","-u", "cvpack.exe",NULL); // qh returns 3 if no help was found on the topic. // qh returns -ve exit codes if some system level // error occured. Both cases , print usage message if (iRet == 3 || iRet < 0) { ErrorExit (ERR_USAGE, NULL, NULL); exit (0); } break; case 'M': // preserve minimum information (publics and srcModule) delete = TRUE; break; case 'V': fVerbose = TRUE; break; case '?': default: ErrorExit (ERR_USAGE, NULL, NULL); break; } argv++; argc--; } if (argc != 1) { ErrorExit (ERR_USAGE, NULL, NULL); } } void Banner (void) { printf ("Microsoft Debugging Information Compactor Version %d.%02d.%02d\n" \ "Copyright(c) 1987-1992 Microsoft Corporation\n\n", \ rmj, rmm, rup); NeedsBanner = FALSE; } LOCAL void OpenExe (char *path) { char outpath[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; // try to open the exe file strcpy (outpath, path); // Build output file by splitting path and rebuilding with // new extension. _splitpath( outpath, drive, dir, fname, ext); if (ext[0] == 0) { strcpy (ext, ".exe" ); } _makepath (outpath, drive, dir, fname, ext); if ((exefile = open (outpath, O_RDWR | O_BINARY)) == -1) { if ((exefile = open (outpath, O_RDONLY | O_BINARY)) == -1) { ErrorExit (ERR_EXEOPEN, NULL, NULL); } else { ErrorExit (ERR_READONLY, NULL, NULL); } } } #else /* * ProcessWinArgs(char *pszCmdLine, char *pszExeFile) * * ENTRY: * * pszCmdLine Pointer to command line passed to QCVPACKW * pszExeFile Pointer to buffer that will receive file name * of file to be packed. */ void ProcessWinArgs(char *pszCmdLine, char *pszExeFile) { unsigned short lw, hw; if (sscanf (pszCmdLine, "/CALLBACK:%X:%X %Fs", &hw, &lw, (LPSTR)pszExeFile) != 3) { ErrorExit(ERR_USAGE, NULL, NULL); } InitQUtil( (CALLBACK) ( ( (long)hw<<16 ) + lw) ); } #endif