Minor changes to fix up path seperators.
[fw/sdcc] / src / SDCCmain.c
index 3becb08b915e34005430c518b5f8cc8ec6f91b7f..3573c6bb7aafb34d3ee83421bb5f0dd6311bb7cb 100644 (file)
@@ -1,5 +1,5 @@
 /*-------------------------------------------------------------------------
-  SDCCmain.c - main file               
+  SDCCmain.c - main file
 
              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
 
@@ -7,23 +7,29 @@
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
 #include "common.h"
 #include <ctype.h>
+#include "newalloc.h"
+#include "SDCCerr.h"
+#include "BuildCmd.h"
+#include "MySystem.h"
+#include "SDCCmacro.h"
+#include "SDCCutil.h"
 
 #if NATIVE_WIN32
 #include <process.h>
 #include "spawn.h"
 #endif
 
-/* This is a bit messy.  We cant include unistd.h as it defines
-   'link' which we also use.
-*/
-int access(const char *path, int mode);
-#define X_OK 1
-int unlink(const char *path);
-
-extern void            initSymt                ();
-extern void            initMem                 ();
-extern void            initExpr                ();
-extern void             initiCode               ();
-extern void             initCSupport            ();
-extern void             initPeepHole            ();
-extern void            createObject    ();
-extern int             yyparse                 ();
-extern void             glue ();
-extern struct value    *constVal(char *s);
-extern double            floatFromVal(struct value *);
-extern int              fatalError ;
-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 */
-const char *preArgv[128]          ;/* pre-processor arguments  */
-int   currRegBank = 0 ;
-struct optimize optimize ;
-struct options  options ;
-char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a"*/;
-short preProcOnly = 0;
-short noAssemble = 0;
+#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 */
+char *srcFileName;             /* source file name with the .c stripped */
+char *moduleName;              /* module name is srcFilename stripped of any path */
+const char *preArgv[128];      /* pre-processor arguments  */
+int currRegBank = 0;
+struct optimize optimize;
+struct options options;
+char *VersionString = SDCC_VERSION_STR /*"Version 2.1.8a" */ ;
+int preProcOnly = 0;
+int noAssemble = 0;
 char *linkOptions[128];
 const char *asmOptions[128];
-char *libFiles[128] ;
+char *libFiles[128];
 int nlibFiles = 0;
-char *libPaths[128] ;
+char *libPaths[128];
 int nlibPaths = 0;
 char *relFiles[128];
 int nrelFiles = 0;
 bool verboseExec = FALSE;
-//extern int wait (int *);
-char    *preOutName;
-
-/* Far functions, far data */
-#define OPTION_LARGE_MODEL "-model-large"
-/* Far functions, near data */
-#define OPTION_MEDIUM_MODEL "-model-medium"
-#define OPTION_SMALL_MODEL "-model-small"
-#define OPTION_FLAT24_MODEL "-model-flat24"
-#define OPTION_STACK_AUTO  "-stack-auto"
-#define OPTION_STACK_10BIT "-stack-10bit"
-#define OPTION_XSTACK      "-xstack"
-#define OPTION_GENERIC     "-generic"
-#define OPTION_NO_GCSE     "-nogcse"
-#define OPTION_NO_LOOP_INV "-noinvariant"
-#define OPTION_NO_LOOP_IND "-noinduction"
-#define OPTION_NO_JTBOUND  "-nojtbound"
-#define OPTION_NO_LOOPREV  "-noloopreverse"
-#define OPTION_XREGS       "-regextend"
-#define OPTION_COMP_ONLY   "-compile-only"
-#define OPTION_DUMP_RAW    "-dumpraw"
-#define OPTION_DUMP_GCSE   "-dumpgcse"
-#define OPTION_DUMP_LOOP   "-dumploop"
-#define OPTION_DUMP_KILL   "-dumpdeadcode"
-#define OPTION_DUMP_RANGE  "-dumpliverange"
-#define OPTION_DUMP_PACK   "-dumpregpack"
-#define OPTION_DUMP_RASSGN "-dumpregassign"
-#define OPTION_DUMP_ALL    "-dumpall"
-#define OPTION_XRAM_LOC    "-xram-loc"
-#define OPTION_IRAM_SIZE   "-iram-size"
-#define OPTION_XSTACK_LOC  "-xstack-loc"
-#define OPTION_CODE_LOC    "-code-loc"
-#define OPTION_STACK_LOC   "-stack-loc"
-#define OPTION_DATA_LOC    "-data-loc"
-#define OPTION_IDATA_LOC   "-idata-loc"
-#define OPTION_PEEP_FILE   "-peep-file"
-#define OPTION_LIB_PATH    "-lib-path"
-#define OPTION_INTLONG_RENT "-int-long-reent"
-#define OPTION_FLOAT_RENT  "-float-reent"
-#define OPTION_OUT_FMT_IHX "-out-fmt-ihx"
-#define OPTION_OUT_FMT_S19 "-out-fmt-s19"
-#define OPTION_CYCLOMATIC  "-cyclomatic"
-#define OPTION_NOOVERLAY   "-nooverlay"
-#define OPTION_MAINRETURN  "-main-return"
-#define OPTION_NOPEEP      "-no-peep"
-#define OPTION_ASMPEEP     "-peep-asm"
-#define OPTION_DEBUG       "-debug"
-#define OPTION_VERSION     "-version"
-#define OPTION_STKAFTRDATA "-stack-after-data"
-#define OPTION_PREPROC_ONLY "-preprocessonly"
-#define OPTION_C1_MODE   "-c1mode"
-#define OPTION_HELP         "-help"
-#define OPTION_CALLEE_SAVES "-callee-saves"
-#define OPTION_NOREGPARMS   "-noregparms"
-
-static const char *_preCmd[] = {
-    "sdcpp", "-Wall", "-lang-c++", "-DSDCC=1", 
-    "-I" SDCC_INCLUDE_DIR, "$l", "$1", "$2", NULL
-};
+char *preOutName;
 
-#if !OPT_DISABLE_MCS51
-extern PORT mcs51_port;
-#endif
-#if !OPT_DISABLE_GBZ80
-extern PORT gbz80_port;
-#endif
-#if !OPT_DISABLE_Z80
-extern PORT z80_port;
-#endif
-#if !OPT_DISABLE_AVR
-extern PORT avr_port;
-#endif
-#if !OPT_DISABLE_DS390
-extern PORT ds390_port;
+/* uncomment JAMIN_DS390 to always override and use ds390 port
+  for mcs51 work.  This is temporary, for compatibility testing. */
+/* #define JAMIN_DS390 */
+#ifdef JAMIN_DS390
+int ds390_jammed = 0;
 #endif
 
