mirror of https://git.wuffs.org/MWCC
644 lines
18 KiB
C
644 lines
18 KiB
C
#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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
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(2, 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(24, (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(104, "CmdLine Panel");
|
|
warned = 1;
|
|
}
|
|
|
|
if (version == 0x1000) {
|
|
target->stderr2stdout = 0;
|
|
version++;
|
|
}
|
|
|
|
if (version == 0x1001) {
|
|
target->noCmdLineWarnings = 0;
|
|
version++;
|
|
}
|
|
|
|
if (version < 0x1000 || version > 0x1002) {
|
|
CLReportError(104, "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(104, "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(104, "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(104, "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(104, "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(104, "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(91, "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(91, "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(91, "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(91, "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;
|
|
}
|