DS80C400 support, the beginning
[fw/sdcc] / src / SDCCmain.c
index 417dae3a35b88fdd9386718dab4804146ca30000..033b5afb29386e0aae792984688f567a7af02a10 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"
 #include "MySystem.h"
 #include "SDCCmacro.h"
 #include "SDCCutil.h"
+#include "SDCCdebug.h"
 #include "SDCCargs.h"
 
-#if NATIVE_WIN32
+#ifdef _WIN32
 #include <process.h>
 #else
-#include "spawn.h"
-#endif
-
-#if !defined(__BORLANDC__) && !defined(_MSC_VER)
 #include <sys/stat.h>
 #include <unistd.h>
 #endif
 
-/** Name of the environment variable checked for other instalations. */
-#define SDCCDIR_NAME "SDCCDIR"
-
 //REMOVE ME!!!
 extern int yyparse ();
 
 FILE *srcFile;                 /* source file          */
-FILE *cdbFile = NULL;          /* debugger information output file */
 char *fullSrcFileName;         /* full name for the source file; */
-                               /* can be NULL while linking without compiling */
+                               /* can be NULL while c1mode or linking without compiling */
 char *fullDstFileName;         /* full name for the output file; */
                                /* only given by -o, otherwise NULL */
+size_t fullDstFileNameLen;     /* size of previous string. */
 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 */
+/*
+ * in following definitions fixed length arrays are very dangerous!
+ * Sets should be used instead. See definition of asmOptions.
+ */
 const char *preArgv[128];      /* pre-processor arguments  */
 int currRegBank = 0;
-int RegBankUsed[4]={1, 0, 0, 0};       /*JCF: Reg Bank 0 used by default*/
+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 preProcOnly = 0;
 int noAssemble = 0;
+set *asmOptions = NULL;         /* set of assembler options */
 char *linkOptions[128];
-const char *asmOptions[128];
 char *libFiles[128];
 int nlibFiles = 0;
 char *libPaths[128];
 int nlibPaths = 0;
 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. */
@@ -89,11 +84,7 @@ int ds390_jammed = 0;
 
 // Globally accessible scratch buffer for file names.
 char scratchFileName[PATH_MAX];
-char buffer[PATH_MAX];
-
-// In MSC VC6 default search path for exe's to path for this
-
-char DefaultExePath[128];
+char buffer[PATH_MAX * 2];
 
 #define OPTION_HELP    "-help"
 
@@ -117,15 +108,20 @@ char DefaultExePath[128];
 #define OPTION_DATA_LOC                "--data-loc"
 #define OPTION_CODE_LOC                "--code-loc"
 #define OPTION_IDATA_LOC       "--idata-loc"
+#define OPTION_NO_LABEL_OPT     "--nolabelopt"
 #define OPTION_NO_LOOP_INV     "--noinvariant"
 #define OPTION_NO_LOOP_IND     "--noinduction"
-#define OPTION_LESS_PEDANTIC   "--lesspedantic"
+#define OPTION_LESS_PEDANTIC   "--less-pedantic"
 #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"
+#define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
+#define OPTION_ICODE_IN_ASM    "--i-code-in-asm"
 
-static const OPTION 
+static const OPTION
 optionsTable[] = {
     { 'm',  NULL,                   NULL, "Set the port to use e.g. -mz80." },
     { 'p',  NULL,                   NULL, "Select port specific processor e.g. -mpic14 -p16f84" },
@@ -136,7 +132,7 @@ optionsTable[] = {
     { 'U',  NULL,                   NULL, NULL },
     { 'C',  NULL,                   NULL, "Preprocessor option" },
     { 'M',  NULL,                   NULL, "Preprocessor option" },
-    { 'V',  NULL,                   &verboseExec, "Execute verbosely.  Show sub commands as they are run" },
+    { 'V',  NULL,                   &options.verboseExec, "Execute verbosely.  Show sub commands as they are run" },
     { 'S',  NULL,                   &noAssemble, "Compile only; do not assemble or link" },
     { 'W',  NULL,                   NULL, "Pass through options to the pre-processor (p), assembler (a) or linker (l)" },
     { 'L',  NULL,                   NULL, "Add the next field to the library search path" },
@@ -149,8 +145,8 @@ 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_LABEL_OPT,    NULL, "Disable label 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" },
@@ -167,9 +163,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 },
@@ -188,9 +186,8 @@ 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,    "--c1mode",             &options.c1mode, "Act in c1 mode.  The standard input is preprocessed code, the output is assembly code." },
     { 0,    "--help",               NULL, "Display this help" },
     { 0,    OPTION_CALLEE_SAVES,    NULL, "<func[,func,...]> Cause the called function to save registers insted of the caller" },
     { 0,    "--nostdlib",           &options.nostdlib, "Do not include the standard library directory in the search path" },