+// Globally accessible scratch buffer for file names.
+char scratchFileName[FILENAME_MAX];
+char buffer[FILENAME_MAX];
+
+// In MSC VC6 default search path for exe's to path for this
+
+char DefaultExePath[128];
+
+#define OPTION_HELP    "-help"
+
+#define LENGTH(_a)     (sizeof(_a)/sizeof(*(_a)))
+
+#define OPTION_STACK_8BIT      "--stack-8bit"
+#define OPTION_OUT_FMT_IHX     "--out-fmt-ihx"
+#define OPTION_LARGE_MODEL     "--model-large"
+#define OPTION_MEDIUM_MODEL    "--model-medium"
+#define OPTION_SMALL_MODEL     "--model-small"
+#define OPTION_FLAT24_MODEL    "--model-flat24"
+#define OPTION_DUMP_ALL                "--dumpall"
+#define OPTION_PEEP_FILE       "--peep-file"
+#define OPTION_LIB_PATH                "--lib-path"
+#define OPTION_XSTACK_LOC      "--xstack-loc"
+#define OPTION_CALLEE_SAVES    "--callee-saves"
+#define OPTION_STACK_LOC       "--stack-loc"
+#define OPTION_XRAM_LOC                "--xram-loc"
+#define OPTION_IRAM_SIZE       "--iram-size"
+#define OPTION_VERSION         "--version"
+#define OPTION_DATA_LOC                "--data-loc"
+#define OPTION_CODE_LOC                "--code-loc"
+#define OPTION_IDATA_LOC       "--idata-loc"
+#define OPTION_NO_LOOP_INV     "--noinvariant"
+#define OPTION_NO_LOOP_IND     "--noinduction"
+#define OPTION_LESS_PEDANTIC   "--lesspedantic"
+#define OPTION_NO_GCSE         "--nogcse"
+#define OPTION_SHORT_IS_8BITS  "--short-is-8bits"
+
+/** Table of all options supported by all ports.
+    This table provides:
+      * A reference for all options.
+      * An easy way to maintain help for the options.
+      * Automatic support for setting flags on simple options.
+*/
+typedef struct {
+    /** The short option character e.g. 'h' for -h.  0 for none. */
+    char shortOpt;
+    /** Long option e.g. "--help".  Includes the -- prefix.  NULL for
+        none. */
+    const char *longOpt;
+    /** Pointer to an int that will be incremented every time the
+        option is encountered.  May be NULL.
+    */
+    int *pparameter;
+    /** Help text to go with this option.  May be NULL. */
+    const char *help;
+} OPTION;
+
+static const OPTION 
+optionsTable[] = {
+    { 'm',  NULL,                   NULL, "Set the port to use e.g. -mz80." },
+    { 'd',  NULL,                   NULL, NULL },
+    { 'D',  NULL,                   NULL, "Define macro as in -Dmacro" },
+    { 'I',  NULL,                   NULL, "Add to the include (*.h) path, as in -Ipath" },
+    { 'A',  NULL,                   NULL, NULL },
+    { '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" },
+    { 'S',  NULL,                   &noAssemble, "Compile only; do not assemble or link" },
+    { 'W',  NULL,                   NULL, "Pass through options to the assembler (a) or linker (l)" },
+    { 'L',  NULL,                   NULL, "Add the next field to the library search path" },
+    { 'l',  NULL,                   NULL, "Include the given library in the link" },
+    { 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)" },
+    { 0,    OPTION_FLAT24_MODEL,    NULL, "use the flat24 model for the ds390 (default)" },
+    { 0,    "--stack-auto",         &options.stackAuto, "Stack automatic variables" },
+    { 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" },
+    { 0,    "--dumpraw",            &options.dump_raw, "Dump the internal structure after the initial parse" },
+    { 0,    "--dumpgcse",           &options.dump_gcse, NULL },
+    { 0,    "--dumploop",           &options.dump_loop, NULL },
+    { 0,    "--dumpdeadcode",       &options.dump_kill, NULL },
+    { 0,    "--dumpliverange",      &options.dump_range, NULL },
+    { 0,    "--dumpregpack",        &options.dump_pack, NULL },
+    { 0,    "--dumpregassign",      &options.dump_rassgn, NULL },
+    { 0,    OPTION_DUMP_ALL,        NULL, "Dump the internal structure at all stages" },
+    { 0,    OPTION_XRAM_LOC,        NULL, "<nnnn> External Ram start location" },
+    { 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_STACK_LOC,       NULL, "<nnnn> Stack pointer initial value" },
+    { 0,    OPTION_DATA_LOC,        NULL, "<nnnn> Direct data start location" },
+    { 0,    OPTION_IDATA_LOC,       NULL, NULL },
+    { 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,    OPTION_OUT_FMT_IHX,     NULL, NULL },
+    { 0,    "--out-fmt-s19",        &options.out_fmt, NULL },
+    { 0,    "--cyclomatic",         &options.cyclomatic, NULL },
+    { 0,    "--nooverlay",          &options.noOverlay, NULL },
+    { 0,    "--main-return",        &options.mainreturn, "Issue a return after main()" },
+    { 0,    "--no-peep",            &options.nopeep, "Disable the peephole assembly file optimisation" },
+    { 0,    "--no-reg-params",      &options.noRegParams, "On some ports, disable passing some parameters in registers" },
+    { 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" },
+    { 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" },
+    { 0,    "--nostdinc",           &options.nostdinc, "Do not include the standard include directory in the search path" },
+    { 0,    "--verbose",            &options.verbose, "Trace calls to the preprocessor, assembler, and linker" },
+    { 0,    OPTION_LESS_PEDANTIC,   NULL, "Disable some of the more pedantic warnings" },
+    { 0,    OPTION_SHORT_IS_8BITS,   NULL, "Make short 8bits (for old times sake)" },
+    { 0,    "--profile",            &options.profile, "On supported ports, generate extra profiling information" }
+};
+
+/** Table of all unsupported options and help text to display when one
+    is used.
+*/
+typedef struct {
+    /** shortOpt as in OPTIONS. */
+    char shortOpt;
+    /** longOpt as in OPTIONS. */
+    const char *longOpt;
+    /** Message to display inside W_UNSUPPORTED_OPT when this option
+        is used. */
+    const char *message;
+} UNSUPPORTEDOPT;
+
+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" },
+    { 'p',  NULL,      "use --stack-loc instead" },
+    { 'P',  NULL,      "use --stack-loc instead" },
+    { 'i',  NULL,      "use --idata-loc instead" },
+    { 'r',  NULL,      "use --xdata-loc instead" },
+    { 's',  NULL,      "use --code-loc instead" },
+    { 'Y',  NULL,      "use -I instead" }
+};
+
+/** List of all default constant macros.
+ */
+static const char *_baseValues[] = {
+  "cpp", "{bindir}{sep}sdcpp",
+  "cppextraopts", "",
+  /* Path seperator character */
+  "sep", DIR_SEPARATOR_STRING,
+  NULL
+};
+
+static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
 
 PORT *port;
 
-static PORT *_ports[] = {
+static PORT *_ports[] =
+{
 #if !OPT_DISABLE_MCS51
-   &mcs51_port,
+  &mcs51_port,
 #endif
 #if !OPT_DISABLE_GBZ80
-    &gbz80_port,
+  &gbz80_port,
 #endif
 #if !OPT_DISABLE_Z80
-    &z80_port,
+  &z80_port,
 #endif
 #if !OPT_DISABLE_AVR
-    &avr_port,
+  &avr_port,
 #endif
 #if !OPT_DISABLE_DS390
-    &ds390_port,
+  &ds390_port,
+#endif
+#if !OPT_DISABLE_PIC
+  &pic_port,
+#endif
+#if !OPT_DISABLE_I186
+  &i186_port,
+#endif
+#if !OPT_DISABLE_TLCS900H
+  &tlcs900h_port,
 #endif
 };
 
 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
 
+/**
+   remove me - TSD a hack to force sdcc to generate gpasm format .asm files.
+ */
+extern void picglue ();
+
 /** Sets the port to the one given by the command line option.
-    @param             The name minus the option (eg 'mcs51')
-    @return            0 on success.
+    @param    The name minus the option (eg 'mcs51')
+    @return     0 on success.
 */
-static int _setPort(const char *name)
+static void
+_setPort (const char *name)
 {
-    int i;
-    for (i=0; i<NUM_PORTS; i++) {
-       if (!strcmp(_ports[i]->target, name)) {
-           port = _ports[i];
-           return 0;
+  int i;
+  for (i = 0; i < NUM_PORTS; i++)
+    {
+      if (!strcmp (_ports[i]->target, name))
+       {
+         port = _ports[i];
+         return;
        }
     }
-    /* Error - didnt find */
-    werror(E_UNKNOWN_TARGET,name);
-    exit(1);
+  /* Error - didnt find */
+  werror (E_UNKNOWN_TARGET, name);
+  exit (1);
 }
 
-void buildCmdLine(char *into, char **args, const char **cmds, 
-                         const char *p1, const char *p2, 
-                         const char *p3, const char **list)
+static void
+_validatePorts (void)
 {
-    const char *p, *from;
-
-    while (*cmds) {
-       *args = into;
-       args++;
-
-       from = *cmds;
-       cmds++;
-       *into = '\0';
-
-       /* See if it has a '$' anywhere - if not, just copy */
-       if ((p = strchr(from, '$'))) {
-           strncpy(into, from, p - from);
-           /* NULL terminate it */
-           into[p-from] = '\0';
-           from = p+2;
-           p++;
-           switch (*p) {
-           case '1':
-               if (p1)
-                   strcat(into, p1);
-               break;
-           case '2':
-               if (p2)
-                   strcat(into, p2);
-               break;
-           case '3':
-               if (p3)
-                   strcat(into, p3);
-               break;
-           case 'l': {
-               const char **tmp = list;
-               if (tmp) {
-                   while (*tmp) {
-                       strcpy(into, *tmp);
-                       into += strlen(into)+1;
-                       *args = into;
-                       args++;
-                       tmp++;
-                   }
-               }
-               break;
-           }
-           default:
-               assert(0);
-           }
+  int i;
+  for (i = 0; i < NUM_PORTS; i++)
+    {
+      if (_ports[i]->magic != PORT_MAGIC)
+       {
+         wassertl (0, "Port definition structure is incomplete");
+       }
+    }
+}
+
+static void
+_findPort (int argc, char **argv)
+{
+  _validatePorts ();
+
+  while (argc--)
+    {
+      if (!strncmp (*argv, "-m", 2))
+       {
+         _setPort (*argv + 2);
+         return;
        }
-       strcat(into, from);
-       if (strlen(into) == 0)
-           args--;
-       into += strlen(into)+1;
+      argv++;
     }
-    *args = NULL;
+  /* Use the first in the list */
+  port = _ports[0];
 }
 
 /*-----------------------------------------------------------------*/
-/* printVersionInfo - prints the version info                     */
+/* printVersionInfo - prints the version info        */
 /*-----------------------------------------------------------------*/
-void   printVersionInfo ()
+void
+printVersionInfo ()
 {
-    int i;
-    
-    fprintf (stderr,
-            "SDCC : ");
-    for (i=0; i<NUM_PORTS; i++)
-       fprintf(stderr, "%s%s", i==0 ? "" : "/", _ports[i]->target);
-    fprintf(stderr, " %s"
+  int i;
+
+  fprintf (stderr,
+          "SDCC : ");
+  for (i = 0; i < NUM_PORTS; i++)
+    fprintf (stderr, "%s%s", i == 0 ? "" : "/", _ports[i]->target);
+
+  fprintf (stderr, " %s"
 #ifdef SDCC_SUB_VERSION_STR
-           "/" SDCC_SUB_VERSION_STR
+          "/" SDCC_SUB_VERSION_STR
 #endif
-           " ` "
-#ifdef __CYGWIN32__
-               " (CYGWIN32)\n"
+           " (" __DATE__ ")"
+#ifdef __CYGWIN__
+          " (CYGWIN)\n"
+#else
+#ifdef __DJGPP__
+          " (DJGPP) \n"
+#else
+#if defined(_MSC_VER)
+          " (WIN32) \n"
 #else
-# ifdef __DJGPP__
-               " (DJGPP) \n"
-# else
-               " (UNIX) \n"
-# endif
+          " (UNIX) \n"
+#endif
+#endif
 #endif
 
-           , VersionString
-           );
+          ,VersionString
+    );
 }
 
 /*-----------------------------------------------------------------*/
-/* printUsage - prints command line syntax                        */
+/* printUsage - prints command line syntax         */
 /*-----------------------------------------------------------------*/
-void   printUsage ()
+void
+printUsage ()
 {
-       printVersionInfo ();
-       fprintf (stderr,
-                "Usage : [options] filename\n"
-                "Options :-\n"
-                "\t-m<proc>             -     Target processor <proc>.  Default %s\n"
-                "\t                           Try --version for supported values of <proc>\n"
-                "\t--model-large        -     Large Model\n"
-                "\t--model-small        -     Small Model (default)\n"
-                "\t--stack-auto         -     Stack automatic variables\n"
-                "\t--xstack             -     Use external stack\n"
-                "\t--xram-loc <nnnn>    -     External Ram start location\n"
-                "\t--xstack-loc <nnnn>  -     Xternal Stack Location\n"
-                "\t--code-loc <nnnn>    -     Code Segment Location\n"
-                "\t--stack-loc <nnnn>   -     Stack pointer initial value\n"
-                "\t--data-loc <nnnn>    -     Direct data start location\n"
-                "\t--idata-loc <nnnn>   -     Indirect data start location\n"
-                "\t--iram-size <nnnn>   -     Internal Ram size\n"
-                "\t--nojtbound          -     Don't generate boundary check for jump tables\n"
-                "\t--generic            -     All unqualified ptrs converted to '_generic'\n"
-                "PreProcessor Options :-\n"
-                "\t-Dmacro             -       Define Macro\n"          
-                "\t-Ipath              -       Include \"*.h\" path\n"
-                "Note: this is NOT a complete list of options see docs for details\n",
-                _ports[0]->target
-                );             
-       exit (0);
+    int i;
+    printVersionInfo();
+    fprintf (stdout,
+             "Usage : sdcc [options] filename\n"
+             "Options :-\n"
+             );
+    
+    for (i = 0; i < LENGTH(optionsTable); i++) {
+        fprintf(stdout, "  %c%c  %-20s  %s\n", 
+                optionsTable[i].shortOpt !=0 ? '-' : ' ',
+                optionsTable[i].shortOpt !=0 ? optionsTable[i].shortOpt : ' ',
+                optionsTable[i].longOpt != NULL ? optionsTable[i].longOpt : "",
+                optionsTable[i].help != NULL ? optionsTable[i].help : ""
+                );
+    }
+    exit (0);
 }
 
 /*-----------------------------------------------------------------*/
 /* parseWithComma - separates string with comma                    */
 /*-----------------------------------------------------------------*/
-void parseWithComma (char **dest,char *src)
+void
+parseWithComma (char **dest, char *src)
 {
-    int i = 0;
-    
-    strtok(src,"\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 ;
+  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++;
+      src++;
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* setDefaultOptions - sets the default options                    */
 /*-----------------------------------------------------------------*/
-static void setDefaultOptions()
+static void
+setDefaultOptions ()
 {
-    int i ;
-
-    for ( i = 0 ; i < 128 ; i++)
-       preArgv[i] = asmOptions [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 */
-    options.code_loc  = 0; /* code starts at 0 */
-    options.data_loc  = 0x0030; /* data starts at 0x0030 */
-    options.xdata_loc = 0;
-    options.idata_loc = 0x80;
-    options.genericPtr = 1;   /* default on */
-    options.nopeep    = 0;
-    options.model = port->general.default_model;
-
-    /* now for the optimizations */
-    /* turn on the everything */
-    optimize.global_cse = 1;    
-    optimize.label1 = 1;
-    optimize.label2 = 1;
-    optimize.label3 = 1;
-    optimize.label4 = 1;    
-    optimize.loopInvariant = 1;
-    optimize.loopInduction = 1;
-
-    port->setDefaultOptions();
+  int i;
+
+  for (i = 0; i < 128; i++)
+    preArgv[i] = asmOptions[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 */
+  options.code_loc = 0;                /* code starts at 0 */
+  options.data_loc = 0x0030;   /* data starts at 0x0030 */
+  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;
+  options.nostdinc = 0;
+  options.verbose = 0;
+  options.shortis8bits = 0;
+
+  options.stack10bit=0;
+
+  /* now for the optimizations */
+  /* turn on the everything */
+  optimize.global_cse = 1;
+  optimize.label1 = 1;
+  optimize.label2 = 1;
+  optimize.label3 = 1;
+  optimize.label4 = 1;
+  optimize.loopInvariant = 1;
+  optimize.loopInduction = 1;
+
+  /* now for the ports */
+  port->setDefaultOptions ();
 }
 
 /*-----------------------------------------------------------------*/
 /* processFile - determines the type of file from the extension    */
 /*-----------------------------------------------------------------*/
-static void processFile (char *s)
+static void
+processFile (char *s)
 {
-    char *fext = NULL;
-    
-    /* get the file extension */
-    fext = s + strlen(s);
-    while ((fext != s) && *fext != '.') fext--;
-    
-    /* now if no '.' then we don't know what the file type is
-       so give a warning and return */
-    if (fext == s) {
-       werror(W_UNKNOWN_FEXT,s);
-       return ;
+  char *fext = NULL;
+
+  /* get the file extension */
+  fext = s + strlen (s);
+  while ((fext != s) && *fext != '.')
+    fext--;
+
+  /* now if no '.' then we don't know what the file type is
+     so give a warning and return */
+  if (fext == s)
+    {
+      werror (W_UNKNOWN_FEXT, s);
+      return;
     }
 
-    /* otherwise depending on the file type */
-    if (strcmp(fext,".c") == 0 || strcmp(fext,".C") == 0 || options.c1mode) {
-       /* source file name : not if we already have a 
-          source file */
-       if (srcFileName) {
-           werror(W_TOO_MANY_SRC,s);
-           return ;
+  /* otherwise depending on the file type */
+  if (strcmp (fext, ".c") == 0 || strcmp (fext, ".C") == 0 || options.c1mode)
+    {
+      /* source file name : not if we already have a
+         source file */
+      if (srcFileName)
+       {
+         werror (W_TOO_MANY_SRC, s);
+         return;
        }
 
-       /* the only source file */       
-       if (!(srcFile = fopen((fullSrcFileName = s),"r"))) {
-           werror(E_FILE_OPEN_ERR,s);
-           exit (1);
+      /* the only source file */
+      if (!(srcFile = fopen ((fullSrcFileName = s), "r")))
+       {
+         werror (E_FILE_OPEN_ERR, s);
+         exit (1);
        }
-       
-       /* copy the file name into the buffer */
-       strcpy(buffer,s);
-       
-       /* get rid of the "." */
-       strtok(buffer,".");
-       ALLOC_ATOMIC(srcFileName,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 */
-       fext = buffer + strlen(buffer);
-       while (fext != buffer && 
-              *(fext -1) != '\\'  &&
-              *(fext-1) != '/'   &&
-              *(fext-1) != ':')
-           fext--;
-       ALLOC_ATOMIC(moduleName,strlen(fext)+1);
-       strcpy(moduleName,fext);
-       
-       return ;
+
+      /* copy the file name into the buffer */
+      strcpy (buffer, s);
+
+      /* get rid of the "." */
+      strtok (buffer, ".");
+      srcFileName = Safe_calloc (1, 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 */
+      fext = buffer + strlen (buffer);
+      while (fext != buffer &&
+            *(fext - 1) != '\\' &&
+            *(fext - 1) != '/' &&
+            *(fext - 1) != ':')
+       fext--;
+      moduleName = Safe_calloc (1, strlen (fext) + 1);
+      strcpy (moduleName, fext);
+
+      return;
     }
 
-    /* if the extention is type .rel or .r or .REL or .R 
-       addtional object file will be passed to the linker */
-    if (strcmp(fext,".r") == 0 || strcmp(fext,".rel") == 0 ||
-       strcmp(fext,".R") == 0 || strcmp(fext,".REL") == 0 ||
-       strcmp(fext, port->linker.rel_ext) == 0)
-       {
-       relFiles[nrelFiles++] = s;
-       return ;
+  /* if the extention is type .rel or .r or .REL or .R
+     addtional object file will be passed to the linker */
+  if (strcmp (fext, ".r") == 0 || strcmp (fext, ".rel") == 0 ||
+      strcmp (fext, ".R") == 0 || strcmp (fext, ".REL") == 0 ||
+      strcmp (fext, port->linker.rel_ext) == 0)
+    {
+      relFiles[nrelFiles++] = s;
+      return;
     }
 
-    /* if .lib or .LIB */
-    if (strcmp(fext,".lib") == 0 || strcmp(fext,".LIB") == 0) {
-       libFiles[nlibFiles++] = s;
-       return;
+  /* if .lib or .LIB */
+  if (strcmp (fext, ".lib") == 0 || strcmp (fext, ".LIB") == 0)
+    {
+      libFiles[nlibFiles++] = s;
+      return;
     }
 
-    werror(W_UNKNOWN_FEXT,s);
-  
+  werror (W_UNKNOWN_FEXT, s);
+
 }
 
-static void _processC1Arg(char *s)
+static void
+_processC1Arg (char *s)
 {
-    if (srcFileName) {
-       if (options.out_name) {
-           werror(W_TOO_MANY_SRC,s);
-           return;
+  if (srcFileName)
+    {
+      if (options.out_name)
+       {
+         werror (W_TOO_MANY_SRC, s);
+         return;
        }
-       options.out_name = strdup(s);
+      options.out_name = strdup (s);
     }
-    else {
-       processFile(s);
+  else
+    {
+      processFile (s);
     }
 }
 
-static void _addToList(const char **list, const char *str)
+static void
+_setModel (int model, const char *sz)
 {
-    /* This is the bad way to do things :) */
-    while (*list)
-       list++;
-    *list = strdup(str);
-    if (!*list) {
-       werror(E_OUT_OF_MEM,__FILE__, 0);
-       exit (1);
+  if (port->general.supported_models & model)
+    options.model = model;
+  else
+    werror (W_UNSUPPORTED_MODEL, sz, port->target);
+}
+
+/** Gets the string argument to this option.  If the option is '--opt'
+    then for input of '--optxyz' or '--opt xyz' returns xyz.
+*/
+static char *
+getStringArg(const char *szStart, char **argv, int *pi, int argc)
+{
+  if (argv[*pi][strlen(szStart)]) 
+    {
+      return &argv[*pi][strlen(szStart)];
+    }
+  else 
+    {
+      ++(*pi);
+      if (*pi >= argc) 
+        {
+          werror (E_ARGUMENT_MISSING, szStart);
+          /* Die here rather than checking for errors later. */
+          exit(-1);
+        }
+      else 
+        {
+          return argv[*pi];
+        }
     }
-    *(++list) = NULL;
 }
 
-static void _setModel(int model, const char *sz)
+/** Gets the integer argument to this option using the same rules as
+    getStringArg. 
+*/
+static int
+getIntArg(const char *szStart, char **argv, int *pi, int argc)
 {
-    if (port->general.supported_models & model)
-       options.model = model;
-    else
-       werror(W_UNSUPPORTED_MODEL, sz, port->target);
+    return (int)floatFromVal(constVal(getStringArg(szStart, argv, pi, argc)));
 }
 
-/*-----------------------------------------------------------------*/
-/* parseCmdLine - parses the command line and sets the options     */
-/*-----------------------------------------------------------------*/
-int   parseCmdLine ( int argc, char **argv )
+static void
+verifyShortOption(const char *opt)
 {
-    int i ;      
-    char cdbfnbuf[50];
-
-    /* go thru all whole command line  */
-    for ( i = 1; i < argc; i++ ) {
-       if ( i >= argc )
-           break ;
-
-       /* options */
-       if (argv[i][0] == '-' && argv[i][1] == '-') {
-           
-           if (strcmp(&argv[i][1],OPTION_HELP) == 0) {
-               printUsage();
-                exit(0);
-           }       
-
-           if (strcmp(&argv[i][1],OPTION_XREGS) == 0) {
-               options.regExtend = 1;
-                continue;
-           }
+  if (strlen(opt) != 2)
+    {
+      werror (W_EXCESS_SHORT_OPTIONS, opt);
+    }
+}
 
-           if (strcmp(&argv[i][1],OPTION_LARGE_MODEL) == 0) {
-               _setModel(MODEL_LARGE, argv[i]);
-                continue;
-           }
+static bool
+tryHandleUnsupportedOpt(char **argv, int *pi)
+{
+    if (argv[*pi][0] == '-') 
+        {
+            const char *longOpt = "";
+            char shortOpt = -1;
+            int i;
+
+            if (argv[*pi][1] == '-') 
+                {
+                    // Long option.
+                    longOpt = argv[*pi];
+                }
+            else 
+                {
+                    shortOpt = argv[*pi][1];
+                }
+            for (i = 0; i < LENGTH(unsupportedOptTable); i++) 
+                {
+                    if (unsupportedOptTable[i].shortOpt == shortOpt || 
+                        (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 : ' ');
+                        werror (W_UNSUPP_OPTION, buffer, unsupportedOptTable[i].message);
+                        return 1;
+                    }
+                }
+            // Didn't find in the table
+            return 0;
+        }
+    else 
+        {
+            // Not an option, so can't be unsupported :)
+            return 0;
+    }
+}
 
-           if (strcmp(&argv[i][1],OPTION_MEDIUM_MODEL) == 0) {
-               _setModel(MODEL_MEDIUM, argv[i]);
-                continue;
-           }
-           
-           if (strcmp(&argv[i][1],OPTION_SMALL_MODEL) == 0) {
-               _setModel(MODEL_SMALL, argv[i]);
-                continue;
-           }
-           
-           if (strcmp(&argv[i][1],OPTION_FLAT24_MODEL) == 0) {
-               _setModel(MODEL_FLAT24, argv[i]);
-                continue;
-           }
-           
-           if (strcmp(&argv[i][1],OPTION_STACK_10BIT) == 0) {
-               options.stack10bit = 1;
-               continue;
-           }
+static bool
+tryHandleSimpleOpt(char **argv, int *pi)
+{
+    if (argv[*pi][0] == '-') 
+        {
+            const char *longOpt = "";
+            char shortOpt = -1;
+            int i;
+
+            if (argv[*pi][1] == '-') 
+                {
+                    // Long option.
+                    longOpt = argv[*pi];
+                }
+            else 
+                {
+                    shortOpt = argv[*pi][1];
+                }
+
+            for (i = 0; i < LENGTH(optionsTable); i++) 
+              {
+                if (optionsTable[i].shortOpt == shortOpt ||
+                    (longOpt && optionsTable[i].longOpt && 
+                     strcmp(optionsTable[i].longOpt, longOpt) == 0))
+                  {
+
+                    // If it is a flag then we can handle it here
+                    if (optionsTable[i].pparameter != NULL) 
+                      {
+                        if (optionsTable[i].shortOpt == shortOpt)
+                          {
+                            verifyShortOption(argv[*pi]);
+                          }
+
+                        (*optionsTable[i].pparameter)++;
+                        return 1;
+                      }
+                    else {
+                      // Not a flag.  Handled manually later.
+                      return 0;
+                    }
+                  }
+              }
+            // Didn't find in the table
+            return 0;
+        }
+    else 
+        {
+            // Not an option, so can't be handled.
+            return 0;
+        }
+}
 
-           if (strcmp(&argv[i][1],OPTION_STACK_AUTO) == 0) {
-               options.stackAuto = 1;
-                continue;
-           }
+/*-----------------------------------------------------------------*/
+/* parseCmdLine - parses the command line and sets the options     */
+/*-----------------------------------------------------------------*/
+int
+parseCmdLine (int argc, char **argv)
+{
+  int i;
 
-           if (strcmp(&argv[i][1],OPTION_DUMP_RAW) == 0) {
-               options.dump_raw = 1;
-                continue;
-           }
+  /* go thru all whole command line */
+  for (i = 1; i < argc; i++)
+    {
+      if (i >= argc)
+       break;
 
-           if (strcmp(&argv[i][1],OPTION_CYCLOMATIC) == 0) {
-               options.cyclomatic = 1;
-                continue;
-           }
-           
-           if (strcmp(&argv[i][1],OPTION_DUMP_GCSE) == 0) {
-               options.dump_gcse = 1;
-                continue;
-           }
-           
-           if (strcmp(&argv[i][1],OPTION_DUMP_LOOP) == 0) {
-               options.dump_loop = 1;
-                continue;
-           }
+      if (tryHandleUnsupportedOpt(argv, &i) == TRUE) 
+          {
+              continue;
+          }
 
-           if (strcmp(&argv[i][1],OPTION_DUMP_KILL) == 0) {
-               options.dump_kill = 1;
-                continue;
-           }
+      if (tryHandleSimpleOpt(argv, &i) == TRUE)
+          {
+              continue;
+          }
 
-           if (strcmp(&argv[i][1],OPTION_INTLONG_RENT) == 0) {
-               options.intlong_rent = 1;
-                continue;
+      /* options */
+      if (argv[i][0] == '-' && argv[i][1] == '-')
+       {
+         if (strcmp (argv[i], OPTION_HELP) == 0)
+           {
+             printUsage ();
+             exit (0);
            }
 
-           if (strcmp(&argv[i][1],OPTION_FLOAT_RENT) == 0) {
-               options.float_rent = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_STACK_8BIT) == 0)
+           {
+             options.stack10bit = 0;
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_DUMP_RANGE) == 0) {
-               options.dump_range = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_OUT_FMT_IHX) == 0)
+           {
+             options.out_fmt = 0;
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_DUMP_PACK) == 0) {
-               options.dump_pack = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_LARGE_MODEL) == 0)
+           {
+             _setModel (MODEL_LARGE, argv[i]);
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_DUMP_RASSGN) == 0) {
-               options.dump_rassgn = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_MEDIUM_MODEL) == 0)
+           {
+             _setModel (MODEL_MEDIUM, argv[i]);
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_OUT_FMT_IHX) == 0) {
-               options.out_fmt = 0;
-                continue;
+         if (strcmp (argv[i], OPTION_SMALL_MODEL) == 0)
+           {
+             _setModel (MODEL_SMALL, argv[i]);
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_OUT_FMT_S19) == 0) {
-               options.out_fmt = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_FLAT24_MODEL) == 0)
+           {
+             _setModel (MODEL_FLAT24, argv[i]);
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_NOOVERLAY) == 0) {
-               options.noOverlay = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_DUMP_ALL) == 0)
+           {
+             options.dump_rassgn =
+               options.dump_pack =
+               options.dump_range =
+               options.dump_kill =
+               options.dump_loop =
+               options.dump_gcse =
+               options.dump_raw = 1;
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_STKAFTRDATA) == 0) {
-               options.stackOnData = 1;
+         if (strcmp (argv[i], OPTION_PEEP_FILE) == 0)
+           {
+                options.peep_file = getStringArg(OPTION_PEEP_FILE, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_PREPROC_ONLY) == 0) {
-               preProcOnly = 1;
+         if (strcmp (argv[i], OPTION_LIB_PATH) == 0)
+            {
+               libPaths[nlibPaths++] = getStringArg(OPTION_LIB_PATH, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_C1_MODE) == 0) {
-               options.c1mode = 1;
-                continue;
+         if (strcmp (argv[i], OPTION_VERSION) == 0)
+           {
+             printVersionInfo ();
+              exit (0);
+             continue;
            }
 
-           
-           if (strcmp(&argv[i][1],OPTION_DUMP_ALL) == 0) {
-               options.dump_rassgn = 
-                options.dump_pack   =
-                options.dump_range  = 
-                options.dump_kill   = 
-                options.dump_loop   = 
-                options.dump_gcse   = 
-                options.dump_raw    = 1;
+         if (strcmp (argv[i], OPTION_CALLEE_SAVES) == 0)
+           {
+                parseWithComma (options.calleeSaves, getStringArg(OPTION_CALLEE_SAVES, argv, &i, argc));
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_COMP_ONLY) == 0) {
-               options.cc_only = 1;
-                continue;
-           }
-   
-           if (strcmp(&argv[i][1],OPTION_GENERIC) == 0) {
-               options.genericPtr = 1;
-                continue;
-           }
-           
-           if (strcmp(&argv[i][1],OPTION_NOPEEP) == 0) {
-               options.nopeep = 1;
+         if (strcmp (argv[i], OPTION_XSTACK_LOC) == 0)
+           {
+                options.xstack_loc = getIntArg(OPTION_XSTACK_LOC, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_ASMPEEP) == 0) {
-               options.asmpeep = 1;
+         if (strcmp (argv[i], OPTION_STACK_LOC) == 0)
+           {
+                options.stack_loc = getIntArg(OPTION_STACK_LOC, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_DEBUG) == 0) {
-               options.debug = 1;              
+         if (strcmp (argv[i], OPTION_XRAM_LOC) == 0)
+           {
+                options.xdata_loc = getIntArg(OPTION_XRAM_LOC, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_NOREGPARMS) == 0) {
-               options.noregparms = 1;         
+         if (strcmp (argv[i], OPTION_IRAM_SIZE) == 0)
+           {
+                options.iram_size = getIntArg(OPTION_IRAM_SIZE, argv, &i, argc);
                 continue;
            }
-           
-           if (strcmp(&argv[i][1],OPTION_PEEP_FILE) == 0) {
-               if (argv[i][1+strlen(OPTION_PEEP_FILE)]) 
-                   options.peep_file = 
-                       &argv[i][1+strlen(OPTION_PEEP_FILE)];
-               else
-                   options.peep_file = argv[++i];
-               continue ;
-           }
 
-           if (strcmp(&argv[i][1],OPTION_LIB_PATH) == 0) {
-               if (argv[i][1+strlen(OPTION_LIB_PATH)]) 
-                   libPaths[nlibPaths++] = 
-                       &argv[i][1+strlen(OPTION_PEEP_FILE)];
-               else
-                   libPaths[nlibPaths++] = argv[++i];
-               continue ;
-           }
-
-           if (strcmp(&argv[i][1],OPTION_XSTACK_LOC) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_XSTACK_LOC)])
-                   options.xstack_loc = 
-                       (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_XSTACK_LOC)]));
-                   else
-                       options.xstack_loc = 
-                           (int) floatFromVal(constVal(argv[++i]));
-               continue ;
-           }
-
-           if (strcmp(&argv[i][1],OPTION_XSTACK) == 0) {
-               options.useXstack = 1;
+         if (strcmp (argv[i], OPTION_DATA_LOC) == 0)
+           {
+                options.data_loc = getIntArg(OPTION_DATA_LOC, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_MAINRETURN) == 0) {
-               options.mainreturn = 1;
+         if (strcmp (argv[i], OPTION_IDATA_LOC) == 0)
+           {
+                options.idata_loc = getIntArg(OPTION_IDATA_LOC, argv, &i, argc);
                 continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_CALLEE_SAVES) == 0) {
-               if (argv[i][1+strlen(OPTION_CALLEE_SAVES)])
-                   parseWithComma(options.calleeSaves
-                                  ,&argv[i][1+strlen(OPTION_CALLEE_SAVES)]);
-               else
-                   parseWithComma(options.calleeSaves,argv[++i]);
+         if (strcmp (argv[i], OPTION_CODE_LOC) == 0)
+           {
+                options.code_loc = getIntArg(OPTION_CODE_LOC, argv, &i, argc);
                 continue;
            }
-           
-           if (strcmp(&argv[i][1],OPTION_STACK_LOC) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_STACK_LOC)])
-                   options.stack_loc = 
-                       (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_STACK_LOC)]));
-                   else
-                       options.stack_loc = 
-                           (int) floatFromVal(constVal(argv[++i]));
-               continue;
-           }
 
-           if (strcmp(&argv[i][1],OPTION_XRAM_LOC) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_XRAM_LOC)])
-                   options.xdata_loc = 
-                       (unsigned int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_XRAM_LOC)]));
-                   else
-                       options.xdata_loc = 
-                           (unsigned int) floatFromVal(constVal(argv[++i]));
-               continue;
+         if (strcmp (argv[i], OPTION_NO_GCSE) == 0)
+           {
+             optimize.global_cse = 0;
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_IRAM_SIZE) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_IRAM_SIZE)])
-                   options.iram_size = 
-                       (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_IRAM_SIZE)]));
-                   else
-                       options.iram_size = 
-                           (int) floatFromVal(constVal(argv[++i]));
-               continue;
+         if (strcmp (argv[i], OPTION_NO_LOOP_INV) == 0)
+           {
+             optimize.loopInvariant = 0;
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_VERSION) == 0) {              
-               printVersionInfo();
-               exit(0);
-               continue;
+         if (strcmp (argv[i], OPTION_NO_LOOP_IND) == 0)
+           {
+             optimize.loopInduction = 0;
+             continue;
            }
 
-           if (strcmp(&argv[i][1],OPTION_DATA_LOC) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_DATA_LOC)])
-                   options.data_loc = 
-                       (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_DATA_LOC)]));
-                   else
-                       options.data_loc = 
-                           (int) floatFromVal(constVal(argv[++i]));
-               continue;
+          if (strcmp (argv[i], OPTION_LESS_PEDANTIC) == 0) 
+            {
+             options.lessPedantic = 1;
+              setErrorLogLevel(ERROR_LEVEL_WARNING);
+              continue;
+            }
+
+         if (strcmp (&argv[i][1], OPTION_SHORT_IS_8BITS) == 0) 
+            {
+              options.shortis8bits=1;
+              continue;
+            }
+          
+         if (!port->parseOption (&argc, argv, &i))
+           {
+             werror (W_UNKNOWN_OPTION, argv[i]);
            }
