#include "cmdline.h" jmp_buf exit_program; int numPlugins; CLPluginInfo *pluginInfo; int numPanels; const char **panelNames; CWCommandLineArgs *panel_args; CWCommandLineArgs *plugin_args; Project mainProj; Target *gTarg; PCmdLine optsCmdLine; PCmdLineEnvir optsEnvir; PCmdLineCompiler optsCompiler; PCmdLineLinker optsLinker; CLState clState; char cmdline_build_date[32]; char cmdline_build_time[32]; Project *gProj = &mainProj; static CWPLUGIN_ENTRY(CLT_dummymain)(CWPluginContext) { return 0; } static CWPLUGIN_ENTRY(CLT_GetDropInFlags)(const DropInFlags **flags, SInt32 *flagsSize) { static const DropInFlags sFlags = { kCurrentDropInFlagsVersion, CWDROPINDRIVERTYPE, 7, 0, 0, 12 }; *flags = &sFlags; *flagsSize = sizeof(sFlags); return 0; } static CWPLUGIN_ENTRY(CLT_GetDropInName)(const char **dropinName) { static const char *sDropInName = "Command-Line Driver"; *dropinName = sDropInName; return 0; } static CWPLUGIN_ENTRY(CLT_GetDisplayName)(const char **displayName) { static const char *sDisplayName = "Command-Line Driver"; *displayName = sDisplayName; return 0; } static CWPLUGIN_ENTRY(CLT_GetPanelList)(const CWPanelList **panelList) { static const char *sPanelNames[4]; static CWPanelList sPanelList = { kCurrentCWPanelListVersion, 4, sPanelNames }; if (clState.plugintype == CWDROPINCOMPILERTYPE) { sPanelNames[0] = "CmdLine Panel"; sPanelNames[1] = "CmdLine Compiler Panel"; sPanelNames[2] = "CmdLine Linker Panel"; sPanelList.count = 3; } else { sPanelNames[0] = "CmdLine Panel"; sPanelNames[1] = "CmdLine Linker Panel"; sPanelList.count = 2; } *panelList = &sPanelList; return 0; } static CWPLUGIN_ENTRY(CLT_GetTargetList)(const CWTargetList **targetList) { static FourCharCode sCPU = targetCPUAny; static FourCharCode sOS = targetOSAny; static CWTargetList sTargetList = { kCurrentCWTargetListVersion, 1, &sCPU, 1, &sOS }; *targetList = &sTargetList; return 0; } static CWPLUGIN_ENTRY(CLT_GetVersionInfo)(const VersionInfo **versioninfo) { static const VersionInfo vi = { 3, 0, 0, 0 }; *versioninfo = &vi; return 0; } static CWPLUGIN_ENTRY(CLT_GetFileTypeMappings)(const OSFileTypeMappingList **mappinglist) { static const OSFileTypeMapping ftmes[2] = { {CWFOURCHAR('B','r','w','s'), "DubL", 4, 0, 0}, {CWFOURCHAR('M','M','P','r'), "looc", 4, 0, 0} }; static const OSFileTypeMappingList ftml = { 2, ftmes }; *mappinglist = &ftml; return 0; } static BasePluginCallbacks clcb = { CLT_dummymain, CLT_GetDropInFlags, CLT_GetDisplayName, CLT_GetDropInName, CLT_GetPanelList, 0, 0, CLT_GetVersionInfo, CLT_GetFileTypeMappings }; static int RegisterStaticCmdLinePlugin(void) { return RegisterStaticPlugin(&clcb); } #include "command_line/CmdLine/Project/Resources/CLErrors.r" static int RegisterCmdLineResources(void) { return RegisterResource("Command-line strings", 12000, STR12000); } static Boolean special_debug(Boolean pre, char *) { if (pre) { SetupDebuggingTraps(); return 1; } else { return 0; } } static Boolean special_plugin_debug(Boolean pre, char *) { if (pre) { clState.pluginDebug = 1; return 1; } else { return clState.pluginDebug; } } static Boolean special_stdout_base(Boolean pre, char *) { if (pre) { return 1; } else { return clState.stdout_base != 0; } } // TODO: special function goes here for license file struct SpecialOption { const char *optname; char **argp; Boolean (*func)(Boolean a, char *b); }; static struct SpecialOption special_options[3] = { {"", 0, special_debug}, {"--plugin-debug", 0, special_plugin_debug}, {"--stdout", &clState.stdout_base, special_stdout_base} }; void Main_PreParse(int *argc, char ***argv) { int idx; struct SpecialOption *so; if (*argc > 1) { do { idx = 0; so = special_options; do { if (!strcmp(so->optname, (*argv)[1])) { if (so->argp) { *so->argp = (*argv)[2]; so->func(1, *so->argp); (*argv)[1] = (*argv)[0]; (*argc)--; (*argv)++; (*argv)[1] = (*argv)[0]; (*argc)--; (*argv)++; } else { so->func(1, 0); (*argv)[1] = (*argv)[0]; (*argc)--; (*argv)++; } break; } idx++; so++; } while (idx < 3); } while (*argc > 1 && idx < 3); } } void Main_PassSpecialArgs(int *argc, char ***argv) { int idx; struct SpecialOption *so; idx = 0; so = special_options; do { if (so->func(0, 0)) { AppendArgumentList(argc, argv, so->optname); if (so->argp) AppendArgumentList(argc, argv, (*so->argp) ? *so->argp : ""); } idx++; so++; } while (idx < 3); } static int MainInitialized; int Main_Initialize(int argc, char **argv) { static char secret[8]; char exename[256]; OS_InitProgram(&argc, &argv); memset(&clState, 0, sizeof(CLState)); special_options[0].optname = secret; secret[7] = 0; secret[4] = 'b'; secret[1] = '-'; secret[5] = 'u'; secret[2] = 'd'; secret[0] = '-'; secret[3] = 'e'; secret[6] = 'g'; Main_PreParse(&argc, &argv); clState.argc = argc; clState.argv = argv; // TODO: this changes on windows strcpyn(exename, argv[0], strlen(argv[0]), 256); exename[255] = 0; IO_Initialize(); if (!RegisterCmdLineResources()) CLFatalError("Could not initialize resource strings"); if (!OS_IsFullPath(argv[0])) { clState.programName = argv[0]; } else { clState.programName = OS_GetFileNamePtr(argv[0]); } if (OS_FindProgram(exename, &clState.programSpec)) CLReportError(CLStr2, exename); Plugins_Init(); if (!RegisterStaticCmdLinePlugin()) CLFatalError("Could not initialize built-in plugins"); Proj_Initialize(gProj); SystemInitResources(&clState.programSpec); License_Initialize(); MainInitialized = 1; return 0; } int Main_Terminate(int exitcode) { if (MainInitialized) { Plugins_Term(); License_Terminate(); Proj_Terminate(gProj); IO_Terminate(); MainInitialized = 0; } return exitcode; } static int Main_ParseCommandLine(void) { Plugin *parser; CWCommandLineArgs myargs; int x, y; FourCharCode vislang; if ( !Plugins_GetPluginList(0, &numPlugins, &pluginInfo) || !Plugins_GetPrefPanelUnion(0, &numPanels, &panelNames) || !(panel_args = xcalloc(0, numPanels * sizeof(CWCommandLineArgs))) || !(plugin_args = xcalloc(0, numPlugins * sizeof(CWCommandLineArgs))) ) { CLFatalError("Out of memory during init\n"); } parser = Plugins_GetParserForPlugin(0, clState.parserstyle, numPlugins, pluginInfo, gTarg->cpu, gTarg->os, numPanels, panelNames); if (!parser) CLFatalError("Could not find a command-line parser!"); myargs.argc = clState.argc; myargs.argv = clState.argv; myargs.envp = 0; if (!SendParserRequest(parser, gTarg, &myargs, gTarg->cpu, gTarg->os, numPlugins, pluginInfo, numPanels, panelNames, plugin_args, panel_args, cmdline_build_date, cmdline_build_time, Plugin_GetToolVersionInfo())) { return CheckForUserBreak() ? Result_Cancelled : Result_Failed; } if (clState.pluginDebug) { for (y = 0; y < numPanels; y++) { CLPrintErr("Outgoing args for '%s': ", panelNames[y]); for (x = 0; x < panel_args[y].argc; x++) { CLPrintErr("%s ", panel_args[y].argv[x]); } CLPrintErr("\n"); } for (x = 0; x < numPlugins; x++) { vislang = pluginInfo[x].language ? pluginInfo[x].language : CWFOURCHAR('-','-','-','-'); CLPrintErr( "Outgoing args for '%c%c%c%c/%c%c%c%c': ", (pluginInfo[x].plugintype & 0xFF000000) >> 24, (pluginInfo[x].plugintype & 0x00FF0000) >> 16, (pluginInfo[x].plugintype & 0x0000FF00) >> 8, (pluginInfo[x].plugintype & 0x000000FF), (vislang & 0xFF000000) >> 24, (vislang & 0x00FF0000) >> 16, (vislang & 0x0000FF00) >> 8, (vislang & 0x000000FF) ); for (y = 1; y < plugin_args[x].argc; y++) { CLPrintErr("%s ", plugin_args[x].argv[y]); } CLPrintErr("\n"); } } return Result_Success; } static int Main_SetupParamBlock(void) { PrefPanelsChangedCallback(0); if (optsCompiler.outMakefile[0]) { int err = OS_MakeFileSpec(optsCompiler.outMakefile, &clState.makefileSpec); if (err) { CLReportOSError(8, err, optsCompiler.outMakefile); return 1; } OS_Delete(&clState.makefileSpec); } if (optsCompiler.sbmPath[0]) { int err = OS_MakePathSpec(0, optsCompiler.sbmPath, &clState.sbmPathSpec); if (err) { CLReportOSError(23, err, optsCompiler.sbmPath); return 1; } } else { OS_GetCWD(&clState.sbmPathSpec); } return 0; } static int Main_ResolveProject(void) { SInt32 startTime; SInt32 endTime; int err; if (optsCmdLine.state == OptsCmdLineState_0 || optsCmdLine.state == OptsCmdLineState_1) return 0; startTime = LMGetTicks(); err = CompileFilesInProject(); if (err) return err; if (optsCmdLine.state == OptsCmdLineState_3) { err = LinkProject(); if (err) return err; } if (!DeleteTemporaries()) return 1; endTime = LMGetTicks(); if (optsCmdLine.timeWorking) { CLReport(CLStr24, (endTime - startTime) / 60.0, "resolve", "", "project", ""); } return 0; } static int UpdatePCmdLineFromVersion(PCmdLine *given, PCmdLine *target) { static Boolean warned; SInt16 version = given->version; *target = *given; if (clState.pluginDebug && version < 0x1002 && !warned) { CLReportWarning(CLStr104, "CmdLine Panel"); warned = 1; } if (version == 0x1000) { target->stderr2stdout = 0; version++; } if (version == 0x1001) { target->noCmdLineWarnings = 0; version++; } if (version < 0x1000 || version > 0x1002) { CLReportError(CLStr104, "CmdLine Panel"); return 0; } else { target->version = 0x1002; return 1; } } static int UpdatePCmdLineEnvirFromVersion(PCmdLineEnvir *given, PCmdLineEnvir *target) { SInt16 version = given->version; *target = *given; if ((clState.pluginDebug && version < 0x1000) || version > 0x1000) { CLReportError(CLStr104, "CmdLine Environment"); return 0; } else { target->version = 0x1000; return 1; } } static int UpdatePCmdLineCompilerFromVersion(PCmdLineCompiler *given, PCmdLineCompiler *target) { static Boolean warned; SInt16 version = given->version; *target = *given; if (clState.pluginDebug && version < 0x1005 && !warned) { CLReportWarning(CLStr104, "CmdLine Compiler Panel"); warned = 1; } if (version == 0x1001) { target->ignoreMissingFiles = 0; target->printHeaderNames = 0; version++; } if (version == 0x1002) { target->sbmState = 0; target->sbmPath[0] = 0; version++; } if (version == 0x1003) { target->canonicalIncludes = 0; version++; } if (version == 0x1004) { target->keepObjects = 0; version++; } if (version <= 0x1000 || version > 0x1005) { CLReportError(CLStr104, "CmdLine Compiler Panel"); return 0; } else { target->version = 0x1005; return 1; } } static int UpdatePCmdLineLinkerFromVersion(PCmdLineLinker *given, PCmdLineLinker *target) { static Boolean warned; SInt16 version = given->version; *target = *given; if (clState.pluginDebug && version < 0x1002 && !warned) { CLReportWarning(CLStr104, "CmdLine Linker Panel"); warned = 1; } if (version == 0x1000) { target->callPreLinker = 1; target->callPostLinker = 1; target->keepLinkerOutput = 1; version++; } if (version == 0x1001) { target->callLinker = 1; version++; } if (version < 0x1000 || version > 0x1002) { CLReportError(CLStr104, "CmdLine Linker Panel"); return 0; } else { target->version = 0x1002; return 1; } } static int UpdatePrefPanels(const char *name) { PrefPanel *panel; Handle h; if (!name || !ustrcmp(name, "CmdLine Panel")) { if ((panel = Prefs_FindPanel("CmdLine Panel")) && (h = PrefPanel_GetHandle(panel))) { if (name) { if (!UpdatePCmdLineFromVersion((PCmdLine *) *h, &optsCmdLine)) return 0; } } else { CLReportError(CLStr91, "CmdLine Panel"); return 0; } } if (!name || !ustrcmp(name, "CmdLine Environment")) { if ((panel = Prefs_FindPanel("CmdLine Environment")) && (h = PrefPanel_GetHandle(panel))) { if (name) { if (!UpdatePCmdLineEnvirFromVersion((PCmdLineEnvir *) *h, &optsEnvir)) return 0; } } else { CLReportError(CLStr91, "CmdLine Environment"); return 0; } } if (!name || !ustrcmp(name, "CmdLine Compiler Panel")) { if ((panel = Prefs_FindPanel("CmdLine Compiler Panel")) && (h = PrefPanel_GetHandle(panel))) { if (name) { if (!UpdatePCmdLineCompilerFromVersion((PCmdLineCompiler *) *h, &optsCompiler)) return 0; } } else { CLReportError(CLStr91, "CmdLine Compiler Panel"); return 0; } } if (!name || !ustrcmp(name, "CmdLine Linker Panel")) { if ((panel = Prefs_FindPanel("CmdLine Linker Panel")) && (h = PrefPanel_GetHandle(panel))) { if (name) { if (!UpdatePCmdLineLinkerFromVersion((PCmdLineLinker *) *h, &optsLinker)) return 0; } } else { CLReportError(CLStr91, "CmdLine Linker Panel"); return 0; } } return 1; } static int SetupCmdLinePrefPanels(void) { int ret; PrefPanelsChangedCallback = UpdatePrefPanels; ret = Prefs_AddPanel( PrefPanel_New("CmdLine Environment", &optsEnvir, sizeof(PCmdLineEnvir)) ); ret |= ( Prefs_AddPanel(PrefPanel_New("CmdLine Panel", 0, sizeof(PCmdLine))) && Prefs_AddPanel(PrefPanel_New("CmdLine Compiler Panel", 0, sizeof(PCmdLineCompiler))) && Prefs_AddPanel(PrefPanel_New("CmdLine Linker Panel", 0, sizeof(PCmdLineLinker))) ); return ret; } static int Main_SetupContext(void) { gTarg = Target_New("default", clState.cpu, clState.os, clState.language); Target_Add(&gProj->targets, gTarg); Plugins_AddFileTypeMappingsForTarget(0, 0, gTarg->cpu, gTarg->os); gTarg->linker = Plugins_GetLinker(0, gTarg->cpu, gTarg->os); if (gTarg->linker) { gTarg->linkerDropinFlags = Plugin_GetDropInFlags(gTarg->linker)->dropinflags; } else { if (Plugins_GetLinker(0, CWFOURCHAR('*','*','*','*'), CWFOURCHAR('*','*','*','*'))) CLFatalError("A linker is compiled in, but does not match the static target!\n"); gTarg->linkerDropinFlags = 0; } gTarg->preLinker = Plugins_GetPreLinker(0, gTarg->cpu, gTarg->os); if (gTarg->preLinker) { gTarg->preLinkerDropinFlags = Plugin_GetDropInFlags(gTarg->preLinker)->dropinflags; } else { if (Plugins_GetPreLinker(0, CWFOURCHAR('*','*','*','*'), CWFOURCHAR('*','*','*','*'))) CLFatalError("A pre-linker is compiled in, but does not match the static target!\n"); gTarg->preLinkerDropinFlags = 0; } gTarg->postLinker = Plugins_GetPostLinker(0, gTarg->cpu, gTarg->os); if (gTarg->postLinker) { gTarg->postLinkerDropinFlags = Plugin_GetDropInFlags(gTarg->postLinker)->dropinflags; } else { if (Plugins_GetPostLinker(0, CWFOURCHAR('*','*','*','*'), CWFOURCHAR('*','*','*','*'))) CLFatalError("A post-linker is compiled in, but does not match the static target!\n"); gTarg->postLinkerDropinFlags = 0; } if (clState.plugintype == CWDROPINLINKERTYPE) { if (!gTarg->preLinker && !gTarg->linker && !gTarg->postLinker) CLFatalError("The linker plugin was not found!"); } gTarg->linkmodel = LinkModel0; Framework_GetEnvInfo(); return 1; } int Main_Driver(void) { volatile int result; result = setjmp(exit_program); if (!result) { if (!SetupCmdLinePrefPanels()) CLFatalError("Could not initialize preferences"); Main_SetupContext(); if (!(result = Main_ParseCommandLine())) { if (!(result = Main_SetupParamBlock())) result = Main_ResolveProject(); } } else { result = 1; } return result; }