* src/mcs51/gen.c (genCpl): quick fix for bug #974835
[fw/sdcc] / src / SDCCmain.c
index f2add64e18937cc478e7d6063ec36bdf767b14cb..b37a9bf08403fabe6275e1a261f70abb7d05af9e 100644 (file)
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
 #include <signal.h>
 #include "common.h"
 #include <ctype.h>
@@ -41,8 +47,8 @@
 #include <unistd.h>
 #endif
 
-//REMOVE ME!!!
-extern int yyparse ();
+/* REMOVE ME!!! */
+extern int yyparse (void);
 
 FILE *srcFile;                 /* source file          */
 char *fullSrcFileName;         /* full name for the source file; */
@@ -52,27 +58,25 @@ char *fullDstFileName;              /* full name for the output file; */
 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  */
+char *moduleNameBase;          /* module name base is source file without path and extension */
+                                /* can be NULL while linking without compiling */
+char *moduleName;              /* module name is same as module name base, but with all */
+                               /* non-alphanumeric characters replaced with underscore */
 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;
 int preProcOnly = 0;
 int noAssemble = 0;
-set *asmOptions = NULL;         /* set of assembler options */
-char *linkOptions[128];
-char *libFiles[128];
-int nlibFiles = 0;
-char *libPaths[128];
-int nlibPaths = 0;
-char *relFiles[128];
-int nrelFiles = 0;
+set *preArgvSet = NULL;         /* pre-processor arguments  */
+set *asmOptionsSet = NULL;      /* set of assembler options */
+set *linkOptionsSet = NULL;     /* set of linker options */
+set *libFilesSet = NULL;
+set *libPathsSet = NULL;
+set *relFilesSet = NULL;
+set *dataDirsSet = NULL;        /* list of data search directories */
+set *includeDirsSet = NULL;     /* list of include search directories */
+set *libDirsSet = NULL;         /* list of lib search directories */
 
 /* uncomment JAMIN_DS390 to always override and use ds390 port
   for mcs51 work.  This is temporary, for compatibility testing. */
@@ -81,7 +85,7 @@ int nrelFiles = 0;
 int ds390_jammed = 0;
 #endif
 
-// Globally accessible scratch buffer for file names.
+/* Globally accessible scratch buffer for file names. */
 char scratchFileName[PATH_MAX];
 char buffer[PATH_MAX * 2];
 
@@ -120,6 +124,11 @@ char buffer[PATH_MAX * 2];
 #define OPTION_NO_CCODE_IN_ASM "--no-c-code-in-asm"
 #define OPTION_ICODE_IN_ASM    "--i-code-in-asm"
 #define OPTION_PRINT_SEARCH_DIRS "--print-search-dirs"
