/* Name of the target specific runtime library */
static char* TargetLib = 0;
+static int NoStdLib = 0;
+/*****************************************************************************/
+/* Credential functions */
+/*****************************************************************************/
+
+
+
+static void DisableAssembling (void)
+{
+ DoAssemble = 0;
+}
+
+
+
+static void DisableLinking (void)
+{
+ DoLink = 0;
+}
+
+
+
+static void DisableAssemblingAndLinking (void)
+{
+ DisableAssembling ();
+ DisableLinking ();
+}
+
+
+
/*****************************************************************************/
/* Command structure handling */
/*****************************************************************************/
+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 */
" -C name\t\t\tUse linker config file\n"
" -Cl\t\t\t\tMake local variables static\n"
" -D sym[=defn]\t\t\tDefine a preprocessor symbol\n"
+ " -E\t\t\t\tStop after the preprocessing stage\n"
" -I dir\t\t\tSet a compiler include directory path\n"
" -L path\t\t\tSpecify a library search path\n"
" -Ln name\t\t\tCreate a VICE label file\n"
"\n"
"Long options:\n"
" --add-source\t\t\tInclude source as comment\n"
+ " --all-cdecl\t\t\tMake functions default to __cdecl__\n"
" --asm-args options\t\tPass options to the assembler\n"
" --asm-define sym[=v]\t\tDefine an assembler symbol\n"
" --asm-include-dir dir\t\tSet an assembler include directory\n"
" --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 OptAllCDecl (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Make functions default to __cdecl__ */
+{
+ CmdAddArg (&CC65, "--all-cdecl");
+}
+
+
static void OptAsmArgs (const char* Opt attribute ((unused)), const char* Arg)
/* Pass arguments to the assembler */
+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);
}
/* Program long options */
static const LongOpt OptTab[] = {
{ "--add-source", 0, OptAddSource },
+ { "--all-cdecl", 0, OptAllCDecl },
{ "--asm-args", 1, OptAsmArgs },
{ "--asm-define", 1, OptAsmDefine },
{ "--asm-include-dir", 1, OptAsmIncludeDir },
{ "--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 },
case 'S':
/* Dont assemble and link the created files */
- DoAssemble = 0;
- DoLink = 0;
+ DisableAssemblingAndLinking ();
break;
case 'T':
OptVersion (Arg, 0);
break;
+ case 'E':
+ /* Forward -E to compiler */
+ CmdAddArg (&CC65, Arg);
+ DisableAssemblingAndLinking ();
+ break;
+
case 'W':
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 */
case 'c':
/* Don't link the resulting files */
- DoLink = 0;
+ DisableLinking ();
break;
case 'd':