* .version: Updated to 2.3.1
authormichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 23 Sep 2001 18:25:45 +0000 (18:25 +0000)
committermichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 23 Sep 2001 18:25:45 +0000 (18:25 +0000)
* src/z80/main.c (z80_port =): Added macro based linker and assembler command line support.
Added copyright header.

* src/SDCCmain.c: Shifted various functions into SDCCutil.c
(assemble): Added support for macro based assembler commands.
(linkEdit): Added support for macro based linker commands.
(preProcess): Changed the pre-processor to use macros.
(_setPaths): Added functionality to autodetect the include, lib and bin dir paths.
(_discoverPaths): Added support for overriding the install directory using the SDCCDIR env variable.

* device/lib/z80/crt0.s: Added module name for debugging.
* src/SDCCmain.c (printVersionInfo): Added the build date to the version info.

* src/SDCChasht.c (hTabDeleteByKey): Fixed delete as it would delete the last item from a bucket even if it wasn't the real one.

* src/SDCCglue.c: Moved gc_strdup to SDCCutil.c

* src/Makefile.in: Added SDCCmacro and SDCCutil

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1303 4a8a32a2-be11-0410-ad9d-d568d2c75423

24 files changed:
.version
ChangeLog
device/lib/z80/crt0.s
doc/macro-sys-design.txt [new file with mode: 0644]
src/Makefile.in
src/SDCCast.c
src/SDCCglue.c
src/SDCChasht.c
src/SDCCmacro.c [new file with mode: 0644]
src/SDCCmacro.h [new file with mode: 0644]
src/SDCCmain.c
src/SDCCutil.c [new file with mode: 0644]
src/SDCCutil.h [new file with mode: 0644]
src/avr/main.c
src/ds390/main.c
src/izt/i186.c
src/izt/tlcs900h.c
src/mcs51/main.c
src/pic/main.c
src/port.h
src/z80/main.c
support/tests/internal/Makefile [new file with mode: 0644]
support/tests/internal/stubs.c [new file with mode: 0644]
support/tests/internal/testmacro.c [new file with mode: 0644]

index 276cbf9e2858c779297bb9f73b34170302949ec4..2bf1c1ccf363acd53eaf92ef33a7f11f5f4557c2 100644 (file)
--- a/.version
+++ b/.version
@@ -1 +1 @@
-2.3.0
+2.3.1
index a6f8bbfad3dedbb905f308383a558a4979a6fce1..0eb3602dd3d84f3ed1fe45865033e7ddcdd42ad1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2001-09-23  Michael Hope  <michaelh@juju.net.nz>
+       * .version: Updated to 2.3.1
+
+       * src/z80/main.c (z80_port =): Added macro based linker and assembler command line support.
+       Added copyright header.
+
+       * src/SDCCmain.c: Shifted various functions into SDCCutil.c
+       (assemble): Added support for macro based assembler commands.
+       (linkEdit): Added support for macro based linker commands.
+       (preProcess): Changed the pre-processor to use macros.
+       (_setPaths): Added functionality to autodetect the include, lib and bin dir paths.
+       (_discoverPaths): Added support for overriding the install directory using the SDCCDIR env variable.
+
+       * device/lib/z80/crt0.s: Added module name for debugging.
+
+2001-09-20  Michael Hope  <michaelh@juju.net.nz>
+
+       * src/SDCCmain.c (printVersionInfo): Added the build date to the version info.
+
+       * src/SDCChasht.c (hTabDeleteByKey): Fixed delete as it would delete the last item from a bucket even if it wasn't the real one.
+
+       * src/SDCCglue.c: Moved gc_strdup to SDCCutil.c
+
+       * src/Makefile.in: Added SDCCmacro and SDCCutil
+
+2001-09-19  Michael Hope  <michaelh@juju.net.nz>
+
+       * src/SDCCmain.c (printVersionInfo): Added the build date to the version info.
+
 2001-09-16    <johan@FRIJA>
 
        * support/Util/SDCCerr.c: fixed up the error/warning/info database. I only changed the E_ W_ I_ prefix to what SDCCerr.c says it is.
index d5d68dd829064e767967eeb7c43a0b0cffb97bfb..5aa3991d315bc0b3ec33db66401ad7604a2e1ae0 100644 (file)
@@ -1,5 +1,6 @@
        ;; Generic crt0.s for a Z80
-       .globl  _main
+        .module crt0
+               .globl  _main
 
        .area _HEADER (ABS)
        ;; Reset vector