@@ -206,7 +203,9 @@ 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"},
+    { 0,    OPTION_NO_XINIT_OPT,    &options.noXinitOpt, "don't memcpy initialized xram from code"},
+    { 0,    OPTION_NO_CCODE_IN_ASM, &options.noCcodeInAsm, "don't include c-code as comments in the asm file"},
+    { 0,    OPTION_ICODE_IN_ASM,    &options.iCodeInAsm, "include i-code as comments in the asm file"},
     /* End of options */
     { 0,    NULL }
 };
@@ -226,8 +225,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" },
@@ -239,14 +236,14 @@ unsupportedOptTable[] = {
 /** List of all default constant macros.
  */
 static const char *_baseValues[] = {
-  "cpp", "{bindir}{sep}sdcpp",
+  "cpp", "sdcpp",
   "cppextraopts", "",
   /* Path seperator character */
   "sep", DIR_SEPARATOR_STRING,
   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;
 
@@ -276,6 +273,9 @@ static PORT *_ports[] =
 #if !OPT_DISABLE_XA51
   &xa51_port,
 #endif
+#if !OPT_DISABLE_DS400
+  &ds400_port, 
+#endif 
 };
 
 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
@@ -380,26 +380,24 @@ printVersionInfo ()
   for (i = 0; i < NUM_PORTS; i++)
     fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
 
-  fprintf (stderr, " %s"
+  fprintf (stderr, " " SDCC_VERSION_STR
 #ifdef SDCC_SUB_VERSION_STR
           "/" SDCC_SUB_VERSION_STR
 #endif
            " (" __DATE__ ")"
 #ifdef __CYGWIN__
           " (CYGWIN)\n"
-#else
-#ifdef __DJGPP__
+#elif defined __MINGW32__
+          " (MINGW32) \n"
+#elif defined __DJGPP__
           " (DJGPP) \n"
-#else
-#if defined(_MSC_VER)
-          " (WIN32) \n"
+#elif defined(_MSC_VER)
+          " (MSVC) \n"
+#elif defined(__BORLANDC__)
+          " (BORLANDC) \n"
 #else
           " (UNIX) \n"
 #endif
-#endif
-#endif
-
-          ,VersionString
     );
 }
 
@@ -430,7 +428,7 @@ printUsage ()
              "Usage : sdcc [options] filename\n"
              "Options :-\n"
              );
-    
+
     printOptions(optionsTable);
 
     for (i = 0; i < NUM_PORTS; i++)
@@ -472,6 +470,26 @@ parseWithComma (char **dest, char *src)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* setParseWithComma - separates string with comma to a set        */
+/*-----------------------------------------------------------------*/
+void
+setParseWithComma (set **dest, char *src)
+{
+  char *p;
+
+  /* skip the initial white spaces */
+  while (isspace (*src))
+    src++;
+
+  if ((p = strtok(src, ",")) != NULL) {
+    do
+    {
+      addSet(dest, p);
+    } while ((p = strtok(NULL, ",")) != NULL);
+  }
+}
+
 /*-----------------------------------------------------------------*/
 /* setDefaultOptions - sets the default options                    */
 /*-----------------------------------------------------------------*/
@@ -481,9 +499,7 @@ setDefaultOptions ()
   int i;
 
   for (i = 0; i < 128; i++)
-    preArgv[i] = asmOptions[i] =
-      linkOptions[i] = relFiles[i] = libFiles[i] =
-      libPaths[i] = NULL;
+    preArgv[i] = linkOptions[i] = relFiles[i] = libFiles[i] = libPaths[i] = NULL;
 
   /* first the options part */
   options.stack_loc = 0;       /* stack pointer initialised to 0 */
@@ -492,7 +508,6 @@ setDefaultOptions ()
   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;
@@ -538,7 +553,7 @@ processFile (char *s)
     }
 
   /* otherwise depending on the file type */