-
-           if (strcmp(&argv[i][1],OPTION_IDATA_LOC) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_IDATA_LOC)])
-                   options.idata_loc = 
-                       (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_IDATA_LOC)]));
-                   else
-                       options.idata_loc = 
-                           (int) floatFromVal(constVal(argv[++i]));
-               continue;
+         else
+           {
+             continue;
            }
+       }
 
-           if (strcmp(&argv[i][1],OPTION_CODE_LOC) == 0) {
-               
-               if (argv[i][1+strlen(OPTION_CODE_LOC)])
-                   options.code_loc = 
-                       (int) floatFromVal(constVal(&argv[i][1+strlen(OPTION_CODE_LOC)]));
-                   else
-                       options.code_loc = 
-                           (int) floatFromVal(constVal(argv[++i]));
-               continue;
-           }
+      /* if preceded by  '-' then option */
+      if (*argv[i] == '-')
+       {
+         switch (argv[i][1])
+           {
+           case 'h':
+              verifyShortOption(argv[i]);
 
-           
-           if (strcmp(&argv[i][1],OPTION_NO_JTBOUND) == 0) {
-               optimize.noJTabBoundary = 1;
-                continue;
-           }
-           if (strcmp(&argv[i][1],OPTION_NO_GCSE) == 0) {
-               optimize.global_cse = 0;
-                continue;
-           }
+             printUsage ();
+             exit (0);
+             break;
 
-           if (strcmp(&argv[i][1],OPTION_NO_LOOP_INV) == 0) {
-               optimize.loopInvariant = 0;
-                continue;
-           }
+           case 'm':
+             /* Used to select the port */
+             _setPort (argv[i] + 2);
+             break;
 
-           if (strcmp(&argv[i][1],OPTION_NO_LOOP_IND) == 0) {
-               optimize.loopInduction = 0;
-                continue;
-           }
+           case 'c':
+              verifyShortOption(argv[i]);
 
-           if (strcmp(&argv[i][1],OPTION_NO_LOOPREV) == 0) {
-               optimize.noLoopReverse = 1;
-                continue;
-           }
-
-           if (!port->parseOption(&argc, argv, &i))
-           {
-               werror(W_UNKNOWN_OPTION,argv[i]);
-           }
-           else
-           {
-               continue;
-           }
-       }      
-
-       /* these are undocumented options */
-       /* if preceded by '/' then turn off certain optmizations, used
-          for debugging only these are also the legacy options from
-          version 1.xx will be removed gradually.
-          It may be an absolute filename.
-       */
-       if ( *argv[i] == '/' && strlen(argv[i]) < 3) {
-           switch (argv[i][1]) {
-               
-           case 'p':
-               optimize.ptrArithmetic=0;
-               break;
+             options.cc_only = 1;
+             break;
 
            case 'L':
-               switch (argv[i][2]) {
-               case '\0':
-                   optimize.label1 = 
-                       optimize.label2 =
-                       optimize.label3 = 
-                       optimize.label4 = 0 ;
-                   break;
-               case '1':
-                   optimize.label1 = 0;
-                   break;
-               case '2':
-                   optimize.label2 = 0;
-                   break;
-               case '3':
-                   optimize.label3 = 0;
-                   break;
-               case '4':
-                   optimize.label4 = 0;
-                   break;
-               }
-               break;
-               
-           case 'l' :
-               switch (argv[i][2]) {               
-               case 'i' :
-                   optimize.loopInvariant = 0;
-                   break;
-               case 'n' :
-                   optimize.loopInduction = 0;
-                   break;
-
-
-               }
-               break ;
-           case 'g' :
-               optimize.global_cse = 0;
-               break;
-
-           }
-           continue ;
-       }
+                libPaths[nlibPaths++] = getStringArg("-L", argv, &i, argc);
+                break;
 
-       /* if preceded by  '-' then option */
-       if ( *argv[i] == '-' ) {
-           switch (argv[i][1]) {
-           case 'h'    :
-               printUsage();
-               exit(0);
-               break;
-               
-           case 'E':
-               preProcOnly = 1;
-               break;
+            case 'l':
+                libFiles[nlibFiles++] = getStringArg("-l", argv, &i, argc);
+                break;
 
-           case 'm':
-               /* Used to select the port */
-               if (_setPort(argv[i] + 2)) {
-                   werror(W_UNSUPP_OPTION,"-m","Unrecognised processor");
-               }
-               break;
-           
-           case 'a'    : 
-               werror(W_UNSUPP_OPTION,"-a","use --stack-auto instead");
-               break ;
-               
-           case 'g'    :
-               werror(W_UNSUPP_OPTION,"-g","use --generic instead");
-               break;
-                               
-           case 'X'    :       /* use external stack           */
-               werror(W_UNSUPP_OPTION,"-X","use --xstack-loc instead");
-               break ;
-               
-           case 'x'    :
-               werror(W_UNSUPP_OPTION,"-x","use --xstack instead");
-               break;
-               
-           case 'p'    :       /* stack pointer intial value */
-           case 'P'    :
-               werror(W_UNSUPP_OPTION,"-p","use --stack-loc instead");
-               break ;
-                               
-           case 'i'    :
-               werror(W_UNSUPP_OPTION,"-i","use --idata-loc instead");
-               break ;
-               
-           case 'r'    :
-               werror(W_UNSUPP_OPTION,"-r","use --xdata-loc instead");
-               break ;
-               
-           case 's'    :
-               werror(W_UNSUPP_OPTION,"-s","use --code-loc instead");
-               break ;         
-                               
-           case 'c':      
-               options.cc_only = 1;
-               break;  
-
-           case 'Y':
-               werror(W_UNSUPP_OPTION,"-Y","use -I instead");
-               break;
-               
-           case 'L' :
-               if (argv[i][2])
-                   libPaths[nlibPaths++] = &argv[i][2];
-               else
-                   libPaths[nlibPaths++] = argv[++i];
-               break;
-               
            case 'W':
-               /* linker options */
-               if (argv[i][2] == 'l') {
-                   if (argv[i][3])
-                       parseWithComma(linkOptions,&argv[i][3]);
-                   else
-                       parseWithComma(linkOptions,argv[++i]);
-               } else {
-                   /* assembler options */
-                   if (argv[i][2] == 'a') {
-                       if (argv[i][3])
-                           parseWithComma((char **)asmOptions,&argv[i][3]);
-                       else
-                           parseWithComma((char **)asmOptions,argv[++i]);
-                       
-                   } else {
-                       werror(W_UNKNOWN_OPTION,argv[i]);                      
+             /* linker options */
+             if (argv[i][2] == 'l')
+               {
+                    parseWithComma(linkOptions, getStringArg("-Wl", argv, &i, argc));
+               }
+             else
+               {
+                 /* assembler options */
+                 if (argv[i][2] == 'a')
+                   {
+                       parseWithComma ((char **) asmOptions, getStringArg("-Wa", argv, &i, argc));
+                   }
+                 else
+                   {
+                     werror (W_UNKNOWN_OPTION, argv[i]);
                    }
                }
-               break;
-           case 'S':
-               noAssemble = 1;
-               break;
+             break;
 
            case 'v':
-#if FEATURE_VERBOSE_EXEC
-               verboseExec = TRUE;
-#else
-               printVersionInfo();
-               exit(0);
-#endif
-               break;
+              verifyShortOption(argv[i]);
+
+             printVersionInfo ();
+             exit (0);
+             break;
 
-               /* preprocessor options */              
+             /* preprocessor options */
+           case 'M':
+             {
+               preProcOnly = 1;
+               addToList (preArgv, "-M");
+               break;
+             }
+           case 'C':
+             {
+               addToList (preArgv, "-C");
+               break;
+             }
            case 'd':
            case 'D':
            case 'I':
-           case 'M':
-           case 'C':
            case 'A':
            case 'U':
-               {
-                   char sOpt = argv[i][1] ;
-                   char *rest ;
-                   
-                   if ( argv[i][2] == ' ' || argv[i][2] == '\0') {
-                       i++ ;
-                       rest = argv[i] ;
-                   }
-                   else
-                       rest = &argv[i][2] ;
-                   
-                   if ( argv[i][1] == 'Y' )
-                       argv[i][1] = 'I';
-                   if (argv[i][1] == 'M')
-                       preProcOnly = 1;
-
-                   sprintf(buffer, "-%c%s", sOpt, rest);
-                   _addToList(preArgv, buffer);
-               }
-               break ;
+             {
+               char sOpt = argv[i][1];
+               char *rest;
+
+               if (argv[i][2] == ' ' || argv[i][2] == '\0')
+                 {
+                   i++;
+                    if (i >= argc) 
+                      {
+                          /* No argument. */
+                          werror(E_ARGUMENT_MISSING, argv[i-1]);
+                          break;
+                      }
+                    else 
+                      {
+                          rest = argv[i];
+                      }
+                 }
+               else
+                 rest = &argv[i][2];
+
+               if (sOpt == 'Y')
+                 sOpt = 'I';
+
+               sprintf (buffer, "-%c%s", sOpt, rest);
+               addToList (preArgv, buffer);
+             }
+             break;
 
            default:
-               if (!port->parseOption(&argc, argv, &i))
-                   werror(W_UNKNOWN_OPTION,argv[i]);
+             if (!port->parseOption (&argc, argv, &i))
+               werror (W_UNKNOWN_OPTION, argv[i]);
            }
-           continue ;
+         continue;
        }
 
-       if (!port->parseOption(&argc, argv, &i)) {
-           /* no option must be a filename */
-           if (options.c1mode)
-               _processC1Arg(argv[i]);
-           else
-               processFile(argv[i]);
-       }
-    }  
-
-    /* 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) {
-       sprintf(cdbfnbuf,"%s.cdb",srcFileName);
-       if ((cdbFile = fopen(cdbfnbuf,"w")) == NULL)
-           werror(E_FILE_OPEN_ERR,cdbfnbuf);
-       else {
-           /* add a module record */
-           fprintf(cdbFile,"M:%s\n",moduleName);
+      if (!port->parseOption (&argc, argv, &i))
+       {
+         /* no option must be a filename */
+         if (options.c1mode)
+           _processC1Arg (argv[i]);
+         else
+           processFile (argv[i]);
        }
     }
-    return 0;
-}
 