diff --git a/doc/macro-sys-design.txt b/doc/macro-sys-design.txt
new file mode 100644 (file)
index 0000000..ef4e889
--- /dev/null
@@ -0,0 +1,79 @@
+Macro system design
+$Id$
+
+The purposes of the macro system are:
+1.  Provide a way to target other assemblers than asxxxx, such as the
+GB IAR or rgbds assemblers.
+2.  Provide a way to target multiple similar processors at a relatively
+simple level from one backend, such as the gbz80 and z80.
+3.  Provide a way to dynamically build a command line for any spawned
+processes.
+4.  Provide a way for the backend to convientely access volatile global data
+such as the source file name or current function name.  This is mainly
+to get around assembler limitations.
+
+Examples are:
+1.  Different assemblers use different forms for immediate values.
+ Compare:
+            ld a,#0x00
+            ld a,$00
+            ld a,#$00
+    Different assemblers use different forms for certain constructs.
+ Compare:
+            .ds 2
+            DS  2
+            DEFS 2
+
+2.  Some concepts, such as prolog and epilogue can be combined.  
+ Compare:
+            push        ix
+            ld          ix,#0
+            add         ix,sp
+
+            ld          hl,0(sp)
+
+3.  Various paths such as include or library paths may change at run
+time.
+
+4.  Need to use the function name in a temporary variable name as the
+assembler doesn't support temporary local labels
+ Compare:
+            1$:
+            _func_0001:
+
+Types of data:
+1.  Static for a given starting set of parameters, such as target
+assembler or path
+
+          {zero}        -> #0, $0, 0x00
+          {sdccinclude} -> c:/sdcc/include, /usr/share/sdcc/include
+
+2.  Static for a given starting set of parameters, but include
+arguments inside them
+
+          {immeda}       -> #0x%02X, $%02X
+          {areaa}        -> .area %s, SECTION "%s"
+
+3.  Volatile throughout the run time with no parameters
+
+          {currfuncv}    -> _func
+
+4.  Volatile with arguments
+          {templabeldef} -> {currfuncv}_%d:
+
+Rules:
+1.  Macros are surrounded by curly braces {}.  
+2.  Curly braces cannot appear in any data.
+3.  Macros will be recursively expanded.  The expansion cannot be
+cyclic.
+4.  Macros used as values to arguments will be recursively expanded.
+Any macros used as argument values cannot require arguments.  If they
+do the arguments will not be evaluated.
+
+Problems:
+1.  There is no type checking or usage checking due to things being
+evaluated at run time.  This could be verified by using a separate
+perl script to statically evaluate the strings.
+
+-- Michael
+
index ea65a689703d479f40cd0d6e314ddd566fc3cbd3..baf48592aa27a46d9c167f9cee2dd16a955cd1ae 100644 (file)
@@ -27,7 +27,7 @@ OBJECTS       = SDCCy.o SDCChasht.o SDCCmain.o \
                  SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \
                  SDCCBBlock.o SDCCloop.o SDCCcse.o SDCCcflow.o SDCCdflow.o \
                  SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o spawn.o \
-                 asm.o
+                 asm.o SDCCmacro.o SDCCutil.o
 
 SPECIAL                = SDCCy.h 
 ifeq ($(USE_ALT_LEX), 1)
index 0a429066c6c0114f565ce4224a0d5a1aeac55ca7..09ad2b53b5430271b86d47bd3b47d3c4b978521d 100644 (file)
@@ -46,7 +46,6 @@ int labelKey = 1;
 #define ALLOCATE 1
 #define DEALLOCATE 2
 
-char buffer[1024];
 int noLineno = 0;
 int noAlloc = 0;
 symbol *currFunc;
index 68303f381c5203d6191bd3f718c7e21969761680..d74a0f3bea06d25dc9d449303768cd12e470b5e7 100644 (file)
@@ -1573,11 +1573,3 @@ tempfile (void)
   return tmpfile ();
 }
 
-char *
-gc_strdup (const char *s)
-{
-  char *ret;
-  ret = Safe_calloc (1, strlen (s) + 1);
-  strcpy (ret, s);
-  return ret;
-}
index 69d1f2501880730b716771beddc30b3806e8f973..71821860912bff87a50720c5a815399850190a96 100644 (file)
@@ -279,6 +279,7 @@ int
 hTabDeleteByKey (hTab ** h, int key, const void *pkey, int (*compare) (const void *, const void *))
 {
   hashtItem *htip, **htipp;
+  bool found = FALSE;
 
   if (!(*h))
     return 0;
@@ -300,16 +301,22 @@ hTabDeleteByKey (hTab ** h, int key, const void *pkey, int (*compare) (const voi
           pkey == htip->pkey)
        {
          *htipp = htip->next;
+          found = TRUE;
          break;
        }
       htipp = &(htip->next);
     }
-  (*h)->nItems--;
 
-  if (!(*h)->nItems)
+  if (found == TRUE)
     {
-      *h = NULL;
+      (*h)->nItems--;
+      
+      if (!(*h)->nItems)
+        {
+          *h = NULL;
+        }
     }
+
   return 1;
 }
 
diff --git a/src/SDCCmacro.c b/src/SDCCmacro.c
new file mode 100644 (file)
index 0000000..49db2a0
--- /dev/null
@@ -0,0 +1,126 @@
+/*-------------------------------------------------------------------------
+  SDCCmain.c - Macro support code.
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
+
+   This program is free software; you can redistribute it and/or modify it
+   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!
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+
+enum 
+  {
+    MAX_STRING_LENGTH  = FILENAME_MAX,
+    MAX_MACRO_NAME_LENGTH = 128
+  };
+
+void
+_evalMacros(char *apinto, hTab *pvals, const char *pfrom)
+{
+  bool fdidsomething = FALSE;
+  char *pinto = apinto;
+
+  assert(pinto && pvals && pfrom);
+
+  while (*pfrom)
+    {
+      if (*pfrom == '{')
+        {
+          const char *pend = ++pfrom;
+          char name[MAX_MACRO_NAME_LENGTH];
+          const char *pval;
+
+          while (*pend && *pend != '}')
+            {
+              pend++;
+            }
+          if (*pend != '}')
+            {
+              wassertl(0, "Unterminated macro expansion");
+            }
+          /* Pull out the macro name */
+          strncpy(name, pfrom, pend-pfrom);
+          name[pend-pfrom] = '\0';
+
+          /* Look up the value in the hash table */
+          pval = shash_find (pvals, name);
+          
+          if (pval == NULL)
+            {
+             fprintf (stderr, "Cant find macro \"%s\"\n", name);
+             wassertl (0, "Invalid macro name");
+            }
+
+          printf("Mapping %s to \"%s\"\n", name, pval);
+
+          /* Replace */
+          strcpy(pinto, pval);
+          pinto += strlen(pval);
+          fdidsomething = TRUE;
+
+          pfrom = pend+1;
+        }
+      else
+        {
+          /* Pass through */
+          *pinto++ = *pfrom++;
+        }
+    }
+
+  *pinto = '\0';
+
+  /* If we did something then recursivly expand any expanded macros */
+  if (fdidsomething)
+    {
+      char ainto[MAX_STRING_LENGTH];
+      _evalMacros(ainto, pvals, apinto);
+      strcpy(apinto, ainto);
+    }
+}
+
+char *
+mvsprintf(hTab *pvals, const char *pformat, va_list ap)
+{
+  char ainto[MAX_STRING_LENGTH];
+  char atmp[MAX_STRING_LENGTH];
+
+  /* Recursivly evaluate all the macros in the string */
+  _evalMacros(ainto, pvals, pformat);
+  /* Evaluate all the arguments */
+  vsprintf(atmp, ainto, ap);
+  /* Recursivly evaluate any macros that were used as arguments */
+  _evalMacros(ainto, pvals, atmp);
+
+  /* Return a copy of the evaluated string. */
+  return gc_strdup(ainto);
+}
+
+char *msprintf(hTab *pvals, const char *pformat, ...)
+{
+  va_list ap;
+  char *pret;
+
+  va_start(ap, pformat);
+
+  pret = mvsprintf(pvals, pformat, ap);
+
+  va_end(ap);
+
+  return pret;
+}
diff --git a/src/SDCCmacro.h b/src/SDCCmacro.h
new file mode 100644 (file)
index 0000000..b6b499c
--- /dev/null
@@ -0,0 +1,36 @@
+/*-----------------------------------------------------------------
+    SDCChast.h - contains support routines for hashtables/sets .
+
+    Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+    This program is free software; you can redistribute it and/or modify it
+    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!  
+-------------------------------------------------------------------------*/
+
+
+#ifndef SDCCMACRO_H
+#define SDCCMACRO_H
+
+#include "SDCChasht.h"
+#include <stdarg.h>
+
+char *mvsprintf(hTab *pvals, const char *pformat, va_list ap);
+char *msprintf(hTab *pvals, const char *pformat, ...);
+
+#endif
+
index 4222a01d7b43906e4f4b14ebef9549177487fb4e..058f521507dcd657a21a1fa978809e39bd9f9c3a 100644 (file)
@@ -28,6 +28,8 @@
 #include "SDCCerr.h"
 #include "BuildCmd.h"
 #include "MySystem.h"