+#define OPTION_MSVC_ERROR_STYLE "--vc"
+#define OPTION_USE_STDOUT       "--use-stdout"
+#define OPTION_STACK_SIZE      "--stack-size"
+#define OPTION_PACK_IRAM       "--pack-iram"
+#define OPTION_NO_PEEP_COMMENTS        "--no-peep-comments"
 
 static const OPTION
 optionsTable[] = {
@@ -140,10 +149,14 @@ optionsTable[] = {
     { 0,    OPTION_LARGE_MODEL,     NULL, "external data space is used" },
     { 0,    OPTION_MEDIUM_MODEL,    NULL, "not supported" },
     { 0,    OPTION_SMALL_MODEL,     NULL, "internal data space is used (default)" },
+#if !OPT_DISABLE_DS390
     { 0,    OPTION_FLAT24_MODEL,    NULL, "use the flat24 model for the ds390 (default)" },
+#endif
     { 0,    "--stack-auto",         &options.stackAuto, "Stack automatic variables" },
+#if !OPT_DISABLE_DS390
     { 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)" },
+#endif
     { 0,    "--xstack",             &options.useXstack, "Use external stack" },
     { 0,    OPTION_NO_GCSE,         NULL, "Disable the GCSE optimisation" },
     { 0,    OPTION_NO_LABEL_OPT,    NULL, "Disable label optimisation" },
@@ -174,7 +187,7 @@ optionsTable[] = {
     { 0,    OPTION_PEEP_FILE,       NULL, "<file> use this extra peep-hole file" },
     { 0,    OPTION_LIB_PATH,        NULL, "<path> use this path to search for libraries" },
     { 0,    "--int-long-reent",     &options.intlong_rent, "Use reenterant calls on the int and long support functions" },
-    { 0,    "--float-reent",        &options.float_rent, "Use reenterant calls on the floar support functions" },
+    { 0,    "--float-reent",        &options.float_rent, "Use reenterant calls on the float support functions" },
     { 0,    OPTION_OUT_FMT_IHX,     NULL, NULL },
     { 0,    "--out-fmt-s19",        &options.out_fmt, NULL },
     { 0,    "--cyclomatic",         &options.cyclomatic, NULL },
@@ -198,15 +211,31 @@ optionsTable[] = {
     { 0,    "--profile",            &options.profile, "On supported ports, generate extra profiling information" },
     { 0,    "--fommit-frame-pointer", &options.ommitFramePtr, "Leave out the frame pointer." },
     { 0,    "--all-callee-saves",   &options.all_callee_saves, "callee will always save registers used" },
+#if !OPT_DISABLE_DS390
     { 0,    "--use-accelerator",    &options.useAccelerator,"generate code for  DS390 Arithmetic Accelerator"},
+#endif
     { 0,    "--stack-probe",               &options.stack_probe,"insert call to function __stack_probe at each function prologue"},
+#if !OPT_DISABLE_TININative
     { 0,    "--tini-libid",        NULL,"<nnnn> LibraryID used in -mTININative"},
+#endif
+#if !OPT_DISABLE_DS390
     { 0,    "--protect-sp-update",  &options.protect_sp_update,"DS390 - will disable interrupts during ESP:SP updates"},
+#endif
+#if !OPT_DISABLE_DS390 || !OPT_DISABLE_MCS51
     { 0,    "--parms-in-bank1",            &options.parms_in_bank1,"MCS51/DS390 - use Bank1 for parameter passing"},
+    { 0,    OPTION_STACK_SIZE,     NULL,"MCS51/DS390 - Tells the linker to allocate this space for stack"},
+    { 0,    OPTION_PACK_IRAM,      &options.pack_iram,"MCS51/DS390 - Tells the linker to pack variables in internal ram"},
+#endif
     { 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"},
+    { 0,    OPTION_NO_PEEP_COMMENTS, &options.noPeepComments, "don't include peephole optimizer comments"},
     { 0,    OPTION_PRINT_SEARCH_DIRS, &options.printSearchDirs, "display the directories in the compiler's search path"},
+    { 0,    OPTION_MSVC_ERROR_STYLE, &options.vc_err_style, "messages are compatible with Micro$oft visual studio"},
+    { 0,    OPTION_USE_STDOUT, &options.use_stdout, "send errors to stdout instead of stderr"},
+#if !OPT_DISABLE_Z80 || !OPT_DISABLE_GBZ80
+    { 0,    "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"},
+#endif
     /* End of options */
     { 0,    NULL }
 };
@@ -265,6 +294,9 @@ static PORT *_ports[] =
 #if !OPT_DISABLE_DS390
   &ds390_port,
 #endif
+#if !OPT_DISABLE_PIC16
+  &pic16_port,
+#endif
 #if !OPT_DISABLE_PIC
   &pic_port,
 #endif
@@ -276,15 +308,14 @@ static PORT *_ports[] =
 #endif
 #if !OPT_DISABLE_DS400
   &ds400_port, 
-#endif 
+#endif
+#if !OPT_DISABLE_HC08
+  &hc08_port,
+#endif
 };
 
 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
 
-#if !OPT_DISABLE_PIC
-extern void picglue ();
-#endif
-
 /** Sets the port to the one given by the command line option.
     @param    The name minus the option (eg 'mcs51')
     @return     0 on success.
@@ -347,8 +378,9 @@ _findPort (int argc, char **argv)
        }
       argv++;
     }
+
   /* Use the first in the list */
-  port = _ports[0];
+       port = _ports[0];
 }
 
 /* search through the command line options for the processor */
@@ -372,7 +404,7 @@ _findProcessor (int argc, char **argv)
 /* printVersionInfo - prints the version info        */
 /*-----------------------------------------------------------------*/
 void
-printVersionInfo ()
+printVersionInfo (void)
 {
   int i;
 
@@ -380,7 +412,7 @@ printVersionInfo ()
           "SDCC : ");
   for (i = 0; i < NUM_PORTS; i++)
     fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
-
+  
   fprintf (stderr, " " SDCC_VERSION_STR
 #ifdef SDCC_SUB_VERSION_STR
           "/" SDCC_SUB_VERSION_STR
@@ -421,7 +453,7 @@ printOptions(const OPTION *optionsTable)
 /* printUsage - prints command line syntax         */
 /*-----------------------------------------------------------------*/
 void
-printUsage ()
+printUsage (void)
 {
     int i;
     printVersionInfo();
@@ -444,33 +476,6 @@ printUsage ()
     exit (0);
 }
 
-/*-----------------------------------------------------------------*/
-/* parseWithComma - separates string with comma                    */
-/*-----------------------------------------------------------------*/
-void
-parseWithComma (char **dest, char *src)
-{
-  int i = 0;
-
-  strtok (src, "\r\n \t");
-  /* skip the initial white spaces */
-  while (isspace (*src))
-    src++;
-  dest[i++] = src;
-  while (*src)
-    {
-      if (*src == ',')
-       {
-         *src = '\0';
-         src++;
-         if (*src)
-           dest[i++] = src;
-         continue;
-       }
-      src++;
-    }
-}
-
 /*-----------------------------------------------------------------*/
 /* setParseWithComma - separates string with comma to a set        */
 /*-----------------------------------------------------------------*/
@@ -478,30 +483,27 @@ void
 setParseWithComma (set **dest, char *src)
 {
   char *p;
+  int length;
 
   /* skip the initial white spaces */
-  while (isspace (*src))
+  while (isspace(*src))
     src++;
-
-  if ((p = strtok(src, ",")) != NULL) {
-    do
-    {
-      addSet(dest, p);
-    } while ((p = strtok(NULL, ",")) != NULL);
-  }
+  
+  /* skip the trailing white spaces */
+  length = strlen(src);
+  while (length && isspace(src[length-1]))
+    src[--length] = '\0';
+
+  for (p = strtok(src, ","); p != NULL; p = strtok(NULL, ","))
+    addSet(dest, Safe_strdup(p));
 }
 
 /*-----------------------------------------------------------------*/
 /* setDefaultOptions - sets the default options                    */
 /*-----------------------------------------------------------------*/
 static void
-setDefaultOptions ()
+setDefaultOptions (void)
 {
-  int i;
-
-  for (i = 0; i < 128; i++)
-    preArgv[i] = linkOptions[i] = relFiles[i] = libFiles[i] = libPaths[i] = NULL;
-
   /* first the options part */
   options.stack_loc = 0;       /* stack pointer initialised to 0 */
   options.xstack_loc = 0;      /* xternal stack starts at 0 */
@@ -606,7 +608,12 @@ processFile (char *s)
           fext--;
         }
 #endif
+      moduleNameBase = Safe_strdup ( fext );
       moduleName = Safe_strdup ( fext );
+      
+      for (fext = moduleName; *fext; fext++)
+        if (!isalnum (*fext))
+         *fext = '_';
       return;
     }
 
@@ -616,14 +623,14 @@ processFile (char *s)
       strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
       strcmp (fext, port->linker.rel_ext) == 0)
     {
-      relFiles[nrelFiles++] = s;
+      addSet(&relFilesSet, Safe_strdup(s));
       return;
     }
 
   /* if .lib or .LIB */
   if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
     {
-      libFiles[nlibFiles++] = s;
+      addSet(&libFilesSet, Safe_strdup(s));
       return;
     }
 
@@ -643,7 +650,7 @@ _setModel (int model, const char *sz)
 /** Gets the string argument to this option.  If the option is '--opt'
     then for input of '--optxyz' or '--opt xyz' returns xyz.
 */
-static char *
+char *
 getStringArg(const char *szStart, char **argv, int *pi, int argc)
 {
   if (argv[*pi][strlen(szStart)])
@@ -669,7 +676,7 @@ getStringArg(const char *szStart, char **argv, int *pi, int argc)
 /** Gets the integer argument to this option using the same rules as
     getStringArg.
 */
-static int
+int
 getIntArg(const char *szStart, char **argv, int *pi, int argc)
 {
     return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
@@ -695,7 +702,7 @@ tryHandleUnsupportedOpt(char **argv, int *pi)
 
             if (argv[*pi][1] == '-') 
                 {
-                    // Long option.
+                    /* Long option. */
                     longOpt = argv[*pi];
                 }
             else 
@@ -706,7 +713,7 @@ tryHandleUnsupportedOpt(char **argv, int *pi)
                 {
                     if (unsupportedOptTable[i].shortOpt == shortOpt || 
                         (longOpt && unsupportedOptTable[i].longOpt && !strcmp(unsupportedOptTable[i].longOpt, longOpt))) {
-                        // Found an unsupported opt.
+                        /* Found an unsupported opt. */
                         char buffer[100];
                         SNPRINTF(buffer, sizeof(buffer), 
                                 "%s%c%c", 
@@ -716,12 +723,12 @@ tryHandleUnsupportedOpt(char **argv, int *pi)
                         return 1;
                     }
                 }
-            // Didn't find in the table
+            /* Didn't find in the table */
             return 0;
         }
     else 
         {
-            // Not an option, so can't be unsupported :)
+            /* Not an option, so can't be unsupported :) */
             return 0;
     }
 }
@@ -737,7 +744,7 @@ scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt,
           strcmp(optionsTable[i].longOpt, longOpt) == 0))
        {
 
-         // If it is a flag then we can handle it here
+         /* If it is a flag then we can handle it here */
          if (optionsTable[i].pparameter != NULL) 
            {
              if (optionsTable[i].shortOpt == shortOpt)
@@ -749,12 +756,12 @@ scanOptionsTable(const OPTION *optionsTable, char shortOpt, const char *longOpt,
              return 1;
            }
          else {
-           // Not a flag.  Handled manually later.
+           /* Not a flag.  Handled manually later. */
            return 0;
          }
        }
     }