-  if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
+  if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0)
     {
       /* source file name : not if we already have a
          source file */
@@ -549,14 +564,15 @@ processFile (char *s)
        }
 
       /* 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);
        }
 
       /* copy the file name into the buffer */
-      strcpy (buffer, s);
+      strncpyz (buffer, s, sizeof(buffer));
 
       /* get rid of the "."-extension */
 
@@ -614,24 +630,6 @@ processFile (char *s)
 
 }
 
-static void
-_processC1Arg (char *s)
-{
-  if (fullSrcFileName)
-    {
-      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)
 {
@@ -709,7 +707,10 @@ tryHandleUnsupportedOpt(char **argv, int *pi)
                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
                         // Found an unsupported opt.
                         char buffer[100];
-                        sprintf(buffer, "%s%c%c", longOpt ? longOpt : "", shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
+                        SNPRINTF(buffer, sizeof(buffer), 
+                                "%s%c%c", 
+                                longOpt ? longOpt : "", 
+                                shortOpt ? '-' : ' ', shortOpt ? shortOpt : ' ');
                         werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
                         return 1;
                     }
@@ -925,6 +926,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);
@@ -955,6 +969,12 @@ parseCmdLine (int argc, char **argv)
              continue;
            }
 
+         if (strcmp (argv[i], OPTION_NO_LABEL_OPT) == 0)
+           {
+             optimize.label4 = 0;
+             continue;
+           }
+
          if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
            {
              optimize.loopInduction = 0;
@@ -1030,7 +1050,8 @@ parseCmdLine (int argc, char **argv)
                 char *p;
 
                 /* copy the file name into the buffer */
-                strcpy (buffer, getStringArg("-o", argv, &i, argc));
+                strncpyz(buffer, getStringArg("-o", argv, &i, argc), 
+                        sizeof(buffer));
                 /* point to last character */
                 p = buffer + strlen (buffer) - 1;
                 if (*p == DIR_SEPARATOR_CHAR)
@@ -1042,6 +1063,7 @@ parseCmdLine (int argc, char **argv)
                 else
                   {
                     fullDstFileName = Safe_strdup (buffer);
+                   fullDstFileNameLen = strlen(fullDstFileName) + 1;
 
                     /* get rid of the "."-extension */
 
@@ -1079,7 +1101,7 @@ parseCmdLine (int argc, char **argv)
               /* assembler options */
              else if (argv[i][2] == 'a')
                 {
-                  parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
+                  setParseWithComma (&asmOptions, getStringArg("-Wa", argv, &i, argc));
                 }
               else
                 {
@@ -1106,6 +1128,7 @@ parseCmdLine (int argc, char **argv)
                addToList (preArgv, "-C");
                break;
              }
+
            case 'd':
            case 'D':
            case 'I':
@@ -1118,13 +1141,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];
                       }
@@ -1135,7 +1158,8 @@ parseCmdLine (int argc, char **argv)
                if (sOpt == 'Y')
                  sOpt = 'I';
 
-               sprintf (buffer, "-%c%s", sOpt, rest);
+                SNPRINTF (buffer, sizeof(buffer),
+                  ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
                addToList (preArgv, buffer);
              }
              break;
@@ -1149,30 +1173,68 @@ 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]);
+          /* no option must be a filename */
+          if (options.c1mode)
+            {
+               werror (W_NO_FILE_ARG_IN_C1, argv[i]);
+            }
+        else
+            {
+               processFile (argv[i]);
+            }
        }
     }
 