+#include "SDCCmacro.h"
+#include "SDCCutil.h"
 
 #if NATIVE_WIN32
 #include <process.h>
 #endif
 
 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#include <sys/stat.h>
 #include <unistd.h>
 #endif
 
+/** Name of the environment variable checked for other instalations. */
+#define SDCCDIR_NAME "SDCCDIR"
+
 //REMOVE ME!!!
 extern int yyparse ();
 
@@ -74,6 +80,7 @@ int ds390_jammed = 0;
 
 // 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
 
@@ -226,12 +233,14 @@ unsupportedOptTable[] = {
     { 'Y',  NULL,      "use -I instead" }
 };
 
-static const char *_preCmd[] =
-{
-  "sdcpp", "-Wall", "-lang-c++", "-DSDCC=1",
-  "$l", "$1", "$2", NULL
+static const char *_baseValues[] = {
+  "cpp", "{bindir}/sdcpp",
+  "cppextraopts", "",
+  NULL
 };
 
+static const char *_preCmd = "{cpp} -Wall -lang-c++ -DSDCC=1 {cppextraopts} {fullsrcfilename} {cppoutfilename}";
+
 PORT *port;
 
 static PORT *_ports[] =
@@ -302,6 +311,25 @@ _validatePorts (void)
        }
     }
 }
+
+static void
+_findPort (int argc, char **argv)
+{
+  _validatePorts ();
+
+  while (argc--)
+    {
+      if (!strncmp (*argv, "-m", 2))
+       {
+         _setPort (*argv + 2);
+         return;
+       }
+      argv++;
+    }
+  /* Use the first in the list */
+  port = _ports[0];
+}
+
 /*-----------------------------------------------------------------*/
 /* printVersionInfo - prints the version info        */
 /*-----------------------------------------------------------------*/
@@ -319,6 +347,7 @@ printVersionInfo ()
 #ifdef SDCC_SUB_VERSION_STR
           "/" SDCC_SUB_VERSION_STR
 #endif
+           " (" __DATE__ ")"
 #ifdef __CYGWIN__
           " (CYGWIN)\n"
 #else
@@ -534,21 +563,6 @@ _processC1Arg (char *s)
     }
 }
 