-  // Didn't find in the table
+  /* Didn't find in the table */
   return 0;
 }
 
@@ -768,7 +775,7 @@ tryHandleSimpleOpt(char **argv, int *pi)
 
             if (argv[*pi][1] == '-') 
                 {
-                    // Long option.
+                    /* Long option. */
                     longOpt = argv[*pi];
                 }
             else 
@@ -792,7 +799,7 @@ tryHandleSimpleOpt(char **argv, int *pi)
         }
     else 
         {
-            // Not an option, so can't be handled.
+            /* Not an option, so can't be handled. */
             return 0;
         }
 }
@@ -886,7 +893,7 @@ parseCmdLine (int argc, char **argv)
 
          if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
             {
-               libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
+                addSet(&libPathsSet, Safe_strdup(getStringArg(OPTION_LIB_PATH, argv, &i, argc)));
                 continue;
            }
 
@@ -899,7 +906,7 @@ parseCmdLine (int argc, char **argv)
 
          if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
            {
-                parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
+                setParseWithComma(&options.calleeSavesSet, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
                 continue;
            }
 
@@ -914,6 +921,12 @@ parseCmdLine (int argc, char **argv)
                 options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
                 continue;
            }
+         
+      if (strcmp (argv[i], OPTION_STACK_SIZE) == 0)
+           {
+                options.stack_size = getIntArg(OPTION_STACK_SIZE, argv, &i, argc);
+                continue;
+           }
 
          if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
            {
@@ -1004,6 +1017,7 @@ parseCmdLine (int argc, char **argv)
          if (!port->parseOption (&argc, argv, &i))
            {
              werror (W_UNKNOWN_OPTION, argv[i]);
+             continue;
            }
          else
            {
@@ -1039,11 +1053,11 @@ parseCmdLine (int argc, char **argv)
              break;
 
            case 'L':
-                libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
+                addSet(&libPathsSet, Safe_strdup(getStringArg("-L", argv, &i, argc)));
                 break;
 
             case 'l':
-                libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
+                addSet(&libFilesSet, Safe_strdup(getStringArg("-l", argv, &i, argc)));
                 break;
             
             case 'o':
@@ -1091,17 +1105,17 @@ parseCmdLine (int argc, char **argv)
               /* pre-processer options */
               if (argv[i][2] == 'p')
                 {
-                  parseWithComma ((char **)preArgv, getStringArg("-Wp", argv, &i, argc));
+                  setParseWithComma(&preArgvSet, getStringArg("-Wp", argv, &i, argc));
                 }
              /* linker options */
              else if (argv[i][2] == 'l')
                {
-                  parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
+                  setParseWithComma(&linkOptionsSet, getStringArg("-Wl", argv, &i, argc));
                }
               /* assembler options */
              else if (argv[i][2] == 'a')
                 {
-                  setParseWithComma (&asmOptions, getStringArg("-Wa", argv, &i, argc));
+                  setParseWithComma(&asmOptionsSet, getStringArg("-Wa", argv, &i, argc));
                 }
               else
                 {
@@ -1120,12 +1134,15 @@ parseCmdLine (int argc, char **argv)
            case 'M':
              {
                preProcOnly = 1;
-               addToList (preArgv, "-M");
-               break;
+                if (argv[i][2] == 'M')
+                 addSet(&preArgvSet, Safe_strdup("-MM"));
+                else
+                 addSet(&preArgvSet, Safe_strdup("-M"));
+               break;
              }
            case 'C':
              {
-               addToList (preArgv, "-C");
+               addSet(&preArgvSet, Safe_strdup("-C"));
                break;
              }
 
@@ -1160,7 +1177,7 @@ parseCmdLine (int argc, char **argv)
 
                 SNPRINTF (buffer, sizeof(buffer),
                   ((sOpt == 'I') ? "-%c\"%s\"": "-%c%s"), sOpt, rest);
-               addToList (preArgv, buffer);
+               addSet(&preArgvSet, Safe_strdup(buffer));
              }
              break;
 
@@ -1188,7 +1205,7 @@ parseCmdLine (int argc, char **argv)
   /* some sanity checks in c1 mode */
   if (options.c1mode)
     {
-      int i;
+      const char *s;
 
       if (fullSrcFileName)
        {
@@ -1196,16 +1213,18 @@ parseCmdLine (int argc, char **argv)
          werror (W_NO_FILE_ARG_IN_C1, fullSrcFileName);
        }
       fullSrcFileName = NULL;
-      for (i = 0; i < nrelFiles; ++i)
+      for (s = setFirstItem(relFilesSet); s != NULL; s = setNextItem(relFilesSet))
        {
-         werror (W_NO_FILE_ARG_IN_C1, relFiles[i]);
+         werror (W_NO_FILE_ARG_IN_C1, s);
        }
-      for (i = 0; i < nlibFiles; ++i)
+      for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
        {
-         werror (W_NO_FILE_ARG_IN_C1, libFiles[i]);
+         werror (W_NO_FILE_ARG_IN_C1, s);
        }
-      nrelFiles = nlibFiles = 0;
-      if (options.cc_only || noAssemble || preProcOnly)
+      deleteSet(&relFilesSet);
+      deleteSet(&libFilesSet);
+
+        if (options.cc_only || noAssemble || preProcOnly)
        {
          werror (W_ILLEGAL_OPT_COMBINATION);
        }
@@ -1219,22 +1238,24 @@ parseCmdLine (int argc, char **argv)
   /* if no dstFileName given with -o, we've to find one: */
   if (!dstFileName)
     {
+      const char *s;
+
       /* use the modulename from the C-source */
       if (fullSrcFileName)
         {
-         size_t bufSize = strlen (dstPath) + strlen (moduleName) + 1;
+         size_t bufSize = strlen (dstPath) + strlen (moduleNameBase) + 1;
 
          dstFileName = Safe_alloc (bufSize);
           strncpyz (dstFileName, dstPath, bufSize);
-          strncatz (dstFileName, moduleName, bufSize);
+          strncatz (dstFileName, moduleNameBase, bufSize);
         }
       /* use the modulename from the first object file */
-      else if (nrelFiles >= 1)
+      else if ((s = peekSet(relFilesSet)) != NULL)
         {
           char *objectName;
          size_t bufSize;
 
-          strncpyz (buffer, relFiles[0], sizeof(buffer));
+          strncpyz (buffer, s, sizeof(buffer));
           /* remove extension (it must be .rel) */
           *strrchr (buffer, '.') = '\0';
           /* remove path */
@@ -1263,12 +1284,15 @@ parseCmdLine (int argc, char **argv)
   if (options.debug && fullSrcFileName)
     {
       SNPRINTF (scratchFileName, sizeof(scratchFileName),
-               "%s.adb", dstFileName); //JCF: Nov 30, 2002
+               "%s.adb", dstFileName); /*JCF: Nov 30, 2002*/
       if(debugFile->openFile(scratchFileName))
        debugFile->writeModule(moduleName);
       else
        werror (E_FILE_OPEN_ERR, scratchFileName);
     }
+  MSVC_style(options.vc_err_style);
+  if(options.use_stdout) dup2(STDOUT_FILENO, STDERR_FILENO);
+
   return 0;
 }
 
@@ -1280,161 +1304,286 @@ linkEdit (char **envp)
 {
   FILE *lnkfile;
   char *segName, *c;
-  int i, system_ret;
+  int system_ret;
+  const char *s;
 
-  /* first we need to create the <filename>.lnk file */
-  SNPRINTF (scratchFileName, sizeof(scratchFileName),
-           "%s.lnk", dstFileName);
-  if (!(lnkfile = fopen (scratchFileName, "w")))
+
+  if(port->linker.needLinkerScript)
     {
-      werror (E_FILE_OPEN_ERR, scratchFileName);
-      exit (1);
-    }
+      char out_fmt;
+      
+      switch (options.out_fmt)
+        {
+       case 0:
+         out_fmt = 'i';        /* Intel hex */
+         break;
+       case 1:
+         out_fmt = 's';        /* Motorola S19 */
+         break;
+       case 2:
+         out_fmt = 't';        /* Elf */
+         break;
+       default:
+         out_fmt = 'i';
+       }
+      
+      /* first we need to create the <filename>.lnk file */
+      SNPRINTF (scratchFileName, sizeof(scratchFileName),
+        "%s.lnk", dstFileName);
+      if (!(lnkfile = fopen (scratchFileName, "w")))
+        {
+          werror (E_FILE_OPEN_ERR, scratchFileName);
+          exit (1);
+        }
 
-  /* now write the options.  JCF: added option 'y' */
-  fprintf (lnkfile, "-myux%c\n", (options.out_fmt ? 's' : 'i'));
+      if (TARGET_IS_Z80 || TARGET_IS_GBZ80)
+        {
+          fprintf (lnkfile, "--\n-m\n-j\n-x\n-%c %s\n",
+            out_fmt, dstFileName);
+        }
+      else /*For all the other ports.  Including pics???*/
+        {
+          fprintf (lnkfile, "-myux%c\n", out_fmt);
+          if(options.pack_iram)
+              fprintf (lnkfile, "-Y\n");
+        }
 
-  /* if iram size specified */
-  if (options.iram_size)
-    fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
+      if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
+        {
+          /* 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 stack size specified*/
+          if(options.stack_size)
+              fprintf (lnkfile, "-A 0x%02x\n", options.stack_size);
 
-  /* if code size specified */
-  if (options.code_size)
-    fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
+          /* if xram size specified */
+          if (options.xram_size_set)
+            fprintf (lnkfile, "-v 0x%04x\n", options.xram_size);
 
-  if (options.debug)
-    fprintf (lnkfile, "-z\n");
+          /* if code size specified */
+          if (options.code_size)
+            fprintf (lnkfile, "-w 0x%04x\n", options.code_size);
+
+          if (options.debug)
+            fprintf (lnkfile, "-z\n");
+        }
 
 #define WRITE_SEG_LOC(N, L) \
-    segName = Safe_strdup(N); \
-    c = strtok(segName, " \t"); \
-    fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
-    if (segName) { Safe_free(segName); }
+  segName = Safe_strdup(N); \
+  c = strtok(segName, " \t"); \
+  fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
+  if (segName) { Safe_free(segName); }
 
-  /* code segment start */
-  WRITE_SEG_LOC (CODE_NAME, options.code_loc);
+      if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80)) /*Not for the z80, gbz80*/
+        {
 
-  /* data segment start */
-  if(options.data_loc){ /*JCF: If zero, the linker chooses the best place for data*/
-         WRITE_SEG_LOC (DATA_NAME, options.data_loc);
-  }
+          /* code segment start */
+          WRITE_SEG_LOC (CODE_NAME, options.code_loc);
 
-  /* xdata start */
-  WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
+          /* data segment start. If zero, the linker chooses
+             the best place for data */
+          if(options.data_loc)
+            {
+              WRITE_SEG_LOC (DATA_NAME, options.data_loc);
+            }
 
-  /* indirect data */
-  if (IDATA_NAME) {
-    WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
-  }
+          /* xdata start */
+          WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
 
-  /* bit segment start */
-  WRITE_SEG_LOC (BIT_NAME, 0);
+          /* indirect data */
+          if (IDATA_NAME)
+            {
+              WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
+            }
 
-  /* JCF: stack start */
-  if ( (options.stack_loc) && (options.stack_loc<0x100) ) {
-       WRITE_SEG_LOC ("SSEG", options.stack_loc);
-  }
+            /* bit segment start */
+            WRITE_SEG_LOC (BIT_NAME, 0);
+
+            /* stack start */
+            if ( (options.stack_loc) && (options.stack_loc<0x100) )
+              {
+                WRITE_SEG_LOC ("SSEG", options.stack_loc);
+              }
+        }
+      else /*For the z80, gbz80*/
+        {
+          WRITE_SEG_LOC ("_CODE", options.code_loc);
+          WRITE_SEG_LOC ("_DATA", options.data_loc);
+        }
+  
+      /* If the port has any special linker area declarations, get 'em */
+      if (port->extraAreas.genExtraAreaLinkOptions)
+        {
+          port->extraAreas.genExtraAreaLinkOptions(lnkfile);
+        }
 
-  /* add the extra linker options */
-  for (i = 0; linkOptions[i]; i++)
-    fprintf (lnkfile, "%s\n", linkOptions[i]);
+      /* add the extra linker options */
+      fputStrSet(lnkfile, linkOptionsSet);
 
-  /* other library paths if specified */
-  for (i = 0; i < nlibPaths; i++)
-    fprintf (lnkfile, "-k %s\n", libPaths[i]);
+      /* command line defined library paths if specified */
+      for (s = setFirstItem(libPathsSet); s != NULL; s = setNextItem(libPathsSet))
+        fprintf (lnkfile, "-k %s\n", s);
 
-  /* standard library path */
-  if (!options.nostdlib)
-    {
-      switch (options.model)
-       {
-       case MODEL_SMALL:
-         c = "small";
-         break;
-       case MODEL_LARGE:
-         c = "large";
-         break;
-       case MODEL_FLAT24:
-         /* c = "flat24"; */
-           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";
-         break;
-       default:
-         werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
-         c = "unknown";
-         break;
-       }
-      mfprintf (lnkfile, getRuntimeVariables(), "-k {libdir}{sep}%s\n", c);
+      /* standard library path */
+      if (!options.nostdlib)
+        {
+          if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
+            {
+              switch (options.model)
+                {
+                  case MODEL_SMALL:
+                  c = "small";
+                  break;
+                case MODEL_LARGE:
+                  c = "large";
+                  break;
+                case MODEL_FLAT24:
+                  /* c = "flat24"; */
+                  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";
+                  break;
+                default:
+                  werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
+                  c = "unknown";
+                  break;
+                }
+            }
+          else /*for the z80, gbz80*/
+            {
+              if (TARGET_IS_HC08)
+                c = "hc08";
+              else if (TARGET_IS_Z80)
+                c = "z80";
+              else
+                c = "gbz80";
+            }
+          for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
+            mfprintf (lnkfile, getRuntimeVariables(), "-k %s{sep}%s\n", s, c);
+        }
+
+      /* command line defined library files if specified */
+      for (s = setFirstItem(libFilesSet); s != NULL; s = setNextItem(libFilesSet))
+        fprintf (lnkfile, "-l %s\n", s);
 
       /* standard library files */
+      if (!options.nostdlib)
+        {
 #if !OPT_DISABLE_DS390
-      if (options.model == MODEL_FLAT24)
-       {
-           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);
-           }
-       }
+          if (options.model == MODEL_FLAT24)
+            {
+              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
 
 #if !OPT_DISABLE_XA51 
 #ifdef STD_XA51_LIB
-      if (options.model == MODEL_PAGE0)
-       {
-         fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
-       }
+          if (options.model == MODEL_PAGE0)
+            {
+              fprintf (lnkfile, "-l %s\n", STD_XA51_LIB);
+            }
 #endif
 #endif
-      fprintf (lnkfile, "-l %s\n", STD_LIB);
-      fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
-      fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
-      fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
-    }
+          if (TARGET_IS_MCS51)
+           {
+              fprintf (lnkfile, "-l mcs51\n");
+           }
+         if (!(TARGET_IS_Z80 || TARGET_IS_GBZ80
+            || TARGET_IS_HC08)) /*Not for the z80, gbz80*/
+            { /*Why the z80 port is not using the standard libraries?*/
+              fprintf (lnkfile, "-l %s\n", STD_LIB);
+              fprintf (lnkfile, "-l %s\n", STD_INT_LIB);
+              fprintf (lnkfile, "-l %s\n", STD_LONG_LIB);
+              fprintf (lnkfile, "-l %s\n", STD_FP_LIB);
+            }
+          else if (TARGET_IS_HC08)
+            {
+              fprintf (lnkfile, "-l hc08\n");
+            }
+          else if (TARGET_IS_Z80)
+            {
+              fprintf (lnkfile, "-l z80\n");
+            }
+          else if (TARGET_IS_GBZ80)
+            {
+              fprintf (lnkfile, "-l gbz80\n");
+            }
+        }
 
-  /* additional libraries if any */
-  for (i = 0; i < nlibFiles; i++)
-    fprintf (lnkfile, "-l %s\n", libFiles[i]);
+      /*For the z80 and gbz80 ports, try to find where crt0.o is...
+      It is very important for this file to be first on the linking proccess
+      so the areas are set in the correct order, expecially _GSINIT*/
+      if ((TARGET_IS_Z80 || TARGET_IS_GBZ80) &&
+        !options.no_std_crt0 && !options.nostdlib) /*For the z80, gbz80*/
+        {
+          char crt0path[PATH_MAX];
+          FILE * crt0fp;
+          for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet))
+            {
+              sprintf (crt0path, "%s%s%s%scrt0.o",
+                s, DIR_SEPARATOR_STRING, c, DIR_SEPARATOR_STRING);
+
+              crt0fp=fopen(crt0path, "r");
+              if(crt0fp!=NULL)/*Found it!*/
+                {
+                  fclose(crt0fp);
+                  #ifdef __CYGWIN__
+                  {
+                    /*The CYGWIN version of the z80-gbz80 linker is getting confused with
+                    windows paths, so convert them to the CYGWIN format*/
+                    char posix_path[PATH_MAX];
+                    void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
+                    cygwin_conv_to_full_posix_path(crt0path, posix_path);
+                    strcpy(crt0path, posix_path);
+                  }
+                  #endif
+                  fprintf (lnkfile, "%s\n", crt0path);
+                  break;
+                }
+            }
+          if(s==NULL) fprintf (stderr, "Warning: couldn't find crt0.o\n");
+        }
 
