/* Name of the target specific runtime library */
static char* TargetLib = 0;
+static int NoStdLib = 0;
+static char* CmdAllocArg (const char* Arg, unsigned Len)
+/* Alloc (potentially quoted) argument */
+{
+ char* Alloc;
+
+/* The Microsoft docs say on spawnvp():
+** Spaces embedded in strings may cause unexpected behavior; for example,
+** passing _spawn the string "hi there" will result in the new process getting
+** two arguments, "hi" and "there". If the intent was to have the new process
+** open a file named "hi there", the process would fail. You can avoid this by
+** quoting the string: "\"hi there\"".
+*/
+#if defined(_WIN32)
+ /* Quote argument if it contains space(s) */
+ if (memchr (Arg, ' ', Len)) {
+ Alloc = xmalloc (Len + 3);
+ Alloc[0] = '"';
+ memcpy (Alloc + 1, Arg, Len);
+ Alloc[Len + 1] = '"';
+ Alloc[Len + 2] = '\0';
+ } else
+#endif
+ {
+ Alloc = xmalloc (Len + 1);
+ memcpy (Alloc, Arg, Len);
+ Alloc[Len] = '\0';
+ }
+ return Alloc;
+}
+
+
+
static void CmdExpand (CmdDesc* Cmd)
/* Expand the argument vector */
{
/* Add a copy of the new argument, allow a NULL pointer */
if (Arg) {
- Cmd->Args[Cmd->ArgCount++] = xstrdup (Arg);
+ Cmd->Args[Cmd->ArgCount++] = CmdAllocArg (Arg, strlen (Arg));
} else {
Cmd->Args[Cmd->ArgCount++] = 0;
}
}
/* Add the new argument */
- Cmd->Args[Cmd->ArgCount] = memcpy (xmalloc (Len + 1), Arg, Len);
- Cmd->Args[Cmd->ArgCount][Len] = '\0';
- ++Cmd->ArgCount;
+ Cmd->Args[Cmd->ArgCount++] = CmdAllocArg (Arg, Len);
/* If the argument was terminated by a comma, skip it, otherwise
** we're done.
static void SetTargetFiles (void)
/* Set the target system files */
{
- /* Determine the names of the target specific library file */
- if (Target != TGT_NONE) {
+ /* Get a pointer to the system name and its length */
+ const char* TargetName = GetTargetName (Target);
+ unsigned TargetNameLen = strlen (TargetName);
- /* Get a pointer to the system name and its length */
- const char* TargetName = GetTargetName (Target);
- unsigned TargetNameLen = strlen (TargetName);
-
- /* Set the library file */
- TargetLib = xmalloc (TargetNameLen + 4 + 1);
- memcpy (TargetLib, TargetName, TargetNameLen);
- strcpy (TargetLib + TargetNameLen, ".lib");
-
- }
+ /* Set the library file */
+ TargetLib = xmalloc (TargetNameLen + 4 + 1);
+ memcpy (TargetLib, TargetName, TargetNameLen);
+ strcpy (TargetLib + TargetNameLen, ".lib");
}
CmdSetTarget (&LD65, Target);
}
- /* Determine which target libraries are needed */
- SetTargetFiles ();
-
/* Add all object files as parameters */
for (I = 0; I < LD65.FileCount; ++I) {
CmdAddArg (&LD65, LD65.Files [I]);
}
- /* Add the system runtime library */
- if (TargetLib) {
- CmdAddArg (&LD65, TargetLib);
+ /* Add the standard runtime library if it is not disabled */
+ if (!NoStdLib)
+ {
+ /* Determine which target library is needed */
+ SetTargetFiles ();
+
+ if (TargetLib) {
+ CmdAddArg (&LD65, TargetLib);
+ }
}
/* Terminate the argument list with a NULL pointer */
" --memory-model model\t\tSet the memory model\n"
" --module\t\t\tLink as a module\n"
" --module-id id\t\tSpecify a module ID for the linker\n"
+ " --no-std-lib\t\t\tDon't link standard runtime library\n"
" --o65-model model\t\tOverride the o65 model\n"
" --obj file\t\t\tLink this object file\n"
" --obj-path path\t\tSpecify an object file search path\n"
+static void OptNoStdLib (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Disable standard runtime library */
+{
+ NoStdLib = 1;
+}
+
+
+
static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --o65-model option */
{
const char* Arg attribute ((unused)))
/* Print the target file path */
{
- SearchPaths* TargetPath = NewSearchPath ();
- AddSubSearchPathFromEnv (TargetPath, "CC65_HOME", "target");
+ char* TargetPath;
+
+ SearchPaths* TargetPaths = NewSearchPath ();
+ AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target");
#if defined(CL65_TGT) && !defined(_WIN32)
- AddSearchPath (TargetPath, STRINGIZE (CL65_TGT));
+ AddSearchPath (TargetPaths, STRINGIZE (CL65_TGT));
#endif
- AddSubSearchPathFromWinBin (TargetPath, "target");
+ AddSubSearchPathFromWinBin (TargetPaths, "target");
- printf ("%s\n", GetSearchPath (TargetPath, 0));
+ TargetPath = GetSearchPath (TargetPaths, 0);
+ while (*TargetPath) {
+ if (*TargetPath == ' ') {
+ /* Escape spaces */
+ putchar ('\\');
+ }
+ putchar (*TargetPath++);
+ }
+ putchar ('\n');
exit (EXIT_SUCCESS);
}
{ "--memory-model", 1, OptMemoryModel },
{ "--module", 0, OptModule },
{ "--module-id", 1, OptModuleId },
+ { "--no-std-lib", 0, OptNoStdLib },
{ "--o65-model", 1, OptO65Model },
{ "--obj", 1, OptObj },
{ "--obj-path", 1, OptObjPath },
/* Print version number */
OptVersion (Arg, 0);
break;
-
+
case 'E':
/* Forward -E to compiler */
CmdAddArg (&CC65, Arg);
DisableAssemblingAndLinking ();
break;
-
+
case 'W':
- /* avoid && with'\0' in if clauses */
- if (Arg[3] == '\0') {
- switch (Arg[2]) {
- case 'a':
- /* -Wa: Pass options to assembler */
- OptAsmArgs (Arg, GetArg (&I, 3));
- break;
- case 'c':
- /* -Wc: Pass options to compiler
- ** Remember -Wc sub arguments in cc65 arg struct
- */
- OptCCArgs (Arg, GetArg (&I, 3));
- break;
- case 'l':
- /* -Wl: Pass options to linker */
- OptLdArgs (Arg, GetArg (&I, 3));
- break;
- default:
- UnknownOption (Arg);
- break;
- }
+ if (Arg[2] == 'a' && Arg[3] == '\0') {
+ /* -Wa: Pass options to assembler */
+ OptAsmArgs (Arg, GetArg (&I, 3));
+ } else if (Arg[2] == 'c' && Arg[3] == '\0') {
+ /* -Wc: Pass options to compiler */
+ /* Remember -Wc sub arguments in cc65 arg struct */
+ OptCCArgs (Arg, GetArg (&I, 3));
+ } else if (Arg[2] == 'l' && Arg[3] == '\0') {
+ /* -Wl: Pass options to linker */
+ OptLdArgs (Arg, GetArg (&I, 3));
} else {
/* Anything else: Suppress warnings (compiler) */
CmdAddArg2 (&CC65, "-W", GetArg (&I, 2));