-static void
-_addToList (const char **list, const char *str)
-{
-  /* 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);
-    }
-  *(++list) = NULL;
-}
-
 static void
 _setModel (int model, const char *sz)
 {
@@ -945,12 +959,12 @@ parseCmdLine (int argc, char **argv)
            case 'M':
              {
                preProcOnly = 1;
-               _addToList (preArgv, "-M");
+               addToList (preArgv, "-M");
                break;
              }
            case 'C':
              {
-               _addToList (preArgv, "-C");
+               addToList (preArgv, "-C");
                break;
              }
            case 'd':
@@ -983,7 +997,7 @@ parseCmdLine (int argc, char **argv)
                  sOpt = 'I';
 
                sprintf (buffer, "-%c%s", sOpt, rest);
-               _addToList (preArgv, buffer);
+               addToList (preArgv, buffer);
              }
              break;
 
@@ -1143,7 +1157,16 @@ linkEdit (char **envp)
   if (options.verbose)
     printf ("sdcc: Calling linker...\n");
 
-  buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+  if (port->linker.cmd)
+    {
+      buildCmdLine (buffer, port->linker.cmd, srcFileName, NULL, NULL, NULL);
+    }
+  else
+    {
+      printf("Here 1\n");
+      buildCmdLine2 (buffer, port->linker.mcmd);
+    }
+
   if (my_system (buffer))
     {
       exit (1);
@@ -1165,7 +1188,15 @@ linkEdit (char **envp)
 static void
 assemble (char **envp)
 {
-  buildCmdLine (buffer, 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 (buffer))
     {
       /* either system() or the assembler itself has reported an error
@@ -1175,74 +1206,72 @@ assemble (char **envp)
     }
 }
 
-
-
 /*-----------------------------------------------------------------*/
 /* preProcess - spawns the preprocessor with arguments       */
 /*-----------------------------------------------------------------*/
 static int
 preProcess (char **envp)
 {
-  char procDef[128];
-
   preOutName = NULL;
 
   if (!options.c1mode)
     {
       /* if using external stack define the macro */
       if (options.useXstack)
-       _addToList (preArgv, "-DSDCC_USE_XSTACK");
+       addToList (preArgv, "-DSDCC_USE_XSTACK");
 
       /* set the macro for stack autos  */
       if (options.stackAuto)
-       _addToList (preArgv, "-DSDCC_STACK_AUTO");
+       addToList (preArgv, "-DSDCC_STACK_AUTO");
 
       /* set the macro for stack autos  */
       if (options.stack10bit)
-       _addToList (preArgv, "-DSDCC_STACK_TENBIT");
+       addToList (preArgv, "-DSDCC_STACK_TENBIT");
 
       /* set the macro for large model  */
       switch (options.model)
        {
        case MODEL_LARGE:
-         _addToList (preArgv, "-DSDCC_MODEL_LARGE");
+         addToList (preArgv, "-DSDCC_MODEL_LARGE");
          break;
        case MODEL_SMALL:
-         _addToList (preArgv, "-DSDCC_MODEL_SMALL");
+         addToList (preArgv, "-DSDCC_MODEL_SMALL");
          break;
        case MODEL_COMPACT:
-         _addToList (preArgv, "-DSDCC_MODEL_COMPACT");
+         addToList (preArgv, "-DSDCC_MODEL_COMPACT");
          break;
        case MODEL_MEDIUM:
-         _addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
+         addToList (preArgv, "-DSDCC_MODEL_MEDIUM");
          break;
        case MODEL_FLAT24:
-         _addToList (preArgv, "-DSDCC_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" SDCC_INCLUDE_DIR);
+       addToList (preArgv, "-I{includedir}");
       }
 
-      /* add port (processor information to processor */
-      sprintf (procDef, "-DSDCC_%s", port->target);
-      _addToList (preArgv, procDef);
-      sprintf (procDef, "-D__%s", port->target);
-      _addToList (preArgv, procDef);
-
+      setMainValue ("cppextraopts", join(preArgv));
+      
       if (!preProcOnly)
        preOutName = strdup (tmpnam (NULL));
 
+      setMainValue ("cppoutfilename", preOutName);
+
       if (options.verbose)
        printf ("sdcc: Calling preprocessor...\n");
 
-      buildCmdLine (buffer, _preCmd, fullSrcFileName,
-                   preOutName, srcFileName, preArgv);
+      buildCmdLine2 (buffer, _preCmd);
+
       if (my_system (buffer))
        {
           // @FIX: Dario Vecchio 03-05-2001
@@ -1275,22 +1304,144 @@ preProcess (char **envp)
   return 0;
 }
 
-static void
-_findPort (int argc, char **argv)
+static bool
+_setPaths (const char *pprefix)
 {
-  _validatePorts ();
+  /* 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);
+    }
+  else
+    {
+      return FALSE;
+    }
 
-  while (argc--)
+  getStringDifference (buffer, PREFIX, SDCC_LIB_DIR);
+  strcpy (scratchFileName, pprefix);
+  strcat (scratchFileName, buffer);
+
+  if (pathExists (scratchFileName))
     {
-      if (!strncmp (*argv, "-m", 2))
-       {
-         _setPort (*argv + 2);
-         return;
-       }
-      argv++;
+      setMainValue ("libdir", scratchFileName);
     }
-  /* Use the first in the list */
-  port = _ports[0];
+  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);
 }
 
 /*
@@ -1326,15 +1477,6 @@ main (int argc, char **argv, char **envp)
   // Create a default exe search path from the path to the sdcc command
 
 
-
-  if (strchr (argv[0], DIR_SEPARATOR_CHAR))
-    {
-      strcpy (DefaultExePath, argv[0]);
-      *(strrchr (DefaultExePath, DIR_SEPARATOR_CHAR)) = 0;
-      ExePathList[0] = DefaultExePath;
-    }
-
-
   setDefaultOptions ();
 #ifdef JAMIN_DS390
   if (ds390_jammed) {
@@ -1344,11 +1486,6 @@ main (int argc, char **argv, char **envp)
 #endif
   parseCmdLine (argc, argv);
 
-  if (getenv("SDCPP"))
-  {
-    _preCmd[0] = getenv("SDCPP");
-  }
-    
   /* if no input then printUsage & exit */
   if ((!options.c1mode && !srcFileName && !nrelFiles) || 
       (options.c1mode && !srcFileName && !options.out_name))
@@ -1359,6 +1496,9 @@ main (int argc, char **argv, char **envp)
 
   if (srcFileName)
     {
+      initValues ();
+      _discoverPaths (argv[0]);
+
       preProcess (envp);
 
       initMem ();
diff --git a/src/SDCCutil.c b/src/SDCCutil.c
new file mode 100644 (file)
index 0000000..5a3be47
--- /dev/null
@@ -0,0 +1,226 @@
+/*-------------------------------------------------------------------------
+  SDCCutil.c - Small utility functions.
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
+
+   This program is free software; you can redistribute it and/or modify it
+   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!
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+#include "SDCCmacro.h"
+#include "SDCCutil.h"
+#include "newalloc.h"
+#include <sys/stat.h>
+
+/** Given an array of name, value string pairs creates a new hash
+    containing all of the pairs.
+*/
+hTab *
+populateStringHash(const char **pin)
+{
+  hTab *pret = NULL;
+
+  while (*pin)
+    {
+      shash_add (&pret, pin[0], pin[1]);
+      pin += 2;
+    }
+
+  return pret;
+}
+
+/** Given an array of string pointers and another string, adds the
+    string to the end of the list.  The end of the list is assumed to
+    be the first NULL pointer.
+*/
+void
+addToList (const char **list, const char *str)
+{
+  /* 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);
+    }
+  *(++list) = NULL;
+}
+
+/** Given an array of string pointers returns a string containing all
+    of the strings seperated by spaces.  The returned string is on the
+    heap.  The join stops when a NULL pointer is hit.
+*/
+char *
+join(const char **pplist)
+{
+  char *pinto = buffer;
+  *pinto = '\0';
+
+  while (*pplist)
+    {
+      strcpy(pinto, *pplist);
+      pinto += strlen(*pplist);
+      *pinto++ = ' ';
+      pplist++;
+    }
+
+  return buffer;
+}
+
+/** Given an array of string pointers, returns a string containing all
+    of the strings seperated by spaces.  The returned string is on the
+    heap.  n is the number of strings in the list.
+*/
+char *
+joinn(char **pplist, int n)
+{
+  char *pinto = buffer;
+  *pinto = '\0';
+
+  while (n--)
+    {
+      strcpy(pinto, *pplist);
+      pinto += strlen(*pplist);
+      *pinto++ = ' ';
+      pplist++;
+    }
+  *pinto = '\0';
+
+  return buffer;
+}
+
+/** Returns the characters in p2 past the last matching characters in
+    p1.  
+*/
+char *
+getStringDifference (char *pinto, const char *p1, const char *p2)
+{
+  char *p = pinto;
+
+  while (*p1 != '\0' && *p2 != '\0')
+    {
+      if (*p1++ != *p2++)
+        {
+          break;
+        }
+    }
+  while (*p2)
+    {
+      *p++ = *p2++;
+    }
+  *p = '\0';
+
+  return pinto;
+}
+
+/** Given a file with path information in the binary files directory,
+    returns what PREFIX must be to get this path.  Used for discovery
+    of where SDCC is installed.  Returns NULL if the path is
+    impossible.
+*/
+char *
+getPrefixFromBinPath (const char *prel)
+{
+  strcpy(scratchFileName, prel);
+  /* Strip off the /sdcc at the end */
+  *strrchr(scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
+  /* Compute what the difference between the prefix and the bin dir
+     should be. */
+  getStringDifference (buffer, PREFIX, BINDIR);
+
+  /* Verify that the path in has the expected suffix */
+  if (strlen(buffer) > strlen(scratchFileName))
+    {
+      /* Not long enough */
+      return NULL;
+    }
+  if (strcmp(buffer, scratchFileName + strlen(scratchFileName) - strlen(buffer)) != 0)
+    {
+      /* Doesn't match */
+      return NULL;
+    }
+
+  scratchFileName[strlen(scratchFileName) - strlen(buffer)] = '\0';
+
+  return gc_strdup (scratchFileName);
+}
+
+/** Returns true if the given path exists.
+ */
+bool
+pathExists (const char *ppath)
+{
+  struct stat s;
+
+  return stat (ppath, &s) == 0;
+}
+
+static hTab *_mainValues;
+
+void
+setMainValue (const char *pname, const char *pvalue)
+{
+  shash_add (&_mainValues, pname, pvalue);
+}
+
+void
+buildCmdLine2 (char *pbuffer, const char *pcmd)
+{
+  char *poutcmd = msprintf(_mainValues, pcmd);
+  printf("In: \"%s\"\n", pcmd);
+  printf("Out: \"%s\"\n", poutcmd);
+  strcpy(pbuffer, poutcmd);
+}
+
+void
+populateMainValues (const char **ppin)
+{
+  _mainValues = populateStringHash(ppin);
+}
+
+char *
+gc_strdup (const char *s)
+{
+  char *ret;
+  ret = Safe_calloc (1, strlen (s) + 1);
+  strcpy (ret, s);
+  return ret;
+}
+
+/** Returns true if sz starts with the string given in key.
+ */
+bool
+startsWith (const char *sz, const char *key)
+{
+  return !strncmp (sz, key, strlen (key));
+}
+
+/** Removes any newline characters from the string.  Not strictly the
+    same as perl's chomp.
+*/
+void
+chomp (char *sz)
+{
+  char *nl;
+  while ((nl = strrchr (sz, '\n')))
+    *nl = '\0';
+}
+
diff --git a/src/SDCCutil.h b/src/SDCCutil.h
new file mode 100644 (file)
index 0000000..55a8f9f
--- /dev/null
@@ -0,0 +1,88 @@
+/*-------------------------------------------------------------------------
+  SDCCutil.c - Small utility functions.
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
+
+   This program is free software; you can redistribute it and/or modify it
+   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!
+-------------------------------------------------------------------------*/
+
+#ifndef SDCCUTIL_H
+#define SDCCUTIL_H
+
+#include "SDCChasht.h"
+
+/* PENDING: Hacks as I can't work autoconf */
+#define BINDIR PREFIX "/bin"
+
+/** Given an array of name, value string pairs creates a new hash
+    containing all of the pairs.
+*/
+hTab *populateStringHash(const char **pin);
+
+/** Given an array of string pointers and another string, adds the
+    string to the end of the list.  The end of the list is assumed to
+    be the first NULL pointer.
+*/
+void addToList (const char **list, const char *str);
+
+/** Given an array of string pointers returns a string containing all
+    of the strings seperated by spaces.  The returned string is on the
+    heap.  The join stops when a NULL pointer is hit.
+*/
+char *join(const char **pplist);
+
+/** Given an array of string pointers, returns a string containing all
+    of the strings seperated by spaces.  The returned string is on the
+    heap.  n is the number of strings in the list.
+*/
+char *joinn(char **pplist, int n);
+
+/** Returns the characters in p2 past the last matching characters in
+    p1.  
+*/
+char *getStringDifference (char *pinto, const char *p1, const char *p2);
+
+/** Given a file with path information in the binary files directory,
+    returns what PREFIX must be to get this path.  Used for discovery
+    of where SDCC is installed.  Returns NULL if the path is
+    impossible.
+*/
+char *getPrefixFromBinPath (const char *prel);
+
+/** Returns true if the given path exists.
+ */
+bool pathExists (const char *ppath);
+
+void setMainValue (const char *pname, const char *pvalue);
+
+void populateMainValues (const char **ppin);
+
+void buildCmdLine2 (char *pbuffer, const char *pcmd);
+
+/** Returns true if sz starts with the string given in key.
+ */
+bool startsWith (const char *sz, const char *key);
+
+/** Removes any newline characters from the string.  Not strictly the
+    same as perl's chomp.
+*/
+void chomp (char *sz);
+
+#endif
+
index c14ba658c563932b5f918da05f14b6d680ad262b..b3e33659a5a9e1d49a9e6f28c95f9e1854b5d64e 100644 (file)
@@ -156,12 +156,14 @@ PORT avr_port = {
         MODEL_SMALL},
        {
         _asmCmd,
+         NULL,
         "-plosgff",            /* Options with debug */
         "-plosgff",            /* Options without debug */
         0,
        ".s"},
        {
         _linkCmd,
+         NULL,
         NULL,
         ".rel"},
        {
index b1ff65bc770dc8cb4383135c62b529f9ee63989b..2da52b77a15a6209c99b316e480a613e0b3af2cd 100644 (file)
@@ -218,6 +218,7 @@ PORT ds390_port =
   },
   {
     _asmCmd,
+    NULL,
     "-plosgffc",               /* Options with debug */
     "-plosgff",                        /* Options without debug */
     0,
@@ -226,6 +227,7 @@ PORT ds390_port =
   {
     _linkCmd,
     NULL,
+    NULL,
     ".rel"
   },
   {
index 7a4e39ddd4299993217430c07e8c8aa65b56ef23..ba4742e46ffeb9eb945a8c32522277d00a01637a 100644 (file)
@@ -145,12 +145,14 @@ PORT i186_port = {
         _asmCmd,
         NULL,
         NULL,
+        NULL,
         0,
         ".s"
     },
     {
         _linkCmd,
         NULL,
+        NULL,
         ".o"
     },
     {
index e9f852084f0def9f5d412340cc6b349f23416fe2..b06c141cb7124ce7d9b0da7607e96b89facd7272 100644 (file)
@@ -144,12 +144,14 @@ PORT tlcs900h_port =
     _asmCmd,
     NULL,
     NULL,
+    NULL,
     0,
     NULL
   },
   {
     _linkCmd,
     NULL,
+    NULL,
     ".o"
   },
   {
index c06d08a9c6d0b0f6b44360da588127be7f522fe1..3dcb4d86258f15aa223151bfe08ee575ab21ea0b 100644 (file)
@@ -149,6 +149,7 @@ PORT mcs51_port =
   },
   {
     _asmCmd,
+    NULL,
     "-plosgffc",               /* Options with debug */
     "-plosgff",                        /* Options without debug */
     0,
@@ -157,6 +158,7 @@ PORT mcs51_port =
   {
     _linkCmd,
     NULL,
+    NULL,
     ".rel"
   },
   {
index f623d1ca432b69344fffe7d8127f54b7e2a59888..ee7c699a22cdd94e2911dadf43381a4b03868b2d 100644 (file)
@@ -228,6 +228,7 @@ PORT pic_port =
   {
     _asmCmd,
     NULL,
+    NULL,
     NULL,
        //"-plosgffc",          /* Options with debug */
        //"-plosgff",           /* Options without debug */
@@ -237,6 +238,7 @@ PORT pic_port =
   {
     _linkCmd,
     NULL,
+    NULL,
     ".rel"
   },
   {
index 897380323e740ce4d0dc0ee586f74868a3e0e14c..3e8339e64a759b47104cc0f4a8280c575e58c58b 100644 (file)
@@ -55,11 +55,13 @@ typedef struct
     /* assembler related information */
     struct
       {
-/** Command to run and arguments (eg as-z80) */
-       const char **cmd;
-/** Arguments for debug mode.  PENDING: ignored */
+        /** Command to run and arguments (eg as-z80) */
+        const char **cmd;
+        /** Alternate macro based form. */
+        const char *mcmd;
+        /** Arguments for debug mode.  PENDING: ignored */
        const char *debug_opts;
-/** Arguments for normal assembly mode.  PENDING: ignored */
+        /** Arguments for normal assembly mode.  PENDING: ignored */
        const char *plain_opts;
        /* print externs as global */
        int externGlobal;
@@ -71,11 +73,13 @@ typedef struct
     /* linker related info */
     struct
       {
-/** Command to run (eg link-z80) */
+        /** Command to run (eg link-z80) */
        const char **cmd;
-/** If non-null will be used to execute the link. */
+        /** Alternate macro based form. */
+        const char *mcmd;
+        /** If non-null will be used to execute the link. */
        void (*do_link) (void);
-/** Extention for object files (.rel, .obj, ...) */
+        /** Extention for object files (.rel, .obj, ...) */
        const char *rel_ext;
       }
     linker;
index a13db0004787cb0c4da88e2d06ff2a2719e2090c..2a07616fed1889d6e2e66b19d9f6adbac28c6ce0 100644 (file)
@@ -1,6 +1,31 @@
+/*-------------------------------------------------------------------------
+  main.c - Z80 specific definitions.
+
+  Michael Hope <michaelh@juju.net.nz> 2001
+
+   This program is free software; you can redistribute it and/or modify it
+   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!
+-------------------------------------------------------------------------*/
+
 #include "z80.h"
 #include "MySystem.h"
 #include "BuildCmd.h"
+#include "SDCCutil.h"
 
 static char _z80_defaultRules[] =
 {
@@ -86,28 +111,14 @@ _reg_parm (sym_link * l)
     }
 }
 
-static bool
-_startsWith (const char *sz, const char *key)
-{
-  return !strncmp (sz, key, strlen (key));
-}
-
-static void
-_chomp (char *sz)
-{
-  char *nl;
-  while ((nl = strrchr (sz, '\n')))
-    *nl = '\0';
-}
-
 static int
 _process_pragma (const char *sz)
 {
-  if (_startsWith (sz, "bank="))
+  if (startsWith (sz, "bank="))
     {
       char buffer[128];
       strcpy (buffer, sz + 5);
-      _chomp (buffer);
+      chomp (buffer);
       if (isdigit (buffer[0]))
        {
 
@@ -122,7 +133,7 @@ _process_pragma (const char *sz)
             way. */
          char num[128];
          strcpy (num, sz + 5);
-         _chomp (num);
+         chomp (num);
 
          switch (_G.asmType)
            {
@@ -255,6 +266,40 @@ _parseOptions (int *pargc, char **argv, int *i)
   return FALSE;
 }
 
+static void
+_setValues(void)
+{
+  if (options.nostdlib == FALSE)
+    {
+      setMainValue ("z80libspec", "-k{libdir}/{port} -l{port}.lib");
+      setMainValue ("z80crt0", "{libdir}/{port}/crt0{objext}");
+    }
+  else
+    {
+      setMainValue ("z80libspec", "");
+      setMainValue ("z80crt0", "");
+    }
+
+  setMainValue ("z80extralibfiles", joinn (libFiles, nlibFiles));
+  setMainValue ("z80extralibpaths", joinn (libPaths, nlibPaths));
+
+  if (IS_GB)
+    {
+      setMainValue ("z80outputtypeflag", "-z");
+      setMainValue ("z80outext", ".gb");
+    }
+  else
+    {
+      setMainValue ("z80outputtypeflag", "-i");
+      setMainValue ("z80outext", ".ihx");
+    }
+
+  setMainValue ("z80extraobj", joinn (relFiles, nrelFiles));
+  
+  sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc);
+  setMainValue ("z80bases", buffer);
+}
+
 static void
 _finaliseOptions (void)
 {
@@ -262,6 +307,8 @@ _finaliseOptions (void)
   port->mem.default_globl_map = data;
   if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
     asm_addTree (&_asxxxx_gb);
+
+  _setValues();
 }
 
 static void
@@ -339,155 +386,17 @@ _getRegName (struct regs *reg)
   return "err";
 }
 
-/** $1 is always the basename.
-    $2 is always the output file.
-    $3 varies
-    $l is the list of extra options that should be there somewhere...
-    MUST be terminated with a NULL.
-*/
-static const char *_z80_asmCmd[] =
-{
-    "as-z80", 
-    "-plosgff", 
-    "$1.o", 
-    "$1.asm", 
-    NULL
-};
+#define LINKCMD \
+    "{bindir}/link-{port} -n -c -- {z80bases} -m -j" \
+    " {z80libspec}" \
+    " {z80extralibfiles} {z80extralibpaths}" \
+    " {z80outputtypeflag} {srcfilename}{z80outext}" \
+    " {z80crt0}" \
+    " {srcfilename}{objext}" \
+    " {z80extraobj}" 
 
-static const char *_z80_linkCmd[] =
-{
-    "link-z80", 
-    "-n",                       // Don't echo output
-    "-c",                       // Command line input
-    "--",                       // Again, command line input...
-    "-b_CODE=0x200",            // Code starts at 0x200
-    "-b_DATA=0x8000",           // RAM starts at 0x8000
-    "-j",                       // Output a symbol file as well
-    "-k" SDCC_LIB_DIR "/z80",   // Library path
-    "-lz80.lib",                // Library to use
-    "-i",                       // Output Intel IHX
-    "$1.ihx",                   // Output to
-    SDCC_LIB_DIR "/z80/crt0.o", // Link in crt0 first
-    "$1.o",                     // Actual code
-    NULL
-};
-
-static const char *_gbz80_asmCmd[] =
-{
-    "as-gbz80", 
-    "-plosgff", 
-    "$1.o", 
-    "$1.asm", 
-    NULL
-};
-
-static const char *_gbz80_linkCmd[] =
-{
-    "link-gbz80", 
-    "-n",                       // Don't echo output
-    "-c",                       // Command line input
-    "--",                       // Again, command line input...
-    "-b_CODE=0x200",            // Code starts at 0x200
-    "-b_DATA=0xC000",           // RAM starts at 0xC000
-    "-j",                       // Output a symbol file as well
-    "-k" SDCC_LIB_DIR "/gbz80", // Library path
-    "-lgbz80.lib",              // Library to use
-    "-z",                       // Output Gameboy image
-    "$1.gb",                    // Output to
-    SDCC_LIB_DIR "/gbz80/crt0.o",// Link in crt0 first
-    "$1.o",                     // Actual code
-    NULL
-};
-
-/* sprintf that appends to the string. */
-static void
-_saprintf(char *pinto, const char *format, ...)
-{
-    va_list ap;
-    va_start(ap, format);
-
-    vsprintf(pinto + strlen(pinto), format, ap);
-    va_end(ap);
-}
-
-static void
-_link(const char *portName, const char *portExt, const char *portOutputType)
-{
-    int i;
-    // PENDING
-    char buffer[2048];
-
-    sprintf(buffer, 
-            "link-%s "
-            "-n "                       // Don't echo output
-            "-c "                       // Command line input
-            "-- "                       // Again, command line input...
-            "-b_CODE=0x%04X "           // Code starts at 0x200
-            "-b_DATA=0x%04X "           // RAM starts at 0x8000
-            "-m "                      // Map file
-            "-j ",                      // Output a symbol file as well
-            portName,
-            options.code_loc,
-            options.data_loc
-            );
-
-    // Add the standard lib in.
-    if (options.nostdlib == FALSE) {
-        _saprintf(buffer,
-                  "-k" SDCC_LIB_DIR "/%s "    // Library path
-                  "-l%s.lib ",                // Library to use
-                  portName, portName
-                  );
-    }
-
-    // Add in the library paths and libraries
-    for (i = 0; i < nlibFiles; i++) {
-        _saprintf(buffer, "-k%s ", libFiles[i]);
-    }
-    for (i = 0; i < nlibPaths; i++) {
-        _saprintf(buffer, "-l%s ", libPaths[i]);
-    }
-
-    _saprintf(buffer,
-              "-%s "                      // Output type
-              "%s.%s ",                   // Output to
-              portOutputType, srcFileName, portExt
-              );
-
-    if (options.nostdlib == FALSE) {
-        _saprintf(buffer, 
-                  SDCC_LIB_DIR "/%s/crt0.o ", // Link in crt0 first
-                  portName
-                  );
-    }
-
-    _saprintf(buffer,
-              "%s.o ",                    // Actual code
-              srcFileName
-              );
-
-    // Append all the other targets
-    for (i = 0; i < nrelFiles; i++) {
-        _saprintf(buffer, "%s ", relFiles[i]);
-    }
-
-    // Do it.
-    if (my_system (buffer)) {
-        exit(1);
-    }
-}
-
-static void
-_z80_link(void)
-{
-  _link("z80", "ihx", "i");
-}
-
-static void
-_gbz80_link(void)
-{
-  _link("gbz80", "gb", "z");
-}
+#define ASMCMD \
+    "{bindir}/as-{port} -plosgff {srcfilename}{objext} {srcfilename}{asmext}"
 
 /* Globals */
 PORT z80_port =
@@ -501,15 +410,17 @@ PORT z80_port =
     MODEL_SMALL
   },
   {
-    _z80_asmCmd,
+    NULL,
+    ASMCMD,
     "-plosgff",                        /* Options with debug */
     "-plosgff",                        /* Options without debug */
     0,
     ".asm"
   },
   {
-    _z80_linkCmd,
-    _z80_link,
+    NULL,
+    LINKCMD,
+    NULL,
     ".o"
   },
   {
@@ -580,15 +491,17 @@ PORT gbz80_port =
     MODEL_SMALL
   },
   {
-    _gbz80_asmCmd,
+    NULL,
+    ASMCMD,
     "-plosgff",                        /* Options with debug */
     "-plosgff",                        /* Options without debug */
     0,
     ".asm"
   },
   {
-    _gbz80_linkCmd,
-    _gbz80_link,
+    NULL,
+    LINKCMD,
+    NULL,
     ".o"
   },
   {
diff --git a/support/tests/internal/Makefile b/support/tests/internal/Makefile
new file mode 100644 (file)
index 0000000..f3d3c36
--- /dev/null
@@ -0,0 +1,20 @@
+TOPDIR = ../../..
+
+LIBSOURCE = \
+       $(TOPDIR)/src/SDCChasht.c \
+       $(TOPDIR)/support/Util/NewAlloc.c \
+       $(TOPDIR)/support/Util/SDCCerr.c \
+       $(TOPDIR)/src/SDCCmacro.c \
+       stubs.c
+
+SOURCES = testmacro.c $(LIBSOURCE)
+
+include $(TOPDIR)/Makefile.common
+
+CFLAGS += -I$(TOPDIR)/src -I$(TOPDIR)/support/Util -I$(TOPDIR)
+
+all: all-tests
+
+all-tests: $(OBJ)
+       $(CC) -o $@ $(OBJ)
+
diff --git a/support/tests/internal/stubs.c b/support/tests/internal/stubs.c
new file mode 100644 (file)
index 0000000..4786709
--- /dev/null
@@ -0,0 +1,3 @@
+int fatalError;
+int lineno;
+char *filename = "tests";
diff --git a/support/tests/internal/testmacro.c b/support/tests/internal/testmacro.c
new file mode 100644 (file)
index 0000000..d25eecf
--- /dev/null
@@ -0,0 +1,84 @@
+#include <SDCCmacro.h>
+#include <stdio.h>
+
+static const char *_maps[] = 
+  {
+    "immedzero", "#0",
+    "immedvala", "#0x%02X",
+    "stra", "%s",
+    "port", "z80",
+    "stdlibpath", "{basepath}/lib/{port}",
+    "stdlibname", "{port}.lib",
+    "portouttypeflag", "-i",
+    "srcfilename", "fish",
+    "portoutext", ".ihx",
+    "crt0name", "{stdlibpath}/crt0{portobjext}",
+    "portobjext", ".o",
+    "otherobjfiles", "none",
+    "basepath", "/home/michaelh/sdcc",
+    NULL
+  };
+
+static hTab *
+_populateHash(const char **pin)
+{
+  hTab *pret = NULL;
+
+  while (*pin)
+    {
+      printf("Adding %s -> %s\n", pin[0], pin[1]);
+      shash_add (&pret, pin[0], pin[1]);
+      pin += 2;
+
+    }
+
+  return pret;
+}
+
+static void
+_testEval(hTab *ph, const char *pin, const char *pexpect, ...)
+{
+  va_list ap;
+  char *pgot;
+
+  va_start(ap, pexpect);
+
+  pgot = mvsprintf(ph, pin, ap);
+
+  if (strcmp(pgot, pexpect) != 0)
+    {
+      printf("Fail: expected: %s, got %s\n", pexpect, pgot);
+    }
+  else
+    {
+      printf("%s -> %s\n", pin, pgot);
+    }
+
+  va_end(ap);
+}
+
+void
+testMacros(void)
+{
+  hTab *ph = _populateHash(_maps);
+
+  _testEval(ph, "{immedzero}", "#0");
+  _testEval(ph, "{immedvala}", "#0x23", 0x23);
+  _testEval(ph, "{stra}", "#0", "{immedzero}");
+
+  printf("Link command:\n%s\n", 
+         msprintf(ph, 
+                  "link-{port} -n -c -- -b_CODE=0x%04X -b_DATA=0x%04X"
+                  " -m -j -k{stdlibpath} -l{stdlibname} {portouttypeflag}"
+                  " {srcfilename}{portoutext} {crt0name} {srcfilename}{portobjext} {otherobjfiles}", 
+                  0x1234, 0x3456));
+  
+}
+
+int
+main(void)
+{
+  testMacros();
+
+  return 0; 
+}