-  /* put in the object files */
-  if (fullSrcFileName)
-    fprintf (lnkfile, "%s ", dstFileName);
+      /* put in the object files */
+      if (fullSrcFileName)
+        fprintf (lnkfile, "%s%s\n", dstFileName, port->linker.rel_ext);
 
-  for (i = 0; i < nrelFiles; i++)
-    fprintf (lnkfile, "%s\n", relFiles[i]);
+      fputStrSet(lnkfile, relFilesSet);
 
-  fprintf (lnkfile, "\n-e\n");
-  fclose (lnkfile);
+      fprintf (lnkfile, "\n-e\n");
+      fclose (lnkfile);
+    } /* if(port->linker.needLinkerScript) */
 
   if (options.verbose)
     printf ("sdcc: Calling linker...\n");
@@ -1455,26 +1604,44 @@ linkEdit (char **envp)
         }
       else
         {
-          strncpyz (scratchFileName, relFiles[0], sizeof(scratchFileName));
+          s = peekSet(relFilesSet);
+
+          assert(s);
+
+          strncpyz (scratchFileName, s, sizeof(scratchFileName));
           /* strip ".rel" extension */
           *strrchr (scratchFileName, '.') = '\0';
         }
       strncatz (scratchFileName, 
-               options.out_fmt ? ".S19" : ".ihx",
-               sizeof(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, sizeof(buffer));
+      set *libSet=NULL;
+
+      if(TARGET_IS_PIC16) {
+         /* use $3 to set the linker include directories */
+         libSet = appendStrSet(libDirsSet, "-I\"", "\"");
+
+         /* now add the libraries from command line */
+         mergeSets(&libSet, libFilesSet);
+      }
+      
+      buildCmdLine (buffer2, port->linker.cmd, dstFileName, scratchFileName, (libSet?joinStrSet(libSet):NULL), linkOptionsSet);
+      if(libSet)deleteSet(&libSet);
+
+      buildCmdLine2 (buffer, sizeof(buffer), buffer2);
     }
   else
     {
-      buildCmdLine2 (buffer, port->linker.mcmd, sizeof(buffer));
+      buildCmdLine2 (buffer, sizeof(buffer), port->linker.mcmd);
     }
 