-/*-----------------------------------------------------------------*/
-/* my_system - will call a program with arguments                  */
-/*-----------------------------------------------------------------*/
-char *try_dir[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
-int my_system (const char *cmd, char **cmd_argv)
-{    
-    char *dir, *got= NULL; int i= 0;
+  /* set up external stack location if not explicitly specified */
+  if (!options.xstack_loc)
+    options.xstack_loc = options.xdata_loc;
 
-    while (!got && try_dir[i])
+  /* if debug option is set the open the cdbFile */
+  if (options.debug && srcFileName)
     {
-        dir= (char*)malloc(strlen(try_dir[i])+strlen(cmd)+10);
-        strcpy(dir, try_dir[i]);
-        strcat(dir, "/");
-        strcat(dir, cmd);
-
-#if NATIVE_WIN32
-        strcat(dir, ".exe");
-
-        /* Mung slashes into backslashes to keep WIndoze happy. */
+      sprintf (scratchFileName, "%s.cdb", srcFileName);
+      if ((cdbFile = fopen (scratchFileName, "w")) == NULL)
+       werror (E_FILE_OPEN_ERR, scratchFileName);
+      else
        {
-           char *r;
-           r = dir;
-           
-           while (*r)
-               {
-                   if (*r == '/')
-                       {
-                           *r = '\\';
-                       }
-                   r++;
-               }
+         /* add a module record */
+         fprintf (cdbFile, "M:%s\n", moduleName);
        }
-#endif
-
-        if (access(dir, X_OK) == 0)
-        {
-            got= strdup(dir);
-        }
-        free(dir);
-        i++;
-    }
-#if FEATURE_VERBOSE_EXEC
-    if (verboseExec) {
-       char **pCmd = cmd_argv;
-       while (*pCmd) {
-           printf("%s ", *pCmd);
-           pCmd++;
-       }
-       printf("\n");
-    }
-#endif
-    if (got)
-      i= spawnv(P_WAIT,got,cmd_argv) == -1;
-    else
-      i= spawnvp(P_WAIT,cmd,cmd_argv) == -1;
-    if (i) {
-       perror("Cannot exec process ");
-       return -1;
     }
-    
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* linkEdit : - calls the linkage editor  with options             */
 /*-----------------------------------------------------------------*/
-static void linkEdit (char **envp)
+static void
+linkEdit (char **envp)
 {
-    FILE *lnkfile ;
-    char *argv[128];
-    char *segName, *c;
+  FILE *lnkfile;
+  char *segName, *c;
 
-    int i;
-    if (!srcFileName)
-       srcFileName = "temp";
-
-    /* first we need to create the <filename>.lnk file */
-    sprintf(buffer,"%s.lnk",srcFileName);
-    if (!(lnkfile = fopen(buffer,"w"))) {
-       werror(E_FILE_OPEN_ERR,buffer);
-       exit(1);
+  int i;
+  if (!srcFileName)
+    srcFileName = "temp";
+
+  /* first we need to create the <filename>.lnk file */
+  sprintf (scratchFileName, "%s.lnk", srcFileName);
+  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 */
+  fprintf (lnkfile, "-mux%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 (options.debug) */
-    fprintf(lnkfile,"-z\n");
+  /* if iram size specified */
+  if (options.iram_size)
+    fprintf (lnkfile, "-a 0x%04x\n", options.iram_size);
+
+  if (options.debug)
+    fprintf (lnkfile, "-z\n");
 
 #define WRITE_SEG_LOC(N, L) \
     segName = strdup(N); \
     c = strtok(segName, " \t"); \
     fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
-    if (segName) { free(segName); } 
-    
-    /* code segment start */
-    WRITE_SEG_LOC(CODE_NAME, options.code_loc);
-    
-     /* data segment start */
-     WRITE_SEG_LOC(DATA_NAME, options.data_loc);
-                 
-    /* xdata start */
-    WRITE_SEG_LOC(XDATA_NAME, options. xdata_loc);
+    if (segName) { free(segName); }
 
-    /* indirect data */
-    WRITE_SEG_LOC(IDATA_NAME, options.idata_loc);
+  /* code segment start */
+  WRITE_SEG_LOC (CODE_NAME, options.code_loc);
 
-    /* bit segment start */
-    WRITE_SEG_LOC(BIT_NAME, 0);
-    
-    /* add the extra linker options */
-    for (i=0; linkOptions[i] ; i++)
-       fprintf(lnkfile,"%s\n",linkOptions[i]);
+  /* data segment start */
+  WRITE_SEG_LOC (DATA_NAME, options.data_loc);
+
+  /* xdata start */
+  WRITE_SEG_LOC (XDATA_NAME, options.xdata_loc);
+
+  /* indirect data */
+  WRITE_SEG_LOC (IDATA_NAME, options.idata_loc);
+
+  /* bit segment start */
+  WRITE_SEG_LOC (BIT_NAME, 0);
 
-    /* standard library path */
-    switch(options.model)
+  /* add the extra linker options */
+  for (i = 0; linkOptions[i]; i++)
+    fprintf (lnkfile, "%s\n", linkOptions[i]);
+
+  /* other library paths if specified */
+  for (i = 0; i < nlibPaths; i++)
+    fprintf (lnkfile, "-k %s\n", libPaths[i]);
+
+  /* standard library path */
+  if (!options.nostdlib)
+    {
+/****
+      if (TARGET_IS_DS390)
+       {
+         c = "ds390";
+       }
+      else
+*****/
+       {
+         switch (options.model)
+           {
+           case MODEL_SMALL:
+             c = "small";
+             break;
+           case MODEL_LARGE:
+             c = "large";
+             break;
+           case MODEL_FLAT24:
+             /* c = "flat24"; */
+             c = "ds390";
+             break;
+           default:
+             werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
+             c = "unknown";
+             break;
+           }
+       }
+      fprintf (lnkfile, "-k %s/%s\n", SDCC_LIB_DIR /*STD_LIB_PATH */ , c);
+
+      /* standard library files */
+      /* if (strcmp (port->target, "ds390") == 0) */
+      if (options.model == MODEL_FLAT24)
+       {
+         fprintf (lnkfile, "-l %s\n", STD_DS390_LIB);
+       }
+      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);
+    }
+
+  /* additional libraries if any */
+  for (i = 0; i < nlibFiles; i++)
+    fprintf (lnkfile, "-l %s\n", libFiles[i]);
+
+  /* put in the object files */
+  if (strcmp (srcFileName, "temp"))
+    fprintf (lnkfile, "%s ", srcFileName);
+
+  for (i = 0; i < nrelFiles; i++)
+    fprintf (lnkfile, "%s\n", relFiles[i]);
+
+  fprintf (lnkfile, "\n-e\n");
+  fclose (lnkfile);
+
+  if (options.verbose)
+    printf ("sdcc: Calling linker...\n");
+
+  if (port->linker.cmd)
     {
-        case MODEL_SMALL:
-                   c = "small";
-                   break;
-               case MODEL_LARGE:
-                   c = "large";
-                   break;
-               case MODEL_FLAT24:
-                   c = "flat24";
-                   break;
-        default:
-            werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
-            c = "unknown";
-            break;
+      buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
     }
-    fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,c);
-           
-    /* other library paths if specified */
-    for (i = 0 ; i < nlibPaths ; i++ )
-       fprintf (lnkfile,"-k %s\n",libPaths[i]);
-        
-    /* standard library files */
-    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);
-
-    /* additional libraries if any */
-    for (i = 0 ; i < nlibFiles; i++)
-       fprintf (lnkfile,"-l %s\n",libFiles[i]);
-
-    /* put in the object files */
-    if (strcmp(srcFileName,"temp"))
-       fprintf (lnkfile,"%s ",srcFileName);
-
-    for (i = 0 ; i < nrelFiles ; i++ )
-       fprintf (lnkfile,"%s\n",relFiles[i]);
-
-    fprintf (lnkfile,"\n-e\n");
-    fclose(lnkfile);
-
-    buildCmdLine(buffer, argv, port->linker.cmd, srcFileName, NULL, NULL, NULL);
-
-    /* call the linker */
-    if (my_system(argv[0], argv)) {
-       perror("Cannot exec linker");
-       exit(1);
+  else
+    {
+      buildCmdLine2 (buffer, port->linker.mcmd);
     }
 
-    if (strcmp(srcFileName,"temp") == 0) {
-       /* rename "temp.cdb" to "firstRelFile.cdb" */
-       char *f = strtok(strdup(relFiles[0]),".");
-       f = strcat(f,".cdb");
-       rename("temp.cdb",f);       
-       srcFileName = NULL;
+  if (my_system (buffer))
+    {
+      exit (1);
+    }
+
+  if (strcmp (srcFileName, "temp") == 0)
+    {
+      /* rename "temp.cdb" to "firstRelFile.cdb" */
+      char *f = strtok (strdup (relFiles[0]), ".");
+      f = strcat (f, ".cdb");
+      rename ("temp.cdb", f);
+      srcFileName = NULL;
     }
 }
 
 /*-----------------------------------------------------------------*/
 /* assemble - spawns the assembler with arguments                  */
 /*-----------------------------------------------------------------*/
-static void assemble (char **envp)
+static void
+assemble (char **envp)
 {
-    char *argv[128];  /* assembler arguments */
-
-    buildCmdLine(buffer, argv, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
+  if (port->assembler.cmd)
+    {
+      buildCmdLine (buffer, port->assembler.cmd, srcFileName, NULL, NULL, asmOptions);
+    }
+  else
+    {
+      buildCmdLine2 (buffer, port->assembler.mcmd);
+    }
 
-    if (my_system(argv[0], argv)) {
-       perror("Cannot exec assember");
-       exit(1);
+  if (my_system (buffer))
+    {
+      /* either system() or the assembler itself has reported an error
+         perror ("Cannot exec assembler");
+       */
+      exit (1);
     }
 }
 
-
-
 /*-----------------------------------------------------------------*/
-/* preProcess - spawns the preprocessor with arguments            */
+/* preProcess - spawns the preprocessor with arguments       */
 /*-----------------------------------------------------------------*/
-static int preProcess (char **envp)
+static int
+preProcess (char **envp)
 {
-    char *argv[128];
-    char procDef[128];
-
-    preOutName = NULL;
-
-    if (!options.c1mode) {
-       /* if using external stack define the macro */
-       if ( options.useXstack )
-           _addToList(preArgv, "-DSDCC_USE_XSTACK");
-       
-       /* set the macro for stack autos        */
-       if ( options.stackAuto )
-           _addToList(preArgv, "-DSDCC_STACK_AUTO");
-           
-       /* set the macro for stack autos        */
-       if ( options.stack10bit )
-           _addToList(preArgv, "-DSDCC_STACK_TENBIT"); 
-    
-       /* set the macro for large model        */
-       switch(options.model)
-           {
-           case MODEL_LARGE:
-               _addToList(preArgv, "-DSDCC_MODEL_LARGE");
-               break;
-           case MODEL_SMALL:
-               _addToList(preArgv, "-DSDCC_MODEL_SMALL");
-               break;
-           case MODEL_COMPACT:
-               _addToList(preArgv, "-DSDCC_MODEL_COMPACT");
-               break;
-           case MODEL_MEDIUM:
-               _addToList(preArgv, "-DSDCC_MODEL_MEDIUM");
-               break;
-           case MODEL_FLAT24:
-               _addToList(preArgv, "-DSDCC_MODEL_FLAT24");
-               break;
-           default:
-               werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
-               break;
-           }       
-           
-    
-       /* add port (processor information to processor */
-       sprintf(procDef,"-DSDCC_%s",port->target);
-       _addToList(preArgv,procDef);
+  preOutName = NULL;
+
+  if (!options.c1mode)
+    {
+      /* if using external stack define the macro */
+      if (options.useXstack)
+       addToList (preArgv, "-DSDCC_USE_XSTACK");
+
+      /* set the macro for stack autos  */
+      if (options.stackAuto)
+       addToList (preArgv, "-DSDCC_STACK_AUTO");
 
-       if (!preProcOnly)
-           preOutName = strdup(tmpnam(NULL));
+      /* set the macro for stack autos  */
+      if (options.stack10bit)
+       addToList (preArgv, "-DSDCC_STACK_TENBIT");
 
-       buildCmdLine(buffer, argv, _preCmd, fullSrcFileName, 
-                     preOutName, srcFileName, preArgv);
+      /* set the macro for large model  */
+      switch (options.model)
+       {
+       case MODEL_LARGE:
+         addToList (preArgv, "-DSDCC_MODEL_LARGE");
+         break;
+       case MODEL_SMALL:
+         addToList (preArgv, "-DSDCC_MODEL_SMALL");
+         break;
+       case MODEL_COMPACT:
+         addToList (preArgv, "-DSDCC_MODEL_COMPACT");
+         break;
+       case MODEL_MEDIUM:
+         addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
+         break;
+       case MODEL_FLAT24:
+         addToList (preArgv, "-DSDCC_MODEL_FLAT24");
+         break;
+       default:
+         werror (W_UNKNOWN_MODEL, __FILE__, __LINE__);
+         break;
+       }
+
+      /* add port (processor information to processor */
+      addToList (preArgv, "-DSDCC_{port}");
+      addToList (preArgv, "-D__{port}");
+
+      /* standard include path */
+      if (!options.nostdinc) {
+       addToList (preArgv, "-I{includedir}");
+      }
+
+      setMainValue ("cppextraopts", join(preArgv));
+      
+      if (!preProcOnly)
+       preOutName = strdup (tmpnam (NULL));
+
+      setMainValue ("cppoutfilename", preOutName);
+
+      if (options.verbose)
+       printf ("sdcc: Calling preprocessor...\n");
 
-       if (my_system(argv[0], argv)) {
-           unlink (preOutName);
-           perror("Cannot exec Preprocessor");
-           exit(1);
+      buildCmdLine2 (buffer, _preCmd);
+
+      if (my_system (buffer))
+       {
+          // @FIX: Dario Vecchio 03-05-2001
+          if (preOutName)
+            {
+              unlink (preOutName);
+              free (preOutName);
+            }
+          // EndFix
+         exit (1);
        }
 
-       if (preProcOnly)
-           exit(0);
+      if (preProcOnly)
+      {
+       exit (0);
+      }
     }
-    else {
-       preOutName = fullSrcFileName;
+  else
+    {
+      preOutName = fullSrcFileName;
     }
 
-    yyin = fopen(preOutName, "r");
-    if (yyin == NULL) {
-       perror("Preproc file not found\n");
-       exit(1);
+  yyin = fopen (preOutName, "r");
+  if (yyin == NULL)
+    {
+      perror ("Preproc file not found\n");
+      exit (1);
     }
-    
-    return 0;
+
+  return 0;
 }
 
-static void _findPort(int argc, char **argv)
+static bool
+_setPaths (const char *pprefix)
 {
-    argc--;
-    while (argc) {
-       if (!strncmp(*argv, "-m", 2)) {
-           _setPort(*argv + 2);
-           return;
-       }
-       argv++;
-       argc--;
+  /* 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.
+  */
+  getStringDifference (buffer, PREFIX, SDCC_INCLUDE_DIR);
+  strcpy (scratchFileName, pprefix);
+  strcat (scratchFileName, buffer);
+
+  if (pathExists (scratchFileName))
+    {
+      setMainValue ("includedir", scratchFileName);
     }
-    /* Use the first in the list */
-    port = _ports[0];
+  else
+    {
+      return FALSE;
+    }
+
+  getStringDifference (buffer, PREFIX, SDCC_LIB_DIR);
+  strcpy (scratchFileName, pprefix);
+  strcat (scratchFileName, buffer);
+
+  if (pathExists (scratchFileName))
+    {
+      setMainValue ("libdir", scratchFileName);
+    }
+  else
+    {
+      return FALSE;
+    }
+
+  return TRUE;
 }
 
-/* 
+static void
+_discoverPaths (const char *argv0)
+{
+  /* 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.
+   */
+  if (strchr (argv0, DIR_SEPARATOR_CHAR))
+    {
+      strcpy (scratchFileName, argv0);
+      *strrchr (scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
+      setMainValue ("bindir", scratchFileName);
+      ExePathList[0] = gc_strdup (scratchFileName);
+    }
+  else if (getenv (SDCCDIR_NAME) != NULL)
+    {
+      getStringDifference (buffer, PREFIX, BINDIR);
+      strcpy (scratchFileName, getenv (SDCCDIR_NAME));
+      strcat (scratchFileName, buffer);
+      setMainValue ("bindir", scratchFileName);
+      ExePathList[0] = gc_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 wern't where expected. */
+            }
+        }
+      /* Case 2 */
+      if (strchr (argv0, DIR_SEPARATOR_CHAR))
+        {
+          char *pbase = getPrefixFromBinPath (argv0);
+
+          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);
+}
+
+static void
+initValues (void)
+{
+  populateMainValues (_baseValues);
+  setMainValue ("port", port->target);
+  setMainValue ("fullsrcfilename", fullSrcFileName);
+  setMainValue ("srcfilename", srcFileName);
+  setMainValue ("objext", port->linker.rel_ext);
+  setMainValue ("asmext", port->assembler.file_ext);
+}
+
+/*
  * main routine
  * initialises and calls the parser
  */
 
-int main ( int argc, char **argv , char **envp)
+int
+main (int argc, char **argv, char **envp)
 {
-    /* turn all optimizations off by default */
-    memset(&optimize,0,sizeof(struct optimize));
-    
-    /*printVersionInfo ();*/
+  /* turn all optimizations off by default */
+  memset (&optimize, 0, sizeof (struct optimize));
+
+  /*printVersionInfo (); */
+
+  if (NUM_PORTS==0) {
+    fprintf (stderr, "Build error: no ports are enabled.\n");
+    exit (1);
+  }
+
+  _findPort (argc, argv);
+#ifdef JAMIN_DS390
+  if (strcmp(port->target, "mcs51") == 0) {
+    printf("DS390 jammed in A\n");
+         _setPort ("ds390");
+    ds390_jammed = 1;
+  }
+#endif
+  /* Initalise the port. */
+  if (port->init)
+    port->init ();
+
+  // Create a default exe search path from the path to the sdcc command
 
-    _findPort(argc, argv);
-    /* Initalise the port. */
-    if (port->init)
-       port->init();
 
-    setDefaultOptions();
-    parseCmdLine(argc,argv);
+  setDefaultOptions ();
+#ifdef JAMIN_DS390
+  if (ds390_jammed) {
+    options.model = MODEL_SMALL;
+    options.stack10bit=0;
+  }
+#endif
+  parseCmdLine (argc, argv);
+
+  /* if no input then printUsage & exit */
+  if ((!options.c1mode && !srcFileName && !nrelFiles) || 
+      (options.c1mode && !srcFileName && !options.out_name))
+    {
+      printUsage ();
+      exit (0);
+    }
+
+  if (srcFileName)
+    {
+      initValues ();
+      _discoverPaths (argv[0]);
 
-    initMem();
+      preProcess (envp);
 
-    port->finaliseOptions();
+      initMem ();
+
+      port->finaliseOptions ();
+
+      initSymt ();
+      initiCode ();
+      initCSupport ();
+      initPeepHole ();
+
+      if (options.verbose)
+       printf ("sdcc: Generating code...\n");
+
+      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 !OPT_DISABLE_PIC
+           picglue ();
+#endif
+         } else {
+           glue ();
+         }
+
+         if (fatalError)
+           {
+              // @FIX: Dario Vecchio 03-05-2001
+              if (preOutName)
+                {
+                  if (yyin && yyin != stdin)
+                    fclose (yyin);
+                  unlink (preOutName);
+                  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);
+              free (preOutName);
+            }
+          // EndFix
+          #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
+          rm_tmpfiles();
+          #endif
+         return 1;
+       }
 
-    /* if no input then printUsage & exit */
-    if ((!options.c1mode && !srcFileName && !nrelFiles) || (options.c1mode && !srcFileName && !options.out_name)) {
-       printUsage();
-       exit(0);
     }
-       
-    if (srcFileName)
-       preProcess(envp) ;
-
-    if (srcFileName) {
-
-       initSymt();
-       initiCode();
-       initCSupport ();
-       initPeepHole();
-       yyparse();
-
-       if (!fatalError) {
-           glue();
-           if (!options.c1mode)
-               assemble(envp);
-       } else {
-           return 1;
-        }
-       
+
+  closeDumpFiles();
+
+  if (cdbFile)
+    fclose (cdbFile);
+
+  if (preOutName && !options.c1mode)
+    {
+      unlink (preOutName);
+      free (preOutName);
     }
-    
-    if (cdbFile)
-       fclose(cdbFile);
-
-    if (!options.cc_only && 
-       !fatalError      &&
-       !noAssemble      &&
-       !options.c1mode  &&
-       (srcFileName || nrelFiles)) {
-       if (port->linker.do_link)
-           port->linker.do_link();
-       else
-           linkEdit (envp);
+
+  if (!options.cc_only &&
+      !fatalError &&
+      !noAssemble &&
+      !options.c1mode &&
+      (srcFileName || nrelFiles))
+    {
+      if (port->linker.do_link)
+       port->linker.do_link ();
+      else
+       linkEdit (envp);
     }
 
-    if (yyin && yyin != stdin)
-       fclose(yyin);
+  if (yyin && yyin != stdin)
+    fclose (yyin);
 
-    if (preOutName && !options.c1mode) {
-        unlink(preOutName);
-        free(preOutName);
-    }
+  return 0;
 
-    return 0;
-    
 }