+  /* some sanity checks in c1 mode */
+  if (options.c1mode)
+    {
+      int i;
+
+      if (fullSrcFileName)
+       {
+         fclose (srcFile);
+         werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
+       }
+      fullSrcFileName = NULL;
+      for (i = 0; i < nrelFiles; ++i)
+       {
+         werror (W_NO_FILE_ARG_IN_C1, relFiles[i]);
+       }
+      for (i = 0; i < nlibFiles; ++i)
+       {
+         werror (W_NO_FILE_ARG_IN_C1, libFiles[i]);
+       }
+      nrelFiles = nlibFiles = 0;
+      if (options.cc_only || noAssemble || preProcOnly)
+       {
+         werror (W_ILLEGAL_OPT_COMBINATION);
+       }
+      options.cc_only = noAssemble = preProcOnly = 0;
+      if (!dstFileName)
+       {
+         werror (E_NEED_OPT_O_IN_C1);
+         exit (1);
+       }
+    }
   /* 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);
+         size_t bufSize = strlen (dstPath) + strlen (moduleName) + 1;
+
+         dstFileName = Safe_alloc (bufSize);
+          strncpyz (dstFileName, dstPath, bufSize);
+          strncatz (dstFileName, moduleName, bufSize);
         }
       /* use the modulename from the first object file */
       else if (nrelFiles >= 1)
         {
           char *objectName;
+         size_t bufSize;
 
-          strcpy (buffer, relFiles[0]);
+          strncpyz (buffer, relFiles[0], sizeof(buffer));
           /* remove extension (it must be .rel) */
           *strrchr (buffer, '.') = '\0';
           /* remove path */
@@ -1185,9 +1247,10 @@ parseCmdLine (int argc, char **argv)
             {
               objectName = buffer;
             }
-          dstFileName = Safe_alloc (strlen (dstPath) + strlen (objectName) + 1);
-          strcpy (dstFileName, dstPath);
-          strcat (dstFileName, objectName);
+         bufSize = strlen (dstPath) + strlen (objectName) + 1;  
+          dstFileName = Safe_alloc (bufSize);
+          strncpyz (dstFileName, dstPath, bufSize);
+          strncatz (dstFileName, objectName, bufSize);
         }
       /* else no module given: help text is displayed */
     }
@@ -1196,17 +1259,15 @@ parseCmdLine (int argc, char **argv)
   if (!options.xstack_loc)
     options.xstack_loc = options.xdata_loc;
 
-  /* if debug option is set the open the cdbFile */
+  /* if debug option is set then open the cdbFile */
   if (options.debug && fullSrcFileName)
     {
-      sprintf (scratchFileName, "%s.adb", dstFileName); //JCF: Nov 30, 2002
-      if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
-       werror (E_FILE_OPEN_ERR, scratchFileName);
+      SNPRINTF (scratchFileName, sizeof(scratchFileName), 
+               "%s.adb", dstFileName); //JCF: Nov 30, 2002
+      if(debugFile->openFile(scratchFileName))
+       debugFile->writeModule(moduleName);
       else
-       {
-         /* add a module record */
-         fprintf (cdbFile, "M:%s\n", moduleName);
-       }
+       werror (E_FILE_OPEN_ERR, scratchFileName);
     }
   return 0;
 }
