#include "filetype.h"
#include "fname.h"
#include "mmodel.h"
+#include "searchpath.h"
#include "strbuf.h"
#include "target.h"
#include "version.h"
/* 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"
+ " --print-target-path\t\tPrint the target file path\n"
" --register-space b\t\tSet space available for register variables\n"
" --register-vars\t\tEnable register variables\n"
" --rodata-name seg\t\tSet the name of the RODATA segment\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 */
{
+static void OptPrintTargetPath (const char* Opt attribute ((unused)),
+ const char* Arg attribute ((unused)))
+/* Print the target file path */
+{
+ char* TargetPath;
+
+ SearchPaths* TargetPaths = NewSearchPath ();
+ AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target");
+#if defined(CL65_TGT) && !defined(_WIN32)
+ AddSearchPath (TargetPaths, STRINGIZE (CL65_TGT));
+#endif
+ AddSubSearchPathFromWinBin (TargetPaths, "target");
+
+ TargetPath = GetSearchPath (TargetPaths, 0);
+ while (*TargetPath) {
+ if (*TargetPath == ' ') {
+ /* Escape spaces */
+ putchar ('\\');
+ }
+ putchar (*TargetPath++);
+ }
+ putchar ('\n');
+ exit (EXIT_SUCCESS);
+}
+
+
+
static void OptRegisterSpace (const char* Opt attribute ((unused)), const char* Arg)
/* Handle the --register-space option */
{
const char* Arg attribute ((unused)))
/* Print version number */
{
- fprintf (stderr, "cl65 V%s\n", GetVersionAsString ());
+ fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ());
+ exit(EXIT_SUCCESS);
}
{
/* Program long options */
static const LongOpt OptTab[] = {
- { "--add-source", 0, OptAddSource },
- { "--asm-args", 1, OptAsmArgs },
- { "--asm-define", 1, OptAsmDefine },
- { "--asm-include-dir", 1, OptAsmIncludeDir },
- { "--bin-include-dir", 1, OptBinIncludeDir },
- { "--bss-label", 1, OptBssLabel },
- { "--bss-name", 1, OptBssName },
- { "--cc-args", 1, OptCCArgs },
- { "--cfg-path", 1, OptCfgPath },
- { "--check-stack", 0, OptCheckStack },
- { "--code-label", 1, OptCodeLabel },
- { "--code-name", 1, OptCodeName },
- { "--codesize", 1, OptCodeSize },
- { "--config", 1, OptConfig },
- { "--cpu", 1, OptCPU },
- { "--create-dep", 1, OptCreateDep },
- { "--create-full-dep", 1, OptCreateFullDep },
- { "--data-label", 1, OptDataLabel },
- { "--data-name", 1, OptDataName },
- { "--debug", 0, OptDebug },
- { "--debug-info", 0, OptDebugInfo },
- { "--feature", 1, OptFeature },
- { "--force-import", 1, OptForceImport },
- { "--help", 0, OptHelp },
- { "--include-dir", 1, OptIncludeDir },
- { "--ld-args", 1, OptLdArgs },
- { "--lib", 1, OptLib },
- { "--lib-path", 1, OptLibPath },
- { "--list-targets", 0, OptListTargets },
- { "--listing", 1, OptListing },
- { "--list-bytes", 1, OptListBytes },
- { "--mapfile", 1, OptMapFile },
- { "--memory-model", 1, OptMemoryModel },
- { "--module", 0, OptModule },
- { "--module-id", 1, OptModuleId },
- { "--o65-model", 1, OptO65Model },
- { "--obj", 1, OptObj },
- { "--obj-path", 1, OptObjPath },
- { "--register-space", 1, OptRegisterSpace },
- { "--register-vars", 0, OptRegisterVars },
- { "--rodata-name", 1, OptRodataName },
- { "--signed-chars", 0, OptSignedChars },
- { "--standard", 1, OptStandard },
- { "--start-addr", 1, OptStartAddr },
- { "--static-locals", 0, OptStaticLocals },
- { "--target", 1, OptTarget },
- { "--verbose", 0, OptVerbose },
- { "--version", 0, OptVersion },
- { "--zeropage-label", 1, OptZeropageLabel },
- { "--zeropage-name", 1, OptZeropageName },
+ { "--add-source", 0, OptAddSource },
+ { "--all-cdecl", 0, OptAllCDecl },
+ { "--asm-args", 1, OptAsmArgs },
+ { "--asm-define", 1, OptAsmDefine },
+ { "--asm-include-dir", 1, OptAsmIncludeDir },
+ { "--bin-include-dir", 1, OptBinIncludeDir },
+ { "--bss-label", 1, OptBssLabel },
+ { "--bss-name", 1, OptBssName },
+ { "--cc-args", 1, OptCCArgs },
+ { "--cfg-path", 1, OptCfgPath },
+ { "--check-stack", 0, OptCheckStack },
+ { "--code-label", 1, OptCodeLabel },
+ { "--code-name", 1, OptCodeName },
+ { "--codesize", 1, OptCodeSize },
+ { "--config", 1, OptConfig },
+ { "--cpu", 1, OptCPU },
+ { "--create-dep", 1, OptCreateDep },
+ { "--create-full-dep", 1, OptCreateFullDep },
+ { "--data-label", 1, OptDataLabel },
+ { "--data-name", 1, OptDataName },
+ { "--debug", 0, OptDebug },
+ { "--debug-info", 0, OptDebugInfo },
+ { "--feature", 1, OptFeature },
+ { "--force-import", 1, OptForceImport },
+ { "--help", 0, OptHelp },
+ { "--include-dir", 1, OptIncludeDir },
+ { "--ld-args", 1, OptLdArgs },
+ { "--lib", 1, OptLib },
+ { "--lib-path", 1, OptLibPath },
+ { "--list-targets", 0, OptListTargets },
+ { "--listing", 1, OptListing },
+ { "--list-bytes", 1, OptListBytes },
+ { "--mapfile", 1, OptMapFile },
+ { "--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-target-path", 0, OptPrintTargetPath},
+ { "--register-space", 1, OptRegisterSpace },
+ { "--register-vars", 0, OptRegisterVars },
+ { "--rodata-name", 1, OptRodataName },
+ { "--signed-chars", 0, OptSignedChars },
+ { "--standard", 1, OptStandard },
+ { "--start-addr", 1, OptStartAddr },
+ { "--static-locals", 0, OptStaticLocals },
+ { "--target", 1, OptTarget },
+ { "--verbose", 0, OptVerbose },
+ { "--version", 0, OptVersion },
+ { "--zeropage-label", 1, OptZeropageLabel },
+ { "--zeropage-name", 1, OptZeropageName },
};
char* CmdPath;
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':