+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.
;; Generic crt0.s for a Z80
- .globl _main
+ .module crt0
+ .globl _main
.area _HEADER (ABS)
;; Reset vector
--- /dev/null
+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
+
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)
#define ALLOCATE 1
#define DEALLOCATE 2
-char buffer[1024];
int noLineno = 0;
int noAlloc = 0;
symbol *currFunc;
return tmpfile ();
}
-char *
-gc_strdup (const char *s)
-{
- char *ret;
- ret = Safe_calloc (1, strlen (s) + 1);
- strcpy (ret, s);
- return ret;
-}
hTabDeleteByKey (hTab ** h, int key, const void *pkey, int (*compare) (const void *, const void *))
{
hashtItem *htip, **htipp;
+ bool found = FALSE;
if (!(*h))
return 0;
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;
}
--- /dev/null
+/*-------------------------------------------------------------------------
+ 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;
+}
--- /dev/null
+/*-----------------------------------------------------------------
+ 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
+
#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 ();
// 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
{ '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[] =
}
}
}
+
+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 */
/*-----------------------------------------------------------------*/
#ifdef SDCC_SUB_VERSION_STR
"/" SDCC_SUB_VERSION_STR
#endif
+ " (" __DATE__ ")"
#ifdef __CYGWIN__
" (CYGWIN)\n"
#else
}
}
-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)
{
case 'M':
{
preProcOnly = 1;
- _addToList (preArgv, "-M");
+ addToList (preArgv, "-M");
break;
}
case 'C':
{
- _addToList (preArgv, "-C");
+ addToList (preArgv, "-C");
break;
}
case 'd':
sOpt = 'I';
sprintf (buffer, "-%c%s", sOpt, rest);
- _addToList (preArgv, buffer);
+ addToList (preArgv, buffer);
}
break;
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);
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
}
}
-
-
/*-----------------------------------------------------------------*/
/* 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
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);
}
/*
// 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) {
#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))
if (srcFileName)
{
+ initValues ();
+ _discoverPaths (argv[0]);
+
preProcess (envp);
initMem ();
--- /dev/null
+/*-------------------------------------------------------------------------
+ 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';
+}
+
--- /dev/null
+/*-------------------------------------------------------------------------
+ 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
+
MODEL_SMALL},
{
_asmCmd,
+ NULL,
"-plosgff", /* Options with debug */
"-plosgff", /* Options without debug */
0,
".s"},
{
_linkCmd,
+ NULL,
NULL,
".rel"},
{
},
{
_asmCmd,
+ NULL,
"-plosgffc", /* Options with debug */
"-plosgff", /* Options without debug */
0,
{
_linkCmd,
NULL,
+ NULL,
".rel"
},
{
_asmCmd,
NULL,
NULL,
+ NULL,
0,
".s"
},
{
_linkCmd,
NULL,
+ NULL,
".o"
},
{
_asmCmd,
NULL,
NULL,
+ NULL,
0,
NULL
},
{
_linkCmd,
NULL,
+ NULL,
".o"
},
{
},
{
_asmCmd,
+ NULL,
"-plosgffc", /* Options with debug */
"-plosgff", /* Options without debug */
0,
{
_linkCmd,
NULL,
+ NULL,
".rel"
},
{
{
_asmCmd,
NULL,
+ NULL,
NULL,
//"-plosgffc", /* Options with debug */
//"-plosgff", /* Options without debug */
{
_linkCmd,
NULL,
+ NULL,
".rel"
},
{
/* 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;
/* 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;
+/*-------------------------------------------------------------------------
+ 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[] =
{
}
}
-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]))
{
way. */
char num[128];
strcpy (num, sz + 5);
- _chomp (num);
+ chomp (num);
switch (_G.asmType)
{
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)
{
port->mem.default_globl_map = data;
if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
asm_addTree (&_asxxxx_gb);
+
+ _setValues();
}
static void
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 =
MODEL_SMALL
},
{
- _z80_asmCmd,
+ NULL,
+ ASMCMD,
"-plosgff", /* Options with debug */
"-plosgff", /* Options without debug */
0,
".asm"
},
{
- _z80_linkCmd,
- _z80_link,
+ NULL,
+ LINKCMD,
+ NULL,
".o"
},
{
MODEL_SMALL
},
{
- _gbz80_asmCmd,
+ NULL,
+ ASMCMD,
"-plosgff", /* Options with debug */
"-plosgff", /* Options without debug */
0,
".asm"
},
{
- _gbz80_linkCmd,
- _gbz80_link,
+ NULL,
+ LINKCMD,
+ NULL,
".o"
},
{
--- /dev/null
+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)
+
--- /dev/null
+int fatalError;
+int lineno;
+char *filename = "tests";
--- /dev/null
+#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;
+}