* src/SDCCsymt.c (initCSupport): fix compile warning on Cygwin
[fw/sdcc] / src / SDCCmain.c
index c1510d14e16761f8a13c1e3e22a45e8e29046aa4..754b8034802d816d3b6c28bf8514718d976a35dd 100644 (file)
@@ -22,6 +22,7 @@
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
+#include <signal.h>
 #include "common.h"
 #include <ctype.h>
 #include "newalloc.h"
@@ -34,8 +35,6 @@
 
 #if NATIVE_WIN32
 #include <process.h>
-#else
-#include "spawn.h"
 #endif
 
 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
@@ -51,11 +50,18 @@ extern int yyparse ();
 
 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;
@@ -71,6 +77,7 @@ char *relFiles[128];
 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. */
@@ -115,6 +122,9 @@ char DefaultExePath[128];
 #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"
+#define OPTION_XRAM_SIZE       "--xram-size"
+#define OPTION_CODE_SIZE       "--code-size"
 
 static const OPTION 
 optionsTable[] = {
@@ -140,13 +150,13 @@ optionsTable[] = {
     { 0,    OPTION_STACK_8BIT,      NULL, "use the 8bit stack for the ds390 (not supported yet)" },
     { 0,    "--stack-10bit",        &options.stack10bit, "use the 10bit stack for ds390 (default)" },
     { 0,    "--xstack",             &options.useXstack, "Use external stack" },
-    { 0,    "--generic",            &options.genericPtr, "All unqualified ptrs converted to '_generic'" },
     { 0,    OPTION_NO_GCSE,         NULL, "Disable the GCSE optimisation" },
     { 0,    OPTION_NO_LOOP_INV,     NULL, "Disable optimisation of invariants" },
     { 0,    OPTION_NO_LOOP_IND,     NULL, NULL },
     { 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 },
@@ -157,9 +167,11 @@ optionsTable[] = {
     { 0,    "--dumptree",           &options.dump_tree, "dump front-end AST before generating iCode" },
     { 0,    OPTION_DUMP_ALL,        NULL, "Dump the internal structure at all stages" },
     { 0,    OPTION_XRAM_LOC,        NULL, "<nnnn> External Ram start location" },
+    { 0,    OPTION_XRAM_SIZE,       NULL, "<nnnn> External Ram size" },
     { 0,    OPTION_IRAM_SIZE,       NULL, "<nnnn> Internal Ram size" },
     { 0,    OPTION_XSTACK_LOC,      NULL, "<nnnn> External Ram start location" },
     { 0,    OPTION_CODE_LOC,        NULL, "<nnnn> Code Segment Location" },
+    { 0,    OPTION_CODE_SIZE,       NULL, "<nnnn> Code Segment size" },
     { 0,    OPTION_STACK_LOC,       NULL, "<nnnn> Stack pointer initial value" },
     { 0,    OPTION_DATA_LOC,        NULL, "<nnnn> Direct data start location" },
     { 0,    OPTION_IDATA_LOC,       NULL, NULL },
@@ -178,7 +190,6 @@ optionsTable[] = {
     { 0,    "--peep-asm",           &options.asmpeep, NULL },
     { 0,    "--debug",              &options.debug, "Enable debugging symbol output" },
     { 'v',  OPTION_VERSION,         NULL, "Display sdcc's version" },
-    { 0,    "--stack-after-data",   &options.stackOnData, "initialize the stackpointer with the last byte use in DSEG" },
     { 'E',  "--preprocessonly",     &preProcOnly, "Preprocess only, do not compile" },
     { 0,    "--c1mode",             &options.c1mode, "Act in c1 mode.  The input is preprocessed code, the output is assembly code." },
     { 0,    "--help",               NULL, "Display this help" },
@@ -196,6 +207,7 @@ optionsTable[] = {
     { 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 }
 };
@@ -215,8 +227,6 @@ typedef struct {
 
 static const UNSUPPORTEDOPT 
 unsupportedOptTable[] = {
-    { 'a',  NULL,      "use --stack-auto instead." },
-    { 'g',  NULL,      "use --generic instead" },
     { 'X',  NULL,      "use --xstack-loc instead" },
     { 'x',  NULL,      "use --xstack instead" },
     { 'i',  NULL,      "use --idata-loc instead" },
@@ -235,7 +245,7 @@ static const char *_baseValues[] = {
   NULL
 };
 
-static const char *_preCmd = "{cpp} -nostdinc -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
+static const char *_preCmd = "{cpp} -nostdinc -Wall -std=c99 -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
 
 PORT *port;
 
@@ -294,6 +304,15 @@ _setPort (const char *name)
   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)
 {
@@ -330,6 +349,23 @@ _findPort (int argc, char **argv)
   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        */
 /*-----------------------------------------------------------------*/
@@ -350,16 +386,18 @@ printVersionInfo ()
            " (" __DATE__ ")"
 #ifdef __CYGWIN__
           " (CYGWIN)\n"
+#elif defined __MINGW32__
+          " (MINGW32) \n"
 #else
-#ifdef __DJGPP__
+#  ifdef __DJGPP__
           " (DJGPP) \n"
-#else
-#if defined(_MSC_VER)
+#  else
+#    if defined(_MSC_VER)
           " (WIN32) \n"
-#else
+#    else
           " (UNIX) \n"
-#endif
-#endif
+#    endif
+#  endif
 #endif
 
           ,VersionString
@@ -452,10 +490,9 @@ setDefaultOptions ()
   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 */
   options.nopeep = 0;
   options.model = port->general.default_model;
   options.nostdlib = 0;
@@ -505,14 +542,15 @@ processFile (char *s)
     {
       /* source file name : not if we already have a
          source file */
-      if (srcFileName)
+      if (fullSrcFileName)
        {
          werror (W_TOO_MANY_SRC, s);
          return;
        }
 
       /* the only source file */
-      if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
+      fullSrcFileName = s;
+      if (!(srcFile = fopen (fullSrcFileName, "r")))
        {
          werror (E_FILE_OPEN_ERR, s);
          exit (1);
@@ -524,28 +562,35 @@ processFile (char *s)
       /* 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;
     }
 
@@ -570,24 +615,6 @@ processFile (char *s)
 
 }
 
-static void
-_processC1Arg (char *s)
-{
-  if (srcFileName)
-    {
-      if (options.out_name)
-       {
-         werror (W_TOO_MANY_SRC, s);
-         return;
-       }
-      options.out_name = Safe_strdup (s);
-    }
-  else
-    {
-      processFile (s);
-    }
-}
-
 static void
 _setModel (int model, const char *sz)
 {
@@ -597,13 +624,6 @@ _setModel (int model, const char *sz)
     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.
 */
@@ -761,7 +781,7 @@ tryHandleSimpleOpt(char **argv, int *pi)
 /*-----------------------------------------------------------------*/
 /* parseCmdLine - parses the command line and sets the options     */
 /*-----------------------------------------------------------------*/
-int
+static int
 parseCmdLine (int argc, char **argv)
 {
   int i;
@@ -888,6 +908,19 @@ parseCmdLine (int argc, char **argv)
                 continue;
            }
 
+         if (strcmp (argv[i], OPTION_XRAM_SIZE) == 0)
+           {
+                options.xram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
+                options.xram_size_set = TRUE;
+                continue;
+           }
+
+         if (strcmp (argv[i], OPTION_CODE_SIZE) == 0)
+           {
+                options.code_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
+                continue;
+           }
+
          if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
            {
                 options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
@@ -966,13 +999,12 @@ parseCmdLine (int argc, char **argv)
              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':
@@ -988,6 +1020,46 @@ parseCmdLine (int argc, char **argv)
             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 */
@@ -1042,13 +1114,13 @@ parseCmdLine (int argc, char **argv)
                if (argv[i][2] == ' ' || argv[i][2] == '\0')
                  {
                    i++;
-                    if (i >= argc) 
+                    if (i >= argc)
                       {
                           /* No argument. */
                           werror(E_ARGUMENT_MISSING, argv[i-1]);
                           break;
                       }
-                    else 
+                    else
                       {
                           rest = argv[i];
                       }
@@ -1074,21 +1146,53 @@ parseCmdLine (int argc, char **argv)
       if (!port->parseOption (&argc, argv, &i))
        {
          /* no option must be a filename */
-         if (options.c1mode)
-           _processC1Arg (argv[i]);
-         else
-           processFile (argv[i]);
+          processFile (argv[i]);
        }
     }
 
+  /* 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
@@ -1108,26 +1212,31 @@ linkEdit (char **envp)
 {
   FILE *lnkfile;
   char *segName, *c;
-
-  int i;
-  if (!srcFileName)
-    srcFileName = "temp";
+  int i, system_ret;
 
   /* 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)
     fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
 
+  /* if xram size specified */
+  if (options.xram_size_set)
+    fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
+
+  /* if code size specified */
+  if (options.code_size)
+    fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
+
   if (options.debug)
     fprintf (lnkfile, "-z\n");
 
@@ -1141,7 +1250,9 @@ linkEdit (char **envp)
   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);
@@ -1154,6 +1265,11 @@ linkEdit (char **envp)
   /* bit segment start */
   WRITE_SEG_LOC (BIT_NAME, 0);
 
+  /* JCF: stack start */
+  if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
+       WRITE_SEG_LOC ("SSEG", options.stack_loc);
+  }
+
   /* add the extra linker options */
   for (i = 0; linkOptions[i]; i++)
     fprintf (lnkfile, "%s\n", linkOptions[i]);
@@ -1214,8 +1330,8 @@ linkEdit (char **envp)
     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]);
@@ -1226,10 +1342,33 @@ linkEdit (char **envp)
   if (options.verbose)
     printf ("sdcc: Calling linker...\n");
 
+  /* build linker output filename */
+
+  /* -o option overrides default name? */
+  if (fullDstFileName)
+    {
+      strcpy (scratchFileName, fullDstFileName);
+    }
+  else
+    {
+      /* 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");
+    }
+
   if (port->linker.cmd)
     {
       char buffer2[PATH_MAX];
-      buildCmdLine (buffer2, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+      buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, NULL);
       buildCmdLine2 (buffer, buffer2);
     }
   else
@@ -1237,18 +1376,48 @@ linkEdit (char **envp)
       buildCmdLine2 (buffer, port->linker.mcmd);
     }
 
-  if (my_system (buffer))
+  system_ret = my_system (buffer);
+  /* TODO: most linker don't have a -o parameter */
+  /* -o option overrides default name? */
+  if (fullDstFileName)
     {
-      exit (1);
-    }
+      char *p, *q;
+      /* the linked file gets the name of the first modul */
+      if (fullSrcFileName)
+        {
+          strcpy (scratchFileName, dstFileName);
+          p = strlen (scratchFileName) + scratchFileName;
+        }
+      else
+        {
+          strcpy (scratchFileName, relFiles[0]);
+          /* strip "rel" extension */
+          p = strrchr (scratchFileName, '.') + 1;
+        }
+      strcpy (p, options.out_fmt ? "S19" : "ihx");
+      rename (scratchFileName, fullDstFileName);
 
-  if (strcmp (srcFileName, "temp") == 0)
+      q = strrchr (fullDstFileName, '.');
+      if (q)
+        {
+          /* point after the '.' of the extension */
+          q++;
+        }
+      else
+        {
+          /* no extension: append new extensions */
+          q = strlen (fullDstFileName) + fullDstFileName;
+        }
+      strcpy (p, "map");
+      strcpy (q, "map");
+      rename (scratchFileName, fullDstFileName);
+      strcpy (p, "mem");
+      strcpy (q, "mem");
+      rename (scratchFileName, fullDstFileName);
+    }
+  if (system_ret)
     {
-      /* rename "temp.cdb" to "firstRelFile.cdb" */
-      char *f = strtok (Safe_strdup (relFiles[0]), ".");
-      f = strcat (f, ".cdb");
-      rename ("temp.cdb", f);
-      srcFileName = NULL;
+      exit (1);
     }
 }
 
@@ -1258,11 +1427,22 @@ linkEdit (char **envp)
 static void
 assemble (char **envp)
 {
+    /* build assembler output filename */
+
+    /* -o option overrides default name? */
+    if (options.cc_only && fullDstFileName) {
+        strcpy (scratchFileName, fullDstFileName);
+    } else {
+        /* the assembled file gets the name of the first modul */
+        strcpy (scratchFileName, dstFileName);
+        strcat (scratchFileName, port->linker.rel_ext);
+    }
+
     if (port->assembler.do_assemble) {
        port->assembler.do_assemble(asmOptions);
        return ;
     } else if (port->assembler.cmd) {
-       buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL,
+        buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
                      options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
                      asmOptions);
     } else {
@@ -1275,6 +1455,13 @@ assemble (char **envp)
        */
        exit (1);
     }
+    /* TODO: most assembler don't have a -o parameter */
+    /* -o option overrides default name? */
+    if (options.cc_only && fullDstFileName) {
+        strcpy (scratchFileName, dstFileName);
+        strcat (scratchFileName, port->linker.rel_ext);
+        rename (scratchFileName, fullDstFileName);
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1339,13 +1526,18 @@ preProcess (char **envp)
       }
 
       setMainValue ("cppextraopts", join(preArgv));
-      
-      if (!preProcOnly)
+
+      if (preProcOnly)
+        {
+          if (fullDstFileName)
+              preOutName = Safe_strdup (fullDstFileName);
+        }
+      else
           preOutName = Safe_strdup (tempfilename ());
 
       /* Have to set cppoutfilename to something, even if just pre-processing. */
       setMainValue ("cppoutfilename", preOutName ? preOutName : "");
-       
+
       if (options.verbose)
        printf ("sdcc: Calling preprocessor...\n");
 
@@ -1520,8 +1712,55 @@ initValues (void)
   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 ("objdstfilename", fullDstFileName);
+    }
+  else
+    {
+      setMainValue ("objdstfilename", "{stdobjdstfilename}");
+    }
+  if (fullDstFileName)
+    /* if we're linking, -o gives the final file name */
+    {
+      setMainValue ("linkdstfilename", fullDstFileName);
+    }
+  else
+    {
+      setMainValue ("linkdstfilename", "{stdlinkdstfilename}");
+    }
+
+}
+
+static void
+sig_handler (int signal)
+{
+  char *sig_string;
+
+  switch (signal)
+    {
+    case SIGABRT:
+      sig_string = "SIGABRT";
+      break;
+    case SIGTERM:
+      sig_string = "SIGTERM";
+      break;
+    case SIGINT:
+      sig_string = "SIGINT";
+      break;
+    case SIGSEGV:
+      sig_string = "SIGSEGV";
+      break;
+    default:
+      sig_string = "Unknown?";
+      break;
+    }
+  fprintf (stderr, "Catched signal %d: %s\n", signal, sig_string);
+  exit (1);
 }
 
 /*
@@ -1542,7 +1781,24 @@ main (int argc, char **argv, char **envp)
     exit (1);
   }
 
+  /* install atexit handler */
+  atexit(rm_tmpfiles);
+
+  /* install signal handler;
+     it's only purpuse is to call exit() to remove temp files */
+  signal (SIGABRT, sig_handler);
+  signal (SIGTERM, sig_handler);
+  signal (SIGINT , sig_handler);
+  signal (SIGSEGV, sig_handler);
+
+  /* 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");
@@ -1550,6 +1806,9 @@ main (int argc, char **argv, char **envp)
     ds390_jammed = 1;
   }
 #endif
+
+  _findProcessor (argc, argv);
+
   /* Initalise the port. */
   if (port->init)
     port->init ();
@@ -1567,8 +1826,8 @@ main (int argc, char **argv, char **envp)
   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))
     {
       printUsage ();
       exit (0);
@@ -1577,12 +1836,15 @@ main (int argc, char **argv, char **envp)
   initValues ();
   _discoverPaths (argv[0]);
 
-  if (srcFileName)
-    {
-
-      initMem ();
+  /* initMem() is expensive, but
+     initMem() must called before port->finaliseOptions ().
+     And the z80 port needs port->finaliseOptions(),
+     even if we're only linking. */
+  initMem ();
+  port->finaliseOptions ();
 
-      port->finaliseOptions ();
+  if (fullSrcFileName)
+    {
       preProcess (envp);
 
       initSymt ();
@@ -1596,58 +1858,38 @@ main (int argc, char **argv, char **envp)
 
       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();
@@ -1655,6 +1897,9 @@ main (int argc, char **argv, char **envp)
   if (cdbFile)
     fclose (cdbFile);
 
+  if (yyin && yyin != stdin)
+    fclose (yyin);
+
   if (preOutName && !options.c1mode)
     {
       unlink (preOutName);
@@ -1665,7 +1910,7 @@ main (int argc, char **argv, char **envp)
       !fatalError &&
       !noAssemble &&
       !options.c1mode &&
-      (srcFileName || nrelFiles))
+      (fullSrcFileName || nrelFiles))
     {
       if (port->linker.do_link)
        port->linker.do_link ();
@@ -1673,9 +1918,5 @@ main (int argc, char **argv, char **envp)
        linkEdit (envp);
     }
 
-  if (yyin && yyin != stdin)
-    fclose (yyin);
-
   return 0;
-
 }