FILE *srcFile; /* source file */
FILE *cdbFile = NULL; /* debugger information output file */
-char *fullSrcFileName; /* full name for the source file */
-char *srcFileName; /* source file name with the .c stripped */
-char *moduleName; /* module name is srcFilename stripped of any path */
+char *fullSrcFileName; /* full name for the source file; */
+ /* can be NULL while linking without compiling */
+char *fullDstFileName; /* full name for the output file; */
+ /* only given by -o, otherwise NULL */
+char *dstFileName; /* destination file name without extension */
+char *dstPath = ""; /* path for the output files; */
+ /* "" is equivalent with cwd */
+char *moduleName; /* module name is source file without path and extension */
+ /* can be NULL while linking without compiling */
const char *preArgv[128]; /* pre-processor arguments */
int currRegBank = 0;
+int RegBankUsed[4]={1, 0, 0, 0}; /*JCF: Reg Bank 0 used by default*/
struct optimize optimize;
struct options options;
char *VersionString = SDCC_VERSION_STR;
int nrelFiles = 0;
bool verboseExec = FALSE;
char *preOutName;
+bool noXinitOpt = FALSE;
/* uncomment JAMIN_DS390 to always override and use ds390 port
for mcs51 work. This is temporary, for compatibility testing. */
#define OPTION_NO_GCSE "--nogcse"
#define OPTION_SHORT_IS_8BITS "--short-is-8bits"
#define OPTION_TINI_LIBID "--tini-libid"
+#define OPTION_NO_XINIT_OPT "--no-xinit-opt"
static const OPTION
optionsTable[] = {
{ 0, "--nojtbound", &optimize.noJTabBoundary, "Don't generate boundary check for jump tables" },
{ 0, "--noloopreverse", &optimize.noLoopReverse, "Disable the loop reverse optimisation" },
{ 'c', "--compile-only", &options.cc_only, "Compile and assemble, but do not link" },
+ { 'o', NULL, NULL, "Place the output into the given path resp. file" },
{ 0, "--dumpraw", &options.dump_raw, "Dump the internal structure after the initial parse" },
{ 0, "--dumpgcse", &options.dump_gcse, NULL },
{ 0, "--dumploop", &options.dump_loop, NULL },
{ 0, "--tini-libid", NULL,"<nnnn> LibraryID used in -mTININative"},
{ 0, "--protect-sp-update", &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
{ 0, "--parms-in-bank1", &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
+ { 0, OPTION_NO_XINIT_OPT, &noXinitOpt, "don't memcpy initialized xram from code"},
/* End of options */
{ 0, NULL }
};
exit (1);
}
+/* Override the default processor with the one specified
+ * on the command line */
+static void
+_setProcessor (char *_processor)
+{
+ port->processor = _processor;
+ fprintf(stderr,"Processor: %s\n",_processor);
+}
+
static void
_validatePorts (void)
{
port = _ports[0];
}
+/* search through the command line options for the processor */
+static void
+_findProcessor (int argc, char **argv)
+{
+ while (argc--)
+ {
+ if (!strncmp (*argv, "-p", 2))
+ {
+ _setProcessor (*argv + 2);
+ return;
+ }
+ argv++;
+ }
+
+ /* no error if processor was not specified. */
+}
+
/*-----------------------------------------------------------------*/
/* printVersionInfo - prints the version info */
/*-----------------------------------------------------------------*/
options.stack_loc = 0; /* stack pointer initialised to 0 */
options.xstack_loc = 0; /* xternal stack starts at 0 */
options.code_loc = 0; /* code starts at 0 */
- options.data_loc = 0x0030; /* data starts at 0x0030 */
+ options.data_loc = 0; /* JCF: By default let the linker locate data */
options.xdata_loc = 0;
options.idata_loc = 0x80;
options.genericPtr = 1; /* default on */
{
/* source file name : not if we already have a
source file */
- if (srcFileName)
+ if (fullSrcFileName)
{
werror (W_TOO_MANY_SRC, s);
return;
/* get rid of the "."-extension */
/* is there a dot at all? */
- if (strchr (buffer, '.') &&
+ if (strrchr (buffer, '.') &&
/* is the dot in the filename, not in the path? */
- (strrchr (buffer, '/' ) < strrchr (buffer, '.') ||
- strrchr (buffer, '\\') < strrchr (buffer, '.')))
+ (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
+ {
*strrchr (buffer, '.') = '\0';
-
- srcFileName = Safe_alloc ( strlen (buffer) + 1);
- strcpy (srcFileName, buffer);
+ }
/* get rid of any path information
- for the module name; do this by going
- backwards till we get to either '/' or '\' or ':'
- or start of buffer */
+ for the module name; */
fext = buffer + strlen (buffer);
+#if NATIVE_WIN32
+ /* do this by going backwards till we
+ get '\' or ':' or start of buffer */
while (fext != buffer &&
- *(fext - 1) != '\\' &&
- *(fext - 1) != '/' &&
+ *(fext - 1) != DIR_SEPARATOR_CHAR &&
*(fext - 1) != ':')
+ {
fext--;
- moduleName = Safe_alloc ( strlen (fext) + 1);
- strcpy (moduleName, fext);
-
+ }
+#else
+ /* do this by going backwards till we
+ get '/' or start of buffer */
+ while (fext != buffer &&
+ *(fext - 1) != DIR_SEPARATOR_CHAR)
+ {
+ fext--;
+ }
+#endif
+ moduleName = Safe_strdup ( fext );
return;
}
static void
_processC1Arg (char *s)
{
- if (srcFileName)
+ if (fullSrcFileName)
{
if (options.out_name)
{
werror (W_UNSUPPORTED_MODEL, sz, port->target);
}
-static void
-_setProcessor (char *_processor)
-{
- port->processor = _processor;
- fprintf(stderr,"Processor: %s\n",_processor);
-}
-
/** Gets the string argument to this option. If the option is '--opt'
then for input of '--optxyz' or '--opt xyz' returns xyz.
*/
/*-----------------------------------------------------------------*/
/* parseCmdLine - parses the command line and sets the options */
/*-----------------------------------------------------------------*/
-int
+static int
parseCmdLine (int argc, char **argv)
{
int i;
break;
case 'm':
- /* Used to select the port */
- _setPort (argv[i] + 2);
+ /* Used to select the port. But this has already been done. */
break;
case 'p':
- /* Used to select the processor in port */
- _setProcessor (getStringArg("-p", argv, &i, argc));
+ /* Used to select the processor in port. But this has
+ * already been done. */
break;
case 'c':
case 'l':
libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
break;
+
+ case 'o':
+ {
+ char *p;
+
+ /* copy the file name into the buffer */
+ strcpy (buffer, getStringArg("-o", argv, &i, argc));
+ /* point to last character */
+ p = buffer + strlen (buffer) - 1;
+ if (*p == DIR_SEPARATOR_CHAR)
+ {
+ /* only output path specified */
+ dstPath = Safe_strdup (buffer);
+ fullDstFileName = NULL;
+ }
+ else
+ {
+ fullDstFileName = Safe_strdup (buffer);
+
+ /* get rid of the "."-extension */
+
+ /* is there a dot at all? */
+ if (strrchr (buffer, '.') &&
+ /* is the dot in the filename, not in the path? */
+ (strrchr (buffer, DIR_SEPARATOR_CHAR) < strrchr (buffer, '.')))
+ *strrchr (buffer, '.') = '\0';
+
+ dstFileName = Safe_strdup (buffer);
+
+ /* strip module name to get path */
+ p = strrchr (buffer, DIR_SEPARATOR_CHAR);
+ if (p)
+ {
+ /* path with trailing / */
+ p[1] = '\0';
+ dstPath = Safe_strdup (buffer);
+ }
+ }
+ break;
+ }
case 'W':
/* pre-processer options */
}
}
+ /* if no dstFileName given with -o, we've to find one: */
+ if (!dstFileName)
+ {
+ /* use the modulename from the C-source */
+ if (fullSrcFileName)
+ {
+ dstFileName = Safe_alloc (strlen (dstPath) + strlen (moduleName) + 1);
+ strcpy (dstFileName, dstPath);
+ strcat (dstFileName, moduleName);
+ }
+ /* use the modulename from the first object file */
+ else if (nrelFiles >= 1)
+ {
+ char *objectName;
+
+ strcpy (buffer, relFiles[0]);
+ /* remove extension (it must be .rel) */
+ *strrchr (buffer, '.') = '\0';
+ /* remove path */
+ objectName = strrchr (buffer, DIR_SEPARATOR_CHAR);
+ if (objectName)
+ {
+ ++objectName;
+ }
+ else
+ {
+ objectName = buffer;
+ }
+ dstFileName = Safe_alloc (strlen (dstPath) + strlen (objectName) + 1);
+ strcpy (dstFileName, dstPath);
+ strcat (dstFileName, objectName);
+ }
+ /* else no module given: help text is displayed */
+ }
+
/* set up external stack location if not explicitly specified */
if (!options.xstack_loc)
options.xstack_loc = options.xdata_loc;
/* if debug option is set the open the cdbFile */
- if (options.debug && srcFileName)
+ if (options.debug && fullSrcFileName)
{
- sprintf (scratchFileName, "%s.cdb", srcFileName);
+ sprintf (scratchFileName, "%s.adb", dstFileName); //JCF: Nov 30, 2002
if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
werror (E_FILE_OPEN_ERR, scratchFileName);
else
{
FILE *lnkfile;
char *segName, *c;
-
int i;
- if (!srcFileName)
- srcFileName = "temp";
/* first we need to create the <filename>.lnk file */
- sprintf (scratchFileName, "%s.lnk", srcFileName);
+ sprintf (scratchFileName, "%s.lnk", dstFileName);
if (!(lnkfile = fopen (scratchFileName, "w")))
{
werror (E_FILE_OPEN_ERR, scratchFileName);
exit (1);
}
- /* now write the options */
- fprintf (lnkfile, "-mux%c\n", (options.out_fmt ? 's' : 'i'));
+ /* now write the options. JCF: added option 'y' */
+ fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
/* if iram size specified */
if (options.iram_size)
WRITE_SEG_LOC (CODE_NAME, options.code_loc);
/* data segment start */
- WRITE_SEG_LOC (DATA_NAME, options.data_loc);
+ if(options.data_loc){ /*JCF: If zero, the linker chooses the best place for data*/
+ WRITE_SEG_LOC (DATA_NAME, options.data_loc);
+ }
/* xdata start */
WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
/* bit segment start */
WRITE_SEG_LOC (BIT_NAME, 0);
+ /* JCF: stack start */
+ if(options.stack_loc) {
+ WRITE_SEG_LOC ("SSEG", options.stack_loc & 0xff);
+ }
+
/* add the extra linker options */
for (i = 0; linkOptions[i]; i++)
fprintf (lnkfile, "%s\n", linkOptions[i]);
fprintf (lnkfile, "-l %s\n", libFiles[i]);
/* put in the object files */
- if (strcmp (srcFileName, "temp"))
- fprintf (lnkfile, "%s ", srcFileName);
+ if (fullSrcFileName)
+ fprintf (lnkfile, "%s ", dstFileName);
for (i = 0; i < nrelFiles; i++)
fprintf (lnkfile, "%s\n", relFiles[i]);
if (port->linker.cmd)
{
char buffer2[PATH_MAX];
- buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+ buildCmdLine (buffer2, port->linker.cmd, dstFileName, NULL, NULL, NULL);
buildCmdLine2 (buffer, buffer2);
}
else
{
exit (1);
}
-
- if (strcmp (srcFileName, "temp") == 0)
+ /* -o option overrides default name? */
+ if (fullDstFileName)
{
- /* rename "temp.cdb" to "firstRelFile.cdb" */
- char *f = strtok (Safe_strdup (relFiles[0]), ".");
- f = strcat (f, ".cdb");
- rename ("temp.cdb", f);
- srcFileName = NULL;
+ /* the linked file gets the name of the first modul */
+ if (fullSrcFileName)
+ {
+ strcpy (scratchFileName, dstFileName);
+ }
+ else
+ {
+ strcpy (scratchFileName, relFiles[0]);
+ /* strip ".rel" extension */
+ *strrchr (scratchFileName, '.') = '\0';
+ }
+ strcat (scratchFileName, options.out_fmt ? ".S19" : ".ihx");
+ rename (scratchFileName, fullDstFileName);
}
}
port->assembler.do_assemble(asmOptions);
return ;
} else if (port->assembler.cmd) {
- buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
+ buildCmdLine (buffer, port->assembler.cmd, dstFileName, NULL,
options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
asmOptions);
} else {
*/
exit (1);
}
+ /* -o option overrides default name? */
+ if (options.cc_only && fullDstFileName) {
+ strcpy (scratchFileName, dstFileName);
+ strcat (scratchFileName, ".rel");
+ rename (scratchFileName, fullDstFileName);
+ }
}
/*-----------------------------------------------------------------*/
/* Have to set cppoutfilename to something, even if just pre-processing. */
setMainValue ("cppoutfilename", preOutName ? preOutName : "");
-
+
if (options.verbose)
printf ("sdcc: Calling preprocessor...\n");
setMainValue ("objext", port->linker.rel_ext);
setMainValue ("asmext", port->assembler.file_ext);
+ setMainValue ("dstfilename", dstFileName);
setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
- setMainValue ("srcfilename", srcFileName ? srcFileName : "srcfilename");
+
+ if (options.cc_only && fullDstFileName)
+ /* compile + assemble and -o given: -o specifies name of object file */
+ {
+ setMainValue ("z80objdstfilename", fullDstFileName);
+ }
+ else
+ {
+ setMainValue ("z80objdstfilename", "{z80stdobjdstfilename}");
+ }
+ if (fullDstFileName)
+ /* if we're linking, -o gives the final file name */
+ {
+ setMainValue ("z80linkdstfilename", fullDstFileName);
+ }
+ else
+ {
+ setMainValue ("z80linkdstfilename", "{z80stdlinkdstfilename}");
+ }
+
}
/*
exit (1);
}
+ /* install atexit handler */
+ atexit(rm_tmpfiles);
+
+ /* Before parsing the command line options, do a
+ * search for the port and processor and initialize
+ * them if they're found. (We can't gurantee that these
+ * will be the first options specified).
+ */
+
_findPort (argc, argv);
+
#ifdef JAMIN_DS390
if (strcmp(port->target, "mcs51") == 0) {
printf("DS390 jammed in A\n");
ds390_jammed = 1;
}
#endif
+
+ _findProcessor (argc, argv);
+
/* Initalise the port. */
if (port->init)
port->init ();
parseCmdLine (argc, argv);
/* if no input then printUsage & exit */
- if ((!options.c1mode && !srcFileName && !nrelFiles) ||
- (options.c1mode && !srcFileName && !options.out_name))
+ if ((!options.c1mode && !fullSrcFileName && !nrelFiles) ||
+ (options.c1mode && !fullSrcFileName && !options.out_name))
{
printUsage ();
exit (0);
initValues ();
_discoverPaths (argv[0]);
- if (srcFileName)
+ if (fullSrcFileName)
{
initMem ();
yyparse ();
- if (!fatalError)
- {
- if (TARGET_IS_PIC) {
- /* TSD PIC port hack - if the PIC port option is enabled
- and SDCC is used to generate PIC code, then we will
- generate .asm files in gpasm's format instead of SDCC's
- assembler's format
- */
+ if (fatalError) {
+ // @FIX: Dario Vecchio 03-05-2001
+ if (preOutName) {
+ if (yyin && yyin != stdin)
+ fclose (yyin);
+ unlink (preOutName);
+ Safe_free (preOutName);
+ }
+ // EndFix
+ return 1;
+ }
+
+ if (TARGET_IS_PIC) {
+ /* TSD PIC port hack - if the PIC port option is enabled
+ and SDCC is used to generate PIC code, then we will
+ generate .asm files in gpasm's format instead of SDCC's
+ assembler's format
+ */
#if !OPT_DISABLE_PIC
- picglue ();
+ picglue ();
#endif
- } else {
- glue ();
- }
-
- if (fatalError)
- {
- // @FIX: Dario Vecchio 03-05-2001
- if (preOutName)
- {
- if (yyin && yyin != stdin)
- fclose (yyin);
- unlink (preOutName);
- Safe_free (preOutName);
- }
- // EndFix
- return 1;
- }
- if (!options.c1mode && !noAssemble)
- {
- if (options.verbose)
- printf ("sdcc: Calling assembler...\n");
- assemble (envp);
- }
- }
- else
- {
- // @FIX: Dario Vecchio 03-05-2001
- if (preOutName)
- {
- if (yyin && yyin != stdin)
- fclose (yyin);
- unlink (preOutName);
- Safe_free (preOutName);
- }
- // EndFix
- #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
- rm_tmpfiles();
- #endif
- return 1;
- }
+ }
+ else {
+ glue ();
+ }
+ if (!options.c1mode && !noAssemble)
+ {
+ if (options.verbose)
+ printf ("sdcc: Calling assembler...\n");
+ assemble (envp);
+ }
}
closeDumpFiles();
if (cdbFile)
fclose (cdbFile);
+ if (yyin && yyin != stdin)
+ fclose (yyin);
+
if (preOutName && !options.c1mode)
{
unlink (preOutName);
!fatalError &&
!noAssemble &&
!options.c1mode &&
- (srcFileName || nrelFiles))
+ (fullSrcFileName || nrelFiles))
{
if (port->linker.do_link)
port->linker.do_link ();
linkEdit (envp);
}
- if (yyin && yyin != stdin)
- fclose (yyin);
-
return 0;
-
}