@@ -1219,10 +1280,11 @@ linkEdit (char **envp)
 {
   FILE *lnkfile;
   char *segName, *c;
-  int i;
+  int i, system_ret;
 
   /* first we need to create the <filename>.lnk file */
-  sprintf (scratchFileName, "%s.lnk", dstFileName);
+  SNPRINTF (scratchFileName, sizeof(scratchFileName), 
+           "%s.lnk", dstFileName);
   if (!(lnkfile = fopen (scratchFileName, "w")))
     {
       werror (E_FILE_OPEN_ERR, scratchFileName);
@@ -1236,6 +1298,14 @@ linkEdit (char **envp)
   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");
 
@@ -1265,8 +1335,8 @@ linkEdit (char **envp)
   WRITE_SEG_LOC (BIT_NAME, 0);
 
   /* JCF: stack start */
-  if(options.stack_loc) {
-       WRITE_SEG_LOC ("SSEG", options.stack_loc & 0xff);
+  if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
+       WRITE_SEG_LOC ("SSEG", options.stack_loc);
   }
 
   /* add the extra linker options */
@@ -1290,7 +1360,21 @@ linkEdit (char **envp)
          break;
        case MODEL_FLAT24:
          /* c = "flat24"; */
-         c = "ds390";
+           if (TARGET_IS_DS390)
+           {
+               c = "ds390";
+           }
+           else if (TARGET_IS_DS400)
+           {
+               c = "ds400";
+           }
+           else
+           {
+               fprintf(stderr, 
+                       "Add support for your FLAT24 target in %s @ line %d\n",
+                       __FILE__, __LINE__);
+               exit(-1);
+           }
          break;
        case MODEL_PAGE0:
          c = "xa51";
@@ -1306,7 +1390,21 @@ linkEdit (char **envp)
 #if !OPT_DISABLE_DS390
       if (options.model == MODEL_FLAT24)
        {
-         fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
+           if (TARGET_IS_DS390)
+           {
+               fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
+           }
+           else if (TARGET_IS_DS400)
+           {
+               fprintf (lnkfile, "-l %s\n", STD_DS400_LIB);
+           }
+           else
+           {
+               fprintf(stderr, 
+                       "Add support for your FLAT24 target in %s @ line %d\n",
+                       __FILE__, __LINE__);
+               exit(-1);
+           }       
        }
 #endif
 
@@ -1346,57 +1444,94 @@ linkEdit (char **envp)
   /* -o option overrides default name? */
   if (fullDstFileName)
     {
-      strcpy (scratchFileName, fullDstFileName);
+      strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
     }
   else
     {
       /* the linked file gets the name of the first modul */
       if (fullSrcFileName)
         {
-          strcpy (scratchFileName, dstFileName);
+          strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
         }
       else
         {
-          strcpy (scratchFileName, relFiles[0]);
+          strncpyz (scratchFileName, relFiles[0], sizeof(scratchFileName));
           /* strip ".rel" extension */
           *strrchr (scratchFileName, '.') = '\0';
         }
-      strcat (scratchFileName, options.out_fmt ? ".S19" : ".ihx");
+      strncatz (scratchFileName, 
+               options.out_fmt ? ".S19" : ".ihx",
+               sizeof(scratchFileName));
     }
 
   if (port->linker.cmd)
     {
       char buffer2[PATH_MAX];
       buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, NULL, NULL);
-      buildCmdLine2 (buffer, buffer2);
+      buildCmdLine2 (buffer, buffer2, sizeof(buffer));
     }
   else
     {
-      buildCmdLine2 (buffer, port->linker.mcmd);
+      buildCmdLine2 (buffer, port->linker.mcmd, sizeof(buffer));
     }
 
-  if (my_system (buffer))
-    {
-      exit (1);
-    }
+  system_ret = my_system (buffer);
   /* TODO: most linker don't have a -o parameter */
   /* -o option overrides default name? */
   if (fullDstFileName)
     {
+      char *p, *q;
       /* the linked file gets the name of the first modul */
       if (fullSrcFileName)
-    {
-          strcpy (scratchFileName, dstFileName);
+        {
+          strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
+          p = strlen (scratchFileName) + scratchFileName;
         }
       else
         {
-          strcpy (scratchFileName, relFiles[0]);
-          /* strip ".rel" extension */
-          *strrchr (scratchFileName, '.') = '\0';
+          strncpyz (scratchFileName, relFiles[0], sizeof(scratchFileName));
+          /* strip "rel" extension */
+          p = strrchr (scratchFileName, '.');
+         if (p)
+           {
+               p++;
+               *p = 0;
+           }
+           
         }
-      strcat (scratchFileName, options.out_fmt ? ".S19" : ".ihx");
+      strncatz (scratchFileName,
+               options.out_fmt ? "S19" : "ihx",
+               sizeof(scratchFileName));
+      rename (scratchFileName, fullDstFileName);
+
+      q = strrchr (fullDstFileName, '.');
+      if (q)
+        {
+          /* point after the '.' of the extension */
+          q++;
+        }
+      else
+        {
+          /* no extension: append new extensions */
+         /* Don't we want to append a period here ? */
+          q = strlen (fullDstFileName) + fullDstFileName;
+        }
+               
+      *p = 0;  
+      strncatz (scratchFileName, "map", sizeof(scratchFileName));
+      *q = 0;
+      strncatz(fullDstFileName, "map", fullDstFileNameLen);
+      rename (scratchFileName, fullDstFileName);
+      *p = 0;  
+      strncatz (scratchFileName, "mem", sizeof(scratchFileName));
+      *q = 0;
+      strncatz(fullDstFileName, "mem", fullDstFileNameLen);    
       rename (scratchFileName, fullDstFileName);
     }
+  if (system_ret)
+    {
+      exit (1);
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1409,11 +1544,12 @@ assemble (char **envp)
 
     /* -o option overrides default name? */
     if (options.cc_only && fullDstFileName) {
-        strcpy (scratchFileName, fullDstFileName);
+        strncpyz (scratchFileName, fullDstFileName, sizeof(scratchFileName));
     } else {
         /* the assembled file gets the name of the first modul */
-        strcpy (scratchFileName, dstFileName);
-        strcat (scratchFileName, port->linker.rel_ext);
+        strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
+        strncatz (scratchFileName, port->linker.rel_ext, 
+                 sizeof(scratchFileName));
     }
 
     if (port->assembler.do_assemble) {
@@ -1424,7 +1560,7 @@ assemble (char **envp)
                      options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
                      asmOptions);
     } else {
-       buildCmdLine2 (buffer, port->assembler.mcmd);
+       buildCmdLine2 (buffer, port->assembler.mcmd, sizeof(buffer));
     }
 
     if (my_system (buffer)) {
@@ -1436,8 +1572,10 @@ assemble (char **envp)
     /* 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);
+        strncpyz (scratchFileName, dstFileName, sizeof(scratchFileName));
+        strncatz (scratchFileName, 
+                 port->linker.rel_ext,
+                 sizeof(scratchFileName));
         rename (scratchFileName, fullDstFileName);
     }
 }
@@ -1448,9 +1586,11 @@ assemble (char **envp)
 static int
 preProcess (char **envp)
 {
-  preOutName = NULL;
-
-  if (!options.c1mode)
+  if (options.c1mode)
+    {
+      yyin = stdin;
+    }
+  else
     {
       /* if using external stack define the macro */
       if (options.useXstack)
@@ -1500,186 +1640,157 @@ preProcess (char **envp)
 
       /* standard include path */
       if (!options.nostdinc) {
-       addToList (preArgv, "-I{includedir}");
+       addToList (preArgv, "-I\"{includedir}\"");
       }
 
       setMainValue ("cppextraopts", join(preArgv));
-      
-      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 (preProcOnly && fullDstFileName)
+       {
+         /* -E and -o given */
+         setMainValue ("cppoutfilename", fullDstFileName);
+       }
+      else
+       {
+         /* Piping: set cppoutfilename to NULL, to avoid empty quotes */
+         setMainValue ("cppoutfilename", NULL);
+       }
 
       if (options.verbose)
        printf ("sdcc: Calling preprocessor...\n");
 
-      buildCmdLine2 (buffer, _preCmd);
+      buildCmdLine2 (buffer, _preCmd, sizeof(buffer));
 
-      if (my_system (buffer))
-       {
-          // @FIX: Dario Vecchio 03-05-2001
-          if (preOutName)
-            {
-              unlink (preOutName);
-              Safe_free (preOutName);
-            }
-          // EndFix
+      if (preProcOnly) {
+        if (my_system (buffer)) {
          exit (1);
        }
 
-      if (preProcOnly)
-      {
-       exit (0);
+        exit (0);
       }
-    }
-  else
-    {
-      preOutName = fullSrcFileName;
-    }
 
-  yyin = fopen (preOutName, "r");
-  if (yyin == NULL)
-    {
-      perror ("Preproc file not found\n");
-      exit (1);
+      yyin = my_popen (buffer);
+      if (yyin == NULL) {
+          perror ("Preproc file not found");
+          exit (1);
+      }
+      addSetHead (&pipeSet, yyin);
     }
 
   return 0;
 }
 
-static bool
-_setPaths (const char *pprefix)
+/* Set bin paths */
+static void
+setBinPaths(const char *argv0)
 {
-  /* Logic:
-      Given the prefix and how the directories were layed out at
-      configure time, see if the library and include directories are
-      where expected.  If so, set.
-  */
-  getPathDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
-  strcpy (scratchFileName, pprefix);
-  strcat (scratchFileName, buffer);
-
-  if (pathExists (scratchFileName))
-    {
-      setMainValue ("includedir", scratchFileName);
-    }
-  else
-    {
-      return FALSE;
-    }
+  char *p;
+  char buf[PATH_MAX];
+
+  /*
+   * Search logic:
+   *
+   * 1. - $SDCCDIR/PREFIX2BIN_DIR
+   * 2. - path(argv[0])
+   * 3. - $PATH
+   */
 
-  getPathDifference (buffer, PREFIX, SDCC_LIB_DIR);
-  strcpy (scratchFileName, pprefix);
-  strcat (scratchFileName, buffer);
+  /* do it in reverse mode, so that addSetHead() can be used
+     instaed of slower addSet() */
 
-  if (pathExists (scratchFileName))
-    {
-      setMainValue ("libdir", scratchFileName);
-    }
-  else
-    {
-      return FALSE;
-    }
+  if ((p = getBinPath(argv0)) != NULL)
+    addSetHead(&binPathSet, Safe_strdup(p));
 
-  return TRUE;
+  if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
+    SNPRINTF(buf, sizeof buf, "%s" PREFIX2BIN_DIR, p);
+    addSetHead(&binPathSet, Safe_strdup(buf));
+  }
 }
 
+/* Set system include path */
 static void
-_discoverPaths (const char *argv0)
+setIncludePath(const char *datadir)
 {
-  /* Logic:
-      1.  Try the SDCCDIR environment variable.
-      2.  If (1) fails, and if the argv[0] includes a path, attempt to find the include
-      and library paths with respect to that.  Note that under win32
-      argv[0] is always the full path to the program.
-      3.  If (1) and (2) fail, fall back to the compile time defaults.
-
-      Detecting assumes the same layout as when configured.  If the
-      directories have been further moved about then discovery will
-      fail.
-  */
-
-  /* Some input cases:
-        "c:\fish\sdcc\bin\sdcc"
-        "../bin/sdcc"
-        "/home/fish/bin/sdcc"
-
-      Note that ./sdcc is explicitly not supported as there isn't
-      enough information.
-  */
-  /* bindir is handled differently to the lib and include directories.
-     It's rather unfortunate, but required due to the different
-     install and development layouts.  Logic is different as well.
-     Sigh.
+  char *p;
+  char buf[PATH_MAX];
+
+  /*
+   * Search logic:
+   *
+   * 1. - $SDCC_INCLUDE
+   * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
+   * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
+   * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
    */
-  if (strchr (argv0, DIR_SEPARATOR_CHAR))
-    {
-      strcpy (scratchFileName, argv0);
-      *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
-      setMainValue ("bindir", scratchFileName);
-      ExePathList[0] = Safe_strdup (scratchFileName);
-    }
-  else if (getenv (SDCCDIR_NAME) != NULL)
-    {
-      getPathDifference (buffer, PREFIX, BINDIR);
-      strcpy (scratchFileName, getenv (SDCCDIR_NAME));
-      strcat (scratchFileName, buffer);
-      setMainValue ("bindir", scratchFileName);
-      ExePathList[0] = Safe_strdup (scratchFileName);
-    }
-  else
-    {
-      setMainValue ("bindir", BINDIR);
-      ExePathList[0] = BINDIR;
-    }
 
-  do 
-    {
-      /* Case 1 */
-      if (getenv (SDCCDIR_NAME) != NULL)
-        {
-          if (_setPaths (getenv (SDCCDIR_NAME)))
-            {
-              /* Successfully set. */
-              break;
-            }
-          else
-            {
-              /* Include and lib weren't where expected. */
-            }
-        }
-      /* Case 2 */
-      if (strchr (argv0, DIR_SEPARATOR_CHAR))
-        {
-          char *pbase = getPrefixFromBinPath (argv0);
+  if ((p = getenv(SDCC_INCLUDE_NAME)) == NULL) {
+    SNPRINTF(buf, sizeof buf, "%s" INCLUDE_DIR_SUFFIX, datadir);
+    p = buf;
+  }
 
-          if (pbase == NULL)
-            {
-              /* A bad path.  Skip. */
-            }
-          else
-            {
-              if (_setPaths (pbase))
-                {
-                  /* Successfully set. */
-                  break;
-                }
-              else
-                {
-                  /* Include and lib weren't where expected. */
-                }
-            }
-        }
-      /* Case 3 */
-      setMainValue ("includedir", SDCC_INCLUDE_DIR);
-      setMainValue ("libdir", SDCC_LIB_DIR);
-    } while (0);
+  setMainValue ("includedir", p);
+}
+
+/* Set system lib path */
+static void
+setLibPath(const char *datadir)
+{
+  char *p;
+  char buf[PATH_MAX];
+
+  /*
+   * Search logic:
+   *
+   * 1. - $SDCC_LIB
+   * 2. - $SDCC_HOME/PREFIX2DATA_DIR/LIB_DIR_SUFFIX/<model>
+   * 3. - path(argv[0])/BIN2DATA_DIR/LIB_DIR_SUFFIX/<model>
+   * 4. - DATADIR/LIB_DIR_SUFFIX/<model> (only on *nix)
+   */
+
+  if ((p = getenv(SDCC_LIB_NAME)) == NULL) {
+    SNPRINTF(buf, sizeof buf, "%s" LIB_DIR_SUFFIX, datadir);
+    p = buf;
+  }
+
+  setMainValue ("libdir", p);
+}
+
+/* Set data path */
+static void
+setDataPaths(const char *argv0)
+{
+  char *p;
+  char buf[PATH_MAX];
+
+  /*
+   * Search logic:
+   *
+   * 1. - $SDCC_HOME/PREFIX2DATA_DIR
+   * 2. - path(argv[0])/BIN2DATA_DIR
+   * 3. - DATADIR (only on *nix)
+   */
+
+  if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
+    SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
+    p = buf;
+  }
+  else {
+    if ((p = getBinPath(argv0)) == NULL)
+      p = ".";
+
+    SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
+    p = buf;
+
+#ifndef _WIN32  /* *nix paltform */
+    if (!pathExists(p))
+      p = DATADIR; /* last resort */
+#endif
+  }
+
+  setIncludePath(p);
+  setLibPath(p);
+
+  setMainValue ("datadir", p);
 }
 
 static void
@@ -1692,7 +1803,7 @@ initValues (void)
 
   setMainValue ("dstfilename", dstFileName);
   setMainValue ("fullsrcfilename", fullSrcFileName ? fullSrcFileName : "fullsrcfilename");
-  
+
   if (options.cc_only && fullDstFileName)
     /* compile + assemble and -o given: -o specifies name of object file */
     {
@@ -1714,6 +1825,33 @@ initValues (void)
 
 }
 
+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, "Caught signal %d: %s\n", signal, sig_string);
+  exit (1);
+}
+
 /*
  * main routine
  * initialises and calls the parser
@@ -1735,7 +1873,17 @@ main (int argc, char **argv, char **envp)
   /* install atexit handler */
   atexit(rm_tmpfiles);
 