+  /*  if (options.verbose)fprintf(stderr, "linker command line: %s\n", buffer); */
+
   system_ret = my_system (buffer);
   /* TODO: most linker don't have a -o parameter */
   /* -o option overrides default name? */
@@ -1489,17 +1656,23 @@ linkEdit (char **envp)
         }
       else
         {
-          strncpyz (scratchFileName, relFiles[0], sizeof(scratchFileName));
+          s = peekSet(relFilesSet);
+
+          assert(s);
+
+          strncpyz (scratchFileName, s, sizeof(scratchFileName));
           /* strip ".rel" extension */
           p = strrchr (scratchFileName, '.');
-         if (p)
-           {
-             *p = 0;
-           }
+          if (p)
+            {
+              *p = 0;
+            }
         }
       strncatz (scratchFileName,
-               options.out_fmt ? ".S19" : ".ihx",
-               sizeof(scratchFileName));
+        options.out_fmt ? ".S19" : ".ihx",
+        sizeof(scratchFileName));
+      if (strcmp (fullDstFileName, scratchFileName))
+        unlink (fullDstFileName);
       rename (scratchFileName, fullDstFileName);
 
       strncpyz (buffer, fullDstFileName, sizeof(buffer));
@@ -1514,12 +1687,32 @@ linkEdit (char **envp)
       strncatz (scratchFileName, ".map", sizeof(scratchFileName));
       *q = 0;
       strncatz(buffer, ".map", sizeof(buffer));
