From 2f566bab0a5fe0bf025d6c892d6fc309966618f1 Mon Sep 17 00:00:00 2001 From: michaelh Date: Sun, 23 Sep 2001 18:25:45 +0000 Subject: [PATCH] * .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. * 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 --- .version | 2 +- ChangeLog | 29 +++ device/lib/z80/crt0.s | 3 +- doc/macro-sys-design.txt | 79 ++++++++ src/Makefile.in | 2 +- src/SDCCast.c | 1 - src/SDCCglue.c | 8 - src/SDCChasht.c | 13 +- src/SDCCmacro.c | 126 +++++++++++++ src/SDCCmacro.h | 36 ++++ src/SDCCmain.c | 282 +++++++++++++++++++++-------- src/SDCCutil.c | 226 +++++++++++++++++++++++ src/SDCCutil.h | 88 +++++++++ src/avr/main.c | 2 + src/ds390/main.c | 2 + src/izt/i186.c | 2 + src/izt/tlcs900h.c | 2 + src/mcs51/main.c | 2 + src/pic/main.c | 2 + src/port.h | 18 +- src/z80/main.c | 255 +++++++++----------------- support/tests/internal/Makefile | 20 ++ support/tests/internal/stubs.c | 3 + support/tests/internal/testmacro.c | 84 +++++++++ 24 files changed, 1023 insertions(+), 264 deletions(-) create mode 100644 doc/macro-sys-design.txt create mode 100644 src/SDCCmacro.c create mode 100644 src/SDCCmacro.h create mode 100644 src/SDCCutil.c create mode 100644 src/SDCCutil.h create mode 100644 support/tests/internal/Makefile create mode 100644 support/tests/internal/stubs.c create mode 100644 support/tests/internal/testmacro.c diff --git a/.version b/.version index 276cbf9e..2bf1c1cc 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.3.0 +2.3.1 diff --git a/ChangeLog b/ChangeLog index a6f8bbfa..0eb3602d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2001-09-23 Michael Hope + * .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 + + * 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 + + * src/SDCCmain.c (printVersionInfo): Added the build date to the version info. + 2001-09-16 * 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. diff --git a/device/lib/z80/crt0.s b/device/lib/z80/crt0.s index d5d68dd8..5aa3991d 100644 --- a/device/lib/z80/crt0.s +++ b/device/lib/z80/crt0.s @@ -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 index 00000000..ef4e889b --- /dev/null +++ b/doc/macro-sys-design.txt @@ -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 + diff --git a/src/Makefile.in b/src/Makefile.in index ea65a689..baf48592 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -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) diff --git a/src/SDCCast.c b/src/SDCCast.c index 0a429066..09ad2b53 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -46,7 +46,6 @@ int labelKey = 1; #define ALLOCATE 1 #define DEALLOCATE 2 -char buffer[1024]; int noLineno = 0; int noAlloc = 0; symbol *currFunc; diff --git a/src/SDCCglue.c b/src/SDCCglue.c index 68303f38..d74a0f3b 100644 --- a/src/SDCCglue.c +++ b/src/SDCCglue.c @@ -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; -} diff --git a/src/SDCChasht.c b/src/SDCChasht.c index 69d1f250..71821860 100644 --- a/src/SDCChasht.c +++ b/src/SDCChasht.c @@ -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 index 00000000..49db2a0e --- /dev/null +++ b/src/SDCCmacro.c @@ -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 index 00000000..b6b499c9 --- /dev/null +++ b/src/SDCCmacro.h @@ -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 + +char *mvsprintf(hTab *pvals, const char *pformat, va_list ap); +char *msprintf(hTab *pvals, const char *pformat, ...); + +#endif + diff --git a/src/SDCCmain.c b/src/SDCCmain.c index 4222a01d..058f5215 100644 --- a/src/SDCCmain.c +++ b/src/SDCCmain.c @@ -28,6 +28,8 @@ #include "SDCCerr.h" #include "BuildCmd.h" #include "MySystem.h" +#include "SDCCmacro.h" +#include "SDCCutil.h" #if NATIVE_WIN32 #include @@ -36,9 +38,13 @@ #endif #if !defined(__BORLANDC__) && !defined(_MSC_VER) +#include #include #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 index 00000000..5a3be477 --- /dev/null +++ b/src/SDCCutil.c @@ -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 + +/** 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 index 00000000..55a8f9f6 --- /dev/null +++ b/src/SDCCutil.h @@ -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 + diff --git a/src/avr/main.c b/src/avr/main.c index c14ba658..b3e33659 100644 --- a/src/avr/main.c +++ b/src/avr/main.c @@ -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"}, { diff --git a/src/ds390/main.c b/src/ds390/main.c index b1ff65bc..2da52b77 100644 --- a/src/ds390/main.c +++ b/src/ds390/main.c @@ -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" }, { diff --git a/src/izt/i186.c b/src/izt/i186.c index 7a4e39dd..ba4742e4 100644 --- a/src/izt/i186.c +++ b/src/izt/i186.c @@ -145,12 +145,14 @@ PORT i186_port = { _asmCmd, NULL, NULL, + NULL, 0, ".s" }, { _linkCmd, NULL, + NULL, ".o" }, { diff --git a/src/izt/tlcs900h.c b/src/izt/tlcs900h.c index e9f85208..b06c141c 100644 --- a/src/izt/tlcs900h.c +++ b/src/izt/tlcs900h.c @@ -144,12 +144,14 @@ PORT tlcs900h_port = _asmCmd, NULL, NULL, + NULL, 0, NULL }, { _linkCmd, NULL, + NULL, ".o" }, { diff --git a/src/mcs51/main.c b/src/mcs51/main.c index c06d08a9..3dcb4d86 100644 --- a/src/mcs51/main.c +++ b/src/mcs51/main.c @@ -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" }, { diff --git a/src/pic/main.c b/src/pic/main.c index f623d1ca..ee7c699a 100644 --- a/src/pic/main.c +++ b/src/pic/main.c @@ -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" }, { diff --git a/src/port.h b/src/port.h index 89738032..3e8339e6 100644 --- a/src/port.h +++ b/src/port.h @@ -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; diff --git a/src/z80/main.c b/src/z80/main.c index a13db000..2a07616f 100644 --- a/src/z80/main.c +++ b/src/z80/main.c @@ -1,6 +1,31 @@ +/*------------------------------------------------------------------------- + main.c - Z80 specific definitions. + + Michael Hope 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 index 00000000..f3d3c368 --- /dev/null +++ b/support/tests/internal/Makefile @@ -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 index 00000000..47867095 --- /dev/null +++ b/support/tests/internal/stubs.c @@ -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 index 00000000..d25eecff --- /dev/null +++ b/support/tests/internal/testmacro.c @@ -0,0 +1,84 @@ +#include +#include + +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; +} -- 2.30.2