-  /* Before parsing the command line options, do a 
+  /* install signal handler;
+     it's only purpuse is to call exit() to remove temp files */
+  if (!getenv("SDCC_LEAVE_SIGNALS"))
+    {
+      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).
@@ -1770,15 +1918,15 @@ main (int argc, char **argv, char **envp)
   parseCmdLine (argc, argv);
 
   /* if no input then printUsage & exit */
-  if ((!options.c1mode && !fullSrcFileName && !nrelFiles) ||
-      (options.c1mode && !fullSrcFileName && !options.out_name))
+  if (!options.c1mode && !fullSrcFileName && !nrelFiles)
     {
       printUsage ();
       exit (0);
     }
 
   initValues ();
-  _discoverPaths (argv[0]);
+  setBinPaths(argv[0]);
+  setDataPaths(argv[0]);
 
   /* initMem() is expensive, but
      initMem() must called before port->finaliseOptions ().
@@ -1787,7 +1935,7 @@ main (int argc, char **argv, char **envp)
   initMem ();
   port->finaliseOptions ();
 
-  if (fullSrcFileName)
+  if (fullSrcFileName || options.c1mode)
     {
       preProcess (envp);
 
@@ -1802,16 +1950,11 @@ main (int argc, char **argv, char **envp)
 
       yyparse ();
 
+      pclose(yyin);
+      deleteSetItem(&pipeSet, yyin);
+
       if (fatalError) {
-        // @FIX: Dario Vecchio 03-05-2001
-        if (preOutName) {
-          if (yyin && yyin != stdin)
-            fclose (yyin);
-          unlink (preOutName);
-          Safe_free (preOutName);
-        }
-        // EndFix
-        return 1;
+        exit (1);
       }
 
       if (TARGET_IS_PIC) {
@@ -1835,20 +1978,10 @@ main (int argc, char **argv, char **envp)
           assemble (envp);
         }
     }
-
   closeDumpFiles();
 
-  if (cdbFile)
-    fclose (cdbFile);
-
-  if (yyin && yyin != stdin)
-    fclose (yyin);
-
-  if (preOutName && !options.c1mode)
-    {
-      unlink (preOutName);
-      Safe_free (preOutName);
-    }
+  if (options.debug && debugFile)
+    debugFile->closeFile();
 
   if (!options.cc_only &&
       !fatalError &&