+      if (strcmp (scratchFileName, buffer))
+        unlink (buffer);
       rename (scratchFileName, buffer);
       *p = 0;
       strncatz (scratchFileName, ".mem", sizeof(scratchFileName));
       *q = 0;
       strncatz(buffer, ".mem", sizeof(buffer));
+      if (strcmp (scratchFileName, buffer))
+        unlink (buffer);
       rename (scratchFileName, buffer);
+      if (options.debug)
+        {
+          *p = 0;
+          strncatz (scratchFileName, ".cdb", sizeof(scratchFileName));
+          *q = 0;
+          strncatz(buffer, ".cdb", sizeof(buffer));
+          if (strcmp (scratchFileName, buffer))
+            unlink (buffer);
+          rename (scratchFileName, buffer);
+          /* and the OMF file without extension: */
+          *p = 0;
+          *q = 0;
+          if (strcmp (scratchFileName, buffer))
+            unlink (buffer);
+          rename (scratchFileName, buffer);
+        }
     }
   if (system_ret)
     {
@@ -1546,14 +1739,14 @@ assemble (char **envp)
     }
 
     if (port->assembler.do_assemble) {
-       port->assembler.do_assemble(asmOptions);
+       port->assembler.do_assemble(asmOptionsSet);
        return ;
     } else if (port->assembler.cmd) {
         buildCmdLine (buffer, port->assembler.cmd, dstFileName, scratchFileName,
                      options.debug ? port->assembler.debug_opts : port->assembler.plain_opts,
-                     asmOptions);
+                     asmOptionsSet);
     } else {
-       buildCmdLine2 (buffer, port->assembler.mcmd, sizeof(buffer));
+       buildCmdLine2 (buffer, sizeof(buffer), port->assembler.mcmd);
     }
 
     if (my_system (buffer)) {
@@ -1569,6 +1762,8 @@ assemble (char **envp)
         strncatz (scratchFileName, 
                  port->linker.rel_ext,
                  sizeof(scratchFileName));
+        if (strcmp (scratchFileName, fullDstFileName))
+          unlink (fullDstFileName);
         rename (scratchFileName, fullDstFileName);
     }
 }
