/*********************************************************************** * Microsoft (R) 32-Bit Incremental Linker * * Copyright (C) Microsoft Corp 1992-95. All rights reserved. * * File: coff.cpp * * File Comments: * * The NT COFF Linker/Librarian/Dumper/Editor/Binder * ***********************************************************************/ #include "link.h" #ifdef TIMEBOMB #include #endif // TIMEBOMB typedef MainFunc (*MAINFUNCTION)(int, char *[]); struct calltype { char *Name; int Switch; TOOL_TYPE Tool; MAINFUNCTION CallFunc; } ToolType[] = { { "Linker", 4, Linker, (MAINFUNCTION) LinkerMain }, { "Library Manager", 3, Librarian, (MAINFUNCTION) LibrarianMain }, { "Dumper", 4, Dumper, (MAINFUNCTION) DumperMain }, { "Editor", 4, Editor, (MAINFUNCTION) EditorMain }, #if DBG { "InspectIncrDb", 4, DbInspector, (MAINFUNCTION) DbInspMain }, #endif // DBG { "Helper", 4, NotUsed, (MAINFUNCTION) HelperMain }, { NULL, 0, NotUsed, NULL } }; #define STDIO_BUF_SIZE 2048 // buffer size used by linker BOOL WINAPI ControlCHandler(DWORD /* CtrlType */) { if (Tool == Linker) { fCtrlCSignal = TRUE; return(TRUE); } BadExitCleanup(); return(FALSE); } #if DBG void __cdecl HandleAbort(int /* signal */) { BadExitCleanup(); } #endif // DBG MainFunc __cdecl main(int Argc, char *Argv[]) /*++ Routine Description: Calls either the Linker, Librarian, Dumper, or Editor. Arguments: Argc - Standard C argument count. Argv - Standard C argument strings. Return Value: 0 Successful. 1 Failed. --*/ { InfoStream = stdout; // Initial value. #ifdef TIMEBOMB FcCheckVerDate(0, &ctmOpenBy, &ctmCloseBy, CliTBCallBack); #endif // TIMEBOMB #if DBG #ifdef _M_MRX000 if (getenv("link_noalign") != NULL) { SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT); } #endif #endif __try { char *szDbFlags; int iarg; char szProgramName[_MAX_FNAME]; WORD i; sprintf(szVersion, "Version " VERSION_STR); SetConsoleCtrlHandler(ControlCHandler, TRUE); #if DBG signal(SIGABRT, HandleAbort); // Setup handler for assert() calls. #endif // Pre-scan commandline for a "-db" option; if found, handle and delete. szDbFlags = NULL; for (iarg = 1; iarg < Argc; iarg++) { // Be careful not to recognize -dbgimplib if ((Argv[iarg][0] == '-') && (Argv[iarg][1] == 'd') && (Argv[iarg][2] == 'b') && ((Argv[iarg][3] == '\0') || isdigit(Argv[iarg][3]))) { szDbFlags = &Argv[iarg][3]; memmove(&Argv[iarg], &Argv[iarg + 1], sizeof(Argv[0]) * (Argc - iarg - 1)); Argc--; iarg--; } } dbsetflags(szDbFlags, "LINK_DB"); // Initialize the buffered I/O package FileInit(cfiInSystemNT, cfiCacheableInSystemNT, cfiInSystemTNT, cfiCacheableInSystemTNT); _splitpath(Argv[0], NULL, NULL, szProgramName, NULL); ToolName = _strupr(szProgramName); if (Argc < 2) { goto DefaultToLinker; } if ((Argv[1][0] != '/') && (Argv[1][0] != '-')) { goto DefaultToLinker; } for (i = 0; ToolType[i].Name; i++) { if (!_strnicmp(Argv[1]+1, ToolType[i].Name, ToolType[i].Switch)) { // Remove Argv[1] from the arg vector for (iarg = 1; iarg < Argc; iarg++) { Argv[iarg] = Argv[iarg+1]; } Argc--; FoundTool: switch (ToolType[i].Tool) { case Dumper: break; case Editor: // Editor gets buffers of 0 because the code currently // doesn't do flush(stdout) before gets() ... setvbuf(stdout, NULL, _IOFBF, 0); setvbuf(stderr, NULL, _IOFBF, 0); break; default: setvbuf(stdout, NULL, _IOFBF, STDIO_BUF_SIZE); setvbuf(stderr, NULL, _IOFBF, STDIO_BUF_SIZE); break; } ToolGenericName = ToolType[i].Name; // for printing banner later Tool = ToolType[i].Tool; return(ToolType[i].CallFunc(Argc, Argv)); } } DefaultToLinker: // Default tool is LINK i = 0; goto FoundTool; } __except (fExceptionsOff ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER) { const char *szFilename; // UNDONE: Use Fatal or DisplayMessage? if (fNeedBanner) { PrintBanner(); } if (InternalError.CombinedFilenames[0]) { szFilename = InternalError.CombinedFilenames; } else { szFilename = ToolName; } printf("\n" "%s : error : Internal error during %s\n", szFilename, InternalError.Phase); fflush(NULL); } return(-2); } MainFunc HelperMain(int /* Argc */, char * /* Argv */ []) /*++ Routine Description: Prints usage. Arguments: Argc - Standard C argument count. Argv - Standard C argument strings. Return Value: USAGE. --*/ { WORD i; for (i = 0; ToolType[i].Name; i++) { printf("%s /%.*s for help on %s\n", ToolName, ToolType[i].Switch, ToolType[i].Name, ToolType[i].Name ); } return(USAGE); }