@@ -1585,42 +1780,45 @@ preProcess (char **envp)
     }
   else
     {
+      const char *s;
+      set *inclList = NULL;
+
       /* if using external stack define the macro */
       if (options.useXstack)
-       addToList (preArgv, "-DSDCC_USE_XSTACK");
+       addSet(&preArgvSet, Safe_strdup("-DSDCC_USE_XSTACK"));
 
       /* set the macro for stack autos  */
       if (options.stackAuto)
-       addToList (preArgv, "-DSDCC_STACK_AUTO");
+       addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_AUTO"));
 
       /* set the macro for stack autos  */
       if (options.stack10bit)
-       addToList (preArgv, "-DSDCC_STACK_TENBIT");
+       addSet(&preArgvSet, Safe_strdup("-DSDCC_STACK_TENBIT"));
 
       /* set the macro for no overlay  */
       if (options.noOverlay)
-        addToList (preArgv, "-DSDCC_NOOVERLAY");
+        addSet(&preArgvSet, Safe_strdup("-DSDCC_NOOVERLAY"));
 
       /* set the macro for large model  */
       switch (options.model)
        {
        case MODEL_LARGE:
-         addToList (preArgv, "-DSDCC_MODEL_LARGE");
+         addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_LARGE"));
          break;
        case MODEL_SMALL:
-         addToList (preArgv, "-DSDCC_MODEL_SMALL");
+         addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_SMALL"));
          break;
        case MODEL_COMPACT:
-         addToList (preArgv, "-DSDCC_MODEL_COMPACT");
+         addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_COMPACT"));
          break;
        case MODEL_MEDIUM:
-         addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
+         addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_MEDIUM"));
          break;
        case MODEL_FLAT24:
-         addToList (preArgv, "-DSDCC_MODEL_FLAT24");
+         addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_FLAT24"));
          break;
        case MODEL_PAGE0:
-         addToList (preArgv, "-DSDCC_MODEL_PAGE0");
+         addSet(&preArgvSet, Safe_strdup("-DSDCC_MODEL_PAGE0"));
          break;
        default:
          werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
@@ -1628,15 +1826,19 @@ preProcess (char **envp)
        }
 
       /* add port (processor information to processor */
-      addToList (preArgv, "-DSDCC_{port}");
-      addToList (preArgv, "-D__{port}");
+      addSet(&preArgvSet, Safe_strdup("-DSDCC_{port}"));
+      addSet(&preArgvSet, Safe_strdup("-D__{port}"));
 
       /* standard include path */
       if (!options.nostdinc) {
-       addToList (preArgv, "-I\"{includedir}\"");
+        inclList = appendStrSet(includeDirsSet, "-I\"", "\"");
+        mergeSets(&preArgvSet, inclList);
       }
 
-      setMainValue ("cppextraopts", join(preArgv));
+      setMainValue("cppextraopts", (s = joinStrSet(preArgvSet)));
+      Safe_free((void *)s);
+      if (inclList != NULL)
+        deleteSet(&inclList);
 
       if (preProcOnly && fullDstFileName)
        {
@@ -1652,7 +1854,7 @@ preProcess (char **envp)
       if (options.verbose)
        printf ("sdcc: Calling preprocessor...\n");
 
-      buildCmdLine2 (buffer, _preCmd, sizeof(buffer));
+      buildCmdLine2 (buffer, sizeof(buffer), _preCmd);
 
       if (preProcOnly) {
         if (my_system (buffer)) {
@@ -1699,23 +1901,19 @@ setBinPaths(const char *argv0)
     addSetHead(&binPathSet, Safe_strdup(buf));
   }
 
+#if 0
   if (options.printSearchDirs) {
-    printf("programs: ");
-    if (NULL != (p = (char *)setFirstItem(binPathSet))) {
-      printf("%s", p);
-      while (NULL != (p = (char *)setNextItem(binPathSet)))
-        printf(":%s", p);
-    }
-    putchar('\n');
+    printf("programs:\n");
+    fputStrSet(stdout, binPathSet);
   }
+#endif
 }
 
 /* Set system include path */
 static void
-setIncludePath(const char *datadir)
+setIncludePath(void)
 {
   char *p;
-  char buf[PATH_MAX];
 
   /*
    * Search logic:
@@ -1726,23 +1924,24 @@ setIncludePath(const char *datadir)
    * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
    */
 
-  if ((p = getenv(SDCC_INCLUDE_NAME)) == NULL) {
-    SNPRINTF(buf, sizeof buf, "%s" INCLUDE_DIR_SUFFIX, datadir);
-    p = buf;
-  }
+  includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
 
-  if (options.printSearchDirs)
-    printf("includedir: %s\n", p);
+  if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
+    addSetHead(&includeDirsSet, p);
 
-  setMainValue ("includedir", p);
+#if 0
+  if (options.printSearchDirs) {
+    printf("includedir:\n");
+    fputStrSet(stdout, includeDirsSet);
+  }
+#endif
 }
 
 /* Set system lib path */
 static void
-setLibPath(const char *datadir)
+setLibPath(void)
 {
   char *p;
-  char buf[PATH_MAX];
 
   /*
    * Search logic:
@@ -1753,15 +1952,17 @@ setLibPath(const char *datadir)
    * 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;
-  }
+  libDirsSet = appendStrSet(dataDirsSet, NULL, LIB_DIR_SUFFIX);
 
-  if (options.printSearchDirs)
-    printf("libdir: %s\n", p);
+  if ((p = getenv(SDCC_LIB_NAME)) != NULL)
+    addSetHead(&libDirsSet, p);
 
-  setMainValue ("libdir", p);
+#if 0
+  if (options.printSearchDirs) {
+    printf("libdir:\n");
+    fputStrSet(stdout, libDirsSet);
+  }
+#endif
 }
 
 /* Set data path */
@@ -1781,29 +1982,32 @@ setDataPaths(const char *argv0)
 
   if ((p = getenv(SDCC_DIR_NAME)) != NULL) {
     SNPRINTF(buf, sizeof buf, "%s" PREFIX2DATA_DIR, p);
-    p = buf;
+    addSet(&dataDirsSet, Safe_strdup(buf));
   }
-  else if ((p = getBinPath(argv0)) != NULL) {
+
+  if ((p = getBinPath(argv0)) != NULL) {
     SNPRINTF(buf, sizeof buf, "%s" BIN2DATA_DIR, p);
-    p = buf;
+    addSet(&dataDirsSet, Safe_strdup(buf));
   }
-  else {
+
 #ifdef _WIN32
+  if (peekSet(dataDirsSet) == NULL) {
     /* this should never happen... */
     wassertl(0, "Can't get binary path");
-    p = ".";
-#else /* *nix paltform */
-    p = DATADIR; /* last resort */
-#endif
   }
+#else
+  addSet(&dataDirsSet, Safe_strdup(DATADIR));
+#endif
 
-  if (options.printSearchDirs)
-    printf("datadir: %s\n", p);
-
-  setIncludePath(p);
-  setLibPath(p);
+#if 0
+  if (options.printSearchDirs) {
+    printf("datadir:\n");
+    fputStrSet(stdout, dataDirsSet);
+  }
+#endif
 
-  setMainValue ("datadir", p);
+  setIncludePath();
+  setLibPath();
 }
 
 static void
@@ -1838,6 +2042,22 @@ initValues (void)
 
 }
 
+static void doPrintSearchDirs(void)
+{
+    printf("programs:\n");
+    fputStrSet(stdout, binPathSet);
+
+    printf("datadir:\n");
+    fputStrSet(stdout, dataDirsSet);
+
+    printf("includedir:\n");
+    fputStrSet(stdout, includeDirsSet);
+
+    printf("libdir:\n");
+    fputStrSet(stdout, libDirsSet);
+}
+
+
 static void
 sig_handler (int signal)
 {
@@ -1931,16 +2151,19 @@ main (int argc, char **argv, char **envp)
   setBinPaths(argv[0]);
   setDataPaths(argv[0]);
 
-  /* if print search dirs then exit */
-  if (options.printSearchDirs)
-    exit(0);
+  if(port->initPaths)
+       port->initPaths();
+  
+  if(options.printSearchDirs)
+       doPrintSearchDirs();
 
   /* if no input then printUsage & exit */
-  if (!options.c1mode && !fullSrcFileName && !nrelFiles)
-    {
-      printUsage ();
-      exit (0);
-    }
+  if (!options.c1mode && !fullSrcFileName && peekSet(relFilesSet) == NULL) {
+    if (!options.printSearchDirs)
+      printUsage();
+
+    exit(0);
+  }
 
   /* initMem() is expensive, but
      initMem() must called before port->finaliseOptions ().
@@ -1964,25 +2187,26 @@ main (int argc, char **argv, char **envp)
 
       yyparse ();
 
-      pclose(yyin);
+      if (pclose(yyin))
+        fatalError = 1;
       deleteSetItem(&pipeSet, yyin);
 
       if (fatalError) {
         exit (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 ();
-#endif
-      }
-      else {
-        glue ();
+      if (port->general.do_glue != NULL)
+        (*port->general.do_glue)();
+      else
+        {
+          /* this shouldn't happen */
+          assert(FALSE);
+          /* in case of NDEBUG */
+          glue();
+        }
+
+      if (fatalError) {
+        exit (1);
       }
 
       if (!options.c1mode && !noAssemble)
@@ -2001,7 +2225,7 @@ main (int argc, char **argv, char **envp)
       !fatalError &&
       !noAssemble &&
       !options.c1mode &&
-      (fullSrcFileName || nrelFiles))
+      (fullSrcFileName || peekSet(relFilesSet) != NULL))
     {
       if (port->linker.do_link)
        port->linker.do_link ();