Initial import
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 15 Oct 2003 05:46:28 +0000 (05:46 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 15 Oct 2003 05:46:28 +0000 (05:46 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2941 4a8a32a2-be11-0410-ad9d-d568d2c75423

43 files changed:
as/hc08/Makefile.as_hc08 [new file with mode: 0644]
as/hc08/Makefile.aslink [new file with mode: 0644]
as/hc08/Makefile.bcc [new file with mode: 0644]
as/hc08/Makefile.in [new file with mode: 0644]
as/hc08/alloc.h [new file with mode: 0644]
as/hc08/asdata.c [new file with mode: 0644]
as/hc08/asexpr.c [new file with mode: 0644]
as/hc08/aslex.c [new file with mode: 0644]
as/hc08/aslink.h [new file with mode: 0644]
as/hc08/aslink.mak [new file with mode: 0644]
as/hc08/aslist.c [new file with mode: 0644]
as/hc08/asm.h [new file with mode: 0644]
as/hc08/asmain.c [new file with mode: 0644]
as/hc08/asnoice.c [new file with mode: 0644]
as/hc08/asout.c [new file with mode: 0644]
as/hc08/asstore.c [new file with mode: 0644]
as/hc08/assubr.c [new file with mode: 0644]
as/hc08/assym.c [new file with mode: 0644]
as/hc08/clean.mk [new file with mode: 0644]
as/hc08/conf.mk [new file with mode: 0644]
as/hc08/lkaomf51.c [new file with mode: 0644]
as/hc08/lkarea.c [new file with mode: 0644]
as/hc08/lkdata.c [new file with mode: 0644]
as/hc08/lkeval.c [new file with mode: 0644]
as/hc08/lkhead.c [new file with mode: 0644]
as/hc08/lkihx.c [new file with mode: 0644]
as/hc08/lklex.c [new file with mode: 0644]
as/hc08/lklibr.c [new file with mode: 0644]
as/hc08/lklist.c [new file with mode: 0644]
as/hc08/lkmain.c [new file with mode: 0644]
as/hc08/lkmem.c [new file with mode: 0644]
as/hc08/lknoice.c [new file with mode: 0644]
as/hc08/lkrloc.c [new file with mode: 0644]
as/hc08/lks19.c [new file with mode: 0644]
as/hc08/lkstore.c [new file with mode: 0644]
as/hc08/lksym.c [new file with mode: 0644]
as/hc08/m08adr.c [new file with mode: 0644]
as/hc08/m08ext.c [new file with mode: 0644]
as/hc08/m08mch.c [new file with mode: 0644]
as/hc08/m08pst.c [new file with mode: 0644]
as/hc08/m6808.h [new file with mode: 0644]
as/hc08/strcmpi.c [new file with mode: 0644]
as/hc08/strcmpi.h [new file with mode: 0644]

diff --git a/as/hc08/Makefile.as_hc08 b/as/hc08/Makefile.as_hc08
new file mode 100644 (file)
index 0000000..1edad3d
--- /dev/null
@@ -0,0 +1,62 @@
+CC=gcc
+LEX=flex
+YACC=bison
+INCROOT=.
+CFLAGS=-ggdb -O2 -I $(INCROOT)
+TARGETS=$(SDCCDIR)/bin/as_hc08
+ALLOBJECTS= asmain.o aslex.o assym.o assubr.o asnoice.o \
+            asexpr.o asdata.o aslist.o asout.o asstore.o \
+            h08ext.o h08pst.o h08mch.o h08adr.o strcmpi.o
+
+all:: $(TARGETS)
+
+clean::
+       rm -f $(TARGETS) $(ALLOBJECTS)
+
+asmain.o  : asmain.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o asmain.o asmain.c
+
+aslex.o   : aslex.c  asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o aslex.o aslex.c
+
+assym.o   : assym.c  asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o assym.o assym.c
+
+assubr.o  : assubr.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o assubr.o assubr.c
+
+asexpr.o  : asexpr.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o asexpr.o asexpr.c
+
+asdata.o  : asdata.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o asdata.o asdata.c
+
+aslist.o  : aslist.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o aslist.o aslist.c
+
+asout.o   : asout.c  asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o asout.o asout.c
+
+asnoice.o : asnoice.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o asnoice.o asnoice.c
+
+asstore.o : asstore.c asm.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o asstore.o asstore.c
+
+h08ext.o  : h08ext.c asm.h m6808.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08ext.o h08ext.c
+
+h08pst.o  : h08pst.c asm.h m6808.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08pst.o h08pst.c
+
+h08mch.o  : h08mch.c asm.h m6808.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08mch.o h08mch.c
+
+h08adr.o  : h08adr.c asm.h m6808.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08adr.o h08adr.c
+
+strcmpi.o  : strcmpi.c strcmpi.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o strcmpi.o strcmpi.c
+
+$(TARGETS): $(ALLOBJECTS)
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALLOBJECTS) 
diff --git a/as/hc08/Makefile.aslink b/as/hc08/Makefile.aslink
new file mode 100644 (file)
index 0000000..0aebe56
--- /dev/null
@@ -0,0 +1,68 @@
+CC=gcc
+LEX=flex
+YACC=bison
+INCROOT=.
+CFLAGS=-ggdb -O2 -I $(INCROOT)
+TARGETS=$(SDCCDIR)/bin/aslink
+ALLOBJECTS= lkmain.o lkhead.o lkarea.o lkdata.o\
+             lkeval.o lklex.o lksym.o lkrloc.o\
+             lklibr.o lklist.o lkihx.o lks19.o\
+             lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o
+all:: $(TARGETS)
+
+clean::
+       rm -f $(TARGETS) $(ALLOBJECTS)
+
+lkmain.o : lkmain.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmain.o lkmain.c
+
+lkhead.o : lkhead.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkhead.o lkhead.c
+
+lkarea.o : lkarea.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkarea.o lkarea.c
+
+lkdata.o : lkdata.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkdata.o lkdata.c
+
+lkeval.o : lkeval.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkeval.o lkeval.c
+
+lklex.o  : lklex.c  aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklex.o lklex.c
+
+lksym.o  : lksym.c  aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lksym.o lksym.c
+
+lkrloc.o : lkrloc.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkrloc.o lkrloc.c
+
+lklibr.o : lklibr.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklibr.o lklibr.c
+
+lklist.o : lklist.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklist.o lklist.c
+
+lkihx.o  : lkihx.c  aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkihx.o lkihx.c
+
+lks19.o  : lks19.c  aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lks19.o lks19.c
+
+lkstore.o : lkstore.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkstore.o lkstore.c
+
+lknoice.o : lknoice.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lknoice.o lknoice.c
+
+strcmpi.o : strcmpi.c strcmpi.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o strcmpi.o strcmpi.c
+
+lkmem.o : lkmem.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmem.o lkmem.c
+
+lkaomf51.o : lkaomf51.c aslink.h
+       $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkaomf51.o lkaomf51.c
+
+$(TARGETS): $(ALLOBJECTS)
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALLOBJECTS) 
diff --git a/as/hc08/Makefile.bcc b/as/hc08/Makefile.bcc
new file mode 100644 (file)
index 0000000..b30978c
--- /dev/null
@@ -0,0 +1,25 @@
+# Makefile for Borlad C++
+
+PRJDIR          = ../..
+
+!include $(PRJDIR)/Bcc.inc
+
+ASOBJECTS       = asmain.obj aslex.obj assym.obj assubr.obj asnoice.obj \
+                  asexpr.obj asdata.obj aslist.obj asout.obj asstore.obj \
+                  h08ext.obj h08pst.obj h08mch.obj h08adr.obj strcmpi.obj
+
+LKOBJECTS       = lkmain.obj lkhead.obj lkarea.obj lkdata.obj \
+                  lkeval.obj lklex.obj lksym.obj lkrloc.obj \
+                  lklibr.obj lklist.obj lkihx.obj lks19.obj \
+                  lkstore.obj lknoice.obj lkmem.obj lkaomf51.obj strcmpi.obj
+
+ASX8051         = $(PRJDIR)/bin/asx8051.exe
+ASLINK          = $(PRJDIR)/bin/aslink.exe
+
+all: $(ASX8051) $(ASLINK)
+
+$(ASX8051): $(ASOBJECTS)
+        $(CC) $(CFLAGS) -e$@ $(ASOBJECTS)
+
+$(ASLINK): $(LKOBJECTS)
+        $(CC) $(CFLAGS) -e$@ $(LKOBJECTS)
diff --git a/as/hc08/Makefile.in b/as/hc08/Makefile.in
new file mode 100644 (file)
index 0000000..c7d7a0e
--- /dev/null
@@ -0,0 +1,116 @@
+#
+#
+#
+
+VERSION         = @VERSION@
+VERSIONHI       = @VERSIONHI@
+VERSIONLO       = @VERSIONLO@
+VERSIONP        = @VERSIONP@
+
+SHELL          = /bin/sh
+CC             = @CC@
+CPP            = @CPP@
+INSTALL                = @INSTALL@
+STRIP           = @STRIP@
+
+PRJDIR         = ../..
+
+srcdir         = @srcdir@
+prefix         = @prefix@
+exec_prefix     = @exec_prefix@
+bindir          = @bindir@
+libdir          = @libdir@
+datadir         = @datadir@
+includedir      = @includedir@
+mandir          = @mandir@
+man1dir         = $(mandir)/man1
+man2dir         = $(mandir)/man2
+infodir         = @info@
+
+EXEEXT          = @EXEEXT@
+
+CPPFLAGS       = @CPPFLAGS@ -I. -I$(PRJDIR)
+CFLAGS         = @CFLAGS@ -Wall
+M_OR_MM                = @M_OR_MM@
+LDFLAGS                = @LDFLAGS@
+
+ASOBJECTS      = asmain.o aslex.o assym.o assubr.o asnoice.o \
+                 asexpr.o asdata.o aslist.o asout.o asstore.o \
+                 h08ext.o h08pst.o h08mch.o h08adr.o strcmpi.o
+ASSOURCES      = $(patsubst %.o,%.c,$(ASOBJECTS))
+
+LKOBJECTS      = lkmain.o lkhead.o lkarea.o lkdata.o \
+                 lkeval.o lklex.o lksym.o lkrloc.o \
+                 lklibr.o lklist.o lkihx.o lks19.o \
+                 lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o
+LKSOURCES      = $(patsubst %.o,%.c,$(LKOBJECTS))
+
+ASX8051                = $(PRJDIR)/bin/as-hc08$(EXEEXT)
+ASLINK         = $(PRJDIR)/bin/link-hc08$(EXEEXT)
+
+transform       = @program_transform_name@
+
+# Compiling entire program or any subproject
+# ------------------------------------------
+all: checkconf $(ASX8051) $(ASLINK)
+
+$(ASX8051): $(ASOBJECTS)
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ASOBJECTS) 
+
+$(ASLINK): $(LKOBJECTS)
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LKOBJECTS)
+
+# Compiling and installing everything and runing test
+# ---------------------------------------------------
+install: all installdirs
+       $(INSTALL) $(ASX8051) `echo $(bindir)/asx8051$(EXEEXT)|sed '$(transform)'`
+       $(STRIP) `echo $(bindir)/as-hc08$(EXEEXT)|sed '$(transform)'`
+       $(INSTALL) $(ASLINK) `echo $(bindir)/aslink$(EXEEXT)|sed '$(transform)'`
+       $(STRIP) `echo $(bindir)/link-hc08$(EXEEXT)|sed '$(transform)'`
+
+# Deleting all the installed files
+# --------------------------------
+uninstall:
+       rm -f $(bindir)/as-hc08$(EXEEXT) $(bindir)/link-hc08$(EXEEXT)
+
+
+# Performing self-test
+# --------------------
+check:
+
+
+# Performing installation test
+# ----------------------------
+installcheck:
+
+
+# Creating installation directories
+# ---------------------------------
+installdirs:
+       $(INSTALL) -d $(bindir)
+
+
+# Creating dependencies
+# ---------------------
+dep: Makefile.dep
+
+Makefile.dep: $(ASSOURCES) $(LKSOURCES) *.h $(PRJDIR)/*.h
+       $(CPP) $(CPPFLAGS) $(M_OR_MM) $(ASSOURCES) $(LKSOURCES) >Makefile.dep
+
+include Makefile.dep
+include clean.mk
+
+# My rules
+# --------
+.c.o:
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+
+# Remaking configuration
+# ----------------------
+checkconf:
+       @if [ -f $(PRJDIR)/devel ]; then\
+          $(MAKE) -f conf.mk srcdir="$(srcdir)" PRJDIR="$(PRJDIR)" freshconf;\
+        fi
+
+# End of Makefile
diff --git a/as/hc08/alloc.h b/as/hc08/alloc.h
new file mode 100644 (file)
index 0000000..dd404a8
--- /dev/null
@@ -0,0 +1,4 @@
+/* alloc.h */
+/* DECUS C */
+
+#include <stdlib.h>
diff --git a/as/hc08/asdata.c b/as/hc08/asdata.c
new file mode 100644 (file)
index 0000000..1665752
--- /dev/null
@@ -0,0 +1,289 @@
+/* asdata.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - change s_id from [NCPS] to pointer (comment)
+ *  2-Nov-97 JLH:
+ *           - add jflag for debug control
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module      asdata.c
+ *
+ *     The module asdata.c contains the global constants,
+ *     structures, and variables used in the assembler.
+ */
+
+int    aserr;          /*      ASxxxx error counter
+                        */
+jmp_buf        jump_env;       /*      compiler dependent structure
+                        *      used by setjmp() and longjmp()
+                        */
+int    inpfil;         /*      count of assembler
+                        *      input files specified
+                        */
+int    incfil;         /*      current file handle index
+                        *      for include files
+                        */
+int    cfile;          /*      current file handle index
+                        *      of input assembly files
+                        */
+int    flevel;         /*      IF-ELSE-ENDIF flag will be non
+                        *      zero for false conditional case
+                        */
+int    tlevel;         /*      current conditional level
+                        */
+int    ifcnd[MAXIF+1]; /*      array of IF statement condition
+                        *      values (0 = FALSE) indexed by tlevel
+                        */
+int    iflvl[MAXIF+1]; /*      array of IF-ELSE-ENDIF flevel
+                        *      values indexed by tlevel
+                        */
+
+char   afn[PATH_MAX];          /*      afile temporary file name
+                                */
+char   srcfn[MAXFIL][PATH_MAX];        /*      array of source file names
+                                */
+int    srcline[MAXFIL];        /*      source line number
+                                */
+char   incfn[MAXINC][PATH_MAX];        /*      array of include file names
+                                */
+int    incline[MAXINC];        /*      include line number
+                                */
+
+int    radix;          /*      current number conversion radix:
+                        *      2 (binary), 8 (octal), 10 (decimal),
+                        *      16 (hexadecimal)
+                        */
+int    line;           /*      current assembler source
+                        *      line number
+                        */
+int    page;           /*      current page number
+                        */
+int    lop;            /*      current line number on page
+                        */
+int    pass;           /*      assembler pass number
+                        */
+int    lflag;          /*      -l, generate listing flag
+                        */
+int    cflag;          /*      -lc, generate sdcdb debug info
+                        */
+int    gflag;          /*      -g, make undefined symbols global flag
+                        */
+int    aflag;          /*      -a, make all symbols global flag
+                        */
+int    jflag;          /*      -j, generate debug information flag
+                        */
+int    oflag;          /*      -o, generate relocatable output flag
+                        */
+int    sflag;          /*      -s, generate symbol table flag
+                        */
+int    pflag;          /*      -p, enable listing pagination
+                        */
+int    xflag;          /*      -x, listing radix flag
+                        */
+int    fflag;          /*      -f(f), relocations flagged flag
+                        */
+Addr_T laddr;          /*      address of current assembler line
+                        *      or value of .if argument
+                        */
+Addr_T fuzz;           /*      tracks pass to pass changes in the
+                        *      address of symbols caused by
+                        *      variable length instruction formats
+                        */
+int    lmode;          /*      listing mode
+                        */
+char   *ep;            /*      pointer into error list
+                        *      array eb[NERR]
+                        */
+char   eb[NERR];       /*      array of generated error codes
+                        */
+char   *ip;            /*      pointer into the assembler-source
+                        *      text line in ib[]
+                        */
+char   ib[NINPUT];     /*      assembler-source text line
+                        */
+char   *cp;            /*      pointer to assembler output
+                        *      array cb[]
+                        */
+char   cb[NCODE];      /*      array of assembler output values
+                        */
+int    *cpt;           /*      pointer to assembler relocation type
+                        *      output array cbt[]
+                        */
+int    cbt[NCODE];     /*      array of assembler relocation types
+                        *      describing the data in cb[]
+                        */
+char   tb[NTITL];      /*      Title string buffer
+                        */
+char   stb[NSBTL];     /*      Subtitle string buffer
+                        */
+char   optsdcc[NINPUT];        /*      sdcc compile options 
+                        */
+int    flat24Mode;     /*      non-zero if we are using DS390 24 bit 
+                        *      flat mode (via .flat24 directive). 
+                        */
+
+char   symtbl[] = { "Symbol Table" };
+char   aretbl[] = { "Area Table" };
+
+char   module[NCPS];   /*      module name string
+                        */
+
+/*
+ *     The mne structure is a linked list of the assembler
+ *     mnemonics and directives.  The list of mnemonics and
+ *     directives contained in the device dependent file
+ *     xxxpst.c are hashed and linked into NHASH lists in
+ *     module assym.c by syminit().  The structure contains
+ *     the mnemonic/directive name, a subtype which directs
+ *     the evaluation of this mnemonic/directive, a flag which
+ *     is used to detect the end of the mnemonic/directive
+ *     list in xxxpst.c, and a value which is normally
+ *     associated with the assembler mnemonic base instruction
+ *     value.
+ *
+ *     struct  mne
+ *     {
+ *             struct  mne *m_mp;      Hash link
+ *             char    m_id[NCPS];     Mnemonic
+ *             char    m_type;         Mnemonic subtype
+ *             char    m_flag;         Mnemonic flags
+ *             Addr_T  m_valu;         Value
+ *     };
+ */
+struct mne     *mnehash[NHASH];
+
+/*
+ *     The sym structure is a linked list of symbols defined
+ *     in the assembler source files.  The first symbol is "."
+ *     defined here.  The entry 'struct tsym *s_tsym'
+ *     links any temporary symbols following this symbol and
+ *     preceeding the next normal symbol.  The structure also
+ *     contains the symbol's name, type (USER or NEW), flag
+ *     (global, assigned, and multiply defined), a pointer
+ *     to the area structure defining where the symbol is
+ *     located, a reference number assigned by outgsd() in
+ *     asout.c, and the symbols address relative to the base
+ *     address of the area where the symbol is located.
+ *
+ *     struct  sym
+ *     {
+ *             struct  sym  *s_sp;     Hash link
+ *             struct  tsym *s_tsym;   Temporary symbol link
+ *             char    *s_id;          Symbol (JLH)
+ *             char    s_type;         Symbol subtype
+ *             char    s_flag;         Symbol flags
+ *             struct  area *s_area;   Area line, 0 if absolute
+ *             int     s_ref;          Ref. number
+ *             Addr_T  s_addr;         Address
+ *     };
+ */
+struct sym     sym[] = {
+    {NULL,     NULL,   ".",    S_USER, S_END,  NULL,   0,      0}
+};
+
+struct sym     *symp;          /*      pointer to a symbol structure
+                                */
+struct sym *symhash[NHASH];    /*      array of pointers to NHASH
+                                *      linked symbol lists
+                                */
+
+/*
+ *     The area structure contains the parameter values for a
+ *     specific program or data section.  The area structure
+ *     is a linked list of areas.  The initial default area
+ *     is "_CODE" defined here, the next area structure
+ *     will be linked to this structure through the structure
+ *     element 'struct area *a_ep'.  The structure contains the
+ *     area name, area reference number ("_CODE" is 0) determined
+ *     by the order of .area directives, area size determined
+ *     from the total code and/or data in an area, area fuzz is
+ *     an variable used to track pass to pass changes in the
+ *     area size caused by variable length instruction formats,
+ *     and area flags which specify the area's relocation type.
+ *
+ *     struct  area
+ *     {
+ *             struct  area *a_ap;     Area link
+ *             char    a_id[NCPS];     Area Name
+ *             int     a_ref;          Reference number
+ *             Addr_T  a_size;         Area size
+ *             Addr_T  a_fuzz;         Area fuzz
+ *             int     a_flag;         Area flags
+ *     };
+ */
+struct area    area[] = {
+    {NULL,     "_CODE",        0,      0,      0,      A_CON|A_REL}
+};
+
+struct area    *areap; /*      pointer to an area structure
+                        */
+
+FILE   *lfp;           /*      list output file handle
+                        */
+FILE   *ofp;           /*      relocation output file handle
+                        */
+FILE   *tfp;           /*      symbol table output file handle
+                        */
+FILE   *sfp[MAXFIL];   /*      array of assembler-source file handles
+                        */
+FILE   *ifp[MAXINC];   /*      array of include-file file handles
+                        */
+
+/*
+ *     array of character types, one per
+ *     ASCII character
+ */
+unsigned char  ctype[128] = {
+/*NUL*/        ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,
+/*BS*/ ILL,    SPACE,  ILL,    ILL,    SPACE,  ILL,    ILL,    ILL,
+/*DLE*/        ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,
+/*CAN*/        ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,
+/*SPC*/        SPACE,  ETC,    ETC,    ETC,    LETTER, BINOP,  BINOP,  ETC,
+/*(*/  ETC,    ETC,    BINOP,  BINOP,  ETC,    BINOP,  LETTER, BINOP,
+/*0*/  DGT2,   DGT2,   DGT8,   DGT8,   DGT8,   DGT8,   DGT8,   DGT8,
+/*8*/  DGT10,  DGT10,  ETC,    ETC,    BINOP,  ETC,    BINOP,  ETC,
+/*@*/  ETC,    LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LETTER,
+/*H*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*P*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*X*/  LETTER, LETTER, LETTER, ETC,    ETC,    ETC,    BINOP,  LETTER,
+/*`*/  ETC,    LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LETTER,
+/*h*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*p*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*x*/  LETTER, LETTER, LETTER, ETC,    BINOP,  ETC,    ETC,    ETC
+};
+
+/*
+ *     an array of characters which
+ *     perform the case translation function
+ */
+char   ccase[128] = {
+/*NUL*/        '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+/*DLE*/        '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+/*CAN*/        '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+/*SPC*/        '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+/*(*/  '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+/*0*/  '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+/*8*/  '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+/*@*/  '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*H*/  '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*P*/  '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*X*/  '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+/*`*/  '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*h*/  '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*p*/  '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*x*/  '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177'
+};     
diff --git a/as/hc08/asexpr.c b/as/hc08/asexpr.c
new file mode 100644 (file)
index 0000000..26aea4b
--- /dev/null
@@ -0,0 +1,711 @@
+       /* asexpr.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module      asexpr.c
+ *
+ *     The module asexpr.c contains the routines to evaluate
+ *     arithmetic/numerical expressions.  The functions in
+ *     asexpr.c perform a recursive evaluation of the arithmetic
+ *     expression read from the assembler-source text line.
+ *     The expression may include binary/unary operators, brackets,
+ *     symbols, labels, and constants in hexadecimal, decimal, octal
+ *     and binary.  Arithmetic operations are prioritized and
+ *     evaluated by normal arithmetic conventions.
+ *
+ *     asexpr.c contains the following functions:
+ *             VOID    abscheck()
+ *             Addr_T  absexpr()
+ *             VOID    clrexpr()
+ *             int     digit()
+ *             VOID    expr()
+ *             int     oprio()
+ *             VOID    term()
+ *
+ *     asexpr.c contains no local/static variables
+ */
+
+/*)Function    VOID    expr(esp, n)
+ *
+ *             expr *  esp             pointer to an expr structure
+ *             int     n               a firewall priority; all top
+ *                                     level calls (from the user)
+ *                                     should be made with n set to 0.
+ *
+ *     The function expr() evaluates an expression and
+ *     stores its value and relocation information into
+ *     the expr structure supplied by the user.
+ *
+ *     local variables:
+ *             int     c               current assembler-source
+ *                                     text character
+ *             int     p               current operator priority
+ *             area *  ap              pointer to an area structure
+ *             exp     re              internal expr structure
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *
+ *     functions called:
+ *             VOID    abscheck()      asexpr.c
+ *             VOID    clrexpr()       asexpr.c
+ *             VOID    expr()          asexpr.c
+ *             int     getnb()         aslex.c
+ *             int     oprio()         asexpr.c
+ *             VOID    qerr()          assubr.c
+ *             VOID    rerr()          assubr.c
+ *             VOID    term()          asexpr.c
+ *             VOID    unget()         aslex.c
+ *
+ *
+ *     side effects:
+ *             An expression is evaluated modifying the user supplied
+ *             expr structure, a sym structure maybe created for an
+ *             undefined symbol, and the parse of the expression may
+ *             terminate if a 'q' error occurs.
+ */
+
+VOID
+expr(esp, n)
+register struct expr *esp;
+int n;
+{
+        register int c, p;
+        struct area *ap;
+        struct expr re;
+
+        term(esp);
+        while (ctype[c = getnb()] & BINOP) {
+               /*
+                * Handle binary operators + - * / & | % ^ << >>
+                */
+                if ((p = oprio(c)) <= n)
+                        break;
+                if ((c == '>' || c == '<') && c != get())
+                        qerr();
+               clrexpr(&re);
+                expr(&re, p);
+               esp->e_rlcf |= re.e_rlcf;
+                if (c == '+') {
+                       /*
+                        * esp + re, at least one must be absolute
+                        */
+                        if (esp->e_base.e_ap == NULL) {
+                               /*
+                                * esp is absolute (constant),
+                                * use area from re
+                                */
+                                esp->e_base.e_ap = re.e_base.e_ap;
+                        } else
+                        if (re.e_base.e_ap) {
+                               /*
+                                * re should be absolute (constant)
+                                */
+                                rerr();
+                        }
+                        if (esp->e_flag && re.e_flag)
+                                rerr();
+                        if (re.e_flag)
+                                esp->e_flag = 1;
+                        esp->e_addr += re.e_addr;
+                } else
+                if (c == '-') {
+                       /*
+                        * esp - re
+                        */
+                        if ((ap = re.e_base.e_ap) != NULL) {
+                                if (esp->e_base.e_ap == ap) {
+                                        esp->e_base.e_ap = NULL;
+                                } else {
+                                        rerr();
+                                }
+                        }
+                        if (re.e_flag)
+                                rerr();
+                        esp->e_addr -= re.e_addr;
+                } else {
+                       /*
+                        * Both operands (esp and re) must be constants
+                        */
+                   /* SD :- moved the abscheck to each case
+                      case and change the right shift operator.. if
+                      right shift by 8 bits of a relocatable address then
+                      the user wants the higher order byte. set the R_MSB
+                      for the expression */
+                       switch (c) {
+
+                        case '*':
+                           abscheck(esp);
+                           abscheck(&re);
+                           esp->e_addr *= re.e_addr;
+                           break;
+
+                        case '/':
+                           abscheck(esp);
+                           abscheck(&re);                          
+                           esp->e_addr /= re.e_addr;
+                           break;
+
+                        case '&':
+                           abscheck(esp);
+                           abscheck(&re);                          
+                           esp->e_addr &= re.e_addr;
+                           break;
+
+                        case '|':
+                           abscheck(esp);
+                           abscheck(&re);                          
+                           esp->e_addr |= re.e_addr;
+                           break;
+
+                        case '%':
+                           abscheck(esp);
+                           abscheck(&re);                          
+                           esp->e_addr %= re.e_addr;
+                           break;
+
+                        case '^':
+                           abscheck(esp);
+                           abscheck(&re);                          
+                           esp->e_addr ^= re.e_addr;
+                           break;
+
+                        case '<':
+                           abscheck(esp);
+                           abscheck(&re);                          
+                           esp->e_addr <<= re.e_addr;
+                           break;
+
+                        case '>':
+                           /* SD change here */                           
+                           abscheck(&re);      
+                           /* if the left is a relative address &
+                              the right side is == 8 then */
+                           if (esp->e_base.e_ap && re.e_addr == 8) {
+                               esp->e_rlcf |= R_MSB ;
+                               break;
+                           }
+                           else if (esp->e_base.e_ap && re.e_addr == 16)
+                           {
+                               if (flat24Mode)
+                               {
+                                   esp->e_rlcf |= R_HIB;
+                               }
+                               else
+                               {
+                                   warnBanner();
+                                   fprintf(stderr, 
+                                           "(expr >> 16) is only meaningful in "
+                                           ".flat24 mode.\n");
+                                   qerr();
+                               }
+                                   
+                              break;
+                           }
+                           /* else continue with the normal processing */
+                           abscheck(esp);
+                           esp->e_addr >>= re.e_addr;
+                           break;
+                           
+                      default:
+                          qerr();
+                          break;
+                      }
+                }
+        }
+        unget(c);
+}
+
+/*)Function    Addr_T  absexpr()
+ *
+ *     The function absexpr() evaluates an expression, verifies it
+ *     is absolute (i.e. not position dependent or relocatable), and
+ *     returns its value.
+ *
+ *     local variables:
+ *             expr    e               expr structure
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             VOID    abscheck()      asexpr.c
+ *             VOID    clrexpr()       asexpr.c
+ *             VOID    expr()          asexpr.c
+ *
+ *     side effects:
+ *             If the expression is not absolute then
+ *             a 'r' error is reported.
+ */
+
+Addr_T
+absexpr()
+{
+        struct expr e;
+
+       clrexpr(&e);
+       expr(&e, 0);
+       abscheck(&e);
+       return (e.e_addr);
+}
+
+/*)Function    VOID    term(esp)
+ *
+ *             expr *  esp             pointer to an expr structure
+ *
+ *     The function term() evaluates a single constant
+ *     or symbol value prefaced by any unary operator
+ *     ( +, -, ~, ', ", >, or < ).  This routine is also
+ *     responsible for setting the relocation type to symbol
+ *     based (e.flag != 0) on global references.
+ *
+ *     local variables:
+ *             int     c               current character
+ *             char    id[]            symbol name
+ *             char *  jp              pointer to assembler-source text
+ *             int     n               constant evaluation running sum
+ *             int     r               current evaluation radix
+ *             sym *   sp              pointer to a sym structure
+ *             tsym *  tp              pointer to a tsym structure
+ *             int     v               current digit evaluation
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *             sym *   symp            pointer to a symbol structure
+ *
+ *     functions called:
+ *             VOID    abscheck()      asexpr.c
+ *             int     digit()         asexpr.c
+ *             VOID    err()           assubr.c
+ *             VOID    expr()          asexpr.c
+ *             int     is_abs()        asexpr.c
+ *             int     get()           aslex.c
+ *             VOID    getid()         aslex.c
+ *             int     getmap()        aslex.c
+ *             int     getnb()         aslex.c
+ *             sym *   lookup()        assym.c
+ *             VOID    qerr()          assubr.c
+ *             VOID    unget()         aslex.c
+ *
+ *     side effects:
+ *             An arithmetic term is evaluated, a symbol structure
+ *             may be created, term evaluation may be terminated
+ *             by a 'q' error.
+ */
+
+VOID
+term(esp)
+register struct expr *esp;
+{
+        register int c, n;
+        register char *jp;
+        char id[NCPS];
+        struct sym  *sp;
+        struct tsym *tp;
+        int r=0, v;
+
+        c = getnb();
+       /*
+        * Discard the unary '+' at this point and
+        * also any reference to numerical arguments
+        * associated with the '#' prefix.
+        */
+        while (c == '+' || c == '#') { c = getnb(); }
+       /*
+        * Evaluate all binary operators
+        * by recursively calling expr().
+        */
+        if (c == LFTERM) {
+                expr(esp, 0);
+                if (getnb() != RTTERM)
+                        qerr();
+                return;
+        }
+        if (c == '-') {
+                expr(esp, 100);
+                abscheck(esp);
+                esp->e_addr = 0-esp->e_addr;
+                return;
+        }
+        if (c == '~') {
+                expr(esp, 100);
+                abscheck(esp);
+                esp->e_addr = ~esp->e_addr;
+                return;
+        }
+        if (c == '\'') {
+                esp->e_mode = S_USER;
+                esp->e_addr = getmap(-1)&0377;
+                return;
+        }
+        if (c == '\"') {
+                esp->e_mode = S_USER;
+                if (hilo) {
+                    esp->e_addr  = (getmap(-1)&0377)<<8;
+                    esp->e_addr |= (getmap(-1)&0377);
+                } else {
+                    esp->e_addr  = (getmap(-1)&0377);
+                    esp->e_addr |= (getmap(-1)&0377)<<8;
+                }
+                return;
+        }
+        if (c == '>' || c == '<') {
+                expr(esp, 100);
+               if (is_abs (esp)) {
+                       /*
+                        * evaluate msb/lsb directly
+                        */
+                       if (c == '>')
+                               esp->e_addr >>= 8;
+                       esp->e_addr &= 0377;
+                       return;
+               } else {
+                       /*
+                        * let linker perform msb/lsb, lsb is default
+                        */
+                       esp->e_rlcf |= R_BYT2;
+                       if (c == '>')
+                               esp->e_rlcf |= R_MSB;
+                       return;
+               }
+        }
+       /*
+        * Evaluate digit sequences as local symbols
+        * if followed by a '$' or as constants.
+        */
+        if (ctype[c] & DIGIT) {
+                esp->e_mode = S_USER;
+                jp = ip;
+                while (ctype[(int)*jp] & RAD10) {
+                        jp++;
+                }
+                if (*jp == '$') {
+                        n = 0;
+                        while ((v = digit(c, 10)) >= 0) {
+                                n = 10*n + v;
+                                c = get();
+                        }
+                        tp = symp->s_tsym;
+                        while (tp) {
+                                if (n == tp->t_num) {
+                                        esp->e_base.e_ap = tp->t_area;
+                                        esp->e_addr = tp->t_addr;
+                                        return;
+                                }
+                                tp = tp->t_lnk;
+                        }
+                        /* err('u'); */
+                        return;
+                }
+                r = radix;
+                if (c == '0') {
+                        c = get();
+                        switch (c) {
+                                case 'b':
+                                case 'B':
+                                        r = 2;
+                                        c = get();
+                                        break;
+                                case 'o':
+                                case 'O':
+                                case 'q':
+                                case 'Q':
+                                        r = 8;
+                                        c = get();
+                                        break;
+                                case 'd':
+                                case 'D':
+                                        r = 10;
+                                        c = get();
+                                        break;
+                                case 'h':
+                                case 'H':
+                                case 'x':
+                                case 'X':
+                                        r = 16;
+                                        c = get();
+                                        break;
+                                default:
+                                        break;
+                        }
+                }
+                n = 0;
+                while ((v = digit(c, r)) >= 0) {
+                        n = r*n + v;
+                        c = get();
+                }
+                unget(c);
+                esp->e_addr = n;
+                return;
+        }
+       /*
+        * Evaluate '$' sequences as a temporary radix
+        * if followed by a '%', '&', '#', or '$'.
+        */
+        if (c == '$') {
+                c = get();
+                if (c == '%' || c == '&' || c == '#' || c == '$') {
+                       switch (c) {
+                               case '%':
+                                       r = 2;
+                                       break;
+                               case '&':
+                                       r = 8;
+                                       break;
+                               case '#':
+                                       r = 10;
+                                       break;
+                               case '$':
+                                       r = 16;                         
+                                       break;
+                               default:
+                                       break;
+                       }
+                       c = get();
+                       n = 0;
+                       while ((v = digit(c, r)) >= 0) {
+                               n = r*n + v;
+                               c = get();
+                       }
+                       unget(c);
+                       esp->e_mode = S_USER;
+                       esp->e_addr = n;
+                       return;
+               }
+               unget(c);
+               c = '$';
+        }
+       /*
+        * Evaluate symbols and labels
+        */
+        if (ctype[c] & LETTER) {
+                esp->e_mode = S_USER;
+                getid(id, c);
+                sp = lookup(id);
+                if (sp->s_type == S_NEW) {
+                        esp->e_addr = 0;
+                       if (sp->s_flag&S_GBL) {
+                               esp->e_flag = 1;
+                               esp->e_base.e_sp = sp;
+                               return;
+                       }
+                       /* err('u'); */
+                } else {
+                        esp->e_mode = sp->s_type;
+                        esp->e_addr = sp->s_addr;
+                        esp->e_base.e_ap = sp->s_area;
+                }
+                return;
+        }
+       /*
+        * Else not a term.
+        */
+        qerr();
+}
+
+/*)Function    int     digit(c, r)
+ *
+ *             int     c               digit character
+ *             int     r               current radix
+ *
+ *     The function digit() returns the value of c
+ *     in the current radix r.  If the c value is not
+ *     a number of the current radix then a -1 is returned.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+int
+digit(c, r)
+register int c, r;
+{
+        if (r == 16) {
+                if (ctype[c] & RAD16) {
+                        if (c >= 'A' && c <= 'F')
+                                return (c - 'A' + 10);
+                        if (c >= 'a' && c <= 'f')
+                                return (c - 'a' + 10);
+                        return (c - '0');
+                }
+        } else
+        if (r == 10) {
+                if (ctype[c] & RAD10)
+                        return (c - '0');
+        } else
+        if (r == 8) {
+                if (ctype[c] & RAD8)
+                        return (c - '0');
+        } else
+        if (r == 2) {
+                if (ctype[c] & RAD2)
+                        return (c - '0');
+        }
+        return (-1);
+}
+
+/*)Function    VOID    abscheck(esp)
+ *
+ *             expr *  esp             pointer to an expr structure
+ *
+ *     The function abscheck() tests the evaluation of an
+ *     expression to verify it is absolute.  If the evaluation
+ *     is relocatable then an 'r' error is noted and the expression
+ *     made absolute.
+ *
+ *     Note:   The area type (i.e. ABS) is not checked because
+ *             the linker can be told to explicitly relocate an
+ *             absolute area.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             VOID    rerr()          assubr.c
+ *
+ *     side effects:
+ *             The expression may be changed to absolute and the
+ *             'r' error invoked.
+ */
+
+VOID
+abscheck(esp)
+register struct expr *esp;
+{
+        if (esp->e_flag || esp->e_base.e_ap) {
+                esp->e_flag = 0;
+                esp->e_base.e_ap = NULL;
+                rerr();
+        }
+}
+
+/*)Function    int     is_abs(esp)
+ *
+ *             expr *  esp             pointer to an expr structure
+ *
+ *     The function is_abs() tests the evaluation of an
+ *     expression to verify it is absolute.  If the evaluation
+ *     is absolute then 1 is returned, else 0 is returned.
+ *
+ *     Note:   The area type (i.e. ABS) is not checked because
+ *             the linker can be told to explicitly relocate an
+ *             absolute area.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+int
+is_abs (esp)
+register struct expr *esp;
+{
+        if (esp->e_flag || esp->e_base.e_ap) {
+               return(0);
+        }
+       return(1);
+}
+
+/*)Function    int     oprio(c)
+ *
+ *             int     c               operator character
+ *
+ *     The function oprio() returns a relative priority
+ *     for all valid unary and binary operators.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+int
+oprio(c)
+register int c;
+{
+        if (c == '*' || c == '/' || c == '%')
+                return (10);
+        if (c == '+' || c == '-')
+                return (7);
+        if (c == '<' || c == '>')
+                return (5);
+        if (c == '^')
+                return (4);
+        if (c == '&')
+                return (3);
+        if (c == '|')
+                return (1);
+        return (0);
+}
+
+/*)Function    VOID    clrexpr(esp)
+ *
+ *             expr *  esp             pointer to expression structure
+ *
+ *     The function clrexpr() clears the expression structure.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             expression structure cleared.
+ */
+VOID
+clrexpr(esp)
+register struct expr *esp;
+{
+       esp->e_mode = 0;
+       esp->e_flag = 0;
+       esp->e_addr = 0;
+       esp->e_base.e_ap = NULL;
+       esp->e_rlcf = 0;
+}
diff --git a/as/hc08/aslex.c b/as/hc08/aslex.c
new file mode 100644 (file)
index 0000000..4f774c4
--- /dev/null
@@ -0,0 +1,520 @@
+/* aslex.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH bug in getst(): sign extend on ~(SPACE|ILL)
+ *           causes infinite loop
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module      aslex.c
+ *
+ *     The module aslex.c includes the general lexical
+ *     analysis routines for the assembler.
+ *
+ *     aslex.c contains the following functions:
+ *             char    endline()
+ *             char    get()
+ *             VOID    getid(id,c)
+ *             int     getline()
+ *             int     getmap()
+ *             char    getnb()
+ *             VOID    getst()
+ *             int     more()
+ *             VOID    unget(c)
+ *
+ *     aslex.c contains no local/static variables
+ */
+
+/*)Function    VOID    getid(id,c)
+ *
+ *             char *  id              a pointer to a string of
+ *                                     maximum length NCPS
+ *             int     c               mode flag
+ *                                     >=0     this is first character to
+ *                                             copy to the string buffer
+ *                                     <0      skip white space, first
+ *                                             character must be a LETTER
+ *
+ *     The function getid() scans the current assembler-source text line
+ *     from the current position copying the next LETTER | DIGIT string
+ *     into the external string buffer (id).  The string ends when a non
+ *     LETTER or DIGIT character is found. The maximum number of
+ *     characters copied is NCPS.  If the input string is larger than
+ *     NCPS characters then the string is truncated, if the input string
+ *     is shorter than NCPS characters then the string is NULL filled.
+ *     If the mode argument (c) is >=0 then (c) is the first character
+ *     copied to the string buffer, if (c) is <0 then intervening white
+ *     space (SPACES and TABS) are skipped and the first character found
+ *     must be a LETTER else a 'q' error terminates the parse of this
+ *     assembler-source text line.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           aslex.c
+ *             char    getnb()         aslex.c
+ *             VOID    unget()         aslex.c
+ *
+ *     side effects:
+ *             use of getnb(), get(), and unget() updates the
+ *             global pointer ip, the position in the current
+ *             assembler-source text line.
+ */
+
+VOID
+getid(id, c)
+register int c;
+char *id;
+{
+       register char *p;
+
+       if (c < 0) {
+               c = getnb();
+               if ((ctype[c] & LETTER) == 0)
+                       qerr();
+       }
+       p = id;
+       do {
+               if (p < &id[NCPS])
+                       *p++ = c;
+       } while (ctype[c=get()] & (LETTER|DIGIT));
+       unget(c);
+       while (p < &id[NCPS])
+               *p++ = 0;
+}
+
+/*)Function    VOID    getst(id,c)
+ *
+ *             char *  id              a pointer to a string of
+ *                                     maximum length NCPS
+ *             int     c               mode flag
+ *                                     >=0     this is first character to
+ *                                             copy to the string buffer
+ *                                     <0      skip white space, first
+ *                                             character must be a LETTER
+ *
+ *     The function getnbid() scans the current assembler-source text line
+ *     from the current position copying the next character string into
+ *     the external string buffer (id).  The string ends when a SPACE or
+ *     ILL character is found. The maximum number of
+ *     characters copied is NCPS.  If the input string is larger than
+ *     NCPS characters then the string is truncated, if the input string
+ *     is shorter than NCPS characters then the string is NULL filled.
+ *     If the mode argument (c) is >=0 then (c) is the first character
+ *     copied to the string buffer, if (c) is <0 then intervening white
+ *     space (SPACES and TABS) are skipped and the first character found
+ *     must be a LETTER else a 'q' error terminates the parse of this
+ *     assembler-source text line.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           aslex.c
+ *             char    getnb()         aslex.c
+ *             VOID    unget()         aslex.c
+ *
+ *     side effects:
+ *             use of getnb(), get(), and unget() updates the
+ *             global pointer ip, the position in the current
+ *             assembler-source text line.
+ */
+
+VOID
+getst(id, c)
+register int c;
+char *id;
+{
+       register char *p;
+
+       if (c < 0) {
+               c = getnb();
+               if ((ctype[c] & LETTER) == 0)
+                       qerr();
+       }
+       p = id;
+       do {
+               if (p < &id[NCPS])
+                       *p++ = c;
+       } while (ctype[c=get()] & (0xFF - (SPACE|ILL)));
+       unget(c);
+       while (p < &id[NCPS])
+               *p++ = 0;
+}
+
+/*)Function    char    getnb()
+ *
+ *     The function getnb() scans the current assembler-source
+ *     text line returning the first character not a SPACE or TAB.
+ *
+ *     local variables:
+ *             int     c               current character from
+ *                                     assembler-source text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    get()           aslex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip, the position
+ *             in the current assembler-source text line
+ */
+
+char
+getnb()
+{
+       register int c;
+
+       while ((c=get()) == ' ' || c == '\t')
+               ;
+       return (c);
+}
+
+/*)Function    char    get()
+ *
+ *     The function get() returns the next character in the
+ *     assembler-source text line, at the end of the line a
+ *     NULL character is returned.
+ *
+ *     local variables:
+ *             int     c               current character from
+ *                                     assembler-source text line
+ *
+ *     global variables:
+ *             char *  ip              pointer into the current
+ *                                     assembler-source text line
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             updates ip to the next character position in the
+ *             assembler-source text line.  If ip is at the end of the
+ *             line, ip is not updated.
+ */
+
+char
+get()
+{
+       register int c;
+
+       if ((c = *ip) != 0)
+               ++ip;
+       return (c);
+}
+
+/*)Function    VOID    unget(c)
+ *
+ *             int     c               value of last character read from
+ *                                     assembler-source text line
+ *
+ *     If (c) is not a NULL character then the global pointer ip
+ *     is updated to point to the preceeding character in the
+ *     assembler-source text line.
+ *
+ *     NOTE:   This function does not push the character (c)
+ *             back into the assembler-source text line, only
+ *             the pointer ip is changed.
+ *
+ *     local variables:
+ *             int     c               last character read from
+ *                                     assembler-source text line
+ *
+ *     global variables:
+ *             char *  ip              position into the current
+ *                                     assembler-source text line
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             ip decremented by 1 character position
+ */
+
+VOID
+unget(c)
+{
+       if (c)
+               if (ip != ib)
+                       --ip;
+}
+
+/*)Function    int     getmap(d)
+ *
+ *             int     d               value to compare with the
+ *                                     assembler-source text line character
+ *
+ *     The function getmap() converts the 'C' style characters \b, \f,
+ *     \n, \r, and \t to their equivalent ascii values and also
+ *     converts 'C' style octal constants '\123' to their equivalent
+ *     numeric values.  If the first character is equivalent to (d) then
+ *     a (-1) is returned, if the end of the line is detected then
+ *     a 'q' error terminates the parse for this line, or if the first
+ *     character is not a \ then the character value is returned.
+ *
+ *     local variables:
+ *             int     c               value of character from the
+ *                                     assembler-source text line
+ *             int     n               looping counter
+ *             int     v               current value of numeric conversion
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    get()           aslex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip the position
+ *             in the current assembler-source text line
+ */
+
+int
+getmap(d)
+{
+       register int c, n, v;
+
+       if ((c=get()) == '\0')
+               qerr();
+       if (c == d)
+               return (-1);
+       if (c == '\\') {
+               c = get();
+               switch (c) {
+
+               case 'b':
+                       c = '\b';
+                       break;
+
+               case 'f':
+                       c = '\f';
+                       break;
+
+               case 'n':
+                       c = '\n';
+                       break;
+
+               case 'r':
+                       c = '\r';
+                       break;
+
+               case 't':
+                       c = '\t';
+                       break;
+
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                       n = 0;
+                       v = 0;
+                       while (++n<=3 && c>='0' && c<='7') {
+                               v = (v<<3) + c - '0';
+                               c = get();
+                       }
+                       unget(c);
+                       c = v;
+                       break;
+               }
+       }
+       return (c);
+}
+
+/*)Function    int     getline()
+ *
+ *     The function getline() reads a line of assembler-source text
+ *     from an assembly source text file or an include file.
+ *     Lines of text are processed from assembler-source files until
+ *     all files have been read.  If an include file is opened then
+ *     lines of text are read from the include file (or nested
+ *     include file) until the end of the include file is found.
+ *     The input text line is copied into the global string ib[]
+ *     and converted to a NULL terminated string.  The function
+ *     getline() returns a (1) after succesfully reading a line
+ *     or a (0) if all files have been read.
+ *
+ *     local variables:
+ *             int     i               string length
+ *
+ *     global variables:
+ *             char    ib[]            string buffer containing
+ *                                     assembler-source text line
+ *             char    ifp[]           array of file handles for
+ *                                     include files
+ *             int     incfil          index for ifp[] specifies
+ *                                     active include file
+ *             int     incline[]       array of include file
+ *                                     line numbers
+ *             char    sfp[]           array of file handles for
+ *                                     assembler source files
+ *             int     cfile           index for sfp[] specifies
+ *                                     active source file
+ *             int     srcline[]       array of source file
+ *                                     line numbers
+ *             int     inpfil          maximum input file index
+ *
+ *     called functions:
+ *             int     fclose()        c-library
+ *             char *  fgets()         c-library
+ *             int     strlen()        c-library
+ *
+ *     side effects:
+ *             include file will be closed at detection of end of file.
+ *             the next sequential source file may be selected.
+ *             the global file indexes incfil or cfile may be changed.
+ *             The respective source line or include line counter
+ *             will be updated.
+ */
+
+int
+getline()
+{
+loop:  if (incfil >= 0) {
+               if (fgets(ib, sizeof ib, ifp[incfil]) == NULL) {
+                       fclose(ifp[incfil--]);
+                       lop = NLPP;
+                       goto loop;
+               } else {
+                       ++incline[incfil];
+               }
+       } else {
+               if (fgets(ib, sizeof ib, sfp[cfile]) == NULL) {
+                       if (++cfile <= inpfil) {
+                               srcline[cfile] = 0;
+                               goto loop;
+                       }
+                       return (0);
+               } else {
+                       ++srcline[cfile];
+               }
+       }
+       chop_crlf(ib);
+       return (1);
+}
+
+/*)Function    int     more()
+ *
+ *     The function more() scans the assembler-source text line
+ *     skipping white space (SPACES and TABS) and returns a (0)
+ *     if the end of the line or a comment delimeter (;) is found,
+ *     or a (1) if their are additional characters in the line.
+ *
+ *     local variables:
+ *             int     c               next character from the
+ *                                     assembler-source text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    getnb()         aslex.c
+ *             VOID    unget()         aslex.c
+ *
+ *     side effects:
+ *             use of getnb() and unget() updates the global pointer ip
+ *             the position in the current assembler-source text line
+ */
+
+int
+more()
+{
+       register int c;
+
+       c = getnb();
+       unget(c);
+       return( (c == '\0' || c == ';') ? 0 : 1 );
+}
+
+/*)Function    char    endline()
+ *
+ *     The function endline() scans the assembler-source text line
+ *     skipping white space (SPACES and TABS) and returns the next
+ *     character or a (0) if the end of the line is found or a
+ *     comment delimiter (;) is found.
+ *
+ *     local variables:
+ *             int     c               next character from the
+ *                                     assembler-source text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    getnb()         aslex.c
+ *
+ *     side effects:
+ *             use of getnb() updates the global pointer ip the
+ *             position in the current assembler-source text line
+ */
+
+char
+endline()
+{
+       register int c;
+
+       c = getnb();
+       return( (c == '\0' || c == ';') ? 0 : c );
+}
+
+/*)Function    VOID    chop_crlf(str)
+ *
+ *             char    *str            string to chop
+ *
+ *     The function chop_crlf() removes trailing LF or CR/LF from
+ *     str, if present.
+ *
+ *     local variables:
+ *             int     i               string length
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+VOID
+chop_crlf(str)
+char *str;
+{
+       register int i;
+
+       i = strlen(str);
+       if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
+       if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;
+}
diff --git a/as/hc08/aslink.h b/as/hc08/aslink.h
new file mode 100644 (file)
index 0000000..263467a
--- /dev/null
@@ -0,0 +1,775 @@
+/* aslink.h */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - add proto for StoreString
+ *          - change s_id from [NCPS] to pointer
+ *          - change NCPS to 80
+ *           - case sensitive
+ *           - add R_J11 for 8051 assembler
+ * 31-Oct-97 JLH: 
+ *           - add jflag and jfp for NoICE output
+ * 30-Jan-98 JLH:
+ *           - add memory space flags to a_flag for 8051
+ */
+
+#define        VERSION "V01.70 + NoICE + SDCC Feb 1999"
+
+/*
+ * Case Sensitivity Flag
+ */
+#define        CASE_SENSITIVE  1
+
+/*)Module      asmlnk.h
+ *
+ *     The module asmlnk.h contains the definitions for constants,
+ *     structures, global variables, and LKxxxx functions
+ *     contained in the LKxxxx.c files.
+ */
+
+/*)BUILD
+       $(PROGRAM) =    ASLINK
+       $(INCLUDE) =    ASLINK.H
+       $(FILES) = {
+               LKMAIN.C
+               LKLEX.C
+               LKAREA.C
+               LKHEAD.C
+               LKSYM.C
+               LKEVAL.C
+               LKDATA.C
+               LKLIST.C
+               LKRLOC.C
+               LKLIBR.C
+               LKS19.C
+               LKIHX.C
+       }
+       $(STACK) = 2000
+*/
+
+/* DECUS C void definition */
+/* File/extension seperator */
+
+#ifdef decus
+#define        VOID    char
+#define        FSEPX   '.'
+#endif
+
+/* PDOS C void definition */
+/* File/extension seperator */
+
+#ifdef PDOS
+#define        VOID    char
+#define        FSEPX   ':'
+#endif
+
+/* Default void definition */
+/* File/extension seperator */
+
+#ifndef        VOID
+#define        VOID    void
+#define        FSEPX   '.'
+#define        OTHERSYSTEM 
+#endif
+
+/*
+ * PATH_MAX
+ */
+#include <limits.h>
+#ifndef PATH_MAX               /* POSIX, but not required   */
+ #if defined(__BORLANDC__) || defined(_MSC_VER)
+  #include <stdlib.h>
+  #define PATH_MAX     _MAX_PATH
+ #else
+  #define PATH_MAX     255     /* define a reasonable value */
+ #endif
+#endif
+
+/*
+ * This file defines the format of the
+ * relocatable binary file.
+ */
+
+#define NCPS   80              /* characters per symbol (JLH: change from 8) */
+#define        NDATA   16              /* actual data */
+#define        NINPUT  PATH_MAX        /* Input buffer size */
+#define        NHASH   64              /* Buckets in hash table */
+#define        HMASK   077             /* Hash mask */
+#define        NLPP    60              /* Lines per page */
+#define        NTXT    16              /* T values */
+
+/*
+ *     The "R_" relocation constants define values used in
+ *     generating the assembler relocation output data for
+ *     areas, symbols, and code.
+ *
+ *
+ *     Relocation types.
+ *
+ *            7     6     5     4     3     2     1     0
+ *         +-----+-----+-----+-----+-----+-----+-----+-----+
+ *         | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
+ *         +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define        R_WORD  0x00            /* 16 bit */
+#define        R_BYTE  0x01            /*  8 bit */
+
+#define        R_AREA  0x00            /* Base type */
+#define        R_SYM   0x02
+
+#define        R_NORM  0x00            /* PC adjust */
+#define        R_PCR   0x04
+
+#define        R_BYT1  0x00            /* Byte count for R_BYTE = 1 */
+#define        R_BYT2  0x08            /* Byte count for R_BYTE = 2 */
+
+#define        R_SGND  0x00            /* Signed Byte */
+#define        R_USGN  0x10            /* Unsigned Byte */
+
+#define        R_NOPAG 0x00            /* Page Mode */
+#define        R_PAG0  0x20            /* Page '0' */
+#define        R_PAG   0x40            /* Page 'nnn' */
+
+#define        R_LSB   0x00            /* low byte */
+#define        R_MSB   0x80            /* high byte */
+
+#define R_BYT3 0x100           /* if R_BYTE is set, this is a 
+                                * 3 byte address, of which
+                                * the linker must select one byte.
+                                */
+#define R_HIB  0x200           /* If R_BYTE & R_BYT3 are set, linker
+                                * will select byte 3 of the relocated
+                                * 24 bit address.
+                                */
+
+#define R_J11   (R_WORD|R_BYT2)        /* JLH: 11 bit JMP and CALL (8051) */
+#define R_J19   (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */
+#define R_C24   (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */
+#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB)
+
+#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19)
+#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11)
+#define IS_C24(x) (((x) & R_J19_MASK) == R_C24)
+
+#define R_ESCAPE_MASK  0xf0    /* Used to escape relocation modes
+                                * greater than 0xff in the .rel
+                                * file.
+                                */
+
+/*
+ * Global symbol types.
+ */
+#define        S_REF   1               /* referenced */
+#define        S_DEF   2               /* defined */
+
+/*
+ * Area type flags
+ */
+#define        A_CON   0000            /* concatenate */
+#define        A_OVR   0004            /* overlay */
+#define        A_REL   0000            /* relocatable */
+#define        A_ABS   0010            /* absolute */
+#define        A_NOPAG 0000            /* non-paged */
+#define        A_PAG   0020            /* paged */
+
+/* Additional flags for 8051 address spaces */
+#define A_DATA  0000           /* data space (default)*/
+#define A_CODE  0040           /* code space */
+#define A_XDATA 0100           /* external data space */
+#define A_BIT   0200           /* bit addressable space */
+
+/*
+ * File types
+ */
+#define        F_STD   1               /* stdin */
+#define        F_LNK   2               /* File.lnk */
+#define        F_REL   3               /* File.rel */
+
+/*
+ *     General assembler address type
+ */
+typedef unsigned int Addr_T;
+
+/*
+ *     The structures of head, area, areax, and sym are created
+ *     as the REL files are read during the first pass of the
+ *     linker.  The struct head is created upon encountering a
+ *     H directive in the REL file.  The structure contains a
+ *     link to a link file structure (struct lfile) which describes
+ *     the file containing the H directive, the number of data/code
+ *     areas contained in this header segment, the number of
+ *     symbols referenced/defined in this header segment, a pointer
+ *     to an array of pointers to areax structures (struct areax)
+ *     created as each A directive is read, and a pointer to an
+ *     array of pointers to symbol structures (struct sym) for
+ *     all referenced/defined symbols.  As H directives are read
+ *     from the REL files a linked list of head structures is
+ *     created by placing a link to the new head structure
+ *     in the previous head structure.
+ */
+struct head
+{
+       struct  head   *h_hp;   /* Header link */
+       struct  lfile  *h_lfile;/* Associated file */
+       int     h_narea;        /* # of areas */
+       struct  areax **a_list; /* Area list */
+       int     h_nglob;        /* # of global symbols */
+       struct  sym   **s_list; /* Globle symbol list */
+       char    m_id[NCPS];     /* Module name */
+};
+
+/*
+ *     A structure area is created for each 'unique' data/code
+ *     area definition found as the REL files are read.  The
+ *     struct area contains the name of the area, a flag byte
+ *     which contains the area attributes (REL/CON/OVR/ABS),
+ *     an area subtype (not used in this assembler), and the
+ *     area base address and total size which will be filled
+ *     in at the end of the first pass through the REL files.
+ *     As A directives are read from the REL files a linked
+ *     list of unique area structures is created by placing a
+ *     link to the new area structure in the previous area structure.
+ */
+struct area
+{
+       struct  area    *a_ap;  /* Area link */
+       struct  areax   *a_axp; /* Area extension link */
+       Addr_T  a_addr;         /* Beginning address of area */
+       Addr_T  a_size;         /* Total size of the area */
+       char    a_type;         /* Area subtype */
+       char    a_flag;         /* Flag byte */
+       char    a_id[NCPS];     /* Name */
+};
+
+/*
+ *     An areax structure is created for every A directive found
+ *     while reading the REL files.  The struct areax contains a
+ *     link to the 'unique' area structure referenced by the A
+ *     directive and to the head structure this area segment is
+ *     a part of.  The size of this area segment as read from the
+ *     A directive is placed in the areax structure.  The beginning
+ *     address of this segment will be filled in at the end of the
+ *     first pass through the REL files.  As A directives are read
+ *     from the REL files a linked list of areax structures is
+ *     created for each unique area.  The final areax linked
+ *     list has at its head the 'unique' area structure linked
+ *     to the linked areax structures (one areax structure for
+ *     each A directive for this area).
+ */
+struct areax
+{
+       struct  areax   *a_axp; /* Area extension link */
+       struct  area    *a_bap; /* Base area link */
+       struct  head    *a_bhp; /* Base header link */
+       Addr_T  a_addr;         /* Beginning address of section */
+       Addr_T  a_size;         /* Size of the area in section */
+};
+
+/*
+ *     A sym structure is created for every unique symbol
+ *     referenced/defined while reading the REL files.  The
+ *     struct sym contains the symbol's name, a flag value
+ *     (not used in this linker), a symbol type denoting
+ *     referenced/defined, and an address which is loaded
+ *     with the relative address within the area in which
+ *     the symbol was defined.  The sym structure also
+ *     contains a link to the area where the symbol was defined.
+ *     The sym structures are linked into linked lists using
+ *     the symbol link element.
+ */
+struct sym
+{
+       struct  sym     *s_sp;  /* Symbol link */
+       struct  areax   *s_axp; /* Symbol area link */
+       char    s_type;         /* Symbol subtype */
+       char    s_flag;         /* Flag byte */
+       Addr_T  s_addr;         /* Address */
+       char    *s_id;          /* Name: JLH change from [NCPS] */
+};
+
+/*
+ *     The structure lfile contains a pointer to a
+ *     file specification string, the file type, and
+ *     a link to the next lfile structure.
+ */
+struct lfile
+{
+       struct  lfile   *f_flp; /* lfile link */
+       int     f_type;         /* File type */
+       char    *f_idp;         /* Pointer to file spec */
+};
+
+/*
+ *     The struct base contains a pointer to a
+ *     base definition string and a link to the next
+ *     base structure.
+ */
+struct base
+{
+       struct  base  *b_base;  /* Base link */
+       char          *b_strp;  /* String pointer */
+};
+
+/*
+ *     The struct globl contains a pointer to a
+ *     global definition string and a link to the next
+ *     global structure.
+ */
+struct globl
+{
+       struct  globl *g_globl; /* Global link */
+       char          *g_strp;  /* String pointer */
+};
+
+/*
+ *     A structure sdp is created for each 'unique' paged
+ *     area definition found as the REL files are read.
+ *     As P directives are read from the REL files a linked
+ *     list of unique sdp structures is created by placing a
+ *     link to the new sdp structure in the previous area structure.
+ */
+struct sdp
+{
+       struct  area  *s_area;  /* Paged Area link */
+       struct  areax *s_areax; /* Paged Area Extension Link */
+       Addr_T  s_addr;         /* Page address offset */
+};
+
+/*
+ *     The structure rerr is loaded with the information
+ *     required to report an error during the linking
+ *     process.  The structure contains an index value
+ *     which selects the areax structure from the header
+ *     areax structure list, a mode value which selects
+ *     symbol or area relocation, the base address in the
+ *     area section, an area/symbol list index value, and
+ *     an area/symbol offset value.
+ */
+struct rerr
+{
+       int     aindex;         /* Linking area */
+       int     mode;           /* Relocation mode */
+       Addr_T  rtbase;         /* Base address in section */
+       int     rindex;         /* Area/Symbol reloaction index */
+       Addr_T  rval;           /* Area/Symbol offset value */
+};
+
+/*
+ *     The structure lbpath is created for each library
+ *     path specification input by the -k option.  The
+ *     lbpath structures are linked into a list using
+ *     the next link element.
+ */
+struct lbpath {
+       struct  lbpath  *next;
+       char            *path;
+};
+
+/*
+ *     The structure lbname is created for all combinations of the
+ *     library path specifications (input by the -k option) and the
+ *     library file specifications (input by the -l option) that
+ *     lead to an existing file.  The element path points to
+ *     the path string, element libfil points to the library
+ *     file string, and the element libspc is the concatenation
+ *     of the valid path and libfil strings.
+ *
+ *     The lbpath structures are linked into a list
+ *     using the next link element.
+ *
+ *     Each library file contains a list of object files
+ *     that are contained in the particular library. e.g.:
+ *
+ *             \iolib\termio
+ *             \inilib\termio
+ *
+ *     Only one specification per line is allowed.
+ */
+struct lbname {
+       struct  lbname  *next;
+       char            *path;
+       char            *libfil;
+       char            *libspc;
+};
+
+/*
+ *     The function fndsym() searches through all combinations of the
+ *     library path specifications (input by the -k option) and the
+ *     library file specifications (input by the -l option) that
+ *     lead to an existing file for a symbol definition.
+ *
+ *     The structure lbfile is created for the first library
+ *     object file which contains the definition for the
+ *     specified undefined symbol.
+ *
+ *     The element libspc points to the library file path specification
+ *     and element relfil points to the object file specification string.
+ *     The element filspc is the complete path/file specification for
+ *     the library file to be imported into the linker.  The
+ *     file specicifation may be formed in one of two ways:
+ *
+ *     (1)     If the library file contained an absolute
+ *             path/file specification then this becomes filspc.
+ *             (i.e. C:\...)
+ *
+ *     (2)     If the library file contains a relative path/file
+ *             specification then the concatenation of the path
+ *             and this file specification becomes filspc.
+ *             (i.e. \...)
+ *
+ *     The lbpath structures are linked into a list
+ *     using the next link element.
+ */
+struct lbfile {
+       struct  lbfile  *next;
+       char            *libspc;
+       char            *relfil;
+       char            *filspc;
+       long            offset; /*>=0 if rel file is embedded in a lib file at this offset*/
+};
+
+/*
+ *     External Definitions for all Global Variables
+ */
+
+extern char    *_abs_;         /*      = { ".  .ABS." };
+                                */
+extern int     lkerr;          /*      ASLink error flag
+                                */
+extern char    *ip;            /*      pointer into the REL file
+                                *      text line in ib[]
+                                */
+extern char    ib[NINPUT];     /*      REL file text line
+                                */
+extern char    *rp;            /*      pointer into the LST file
+                                *      text line in rb[]
+                                */
+extern char    rb[NINPUT];     /*      LST file text line being
+                                *      address relocated
+                                */
+extern unsigned char   ctype[];        /*      array of character types, one per
+                                *      ASCII character
+                                */
+
+extern char sdccopt[NINPUT];
+extern char sdccopt_module[NINPUT];
+extern char curr_module[NINPUT];
+
+/*
+ *     Character Type Definitions
+ */
+#define        SPACE   0000
+#define ETC    0000
+#define        LETTER  0001
+#define        DIGIT   0002
+#define        BINOP   0004
+#define        RAD2    0010
+#define        RAD8    0020
+#define        RAD10   0040
+#define        RAD16   0100
+#define        ILL     0200
+
+#define        DGT2    DIGIT|RAD16|RAD10|RAD8|RAD2
+#define        DGT8    DIGIT|RAD16|RAD10|RAD8
+#define        DGT10   DIGIT|RAD16|RAD10
+#define        LTR16   LETTER|RAD16
+
+#if    CASE_SENSITIVE
+#else
+extern char    ccase[];        /*      an array of characters which
+                                *      perform the case translation function
+                                */
+#endif
+
+extern struct  lfile   *filep; /*      The pointers (lfile *) filep,
+                                *      (lfile *) cfp, and (FILE *) sfp
+                                *      are used in conjunction with
+                                *      the routine getline() to read
+                                *      asmlnk commands from
+                                *      (1) the standard input or
+                                *      (2) or a command file
+                                *      and to read the REL files
+                                *      sequentially as defined by the
+                                *      asmlnk input commands.
+                                *
+                                *      The pointer *filep points to the
+                                *      beginning of a linked list of
+                                *      lfile structures.
+                                */
+extern struct  lfile   *cfp;   /*      The pointer *cfp points to the
+                                *      current lfile structure
+                                */
+extern struct  lfile   *startp;/*      asmlnk startup file structure
+                                */
+extern struct  lfile   *linkp; /*      pointer to first lfile structure
+                                *      containing an input REL file
+                                *      specification
+                                */
+extern struct  lfile   *lfp;   /*      pointer to current lfile structure
+                                *      being processed by parse()
+                                */
+extern struct  head    *headp; /*      The pointer to the first
+                                *      head structure of a linked list
+                                */
+extern struct  head    *hp;    /*      Pointer to the current
+                                *      head structure
+                                */
+extern struct  area    *areap; /*      The pointer to the first
+                                *      area structure of a linked list
+                                */
+extern struct  area    *ap;    /*      Pointer to the current
+                                *      area structure
+                                */
+extern struct  areax   *axp;   /*      Pointer to the current
+                                *      areax structure
+                                */
+extern struct  sym *symhash[NHASH]; /* array of pointers to NHASH
+                                     * linked symbol lists
+                                     */
+extern struct  base    *basep; /*      The pointer to the first
+                                *      base structure
+                                */
+extern struct  base    *bsp;   /*      Pointer to the current
+                                *      base structure
+                                */
+extern struct  globl   *globlp;/*      The pointer to the first
+                                *      globl structure
+                                */
+extern struct  globl   *gsp;   /*      Pointer to the current
+                                *      globl structure
+                                */
+extern struct  sdp     sdp;    /*      Base Paged structure
+                                */
+extern struct  rerr    rerr;   /*      Structure containing the
+                                *      linker error information
+                                */
+extern FILE    *ofp;           /*      Linker Output file handle
+                                */
+extern FILE    *mfp;           /*      Map output file handle
+                                */
+extern  FILE   *jfp;           /*      NoICE output file handle
+                                */
+extern FILE    *rfp;           /*      File handle for output
+                                *      address relocated ASxxxx
+                                *      listing file
+                                */
+extern FILE    *sfp;           /*      The file handle sfp points to the
+                                *      currently open file
+                                */
+extern FILE    *tfp;           /*      File handle for input
+                                *      ASxxxx listing file
+                                */
+extern  FILE    *dfp;           /*      File handle for debug info output
+                                */
+extern  int     dflag;          /*      Output debug information flag
+                                */
+extern int     oflag;          /*      Output file type flag
+                                */
+extern int     mflag;          /*      Map output flag
+                                */
+extern int     sflag;          /*      JCF: Memory usage output flag
+                                */
+extern int     jflag;          /*      NoICE output flag
+                                */
+extern int     xflag;          /*      Map file radix type flag
+                                */
+extern int     pflag;          /*      print linker command file flag
+                                */
+extern int     uflag;          /*      Listing relocation flag
+                                */
+extern int     rflag;          /*      Extended linear address record flag.
+                               */                               
+extern int     radix;          /*      current number conversion radix:
+                                *      2 (binary), 8 (octal), 10 (decimal),
+                                *      16 (hexadecimal)
+                                */
+extern int     line;           /*      current line number
+                                */
+extern int     page;           /*      current page number
+                                */
+extern int     lop;            /*      current line number on page
+                                */
+extern int     pass;           /*      linker pass number
+                                */
+extern int     rtcnt;          /*      count of elements in the
+                                *      rtval[] and rtflg[] arrays
+                                */
+extern Addr_T  rtval[];        /*      data associated with relocation
+                                */
+extern int     rtflg[];        /*      indicates if rtval[] value is
+                                *      to be sent to the output file.
+                                *      (always set in this linker)
+                                */
+extern int     hilo;           /*      REL file byte ordering
+                                */
+extern int     gline;          /*      LST file relocation active
+                                *      for current line
+                                */
+extern int     gcntr;          /*      LST file relocation active
+                                *      counter
+                                */
+extern struct lbpath *lbphead; /*      pointer to the first
+                                *      library path structure
+                                */
+extern struct lbname *lbnhead; /*      pointer to the first
+                                *      library name structure
+                                */
+extern struct lbfile *lbfhead; /*      pointer to the first
+                                *      library file structure
+                                */
+extern Addr_T iram_size;       /*      internal ram size
+                                */
+extern long xram_size; /*      external ram size
+                                */
+extern long code_size; /*      code size
+                                */
+
+
+/* C Library function definitions */
+/* for reference only
+extern VOID            exit();
+extern int             fclose();
+extern char *          fgets();
+extern FILE *          fopen();
+extern int             fprintf();
+extern VOID            free();
+extern VOID *          malloc();
+extern char            putc();
+extern char *          strcpy();
+extern int             strlen();
+extern char *          strncpy();
+*/
+
+/* Program function definitions */
+
+/* lkmain.c */
+extern FILE *          afile();
+extern VOID            bassav();
+extern VOID            gblsav();
+extern VOID            iramsav();
+extern VOID            xramsav();
+extern VOID            codesav();
+extern VOID            iramcheck();
+extern VOID            link_main();
+extern VOID            lkexit();
+extern int             main();
+extern VOID            map();
+extern int             parse();
+extern VOID            setbas();
+extern VOID            setgbl();
+extern VOID            usage();
+extern  VOID            copyfile();
+
+/* lklex.c */
+extern char            endline();
+extern char            get();
+extern VOID            getfid();
+extern VOID            getid();
+extern VOID            getSid();
+extern int             getline();
+extern int             getmap();
+extern char            getnb();
+extern int             more();
+extern VOID            skip();
+extern VOID            unget();
+extern VOID            chop_crlf();
+
+/* lkarea.c */
+extern VOID            lkparea();
+extern VOID            lnkarea();
+extern VOID            lnksect();
+extern VOID            newarea();
+
+/* lkhead.c */
+extern VOID            module();
+extern VOID            newhead();
+
+/* lksym.c */
+extern int             hash();
+extern struct  sym *   lkpsym();
+extern VOID *          new();
+extern struct  sym *   newsym();
+extern VOID            symdef();
+extern int             symeq();
+extern VOID            syminit();
+extern VOID            symmod();
+extern Addr_T          symval();
+
+/* lkeval.c */
+extern int             digit();
+extern Addr_T          eval();
+extern Addr_T          expr();
+extern int             oprio();
+extern Addr_T          term();
+
+/* lklist.c */
+extern int             dgt();
+extern VOID            lkulist();
+extern VOID            lkalist();
+extern VOID            lkglist();
+extern VOID            lstarea();
+extern VOID            newpag();
+extern VOID            slew();
+
+/* lkrloc.c */
+extern Addr_T          adb_b();
+extern Addr_T          adb_hi();
+extern Addr_T          adb_lo();
+extern Addr_T          adb_24_hi(Addr_T v, int i);
+extern Addr_T          adb_24_mid(Addr_T v, int i);
+extern Addr_T          adb_24_lo(Addr_T v, int i);
+extern Addr_T          adw_w();
+extern Addr_T          adw_24(Addr_T, int);
+extern Addr_T          adw_hi();
+extern Addr_T          adw_lo();
+extern Addr_T          evword();
+extern VOID            rele();
+extern VOID            reloc();
+extern VOID            relt();
+extern VOID            relr();
+extern VOID            relp();
+extern VOID            relerr();
+extern char *          errmsg[];
+extern VOID            errdmp();
+extern VOID            relerp();
+extern VOID            erpdmp();
+extern VOID            prntval();
+extern  int            lastExtendedAddress;
+
+/* lklibr.c */
+extern int             addfile();
+extern VOID            addlib();
+extern VOID            addpath();
+extern int             fndsym();
+extern VOID            library();
+extern VOID            loadfile();
+extern VOID            search();
+
+/* lks19.c */
+extern VOID            s19();
+
+/* lkihx.c */
+extern VOID            ihx();
+extern VOID            ihxEntendedLinearAddress(Addr_T);
+extern VOID            newArea();
+
+/* lkstore.c */
+extern char            *StoreString( char *str );
+
+/* lknoice.c */
+extern void             DefineNoICE( char *name, Addr_T value, int page );
+
+/* JCF: lkmem.c */
+extern int summary(struct area * xp);
+
+/* JCF: lkaomf51.c */
+extern void SaveLinkedFilePath(char * filepath);
+extern void CreateAOMF51(void);
diff --git a/as/hc08/aslink.mak b/as/hc08/aslink.mak
new file mode 100644 (file)
index 0000000..300803d
--- /dev/null
@@ -0,0 +1,263 @@
+ORIGIN         = Symantec C++
+ORIGIN_VER     = Version 7.00
+VERSION                = RELEASE
+
+!IFDEF SUB_DEBUG
+DEBUG          = $(SUB_DEBUG)
+NDEBUG         = !$(SUB_DEBUG)
+!ELSE
+DEBUG          = 0
+NDEBUG         = 1
+!ENDIF
+
+PROJ           = ASLINK
+APPTYPE                = DOS EXE
+PROJTYPE       = EXE
+
+CC             = SC
+CPP            = SPP
+MAKE           = SMAKE
+RC             = RCC
+HC             = HC31
+ASM            = SC
+DISASM         = OBJ2ASM
+LNK            = LINK
+DLLS           = 
+
+HEADERS                = ..\linksrc\aslink.h 
+
+DEFFILE                = ASLINK.DEF
+
+!IF $(DEBUG)
+OUTPUTDIR      = .
+CREATEOUTPUTDIR        =
+TARGETDIR      = .
+CREATETARGETDIR        =
+
+LIBS           = 
+
+CFLAGS         =  -A -Jm -J -ms -o+time -S -2 -a2 -c 
+LFLAGS         =  /PACKF
+DEFINES                = -D_DEBUG=1
+!ELSE
+OUTPUTDIR      = .
+CREATEOUTPUTDIR        =
+TARGETDIR      = .
+CREATETARGETDIR        =
+
+LIBS           = 
+
+CFLAGS         =  -A -Jm -J -ms -o+time -S -2 -a2 -c 
+LFLAGS         =  /PACKF
+DEFINES                = 
+!ENDIF
+
+HFLAGS         = $(CFLAGS) 
+MFLAGS         = MASTERPROJ=$(PROJ) 
+LIBFLAGS       =  /C 
+RESFLAGS       =  
+DEBUGGERFLAGS  =  -LOADSYMBOLS 
+AFLAGS         = $(CFLAGS) 
+HELPFLAGS      = 
+
+MODEL          = S
+
+PAR            = PROJS BATS OBJS
+
+RCDEFINES      = 
+
+LIBDIRS                = 
+
+INCLUDES       = -Ic:\asxxxx\linksrc
+
+INCLUDEDOBJS   = 
+
+OBJS           =  $(OUTPUTDIR)\lkarea.OBJ  $(OUTPUTDIR)\lkdata.OBJ  $(OUTPUTDIR)\lkeval.OBJ  \
+                $(OUTPUTDIR)\lkhead.OBJ  $(OUTPUTDIR)\lkihx.OBJ  $(OUTPUTDIR)\lklex.OBJ  $(OUTPUTDIR)\lklibr.OBJ  \
+                $(OUTPUTDIR)\lklist.OBJ  $(OUTPUTDIR)\lkmain.OBJ  $(OUTPUTDIR)\lkrloc.OBJ  $(OUTPUTDIR)\lks19.OBJ  \
+                $(OUTPUTDIR)\lksym.OBJ 
+
+RCFILES                = 
+
+RESFILES       = 
+
+SYMS           = 
+
+HELPFILES      = 
+
+BATS           = 
+
+.SUFFIXES: .C .CP .CPP .CXX .CC .H .HPP .HXX .COM .EXE .DLL .LIB .RTF .DLG .ASM .RES .RC .OBJ 
+
+.C.OBJ:
+       $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.c
+
+.CPP.OBJ:
+       $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cpp
+
+.CXX.OBJ:
+       $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cxx
+
+.CC.OBJ:
+       $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cc
+
+.CP.OBJ:
+       $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cp
+
+.H.SYM:
+       $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.h
+
+.HPP.SYM:
+       $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hpp
+
+.HXX.SYM:
+       $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hxx
+
+.C.EXP:
+       $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES)   $*.c   -o$*.lst
+
+.CPP.EXP:
+       $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cpp -o$*.lst
+
+.CXX.EXP:
+       $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cxx -o$*.lst
+
+.CP.EXP:
+       $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES)  $*.cp  -o$*.lst
+
+.CC.EXP:
+       $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES)  $*.cc  -o$*.lst
+
+.ASM.EXP:
+       $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.asm -o$*.lst
+
+.OBJ.COD:
+       $(DISASM) $*.OBJ >$*.cod
+
+.OBJ.EXE:
+       $(LNK) $(LFLAGS) @$(PROJ).LNK
+
+.RTF.HLP:
+       $(HC) $(HELPFLAGS) $*.HPJ
+
+.ASM.OBJ:
+       $(ASM) $(AFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.asm
+
+.RC.RES: 
+       $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $*.rc -o$*.res
+
+.DLG.RES:
+       echo ^#include "windows.h" >$$$*.rc
+       echo ^IF EXIST "$*.h" >>$$$*.rc
+       echo ^#include "$*.h" >>$$$*.rc
+       echo ^#include "$*.dlg" >>$$$*.rc
+       $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $$$*.rc
+       -del $*.res
+       -ren $$$*.res $*.res
+
+
+
+all:   createdir $(PRECOMPILE) $(SYMS) $(OBJS) $(INCLUDEDOBJS) $(POSTCOMPILE) $(TARGETDIR)\$(PROJ).$(PROJTYPE) $(POSTLINK) _done
+
+createdir:
+       $(CREATEOUTPUTDIR)
+       $(CREATETARGETDIR)
+
+$(TARGETDIR)\$(PROJ).$(PROJTYPE): $(OBJS) $(INCLUDEDOBJS) $(RCFILES) $(RESFILES) $(HELPFILES) 
+                       $(LNK) $(LFLAGS) @$(PROJ).LNK;
+                       -del $(TARGETDIR)\$(PROJ).$(PROJTYPE)
+                       -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE)
+                       -echo $(TARGETDIR)\$(PROJ).$(PROJTYPE) built
+
+_done:
+               -echo $(PROJ).$(PROJTYPE) done
+
+buildall:      clean   all
+
+
+clean:
+               -del $(TARGETDIR)\$$SCW$$.$(PROJTYPE)
+               -del $(TARGETDIR)\$(PROJ).CLE
+               -del $(OUTPUTDIR)\SCPH.SYM
+               -del $(OBJS)
+
+cleanres:
+
+res:           cleanres $(RCFILES) all
+
+
+link:
+               $(LNK) $(LFLAGS) @$(PROJ).LNK;
+               -del $(TARGETDIR)\$(PROJ).$(PROJTYPE)
+               -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE)
+
+
+
+
+!IF EXIST (ASLINK.dpd)
+!INCLUDE ASLINK.dpd
+!ENDIF
+
+
+
+$(OUTPUTDIR)\lkarea.OBJ:       ..\linksrc\lkarea.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkarea.obj ..\linksrc\lkarea.c
+
+
+
+$(OUTPUTDIR)\lkdata.OBJ:       ..\linksrc\lkdata.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkdata.obj ..\linksrc\lkdata.c
+
+
+
+$(OUTPUTDIR)\lkeval.OBJ:       ..\linksrc\lkeval.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkeval.obj ..\linksrc\lkeval.c
+
+
+
+$(OUTPUTDIR)\lkhead.OBJ:       ..\linksrc\lkhead.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkhead.obj ..\linksrc\lkhead.c
+
+
+
+$(OUTPUTDIR)\lkihx.OBJ:        ..\linksrc\lkihx.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkihx.obj ..\linksrc\lkihx.c
+
+
+
+$(OUTPUTDIR)\lklex.OBJ:        ..\linksrc\lklex.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklex.obj ..\linksrc\lklex.c
+
+
+
+$(OUTPUTDIR)\lklibr.OBJ:       ..\linksrc\lklibr.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklibr.obj ..\linksrc\lklibr.c
+
+
+
+$(OUTPUTDIR)\lklist.OBJ:       ..\linksrc\lklist.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklist.obj ..\linksrc\lklist.c
+
+
+
+$(OUTPUTDIR)\lkmain.OBJ:       ..\linksrc\lkmain.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkmain.obj ..\linksrc\lkmain.c
+
+
+
+$(OUTPUTDIR)\lkrloc.OBJ:       ..\linksrc\lkrloc.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkrloc.obj ..\linksrc\lkrloc.c
+
+
+
+$(OUTPUTDIR)\lks19.OBJ:        ..\linksrc\lks19.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lks19.obj ..\linksrc\lks19.c
+
+
+
+$(OUTPUTDIR)\lksym.OBJ:        ..\linksrc\lksym.c
+               $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lksym.obj ..\linksrc\lksym.c
+
+
+
+
diff --git a/as/hc08/aslist.c b/as/hc08/aslist.c
new file mode 100644 (file)
index 0000000..2224403
--- /dev/null
@@ -0,0 +1,739 @@
+/* aslist.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - lstsym: show s_id as string rather than array [NCPS]
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdlib.h>
+#include "asm.h"
+
+/*)Module      aslist.c
+ *
+ *     The module aslist.c contains all the functions used
+ *     to generate the assembler list and symbol output files.
+ *
+ *     aslist.c contains the following functions:
+ *             VOID    list()
+ *             VOID    list1()
+ *             VOID    list2()
+ *             VOID    slew()
+ *             VOID    lstsym()
+ *
+ *     The module aslist.c contains no local/static variables
+ */
+
+/*)Function    VOID    list()
+ *
+ *     The function list() generates the listing output
+ *     which includes the input source, line numbers,
+ *     and generated code.  Numerical output may be selected
+ *     as hexadecimal, decimal, or octal.
+ * 
+ *     local variables:
+ *             int *   wp              pointer to the assembled data bytes
+ *             int *   wpt             pointer to the data byte mode
+ *             int     nb              computed number of assembled bytes
+ *
+ *     global variables:
+ *             int     cb[]            array of assembler output values
+ *             int     cbt[]           array of assembler relocation types
+ *                                     describing the data in cb[]
+ *             int *   cp              pointer to assembler output array cb[]
+ *             int *   cpt             pointer to assembler relocation type
+ *                                     output array cbt[]
+ *             char    eb[]            array of generated error codes
+ *             char *  ep              pointer into error list
+ *                                     array eb[]
+ *             char    ib[]            assembler-source text line
+ *             FILE *  lfp             list output file handle
+ *             int     line            current assembler source line number
+ *             int     lmode           listing mode
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    list1()         aslist.c
+ *             int     putc()          c_library
+ *             VOID    slew()          asslist.c
+ *
+ *     side effects:
+ *             Listing or symbol output updated.
+ */
+
+VOID
+list()
+{
+       register char *wp;
+       register int *wpt;
+       register int nb;
+
+       if (lfp == NULL || lmode == NLIST)
+               return;
+
+       /*
+        * Get Correct Line Number
+        */
+       if (incfil >= 0) {
+               line = incline[incfil];
+               if (line == 0) {
+                       if (incfil > 0) {
+                               line = incline[incfil-1];
+                       } else {
+                               line = srcline[cfile];
+                       }
+               }
+       } else {
+               line = srcline[cfile];
+       }
+
+       /*
+        * Move to next line.
+        */
+       slew(lfp, pflag);
+
+       /*
+        * Output a maximum of NERR error codes with listing.
+        */
+       while (ep < &eb[NERR])
+               *ep++ = ' ';
+       fprintf(lfp, "%.2s", eb);
+
+       /*
+        * Source listing only option.
+        */
+       if (lmode == SLIST) {
+               fprintf(lfp, "%24s%5u %s\n", "", line, ib);
+               return;
+       }
+       if (lmode == ALIST) {
+               outchk(HUGE,HUGE);
+       }
+
+       /*
+        * HEX output Option.
+        */
+       if (xflag == 0) {               /* HEX */
+               /*
+                * Equate only
+                */
+               if (lmode == ELIST) {
+                       fprintf(lfp, "%18s%04X", "", laddr);
+                       fprintf(lfp, "  %5u %s\n", line, ib);
+                       return;
+               }
+
+               /*
+                * Address (with allocation)
+                */
+               fprintf(lfp, " %04X", laddr);
+               if (lmode == ALIST || lmode == BLIST) {
+                       fprintf(lfp, "%19s%5u %s\n", "", line, ib);
+                       outdot();
+                       return;
+               }
+               wp = cb;
+               wpt = cbt;
+               nb = (int) (cp - cb);
+
+               /*
+                * First line of output for this source line with data.
+                */
+               list1(wp, wpt, nb, 1);
+               fprintf(lfp, " %5u %s\n", line, ib);
+
+               /*
+                * Subsequent lines of output if more data.
+                */
+               while ((nb -= 6) > 0) {
+                       wp += 6;
+                       wpt += 6;
+                       slew(lfp, 0);
+                       fprintf(lfp, "%7s", "");
+                       list1(wp, wpt, nb, 0);
+                       putc('\n', lfp);
+               }
+       } else
+       /*
+        * OCTAL output Option.
+        */
+       if (xflag == 1) {               /* OCTAL */
+               /*
+                * Equate only
+                */
+               if (lmode == ELIST) {
+                       fprintf(lfp, "%16s%06o", "", laddr);
+                       fprintf(lfp, "  %5u %s\n", line, ib);
+                       return;
+               }
+
+               /*
+                * Address (with allocation)
+                */
+               fprintf(lfp, " %06o", laddr);
+               if (lmode == ALIST || lmode == BLIST) {
+                       fprintf(lfp, "%17s%5u %s\n", "", line, ib);
+                       outdot();
+                       return;
+               }
+               wp = cb;
+               wpt = cbt;
+               nb = (int) (cp - cb);
+
+               /*
+                * First line of output for this source line with data.
+                */
+               list1(wp, wpt, nb, 1);
+               fprintf(lfp, " %5u %s\n", line, ib);
+
+               /*
+                * Subsequent lines of output if more data.
+                */
+               while ((nb -= 4) > 0) {
+                       wp += 4;
+                       wpt += 4;
+                       slew(lfp, 0);
+                       fprintf(lfp, "%9s", "");
+                       list1(wp, wpt, nb, 0);
+                       putc('\n', lfp);
+               }
+       } else
+       /*
+        * DECIMAL output Option.
+        */
+       if (xflag == 2) {               /* DECIMAL */
+               /*
+                * Equate only
+                */
+               if (lmode == ELIST) {
+                       fprintf(lfp, "%16s%05u", "", laddr);
+                       fprintf(lfp, "   %5u %s\n", line, ib);
+                       return;
+               }
+
+               /*
+                * Address (with allocation)
+                */
+               fprintf(lfp, "  %05u", laddr);
+               if (lmode == ALIST || lmode == BLIST) {
+                       fprintf(lfp, "%17s%5u %s\n", "", line, ib);
+                       outdot();
+                       return;
+               }
+               wp = cb;
+               wpt = cbt;
+               nb = (int) (cp - cb);
+
+               /*
+                * First line of output for this source line with data.
+                */
+               list1(wp, wpt, nb, 1);
+               fprintf(lfp, " %5u %s\n", line, ib);
+
+               /*
+                * Subsequent lines of output if more data.
+                */
+               while ((nb -= 4) > 0) {
+                       wp += 4;
+                       wpt += 4;
+                       slew(lfp, 0);
+                       fprintf(lfp, "%9s", "");
+                       list1(wp, wpt, nb, 0);
+                       putc('\n', lfp);
+               }
+       }
+}
+
+/*)Function    VOID    list1(wp, wpt, nw, f)
+ *
+ *             int     f               fill blank fields (1)
+ *             int     nb              number of data bytes
+ *             int *   wp              pointer to data bytes
+ *             int *   wpt             pointer to data byte mode
+ *
+ *     local variables:
+ *             int     i               loop counter
+ *
+ *     global variables:
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             VOID    list2()         asslist.c
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             Data formatted and output to listing.
+ */
+
+VOID
+list1(wp, wpt, nb, f)
+register char *wp;
+register int *wpt, nb, f;
+{
+       register int i;
+
+       /*
+        * HEX output Option.
+        */
+       if (xflag == 0) {               /* HEX */
+               /*
+                * Bound number of words to HEX maximum per line.
+                */
+               if (nb > 6)
+                       nb = 6;
+
+               /*
+                * Output bytes.
+                */
+               for (i=0; i<nb; ++i) {
+                       list2(*wpt++);
+                       fprintf(lfp, "%02X", (*wp++)&0377);
+               }
+
+               /*
+                * Output blanks if required.
+                */
+               if (f) {
+                       while (i < 6) {
+                               fprintf(lfp, "   ");
+                               ++i;
+                       }
+               }
+       } else
+       /*
+        * OCTAL output Option.
+        */
+       if (xflag == 1) {               /* OCTAL */
+               /*
+                * Bound number of words to OCTAL maximum per line.
+                */
+               if (nb > 4)
+                       nb = 4;
+
+               /*
+                * Output bytes.
+                */
+               for (i=0; i<nb; ++i) {
+                       list2(*wpt++);
+                       fprintf(lfp, "%03o", (*wp++)&0377);
+               }
+
+               /*
+                * Output blanks if required.
+                */
+               if (f) {
+                       while (i < 4) {
+                               fprintf(lfp, "    ");
+                               ++i;
+                       }
+               }
+       } else
+       /*
+        * DECIMAL output Option.
+        */
+       if (xflag == 2) {               /* DECIMAL */
+               /*
+                * Bound number of words to DECIMAL maximum per line.
+                */
+               if (nb > 4)
+                       nb = 4;
+
+               /*
+                * Output bytes.
+                */
+               for (i=0; i<nb; ++i) {
+                       list2(*wpt++);
+                       fprintf(lfp, "%03u", (*wp++)&0377);
+               }
+
+               /*
+                * Output blanks if required.
+                */
+               if (f) {
+                       while (i < 4) {
+                               fprintf(lfp, "    ");
+                               ++i;
+                       }
+               }
+       }
+}
+
+/*)Function    VOID    list2(wpt)
+ *
+ *             int *   wpt             pointer to relocation mode
+ *
+ *     The function list2() outputs the selected
+ *     relocation flag as specified by fflag.
+ *
+ *     local variables:
+ *             int     c               relocation flag character
+ *             int     t               relocation mode
+ *
+ *     global variables:
+ *             int     fflag           -f(f), relocations flagged flag
+ *
+ *     functions called:
+ *             int     putc()          c_library
+ *
+ *     side effects:
+ *             Relocation flag output to listing file.
+ */
+
+VOID
+list2(t)
+register int t;
+{
+       register int c;
+
+       c = ' ';
+
+       /*
+        * Designate a relocatable word by `.
+        */
+       if (fflag == 1) {
+               if (t & R_RELOC) {
+                       c = '`';
+               }
+       } else
+       /*
+        * Designate a relocatable word by its mode:
+        *      page0 or paged          *
+        *      unsigned                u (v)
+        *      operand offset          p (q)
+        *      relocatable symbol      r (s)
+        */
+       if (fflag >= 2) {
+               if (t & R_RELOC) {
+                       if (t & (R_PAG0|R_PAG)) {
+                               c = '*';
+                       } else if (t & R_USGN) {
+                               c = 'u';
+                       } else if (t & R_PCR) {
+                               c = 'p';
+                       } else {
+                               c = 'r';
+                       }
+                       if (t & R_HIGH) c += 1;
+               }
+       }
+
+       /*
+        * Output the selected mode.
+        */
+       putc(c, lfp);
+}
+
+/*)Function    VOID    slew(fp, flag)
+ *
+ *             FILE *  fp              file handle for listing
+ *             int     flag            enable pagination
+ *
+ *     The function slew() increments the page line count.
+ *     If the page overflows and pagination is enabled:
+ *             1)      put out a page skip,
+ *             2)      a title,
+ *             3)      a subtitle,
+ *             4)      and reset the line count.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             char    cpu[]           cpu type string
+ *             int     lop             current line number on page
+ *             int     page            current page number
+ *             char    stb[]           Subtitle string buffer
+ *             char    tb[]            Title string buffer
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             Increments page line counter, on overflow
+ *             a new page header is output to the listing file.
+ */
+
+VOID
+slew(fp,flag)
+FILE *fp;
+int flag;
+{
+       if ((lop++ >= NLPP) && flag) {
+               fprintf(fp, "\fASxxxx Assembler %s  (%s), page %u.\n",
+                       VERSION, cpu, ++page);
+               fprintf(fp, "%s\n", tb);
+               fprintf(fp, "%s\n\n", stb);
+               lop = 5;
+       }
+}
+
+/* Used for qsort call in lstsym */
+static int _cmpSym(const void *p1, const void *p2)
+{
+    struct sym **s1 = (struct sym **)(p1);
+    struct sym **s2 = (struct sym **)(p2);
+    return strcmp((*s1)->s_id,(*s2)->s_id);
+}
+
+/*)Function    VOID    lstsym(fp)
+ *
+ *             FILE *  fp              file handle for output
+ *
+ *     The function lstsym() outputs alphabetically
+ *     sorted symbol and area tables.
+ *
+ *     local variables:
+ *             int     c               temporary
+ *             int     i               loop counter
+ *             int     j               temporary
+ *             int     k               temporary
+ *             char *  ptr             pointer to an id string
+ *             int     nmsym           number of symbols
+ *             int     narea           number of areas
+ *             sym *   sp              pointer to symbol structure
+ *             sym **  p               pointer to an array of
+ *                                     pointers to symbol structures
+ *             area *  ap              pointer to an area structure
+ *
+ *     global variables:
+ *             area *  areap           pointer to an area structure
+ *             char    aretbl[]        string "Area Table"
+ *             sym     dot             defined as sym[0]
+ *             char    stb[]           Subtitle string buffer
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *             char    symtbl[]        string "Symbol Table"
+ *             FILE *  tfp             symbol table output file handle
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             int     putc()          c_library
+ *             VOID    slew()          aslist.c
+ *             int     strcmp()        c_library
+ *             char *  strcpy()        c_library
+ *
+ *     side effects:
+ *             Symbol and area tables output.
+ */
+
+VOID
+lstsym(fp)
+FILE *fp;
+{
+       register int c, i, j, k;
+       register char *ptr;
+       int nmsym, narea;
+       struct sym *sp;
+       struct sym **p;
+       struct area *ap;
+
+       /*
+        * Symbol Table Header
+        */
+       strcpy(stb, &symtbl[0]);
+       lop = NLPP;
+       if (fp == tfp)
+               page = 0;
+       slew(fp, 1);
+
+       /*
+        * Find number of symbols
+        */
+       nmsym = 0;
+       for (i=0; i<NHASH; i++) {
+               sp = symhash[i];
+               while (sp) {
+                       if (sp != &dot)
+                               ++nmsym;
+                       sp = sp->s_sp;
+               }
+       }
+       if (nmsym == 0)
+               goto atable;
+
+       /*
+        * Allocate space for an array of pointers to symbols
+        * and load array.
+        */
+       if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
+               == NULL) {
+               fprintf(fp, "Insufficient space to build Symbol Table.\n");
+               return;
+       }
+       nmsym = 0;
+       for (i=0; i<NHASH; i++) {
+               sp = symhash[i];
+               while (sp) {
+                       if (sp != &dot)
+                               p[nmsym++] = sp;
+                       sp = sp->s_sp;
+               }
+       }
+
+#if 0
+       /* BUBBLE SORT?? WTF??? */
+       /*
+        * Bubble Sort on Symbol Table Array
+        */
+       j = 1;
+       c = nmsym - 1;
+       while (j) {
+               j = 0;
+               for (i=0; i<c; ++i) {
+                       if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
+                               j = 1;
+                               sp = p[i+1];
+                               p[i+1] = p[i];
+                               p[i] = sp;
+                       }
+               }
+       }
+#else
+
+       qsort(p, nmsym, sizeof(struct sym *), _cmpSym);
+#endif 
+
+       /*
+        * Symbol Table Output
+        */
+       for (i=0; i<nmsym;) {
+               sp = p[i];
+               if (sp->s_area) {
+                       j = sp->s_area->a_ref;
+                       if (xflag == 0) {
+                               fprintf(fp, " %2X ", j);
+                       } else
+                       if (xflag == 1) {
+                               fprintf(fp, "%3o ", j);
+                       } else
+                       if (xflag == 2) {
+                               fprintf(fp, "%3u ", j);
+                       }
+               } else {
+                       fprintf(fp, "    ");
+               }
+               ptr = &sp->s_id[0];
+               fprintf(fp, "%-60s", ptr );     /* JLH */
+
+               if (sp->s_flag & S_ASG) {
+                       putc('=', fp);
+               } else {
+                       putc(' ', fp);
+               }
+               if (sp->s_type == S_NEW) {
+                       if (xflag == 0) {
+                               fprintf(fp, "  **** ");
+                       } else
+                       if (xflag == 1) {
+                               fprintf(fp, "****** ");
+                       } else
+                       if (xflag == 2) {
+                               fprintf(fp, " ***** ");
+                       }
+               } else {
+                       j = sp->s_addr;
+                       if (xflag == 0) {
+                               fprintf(fp, "  %04X ", j);
+                       } else
+                       if (xflag == 1) {
+                               fprintf(fp, "%06o ", j);
+                       } else
+                       if (xflag == 2) {
+                               fprintf(fp, " %05u ", j);
+                       }
+               }
+               j = 0;
+               if (sp->s_flag & S_GBL) {
+                       putc('G', fp);
+                       ++j;
+               }
+               if (sp->s_area != NULL) {
+                       putc('R', fp);
+                       ++j;
+               }
+               if (sp->s_type == S_NEW) {
+                       putc('X', fp);
+                       ++j;
+               }
+#if NCPS-8
+               putc('\n', fp);
+               slew(fp, 0);
+               ++i;
+#else
+               if (++i % 3 == 0) {
+                       putc('\n', fp);
+                       slew(fp, pflag);
+               } else
+               if (i < nmsym) {
+                       while (j++ < 4)
+                               putc(' ', fp);
+                       fprintf(fp, "| ");
+               }
+#endif
+       }
+       putc('\n', fp);
+
+       /*
+        * Area Table Header
+        */
+
+atable:
+       strcpy(stb, &aretbl[0]);
+       lop = NLPP;
+       slew(fp, 1);
+
+       /*
+        * Area Table Output
+        */
+       narea = 0;
+       ap = areap;
+       while (ap) {
+               ++narea;
+               ap = ap->a_ap;
+       }
+       for (i=0; i<narea; ++i) {
+               ap = areap;
+               for (j=i+1; j<narea; ++j)
+                       ap = ap->a_ap;
+               j = ap->a_ref;
+               if (xflag == 0) {
+                       fprintf(fp, "  %2X ", j);
+               } else
+               if (xflag == 1) {
+                       fprintf(fp, " %3o ", j);
+               } else
+               if (xflag == 2) {
+                       fprintf(fp, " %3u ", j);
+               }
+               ptr = &ap->a_id[0];
+               while (ptr < &ap->a_id[NCPS]) {
+                       if ((c = *ptr++) != 0) {
+                               putc(c, fp);
+                       } else {
+                               putc(' ', fp);
+                       }
+               }
+               j = ap->a_size;
+               k = ap->a_flag;
+               if (xflag==0) {
+                       fprintf(fp, "   size %4X   flags %X\n", j, k);
+               } else
+               if (xflag==1) {
+                       fprintf(fp, "   size %6o   flags %o\n", j, k);
+               } else
+               if (xflag==2) {
+                       fprintf(fp, "   size %5u   flags %u\n", j, k);
+               }
+       }               
+}
diff --git a/as/hc08/asm.h b/as/hc08/asm.h
new file mode 100644 (file)
index 0000000..c81374a
--- /dev/null
@@ -0,0 +1,679 @@
+/* asm.h */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - add proto for StoreString
+ *          - change s_id from [NCPS] to pointer
+ *          - change m_id from [NCPS] to pointer
+ *          - change NCPS to 80
+ *           - case sensitive
+ *           - add R_J11 for 8051 assembler
+ *           - add outr11 prototype for 8051 assembler
+ *           - always define "ccase"
+ *  2-Nov-97 JLH:
+ *           - add jflag for debug control
+ *           - prototypes for DefineNoICE_Line
+ * 30-Jan-98 JLH:
+ *           - add memory space flags to a_flag for 8051
+ *
+ *  3-Feb-00 KV:
+ *          - add DS80C390 flat mode support.
+ */
+
+#define        VERSION "V01.70 + NoICE + SDCC mods + Flat24 Feb-1999"
+
+#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#include <unistd.h>
+#endif
+
+/*
+ * Case Sensitivity Flag
+ */
+#define        CASE_SENSITIVE  1
+
+/*)Module      asm.h
+ *
+ *     The module asm.h contains the definitions for constants,
+ *     structures, global variables, and ASxxxx functions
+ *     contained in the ASxxxx.c files.  The two functions
+ *     and three global variables from the machine dependent
+ *     files are also defined.
+ */
+
+/*
+ *      compiler/operating system specific definitions
+ */
+
+/* DECUS C void definition */
+/* File/extension seperator */
+
+#ifdef decus
+#define        VOID    char
+#define        FSEPX   '.'
+#endif
+
+/* PDOS C void definition */
+/* File/extension seperator */
+
+#ifdef PDOS
+#define        VOID    char
+#define        FSEPX   ':'
+#endif
+
+/* Default void definition */
+/* File/extension seperator */
+
+#ifndef        VOID
+#define        VOID    void
+#define        FSEPX   '.'
+#define        OTHERSYSTEM
+#endif
+
+/*
+ * PATH_MAX
+ */
+#include <limits.h>
+#ifndef PATH_MAX               /* POSIX, but not required   */
+#if defined(_MSC_VER) || defined(__BORLANDC__)  /* Microsoft C or Borland C*/
+#include <stdlib.h>
+#define PATH_MAX       _MAX_PATH
+#else
+#define PATH_MAX               /* define a reasonable value */
+#endif
+#endif
+
+/*
+ * Assembler definitions.
+ */
+#define        LFTERM  '('             /* Left expression delimeter */
+#define        RTTERM  ')'             /* Right expression delimeter */
+
+#define NCPS   80              /* Chars. per symbol (JLH: change from 8) */
+#define        HUGE    1000            /* A huge number */
+#define NERR   3               /* Errors per line */
+#define        NINPUT  1024            /* Input buffer size (icodes need space) */
+#define NCODE  128             /* Listing code buffer size */
+#define NTITL  64              /* Title buffer size */
+#define        NSBTL   64              /* SubTitle buffer size */
+#define        NHASH   64              /* Buckets in hash table */
+#define        HMASK   077             /* Hash mask */
+#define        NLPP    60              /* Lines per page */
+#define        MAXFIL  6               /* Maximum command line input files */
+#define        MAXINC  6               /* Maximum nesting of include files */
+#define        MAXIF   10              /* Maximum nesting of if/else/endif */
+
+#define NLIST  0               /* No listing */
+#define SLIST  1               /* Source only */
+#define ALIST  2               /* Address only */
+#define        BLIST   3               /* Address only with allocation */
+#define CLIST  4               /* Code */
+#define        ELIST   5               /* Equate only */
+
+#define        dot     sym[0]          /* Dot, current loc */
+#define        dca     area[0]         /* Dca, default code area */
+
+
+/* NB: for Flat24 extentions to work, Addr_T must be at least 24
+ * bits. This is checked at runtime when the .flat24 directive 
+ * is processed.
+ */
+typedef        unsigned int Addr_T;
+
+/*
+ *     The area structure contains the parameter values for a
+ *     specific program or data section.  The area structure
+ *     is a linked list of areas.  The initial default area
+ *     is "_CODE" defined in asdata.c, the next area structure
+ *     will be linked to this structure through the structure
+ *     element 'struct area *a_ap'.  The structure contains the
+ *     area name, area reference number ("_CODE" is 0) determined
+ *     by the order of .area directives, area size determined
+ *     from the total code and/or data in an area, area fuzz is
+ *     a variable used to track pass to pass changes in the
+ *     area size caused by variable length instruction formats,
+ *     and area flags which specify the area's relocation type.
+ */
+struct area
+{
+       struct  area *a_ap;     /* Area link */
+       char    a_id[NCPS];     /* Area Name */
+       int     a_ref;          /* Ref. number */
+       Addr_T  a_size;         /* Area size */
+       Addr_T  a_fuzz;         /* Area fuzz */
+       int     a_flag;         /* Area flags */
+};
+
+/*
+ *     The "A_" area constants define values used in
+ *     generating the assembler area output data.
+ *
+ * Area flags
+ *
+ *        7     6      5    4     3     2     1     0
+ *     +-----+-----+-----+-----+-----+-----+-----+-----+
+ *     | BIT |XDATA|DATA | PAG | ABS | OVR |     |     |
+ *     +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define        A_CON   0000            /* Concatenating */
+#define        A_OVR   0004            /* Overlaying */
+#define        A_REL   0000            /* Relocatable */
+#define        A_ABS   0010            /* absolute */
+#define        A_NOPAG 0000            /* Non-Paged */
+#define        A_PAG   0020            /* Paged */
+
+/* Additional flags for 8051 address spaces */
+#define A_DATA  0000           /* data space (default)*/
+#define A_CODE  0040           /* code space */
+#define A_XDATA 0100           /* external data space */
+#define A_BIT   0200           /* bit addressable space */
+
+/*
+ *     The "R_" relocation constants define values used in
+ *     generating the assembler relocation output data for
+ *     areas, symbols, and code.
+ *
+ * Relocation flags
+ *
+ *        7     6     5     4     3     2     1     0
+ *     +-----+-----+-----+-----+-----+-----+-----+-----+
+ *     | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
+ *     +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define        R_WORD  0x00            /* 16 bit */
+#define        R_BYTE  0x01            /*  8 bit */
+
+#define        R_AREA  0x00            /* Base type */
+#define        R_SYM   0x02
+
+#define        R_NORM  0x00            /* PC adjust */
+#define        R_PCR   0x04
+
+#define        R_BYT1  0x00            /* Byte count for R_BYTE = 1 */
+#define        R_BYT2  0x08            /* Byte count for R_BYTE = 2 */
+
+#define        R_SGND  0x00            /* Signed Byte */
+#define        R_USGN  0x10            /* Unsigned Byte */
+
+#define        R_NOPAG 0x00            /* Page Mode */
+#define        R_PAG0  0x20            /* Page '0' */
+#define        R_PAG   0x40            /* Page 'nnn' */
+
+#define        R_LSB   0x00            /* low byte */
+#define        R_MSB   0x80            /* high byte */
+
+#define R_BYT3 0x100           /* if R_BYTE is set, this is a 
+                                * 3 byte address, of which
+                                * the linker must select one byte.
+                                */
+#define R_HIB  0x200           /* If R_BYTE & R_BYT3 are set, linker
+                                * will select byte 3 of the relocated
+                                * 24 bit address.
+                                */
+
+#define R_J11   (R_WORD|R_BYT2)        /* JLH: 11 bit JMP and CALL (8051) */
+#define R_J19   (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */
+#define R_C24   (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */
+#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB)
+
+#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19)
+#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11)
+#define IS_C24(x) (((x) & R_J19_MASK) == R_C24)
+
+#define R_ESCAPE_MASK  0xf0    /* Used to escape relocation modes
+                                * greater than 0xff in the .rel
+                                * file.
+                                */
+
+/*
+ * Listing Control Flags
+ */
+
+#define        R_HIGH  0040000         /* High Byte */
+#define        R_RELOC 0100000         /* Relocation */
+
+#define        R_DEF   00              /* Global def. */
+#define        R_REF   01              /* Global ref. */
+#define        R_REL   00              /* Relocatable */
+#define        R_ABS   02              /* Absolute */
+#define        R_GBL   00              /* Global */
+#define        R_LCL   04              /* Local */
+
+/*
+ *     The mne structure is a linked list of the assembler
+ *     mnemonics and directives.  The list of mnemonics and
+ *     directives contained in the device dependent file
+ *     xxxpst.c are hashed and linked into NHASH lists in
+ *     module assym.c by syminit().  The structure contains
+ *     the mnemonic/directive name, a subtype which directs
+ *     the evaluation of this mnemonic/directive, a flag which
+ *     is used to detect the end of the mnemonic/directive
+ *     list in xxxpst.c, and a value which is normally
+ *     associated with the assembler mnemonic base instruction
+ *     value.
+ */
+struct mne
+{
+       struct  mne *m_mp;      /* Hash link */
+       char    *m_id;          /* Mnemonic JLH: change from [NCPS] */
+       char    m_type;         /* Mnemonic subtype */
+       char    m_flag;         /* Mnemonic flags */
+       Addr_T  m_valu;         /* Value */
+};
+
+/*
+ *     The sym structure is a linked list of symbols defined
+ *     in the assembler source files.  The first symbol is "."
+ *     defined in asdata.c.  The entry 'struct tsym *s_tsym'
+ *     links any temporary symbols following this symbol and
+ *     preceeding the next normal symbol.  The structure also
+ *     contains the symbol's name, type (USER or NEW), flag
+ *     (global, assigned, and multiply defined), a pointer
+ *     to the area structure defining where the symbol is
+ *     located, a reference number assigned by outgsd() in
+ *     asout.c, and the symbols address relative to the base
+ *     address of the area where the symbol is located.
+ */
+struct sym
+{
+       struct  sym  *s_sp;     /* Hash link */
+       struct  tsym *s_tsym;   /* Temporary symbol link */
+       char    *s_id;          /* Symbol: JLH change from [NCPS] */
+       char    s_type;         /* Symbol subtype */
+       char    s_flag;         /* Symbol flags */
+       struct  area *s_area;   /* Area line, 0 if absolute */
+       int     s_ref;          /* Ref. number */
+       Addr_T  s_addr;         /* Address */
+};
+
+#define        S_GBL           01      /* Global */
+#define        S_ASG           02      /* Assigned */
+#define        S_MDF           04      /* Mult. def */
+#define        S_END           010     /* End mark for pst. */
+
+#define        S_NEW           0       /* New name */
+#define        S_USER          1       /* User name */
+                               /* unused slot */
+                               /* unused slot */
+                               /* unused slot */
+
+#define        S_BYTE          5       /* .byte */
+#define        S_WORD          6       /* .word */
+#define        S_ASCII         7       /* .ascii */
+#define        S_ASCIZ         8       /* .asciz */
+#define        S_BLK           9       /* .blkb or .blkw */
+#define        S_INCL          10      /* .include */
+#define        S_DAREA         11      /* .area */
+#define        S_ATYP          12      /* .area type */
+#define        S_AREA          13      /* .area name */
+#define        S_GLOBL         14      /* .globl */
+#define        S_PAGE          15      /* .page */
+#define        S_TITLE         16      /* .title */
+#define        S_SBTL          17      /* .sbttl */
+#define        S_IF            18      /* .if */
+#define        S_ELSE          19      /* .else */
+#define        S_ENDIF         20      /* .endif */
+#define        S_EVEN          21      /* .even */
+#define        S_ODD           22      /* .odd */
+#define        S_RADIX         23      /* .radix */
+#define        S_ORG           24      /* .org */
+#define        S_MODUL         25      /* .module */
+#define        S_ASCIS         26      /* .ascis */
+#define        S_FLAT24        27  /* .flat24 */
+#define        S_OPTSDCC       28  /* .optsdcc */
+
+
+/*
+ *     The tsym structure is a linked list of temporary
+ *     symbols defined in the assembler source files following
+ *     a normal symbol.  The structure contains the temporary
+ *     symbols number, a flag (multiply defined), a pointer to the
+ *     area structure defining where the temporary structure
+ *     is located, and the temporary symbol's address relative
+ *     to the base address of the area where the symbol
+ *     is located.
+ */
+struct tsym
+{
+       struct  tsym *t_lnk;    /* Link to next */
+/* sandeep changed to 'int' from 'char' */
+/* this will increase the number temp symbols
+   that can be defined from 255 to INT_MAX */
+       int t_num;              /* 0-INT_MAX$ */
+       int t_flg;              /* flags */
+
+       struct  area *t_area;   /* Area */
+       Addr_T  t_addr;         /* Address */
+};
+
+/*
+ *     External Definitions for all Global Variables
+ */
+
+extern int     aserr;          /*      ASxxxx error counter
+                                */
+extern jmp_buf jump_env;       /*      compiler dependent structure
+                                *      used by setjmp() and longjmp()
+                                */
+extern int     inpfil;         /*      count of assembler
+                                *      input files specified
+                                */
+extern int     incfil;         /*      current file handle index
+                                *      for include files
+                                */
+extern int     cfile;          /*      current file handle index
+                                *      of input assembly files
+                                */
+extern int     flevel;         /*      IF-ELSE-ENDIF flag will be non
+                                *      zero for false conditional case
+                                */
+extern int     tlevel;         /*      current conditional level
+                                */
+extern int     ifcnd[MAXIF+1]; /*      array of IF statement condition
+                                *      values (0 = FALSE) indexed by tlevel
+                                */
+extern int     iflvl[MAXIF+1]; /*      array of IF-ELSE-ENDIF flevel
+                                *      values indexed by tlevel
+                                */
+extern char
+       afn[PATH_MAX];          /*      afile() temporary filespec
+                                */
+extern char
+       srcfn[MAXFIL][PATH_MAX];        /*      array of source file names
+                                */
+extern int
+       srcline[MAXFIL];        /*      current source file line
+                                */
+extern char
+       incfn[MAXINC][PATH_MAX];        /*      array of include file names
+                                */
+extern int
+       incline[MAXINC];        /*      current include file line
+                                */
+extern int     radix;          /*      current number conversion radix:
+                                *      2 (binary), 8 (octal), 10 (decimal),
+                                *      16 (hexadecimal)
+                                */
+extern int     line;           /*      current assembler source
+                                *      line number
+                                */
+extern int     page;           /*      current page number
+                                */
+extern int     lop;            /*      current line number on page
+                                */
+extern int     pass;           /*      assembler pass number
+                                */
+extern int     lflag;          /*      -l, generate listing flag
+                                */
+extern int     cflag;          /*      -c, generate sdcdb debug information
+                                */
+extern int     gflag;          /*      -g, make undefined symbols global flag
+                                */
+extern int     aflag;          /*      -a, make all symbols global flag
+                                */
+extern  int    jflag;          /*      -j, generate debug information flag
+                                */
+extern int     oflag;          /*      -o, generate relocatable output flag
+                                */
+extern int     sflag;          /*      -s, generate symbol table flag
+                                */
+extern int     pflag;          /*      -p, enable listing pagination
+                                */
+extern int     xflag;          /*      -x, listing radix flag
+                                */
+extern int     fflag;          /*      -f(f), relocations flagged flag
+                                */
+extern Addr_T  laddr;          /*      address of current assembler line
+                                *      or value of .if argument
+                                */
+extern Addr_T  fuzz;           /*      tracks pass to pass changes in the
+                                *      address of symbols caused by
+                                *      variable length instruction formats
+                                */
+extern int     lmode;          /*      listing mode
+                                */
+extern struct  area    area[]; /*      array of 1 area
+                                */
+extern struct  area *areap;    /*      pointer to an area structure
+                                */
+extern struct  sym     sym[];  /*      array of 1 symbol
+                                */
+extern struct  sym *symp;      /*      pointer to a symbol structure
+                                */
+extern struct  sym *symhash[NHASH]; /* array of pointers to NHASH
+                                     * linked symbol lists
+                                     */
+extern struct  mne *mnehash[NHASH]; /* array of pointers to NHASH
+                                     * linked mnemonic/directive lists
+                                     */
+extern char    *ep;            /*      pointer into error list
+                                *      array eb[NERR]
+                                */
+extern char    eb[NERR];       /*      array of generated error codes
+                                */
+extern char    *ip;            /*      pointer into the assembler-source
+                                *      text line in ib[]
+                                */
+extern char    ib[NINPUT];     /*      assembler-source text line
+                                */
+extern char    *cp;            /*      pointer to assembler output
+                                *      array cb[]
+                                */
+extern char    cb[NCODE];      /*      array of assembler output values
+                                */
+extern int     *cpt;           /*      pointer to assembler relocation type
+                                *      output array cbt[]
+                                */
+extern int     cbt[NCODE];     /*      array of assembler relocation types
+                                *      describing the data in cb[]
+                                */
+extern char    tb[NTITL];      /*      Title string buffer
+                                */
+extern char    stb[NSBTL];     /*      Subtitle string buffer
+                                */
+extern  char   optsdcc[NINPUT];        /*      sdcc compile options 
+                        */
+extern         int     flat24Mode;     /*      non-zero if we are using DS390 24 bit 
+                                *      flat mode (via .flat24 directive). 
+                                */
+extern char    symtbl[];       /*      string "Symbol Table"
+                                */
+extern char    aretbl[];       /*      string "Area Table"
+                                */
+extern char    module[NCPS];   /*      module name string
+                                */
+extern FILE    *lfp;           /*      list output file handle
+                                */
+extern FILE    *ofp;           /*      relocation output file handle
+                                */
+extern FILE    *tfp;           /*      symbol table output file handle
+                                */
+extern FILE    *sfp[MAXFIL];   /*      array of assembler-source file handles
+                                */
+extern FILE    *ifp[MAXINC];   /*      array of include-file file handles
+                                */
+extern unsigned char   ctype[128];     /*      array of character types, one per
+                                *      ASCII character
+                                */
+
+extern char    ccase[128];     /* an array of characters which 
+                                * perform the case translation function
+                                */
+/*
+ * Definitions for Character Types
+ */
+#define        SPACE   0000
+#define ETC    0000
+#define        LETTER  0001
+#define        DIGIT   0002
+#define        BINOP   0004
+#define        RAD2    0010
+#define        RAD8    0020
+#define        RAD10   0040
+#define        RAD16   0100
+#define        ILL     0200
+
+#define        DGT2    DIGIT|RAD16|RAD10|RAD8|RAD2
+#define        DGT8    DIGIT|RAD16|RAD10|RAD8
+#define        DGT10   DIGIT|RAD16|RAD10
+#define        LTR16   LETTER|RAD16
+
+/*
+ *     The exp structure is used to return the evaluation
+ *     of an expression.  The structure supports three valid
+ *     cases:
+ *     (1)     The expression evaluates to a constant,
+ *             mode = S_USER, flag = 0, addr contains the
+ *             constant, and base = NULL.
+ *     (2)     The expression evaluates to a defined symbol
+ *             plus or minus a constant, mode = S_USER,
+ *             flag = 0, addr contains the constant, and
+ *             base = pointer to area symbol.
+ *     (3)     The expression evaluates to a external
+ *             global symbol plus or minus a constant,
+ *             mode = S_NEW, flag = 1, addr contains the
+ *             constant, and base = pointer to symbol.
+ */
+struct expr
+{
+       char    e_mode;         /* Address mode */
+       char    e_flag;         /* Symbol flag */
+       Addr_T  e_addr;         /* Address */
+       union   {
+               struct area *e_ap;
+               struct sym  *e_sp;
+       } e_base;               /* Rel. base */
+       int     e_rlcf;         /* Rel. flags */
+};
+
+/* C Library functions */
+/* for reference only
+extern VOID            exit();
+extern int             fclose();
+extern char *          fgets();
+extern FILE *          fopen();
+extern int             fprintf();
+extern VOID            longjmp();
+extern VOID *          malloc();
+extern int             printf();
+extern char            putc();
+extern int             rewind();
+extern int             setjmp();
+extern int             strcmp();
+extern char *          strcpy();
+extern int             strlen();
+extern char *          strncpy();
+*/
+
+/* Machine independent functions */
+
+/* asmain.c */
+extern FILE *          afile();
+extern VOID            asexit();
+extern VOID            asmbl();
+extern int             main();
+extern VOID            newdot();
+extern VOID            phase();
+extern VOID            usage();
+
+/* aslex.c */
+extern char            endline();
+extern char            get();
+extern VOID            getid();
+extern int             getline();
+extern int             getmap();
+extern char            getnb();
+extern VOID            getst();
+extern int             more();
+extern VOID            unget();
+extern VOID            chop_crlf();
+
+/* assym.c */
+extern struct  area *  alookup();
+extern struct  mne *   mlookup();
+extern int             hash();
+extern struct  sym *   lookup();
+extern VOID *          new();
+extern int             symeq();
+extern VOID            syminit();
+extern VOID            symglob();
+extern VOID            allglob();
+
+/* assubr.c */
+extern VOID            aerr();
+extern VOID            diag();
+extern VOID            err();
+extern         VOID            warnBanner(void);
+extern char *          geterr();
+extern VOID            qerr();
+extern VOID            rerr();
+
+/* asexpr.c */
+extern VOID            abscheck();
+extern Addr_T          absexpr();
+extern VOID            clrexpr();
+extern int             digit();
+extern int             is_abs();
+extern VOID            expr();
+extern int             oprio();
+extern VOID            term();
+
+/* aslist.c */
+extern VOID            list();
+extern VOID            list1();
+extern VOID            list2();
+extern VOID            lstsym();
+extern VOID            slew();
+
+/* asout.c */
+extern int             hibyte();
+extern int             lobyte();
+extern         int             byte3(int);
+extern VOID            out();
+extern VOID            outab();
+extern VOID            outarea();
+extern VOID            outaw();
+extern VOID            outall();
+extern VOID            outdot();
+extern VOID            outbuf();
+extern VOID            outchk();
+extern VOID            outgsd();
+extern VOID            outrb();
+extern VOID            outrw(struct expr *, int);
+extern VOID            outr24(struct expr *, int);
+extern VOID            outsym();
+extern VOID            out_lb();
+extern VOID            out_lw();
+extern VOID            out_l24(int, int);
+extern VOID            out_rw();
+extern VOID            out_tw();
+extern VOID            out_t24(int);
+extern VOID            outr11();       /* JLH */
+extern VOID            outr19(struct expr *, int, int);
+
+/* asstore.c */
+extern char *StoreString( char *str );
+
+/* asnoice.c */
+extern void DefineNoICE_Line();
+extern void DefineCDB_Line();
+
+/* Machine dependent variables */
+
+extern char *          cpu;
+extern char *          dsft;
+extern int             hilo;
+extern struct  mne     mne[];
+
+/* Machine dependent functions */
+
+extern VOID            minit();
+extern VOID machine(struct mne *);
diff --git a/as/hc08/asmain.c b/as/hc08/asmain.c
new file mode 100644 (file)
index 0000000..cb987f5
--- /dev/null
@@ -0,0 +1,1232 @@
+/* asmain.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 29-Oct-97 JLH pass ";!" comments to output file
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+
+#include "asm.h"
+#include "strcmpi.h"
+
+/*)Module      asmain.c
+ *
+ *     The module asmain.c includes the command argument parser,
+ *     the three pass sequencer, and the machine independent
+ *     assembler parsing code.
+ *
+ *     asmain.c contains the following functions:
+ *             VOID    main(argc, argv)
+ *             VOID    asexit()
+ *             VOID    asmbl()
+ *             FILE *  afile(fn, ft, wf)
+ *             VOID    newdot(nap)
+ *             VOID    phase(ap, a)
+ *             VOID    usage()
+ *
+ *     asmain.c contains the array char *usetxt[] which
+ *     references the usage text strings printed by usage().
+ */
+
+/*)Function    VOID    main(argc, argv)
+ *
+ *             int     argc            argument count
+ *             char *  argv            array of pointers to argument strings
+ *
+ *     The function main() is the entry point to the assembler.
+ *     The purpose of main() is to (1) parse the command line
+ *     arguments for options and source file specifications and
+ *     (2) to process the source files through the 3 pass assembler.
+ *     Before each assembler pass various variables are initialized
+ *     and source files are rewound to their beginning.  During each
+ *     assembler pass each assembler-source text line is processed.
+ *     After each assembler pass the assembler information is flushed
+ *     to any opened output files and the if-else-endif processing
+ *     is checked for proper termination.
+ *
+ *     The function main() is also responsible for opening all
+ *     output files (REL, LST, and SYM), sequencing the global (-g)
+ *     and all-global (-a) variable definitions, and dumping the
+ *     REL file header information.
+ *
+ *     local variables:
+ *             char *  p               pointer to argument string
+ *             int     c               character from argument string
+ *             int     i               argument loop counter
+ *             area *  ap              pointer to area structure
+ *
+ *     global variables:
+ *             int     aflag           -a, make all symbols global flag
+ *             char    afn[]           afile() constructed filespec
+ *             area *  areap           pointer to an area structure
+ *             int     cb[]            array of assembler output values
+ *             int     cbt[]           array of assembler relocation types
+ *                                     describing the data in cb[]
+ *             int     cfile           current file handle index
+ *                                     of input assembly files
+ *             int *   cp              pointer to assembler output array cb[]
+ *             int *   cpt             pointer to assembler relocation type
+ *                                     output array cbt[]
+ *             char    eb[]            array of generated error codes
+ *             char *  ep              pointer into error list array eb[]
+ *             int     fflag           -f(f), relocations flagged flag
+ *             int     flevel          IF-ELSE-ENDIF flag will be non
+ *                                     zero for false conditional case
+ *             Addr_T  fuzz            tracks pass to pass changes in the
+ *                                     address of symbols caused by
+ *                                     variable length instruction formats
+ *             int     gflag           -g, make undefined symbols global flag
+ *             char    ib[]            assembler-source text line
+ *             int     inpfil          count of assembler
+ *                                     input files specified
+ *             int     ifcnd[]         array of IF statement condition
+ *                                     values (0 = FALSE) indexed by tlevel
+ *             int     iflvl[]         array of IF-ELSE-ENDIF flevel
+ *                                     values indexed by tlevel
+ *             int     incfil          current file handle index
+ *                                     for include files
+ *             char *  ip              pointer into the assembler-source
+ *                                     text line in ib[]
+ *             jmp_buf jump_env        compiler dependent structure
+ *                                     used by setjmp() and longjmp()
+ *             int     lflag           -l, generate listing flag
+ *             int     line            current assembler source
+ *                                     line number
+ *             int     lop             current line number on page
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     jflag           -j, generate debug info flag
+ *             int     page            current page number
+ *             int     pflag           enable listing pagination
+ *             int     pass            assembler pass number
+ *             int     radix           current number conversion radix:
+ *                                     2 (binary), 8 (octal), 10 (decimal),
+ *                                     16 (hexadecimal)
+ *             int     sflag           -s, generate symbol table flag
+ *             char    srcfn[][]       array of source file names
+ *             int     srcline[]       current source file line
+ *             char    stb[]           Subtitle string buffer
+ *             sym *   symp            pointer to a symbol structure
+ *             int     tlevel          current conditional level
+ *             int     xflag           -x, listing radix flag
+ *             FILE *  lfp             list output file handle
+ *             FILE *  ofp             relocation output file handle
+ *             FILE *  tfp             symbol table output file handle
+ *             FILE *  sfp[]           array of assembler-source file handles
+ *
+ *     called functions:
+ *             FILE *  afile()         asmain.c
+ *             VOID    allglob()       assym.c
+ *             VOID    asexit()        asmain.c
+ *             VOID    diag()          assubr.c
+ *             VOID    err()           assubr.c
+ *             int     fprintf()       c-library
+ *             int     getline()       aslex.c
+ *             VOID    list()          aslist.c
+ *             VOID    lstsym()        aslist.c
+ *             VOID    minit()         ___mch.c
+ *             VOID    newdot()        asmain.c
+ *             VOID    outchk()        asout.c
+ *             VOID    outgsd()        asout.c
+ *             int     rewind()        c-library
+ *             int     setjmp()        c-library
+ *             VOID    symglob()       assym.c
+ *             VOID    syminit()       assym.c
+ *             VOID    usage()         asmain.c
+ *
+ *     side effects:
+ *             Completion of main() completes the assembly process.
+ *             REL, LST, and/or SYM files may be generated.
+ */
+
+int fatalErrors=0;
+char relFile[128];
+
+int
+main(argc, argv)
+char *argv[];
+{
+       register char *p;
+       register int c, i;
+       struct area *ap;
+
+       /*fprintf(stdout, "\n");*/
+       inpfil = -1;
+       pflag = 1;
+       for (i=1; i<argc; ++i) {
+               p = argv[i];
+               if (*p == '-') {
+                       if (inpfil >= 0)
+                               usage();
+                       ++p;
+                       while ((c = *p++) != 0)
+                               switch(c) {
+
+                               case 'a':
+                               case 'A':
+                                       ++aflag;
+                                       break;
+
+                               case 'c':
+                               case 'C':
+                                   ++cflag;
+                                   break;
+
+                               case 'g':
+                               case 'G':
+                                       ++gflag;
+                                       break;
+
+                               case 'j':               /* JLH: debug info */
+                               case 'J':
+                                       ++jflag;
+                                       ++oflag;        /* force object */
+                                       break;
+
+                               case 'l':
+                               case 'L':
+                                       ++lflag;
+                                       break;
+
+                               case 'o':
+                               case 'O':
+                                       ++oflag;
+                                       break;
+
+                               case 's':
+                               case 'S':
+                                       ++sflag;
+                                       break;
+
+                               case 'p':
+                               case 'P':
+                                       pflag = 0;
+                                       break;
+
+                               case 'x':
+                               case 'X':
+                                       xflag = 0;
+                                       break;
+
+                               case 'q':
+                               case 'Q':
+                                       xflag = 1;
+                                       break;
+
+                               case 'd':
+                               case 'D':
+                                       xflag = 2;
+                                       break;
+
+                               case 'f':
+                               case 'F':
+                                       ++fflag;
+                                       break;
+
+                               default:
+                                       usage();
+                               }
+               } else {
+                       if (++inpfil == MAXFIL) {
+                               fprintf(stderr, "too many input files\n");
+                               asexit(1);
+                       }
+                       sfp[inpfil] = afile(p, "", 0);
+                       strcpy(srcfn[inpfil],afn);
+                       if (inpfil == 0) {
+                               if (lflag)
+                                       lfp = afile(p, "lst", 1);
+                               if (oflag) {
+                                 ofp = afile(p, "rel", 1);
+                                 // save the file name if we have to delete it on error
+                                 strcpy(relFile,afn);
+                               }
+                               if (sflag)
+                                       tfp = afile(p, "sym", 1);
+                       }
+               }
+       }
+       if (inpfil < 0)
+               usage();
+       syminit();
+       for (pass=0; pass<3; ++pass) {
+               if (gflag && pass == 1)
+                       symglob();
+               if (aflag && pass == 1)
+                       allglob();
+               if (oflag && pass == 2)
+                       outgsd();
+               flevel = 0;
+               tlevel = 0;
+               ifcnd[0] = 0;
+               iflvl[0] = 0;
+               radix = 10;
+               srcline[0] = 0;
+               page = 0;
+               stb[0] = 0;
+               lop  = NLPP;
+               cfile = 0;
+               incfil = -1;
+               for (i = 0; i <= inpfil; i++)
+                       rewind(sfp[i]);
+               ap = areap;
+               while (ap) {
+                       ap->a_fuzz = 0;
+                       ap->a_size = 0;
+                       ap = ap->a_ap;
+               }
+               fuzz = 0;
+               dot.s_addr = 0;
+               dot.s_area = &dca;
+               symp = &dot;
+               minit();
+               while (getline()) {
+                       cp = cb;
+                       cpt = cbt;
+                       ep = eb;
+                       ip = ib;
+
+                        /* JLH: if line begins with ";!", then
+                         * pass this comment on to the output file
+                         */
+                        if (oflag && (pass == 1) &&
+                            (ip[0] == ';') && (ip[1] == '!'))
+                        {
+                               fprintf(ofp, "%s\n", ip );
+                        }
+                        
+                       if (setjmp(jump_env) == 0)
+                               asmbl();
+
+                       if (pass == 2) {
+                               diag();
+                               list();
+                       }
+               }
+               newdot(dot.s_area); /* Flush area info */
+               if (flevel || tlevel)
+                       err('i');
+       }
+       if (oflag)
+               outchk(HUGE, HUGE);  /* Flush */
+       if (sflag) {
+               lstsym(tfp);
+       } else
+       if (lflag) {
+               lstsym(lfp);
+       }
+       //printf ("aserr: %d\n", aserr);
+       //printf ("fatalErrors: %d\n", fatalErrors);
+       asexit(fatalErrors);
+       return 0; // hush the compiler
+}
+
+/*)Function    VOID    asexit(i)
+ *
+ *                     int     i       exit code
+ *
+ *     The function asexit() explicitly closes all open
+ *     files and then terminates the program.
+ *
+ *     local variables:
+ *             int     j               loop counter
+ *
+ *     global variables:
+ *             FILE *  ifp[]           array of include-file file handles
+ *             FILE *  lfp             list output file handle
+ *             FILE *  ofp             relocation output file handle
+ *             FILE *  tfp             symbol table output file handle
+ *             FILE *  sfp[]           array of assembler-source file handles
+ *
+ *     functions called:
+ *             int     fclose()        c-library
+ *             VOID    exit()          c-library
+ *
+ *     side effects:
+ *             All files closed. Program terminates.
+ */
+
+VOID
+asexit(i)
+int i;
+{
+       int j;
+
+       if (lfp != NULL) fclose(lfp);
+       if (ofp != NULL) fclose(ofp);
+       if (tfp != NULL) fclose(tfp);
+
+       for (j=0; j<MAXFIL && sfp[j] != NULL; j++) {
+               fclose(sfp[j]);
+       }
+
+       /*for (j=0; j<MAXINC && ifp[j] != NULL; j++) {
+               fclose(ifp[j]);
+               }*/
+       if (i) {
+         // remove output file
+         printf ("removing %s\n", relFile);
+         unlink(relFile);
+       }
+       exit(i);
+}
+
+/*)Function    VOID    asmbl()
+ *
+ *     The function asmbl() scans the assembler-source text for
+ *     (1) labels, global labels, equates, global equates, and local
+ *     symbols, (2) .if, .else, .endif, and .page directives,
+ *     (3) machine independent assembler directives, and (4) machine
+ *     dependent mnemonics.
+ *
+ *     local variables:
+ *             mne *   mp              pointer to a mne structure
+ *             sym *   sp              pointer to a sym structure
+ *             tsym *  tp              pointer to a tsym structure
+ *             int     c               character from assembler-source
+ *                                     text line
+ *             area *  ap              pointer to an area structure
+ *             expr    e1              expression structure
+ *             char    id[]            id string
+ *             char    opt[]           options string
+ *             char    fn[]            filename string
+ *             char *  p               pointer into a string
+ *             int     d               temporary value
+ *             int     n               temporary value
+ *             int     uaf             user area options flag
+ *             int     uf              area options
+ *
+ *     global variables:
+ *             area *  areap           pointer to an area structure
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *             int     flevel          IF-ELSE-ENDIF flag will be non
+ *                                     zero for false conditional case
+ *             Addr_T  fuzz            tracks pass to pass changes in the
+ *                                     address of symbols caused by
+ *                                     variable length instruction formats
+ *             int     ifcnd[]         array of IF statement condition
+ *                                     values (0 = FALSE) indexed by tlevel
+ *             int     iflvl[]         array of IF-ELSE-ENDIF flevel
+ *                                     values indexed by tlevel
+ *             FILE *  ifp[]           array of include-file file handles
+ *             char    incfn[][]       array of include file names
+ *             int     incline[]       current include file line
+ *             int     incfil          current file handle index
+ *                                     for include files
+ *             Addr_T  laddr           address of current assembler line
+ *                                     or value of .if argument
+ *             int     lmode           listing mode
+ *             int     lop             current line number on page
+ *             char    module[]        module name string
+ *             int     pass            assembler pass number
+ *             int     radix           current number conversion radix:
+ *                                     2 (binary), 8 (octal), 10 (decimal),
+ *                                     16 (hexadecimal)
+ *             char    stb[]           Subtitle string buffer
+ *             sym *   symp            pointer to a symbol structure
+ *             char    tb[]            Title string buffer
+ *             int     tlevel          current conditional level
+ *
+ *     functions called:
+ *             Addr_T  absexpr()       asexpr.c
+ *             area *  alookup()       assym.c
+ *             VOID    clrexpr()       asexpr.c
+ *             int     digit()         asexpr.c
+ *             char    endline()       aslex.c
+ *             VOID    err()           assubr.c
+ *             VOID    expr()          asexpr.c
+ *             FILE *  fopen()         c-library
+ *             char    get()           aslex.c
+ *             VOID    getid()         aslex.c
+ *             int     getmap()        aslex.c
+ *             char    getnb()         aslex.c
+ *             VOID    getst()         aslex.c
+ *             sym *   lookup()        assym.c
+ *             VOID    machine()       ___mch.c
+ *             mne *   mlookup()       assym.c
+ *             int     more()          aslex.c
+ *             VOID *  new()           assym.c
+ *             VOID    newdot()        asmain.c
+ *             VOID    outall()        asout.c
+ *             VOID    outab()         asout.c
+ *             VOID    outchk()        asout.c
+ *             VOID    outrb()         asout.c
+ *             VOID    outrw()         asout.c
+ *             VOID    phase()         asmain.c
+ *             VOID    qerr()          assubr.c
+ *             char *  strcpy()        c-library
+ *             char *  strncpy()       c-library
+ *             VOID    unget()         aslex.c
+ */
+
+VOID
+asmbl()
+{
+       register struct mne *mp;
+       register struct sym *sp;
+       register struct tsym *tp;
+       register int c;
+       struct area  *ap;
+       struct expr e1;
+       char id[NCPS];
+       char opt[NCPS];
+       char fn[PATH_MAX];
+       char *p;
+       int d, n, uaf, uf;
+
+       laddr = dot.s_addr;
+       lmode = SLIST;
+loop:
+       if ((c=endline()) == 0) { return; }
+       /*
+        * If the first character is a digit then assume
+        * a local symbol is being specified.  The symbol
+        * must end with $: to be valid.
+        *      pass 0:
+        *              Construct a tsym structure at the first
+        *              occurance of the symbol.  Flag the symbol
+        *              as multiply defined if not the first occurance.
+        *      pass 1:
+        *              Load area, address, and fuzz values
+        *              into structure tsym.
+        *      pass 2:
+        *              Check for assembler phase error and
+        *              multiply defined error.
+        */
+       if (ctype[c] & DIGIT) {
+               if (flevel)
+                       return;
+               n = 0;
+               while ((d = digit(c, 10)) >= 0) {
+                       n = 10*n + d;
+                       c = get();
+               }
+               if (c != '$' || get() != ':')
+                       qerr();
+               tp = symp->s_tsym;
+               if (pass == 0) {
+                       while (tp) {
+                               if (n == tp->t_num) {
+                                       tp->t_flg |= S_MDF;
+                                       break;
+                               }
+                               tp = tp->t_lnk;
+                       }
+                       if (tp == NULL) {
+                               tp=(struct tsym *) new (sizeof(struct tsym));
+                               tp->t_lnk = symp->s_tsym;
+                               tp->t_num = n;
+                               tp->t_flg = 0;
+                               tp->t_area = dot.s_area;
+                               tp->t_addr = dot.s_addr;
+                               symp->s_tsym = tp;
+                       }
+               } else {
+                       while (tp) {
+                               if (n == tp->t_num) {
+                                       break;
+                               }
+                               tp = tp->t_lnk;
+                       }
+                       if (tp) {
+                               if (pass == 1) {
+                                       fuzz = tp->t_addr - dot.s_addr;
+                                       tp->t_area = dot.s_area;
+                                       tp->t_addr = dot.s_addr;
+                               } else {
+                                       phase(tp->t_area, tp->t_addr);
+                                       if (tp->t_flg & S_MDF)
+                                               err('m');
+                               }
+                       } else {
+                               err('u');
+                       }
+               }
+               lmode = ALIST;
+               goto loop;
+       }
+       /*
+        * If the first character is a letter then assume a lable,
+        * symbol, assembler directive, or assembler mnemonic is
+        * being processed.
+        */
+       if ((ctype[c] & LETTER) == 0) {
+               if (flevel) {
+                       return;
+               } else {
+                       qerr();
+               }
+       }
+       getid(id, c);
+       c = getnb();
+       /*
+        * If the next character is a : then a label is being processed.
+        * A double :: defines a global label.  If this is new label
+        * then create a symbol structure.
+        *      pass 0:
+        *              Flag multiply defined labels.
+        *      pass 1:
+        *              Load area, address, and fuzz values
+        *              into structure symp.
+        *      pass 2:
+        *              Check for assembler phase error and
+        *              multiply defined error.
+        */
+       if (c == ':') {
+               if (flevel)
+                       return;
+               if ((c = get()) != ':') {
+                       unget(c);
+                       c = 0;
+               }
+               symp = lookup(id);
+               if (symp == &dot)
+                       err('.');
+               if (pass == 0)
+                       if ((symp->s_type != S_NEW) &&
+                          ((symp->s_flag & S_ASG) == 0))
+                               symp->s_flag |= S_MDF;
+               if (pass != 2) {
+                       fuzz = symp->s_addr - dot.s_addr;
+                       symp->s_type = S_USER;
+                       symp->s_area = dot.s_area;
+                       symp->s_addr = dot.s_addr;
+               } else {
+                       if (symp->s_flag & S_MDF)
+                               err('m');
+                       phase(symp->s_area, symp->s_addr);
+               }
+               if (c) {
+                       symp->s_flag |= S_GBL;
+               }
+               lmode = ALIST;
+               goto loop;
+       }
+       /*
+        * If the next character is a = then an equate is being processed.
+        * A double == defines a global equate.  If this is new variable
+        * then create a symbol structure.
+        */
+       if (c == '=') {
+               if (flevel)
+                       return;
+               if ((c = get()) != '=') {
+                       unget(c);
+                       c = 0;
+               }
+               clrexpr(&e1);
+               expr(&e1, 0);
+               sp = lookup(id);
+               if (sp == &dot) {
+                       outall();
+                       if (e1.e_flag || e1.e_base.e_ap != dot.s_area)
+                               err('.');
+               } else
+               if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) {
+                       err('m');
+               }
+               sp->s_type = S_USER;
+               sp->s_area = e1.e_base.e_ap;
+               sp->s_addr = laddr = e1.e_addr;
+               sp->s_flag |= S_ASG;
+               if (c) {
+                       sp->s_flag |= S_GBL;
+               }
+               lmode = ELIST;
+               goto loop;
+       }
+       unget(c);
+       lmode = flevel ? SLIST : CLIST;
+       if ((mp = mlookup(id)) == NULL) {
+               if (!flevel)
+                       err('o');
+               return;
+       }
+       /*
+        * If we have gotten this far then we have found an
+        * assembler directive or an assembler mnemonic.
+        *
+        * Check for .if, .else, .endif, and .page directives
+        * which are not controlled by the conditional flags
+        */
+       switch (mp->m_type) {
+
+       case S_IF:
+               n = absexpr();
+               if (tlevel < MAXIF) {
+                       ++tlevel;
+                       ifcnd[tlevel] = n;
+                       iflvl[tlevel] = flevel;
+                       if (n == 0) {
+                               ++flevel;
+                       }
+               } else {
+                       err('i');
+               }
+               lmode = ELIST;
+               laddr = n;
+               return;
+
+       case S_ELSE:
+               if (ifcnd[tlevel]) {
+                       if (++flevel > (iflvl[tlevel]+1)) {
+                               err('i');
+                       }
+               } else {
+                       if (--flevel < iflvl[tlevel]) {
+                               err('i');
+                       }
+               }
+               lmode = SLIST;
+               return;
+
+       case S_ENDIF:
+               if (tlevel) {
+                       flevel = iflvl[tlevel--];
+               } else {
+                       err('i');
+               }
+               lmode = SLIST;
+               return;
+
+       case S_PAGE:
+               lop = NLPP;
+               lmode = NLIST;
+               return;
+
+       default:
+               break;
+       }
+       if (flevel)
+               return;
+       /*
+        * If we are not in a false state for .if/.else then
+        * process the assembler directives here.
+        */
+       switch (mp->m_type) {
+
+       case S_EVEN:
+               outall();
+               laddr = dot.s_addr = (dot.s_addr + 1) & ~1;
+               lmode = ALIST;
+               break;
+
+       case S_ODD:
+               outall();
+               laddr = dot.s_addr |= 1;
+               lmode = ALIST;
+               break;
+
+       case S_BYTE:
+       case S_WORD:
+               do {
+                       clrexpr(&e1);
+                       expr(&e1, 0);
+                       if (mp->m_type == S_BYTE) {
+                               outrb(&e1, R_NORM);
+                       } else {
+                               outrw(&e1, R_NORM);
+                       }
+               } while ((c = getnb()) == ',');
+               unget(c);
+               break;
+
+       case S_ASCII:
+       case S_ASCIZ:
+               if ((d = getnb()) == '\0')
+                       qerr();
+               while ((c = getmap(d)) >= 0)
+                       outab(c);
+               if (mp->m_type == S_ASCIZ)
+                       outab(0);
+               break;
+
+       case S_ASCIS:
+               if ((d = getnb()) == '\0')
+                       qerr();
+               c = getmap(d);
+               while (c >= 0) {
+                       if ((n = getmap(d)) >= 0) {
+                               outab(c);
+                       } else {
+                               outab(c | 0x80);
+                       }
+                       c = n;
+               }
+               break;
+
+       case S_BLK:
+               clrexpr(&e1);
+               expr(&e1, 0);
+               outchk(HUGE,HUGE);
+               dot.s_addr += e1.e_addr*mp->m_valu;
+               lmode = BLIST;
+               break;
+
+       case S_TITLE:
+               p = tb;
+               if ((c = getnb()) != 0) {
+                       do {
+                               if (p < &tb[NTITL-1])
+                                       *p++ = c;
+                       } while ((c = get()) != 0);
+               }
+               *p = 0;
+               unget(c);
+               lmode = SLIST;
+               break;
+
+       case S_SBTL:
+               p = stb;
+               if ((c = getnb()) != 0) {
+                       do {
+                               if (p < &stb[NSBTL-1])
+                                       *p++ = c;
+                       } while ((c = get()) != 0);
+               }
+               *p = 0;
+               unget(c);
+               lmode = SLIST;
+               break;
+
+       case S_MODUL:
+               getst(id, getnb()); // a module can start with a digit
+               if (pass == 0) {
+                       if (module[0]) {
+                               err('m');
+                       } else {
+                               strncpy(module, id, NCPS);
+                       }
+               }
+               lmode = SLIST;
+               break;
+
+    case S_OPTSDCC:
+               p = optsdcc;
+               if ((c = getnb()) != 0) {
+                       do {
+                               if (p < &optsdcc[NINPUT-1])
+                                       *p++ = c;
+                       } while ((c = get()) != 0);
+               }
+               *p = 0;
+               unget(c);
+               lmode = SLIST;
+        /*if (pass == 0) printf("optsdcc=%s\n", optsdcc);*/
+        break;
+
+       case S_GLOBL:
+               do {
+                       getid(id, -1);
+                       sp = lookup(id);
+                       sp->s_flag |= S_GBL;
+               } while ((c = getnb()) == ',');
+               unget(c);
+               lmode = SLIST;
+               break;
+
+       case S_DAREA:
+               getid(id, -1);
+               uaf = 0;
+               uf  = A_CON|A_REL;
+               if ((c = getnb()) == '(') {
+                       do {
+                               getid(opt, -1);
+                               mp = mlookup(opt);
+                               if (mp && mp->m_type == S_ATYP) {
+                                       ++uaf;
+                                       uf |= mp->m_valu;
+                               } else {
+                                       err('u');
+                               }
+                       } while ((c = getnb()) == ',');
+                       if (c != ')')
+                               qerr();
+               } else {
+                       unget(c);
+               }
+               if ((ap = alookup(id)) != NULL) {
+                       if (uaf && uf != ap->a_flag)
+                               err('m');
+               } else {
+                       ap = (struct area *) new (sizeof(struct area));
+                       ap->a_ap = areap;
+                       strncpy(ap->a_id, id, NCPS);
+                       ap->a_ref = areap->a_ref + 1;
+                       ap->a_size = 0;
+                       ap->a_fuzz = 0;
+                       ap->a_flag = uaf ? uf : (A_CON|A_REL);
+                       areap = ap;
+               }
+               newdot(ap);
+               lmode = SLIST;
+               break;
+
+       case S_ORG:
+               if (dot.s_area->a_flag & A_ABS) {
+                       outall();
+                       laddr = dot.s_addr = absexpr();
+               } else {
+                       err('o');
+               }
+               outall();
+               lmode = ALIST;
+               break;
+
+       case S_RADIX:
+               if (more()) {
+                       switch (getnb()) {
+                       case 'b':
+                       case 'B':
+                               radix = 2;
+                               break;
+                       case '@':
+                       case 'o':
+                       case 'O':
+                       case 'q':
+                       case 'Q':
+                               radix = 8;
+                               break;
+                       case 'd':
+                       case 'D':
+                               radix = 10;
+                               break;
+                       case 'h':
+                       case 'H':
+                       case 'x':
+                       case 'X':
+                               radix = 16;
+                               break;
+                       default:
+                               radix = 10;
+                               qerr();
+                               break;
+                       }
+               } else {
+                       radix = 10;
+               }
+               lmode = SLIST;
+               break;
+
+       case S_INCL:
+               d = getnb();
+               p = fn;
+               while ((c = get()) != d) {
+                       if (p < &fn[PATH_MAX-1]) {
+                               *p++ = c;
+                       } else {
+                               break;
+                       }
+               }
+               *p = 0;
+               if (++incfil == MAXINC ||
+                  (ifp[incfil] = fopen(fn, "r")) == NULL) {
+                       --incfil;
+                       err('i');
+               } else {
+                       lop = NLPP;
+                       incline[incfil] = 0;
+                       strcpy(incfn[incfil],fn);
+               }
+               lmode = SLIST;
+               break;
+               
+       case S_FLAT24:
+               if (more())
+               {
+                   getst(id, -1);
+                   
+                   if (!as_strcmpi(id, "on"))
+                   {
+                       /* Quick sanity check: size of 
+                        * Addr_T must be at least 24 bits.
+                        */
+                       if (sizeof(Addr_T) < 3)
+                       {
+                           warnBanner();
+                           fprintf(stderr,
+                                   "Cannot enable Flat24 mode: "
+                                   "host system must have 24 bit "
+                                   "or greater integers.\n");
+                       }
+                       else
+                       {
+                           flat24Mode = 1;
+                       }
+                   }
+                   else if (!as_strcmpi(id, "off"))
+                   {
+                       flat24Mode = 0;
+                   }
+                   else
+                   {
+                       qerr();
+                   }
+               }
+               else
+               {
+                   qerr();
+               }
+               lmode = SLIST;
+               #if 0
+               printf("as8051: ds390 flat mode %sabled.\n",
+                       flat24Mode ? "en" : "dis");
+               #endif
+               break;
+                                                                       
+
+       /*
+        * If not an assembler directive then go to
+        * the machine dependent function which handles
+        * all the assembler mnemonics.
+        */
+       default:
+               machine(mp);
+               /* if cdb information the generate the line info */
+               if (cflag && (pass == 1))
+                   DefineCDB_Line();
+
+                /* JLH: if -j, generate a line number symbol */
+                if (jflag && (pass == 1))
+                {
+                   DefineNoICE_Line();
+                }
+
+       }
+       goto loop;
+}
+
+/*)Function    FILE *  afile(fn, ft, wf)
+ *
+ *             char *  fn              file specification string
+ *             char *  ft              file type string
+ *             int     wf              read(0)/write(1) flag
+ *
+ *     The function afile() opens a file for reading or writing.
+ *             (1)     If the file type specification string ft
+ *                     is not NULL then a file specification is
+ *                     constructed with the file path\name in fn
+ *                     and the extension in ft.
+ *             (2)     If the file type specification string ft
+ *                     is NULL then the file specification is
+ *                     constructed from fn.  If fn does not have
+ *                     a file type then the default source file
+ *                     type dsft is appended to the file specification.
+ *
+ *     afile() returns a file handle for the opened file or aborts
+ *     the assembler on an open error.
+ *
+ *     local variables:
+ *             int     c               character value
+ *             FILE *  fp              filehandle for opened file
+ *             char *  p1              pointer to filespec string fn
+ *             char *  p2              pointer to filespec string fb
+ *             char *  p3              pointer to filetype string ft
+ *
+ *     global variables:
+ *             char    afn[]           afile() constructed filespec
+ *             char    dsft[]          default assembler file type string
+ *             char    afn[]           constructed file specification string
+ *
+ *     functions called:
+ *             VOID    asexit()        asmain.c
+ *             FILE *  fopen()         c_library
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             File is opened for read or write.
+ */
+
+FILE *
+afile(fn, ft, wf)
+char *fn;
+char *ft;
+int wf;
+{
+       register char *p2, *p3;
+       register int c;
+       FILE *fp;
+
+       p2 = afn;
+       p3 = ft;
+
+       strcpy (afn, fn);
+       p2 = strrchr (afn, FSEPX);              // search last '.'
+       if (!p2)
+               p2 = afn + strlen (afn);
+       if (p2 > &afn[PATH_MAX-4])              // truncate filename, if it's too long
+               p2 = &afn[PATH_MAX-4];
+       *p2++ = FSEPX;
+
+       // choose a file-extension
+       if (*p3 == 0) {                                 // extension supplied?
+               p3 = strrchr (fn, FSEPX);       // no: extension in fn?
+               if (p3)
+                       ++p3;
+               else
+                       p3 = dsft;                                      // no: default extension
+       }
+
+       while ((c = *p3++) != 0) {              // strncpy
+               if (p2 < &afn[PATH_MAX-1])
+                       *p2++ = c;
+       }
+       *p2++ = 0;
+
+       if ((fp = fopen(afn, wf?"w":"r")) == NULL) {
+               fprintf(stderr, "%s: cannot %s.\n", afn, wf?"create":"open");
+               asexit(1);
+       }
+       return (fp);
+}
+
+/*)Function    VOID    newdot(nap)
+ *
+ *             area *  nap             pointer to the new area structure
+ *
+ *     The function newdot():
+ *             (1)     copies the current values of fuzz and the last
+ *                     address into the current area referenced by dot
+ *             (2)     loads dot with the pointer to the new area and
+ *                     loads the fuzz and last address parameters
+ *             (3)     outall() is called to flush any remaining
+ *                     bufferred code from the old area to the output
+ *
+ *     local variables:
+ *             area *  oap             pointer to old area
+ *
+ *     global variables:
+ *             sym     dot             defined as sym[0]
+ *             Addr_T  fuzz            tracks pass to pass changes in the
+ *                                     address of symbols caused by
+ *                                     variable length instruction formats
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             Current area saved, new area loaded, buffers flushed.
+ */
+
+VOID
+newdot(nap)
+register struct area *nap;
+{
+       register struct area *oap;
+
+       oap = dot.s_area;
+       /* fprintf (stderr, "%s dot.s_area->a_size: %d dot.s_addr: %d\n",
+            oap->a_id, dot.s_area->a_size, dot.s_addr); */
+       oap->a_fuzz = fuzz;
+       if (oap->a_flag & A_OVR) {
+         // the size of an overlay is the biggest size encountered
+         if (oap->a_size < dot.s_addr) {
+           oap->a_size = dot.s_addr;
+         }
+       } else {
+         oap->a_size = dot.s_addr;
+       }
+       if (nap->a_flag & A_OVR) {
+         // a new overlay starts at 0, no fuzz
+         dot.s_addr = 0;
+         fuzz = 0;
+       } else {
+         dot.s_addr = nap->a_size;
+         fuzz = nap->a_fuzz;
+       }
+       dot.s_area = nap;
+       outall();
+}
+
+/*)Function    VOID    phase(ap, a)
+ *
+ *             area *  ap              pointer to area
+ *             Addr_T  a               address in area
+ *
+ *     Function phase() compares the area ap and address a
+ *     with the current area dot.s_area and address dot.s_addr
+ *     to determine if the position of the symbol has changed
+ *     between assembler passes.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global varaibles:
+ *             sym *   dot             defined as sym[0]
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             The p error is invoked if the area and/or address
+ *             has changed.
+ */
+
+VOID
+phase(ap, a)
+struct area *ap;
+Addr_T a;
+{
+       if (ap != dot.s_area || a != dot.s_addr)
+               err('p');
+}
+
+char *usetxt[] = {
+       "Usage: [-dqxjgalopsf] file1 [file2 file3 ...]",
+       "  d    decimal listing",
+       "  q    octal   listing",
+       "  x    hex     listing (default)",
+       "  j    add line number and debug information to file", /* JLH */
+       "  g    undefined symbols made global",
+       "  a    all user symbols made global",
+       "  l    create list   output file1[LST]",
+       "  o    create object output file1[REL]",
+       "  s    create symbol output file1[SYM]",
+       "  p    disable listing pagination",
+       "  f    flag relocatable references by `    in listing file",
+       " ff    flag relocatable references by mode in listing file",
+       "",
+       0
+};
+
+/*)Function    VOID    usage()
+ *
+ *     The function usage() outputs to the stderr device the
+ *     assembler name and version and a list of valid assembler options.
+ *
+ *     local variables:
+ *             char ** dp              pointer to an array of
+ *                                     text string pointers.
+ *
+ *     global variables:
+ *             char    cpu[]           assembler type string
+ *             char *  usetxt[]        array of string pointers
+ *
+ *     functions called:
+ *             VOID    asexit()        asmain.c
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             program is terminated
+ */
+
+VOID
+usage()
+{
+       register char   **dp;
+
+       fprintf(stderr, "\nASxxxx Assembler %s  (%s)\n\n", VERSION, cpu);
+       for (dp = usetxt; *dp; dp++)
+               fprintf(stderr, "%s\n", *dp);
+       asexit(1);       
+}
diff --git a/as/hc08/asnoice.c b/as/hc08/asnoice.c
new file mode 100644 (file)
index 0000000..38d3233
--- /dev/null
@@ -0,0 +1,122 @@
+/* asnoice.c */
+
+/*
+ * Extensions to CUG 292 assembler ASxxxx to produce NoICE debug files
+ *
+ * 3-Nov-1997 by John Hartman
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/* Return basic file name without path or extension */
+static char* BaseFileName( int fileNumber );
+
+char* BaseFileName( int fileNumber )
+{
+       static int prevFile = -1;
+        static char baseName[ PATH_MAX ];
+
+        char *p1, *p2;
+
+       if (fileNumber != prevFile)
+        {
+               prevFile = fileNumber;
+
+                p1 = srcfn[prevFile];
+
+                /* issue a FILE command with full path and extension */
+                fprintf( ofp, ";!FILE %s\n", p1 );
+
+               /* Name starts after any colon or backslash (DOS) */
+               p2 = strrchr( p1, '\\' );
+               if (p2 == NULL) p2 = strrchr( p1, '/' );
+               if (p2 == NULL) p2 = strrchr( p1, ':' );
+               if (p2 == NULL) p2 = p1-1;
+                strcpy( baseName, p2+1 );
+
+               /* Name ends at any separator */
+               p2 = strrchr( baseName, FSEPX );
+               if (p2 != NULL) *p2 = 0;
+               /* SD comment this out since not a ANSI Function */
+                /* strupr( baseName ); */
+       }
+       return baseName;
+}
+
+/* Define a symbol for current location:  FILE.line# */
+void DefineNoICE_Line()
+{
+       char name[ NCPS ];
+        struct sym *pSym;
+
+       /* symbol is FILE.nnn */
+        sprintf( name, "%s.%u", BaseFileName( cfile ), srcline[ cfile ] );
+
+        pSym = lookup( name );
+        pSym->s_type = S_USER;
+        pSym->s_area = dot.s_area;
+        pSym->s_addr = laddr;
+        pSym->s_flag |= S_GBL;
+}
+
+/* Define a symbol for current location:  A$FILE$line# */
+void DefineCDB_Line()
+{
+       char name[ NCPS ];
+        struct sym *pSym;
+
+       /* symbol is FILE.nnn */
+        sprintf( name, "A$%s$%u", BaseFileName( cfile ), srcline[ cfile ] );
+
+        pSym = lookup( name );
+        pSym->s_type = S_USER;
+        pSym->s_area = dot.s_area;
+        pSym->s_addr = laddr;
+        pSym->s_flag |= S_GBL;
+}
+
+#if 0
+OLD VERSION
+/* Define a symbol for current location:  FILE.line# */
+void DefineNoICE_Line()
+{
+        static int prevFile = -1;
+        static struct area *pPrevArea = NULL;
+        static char baseName[ PATH_MAX ];
+
+        int j;
+        char *p1, *p2;
+
+       /* Get outfilename without extension for use as base symbol name */
+        if (baseName[0] == 0)
+        {
+                p1 = srcfn[0];
+                p2 = baseName;
+                while ((*p1 != 0) && (*p1 != FSEPX))
+                {
+                       *p2++ = *p1++;
+                }
+                *p2 = 0;
+               /* SD Commented this out since it is not a 
+                  ASNI Function */
+                /* strupr( baseName ); */
+       }
+
+        if ((cfile != prevFile) || (dot.s_area != pPrevArea))
+        {
+               prevFile = cfile;
+                pPrevArea = dot.s_area;
+
+               /* file or area change: issue FILE command with base @ */
+                fprintf( ofp, ";!FILE %s %s_%s\n", srcfn[ cfile ],
+                        baseName,
+                        dot.s_area->a_id );
+        }
+
+        fprintf( ofp, ";!LINE %u. 0x%X\n", srcline[ cfile ], laddr );
+}
+
+#endif
diff --git a/as/hc08/asout.c b/as/hc08/asout.c
new file mode 100644 (file)
index 0000000..363a2c1
--- /dev/null
@@ -0,0 +1,1476 @@
+/* asout.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - outsym: show s_id as string rather than array [NCPS]
+ *           - Added outr11 to support 8051's 11 bit destination address
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+
+/*)Module      asout.c
+ *
+ *     The module asout.c contains all the functions used to
+ *     generate the .REL assembler output file.
+ *
+ *
+ *     The  assemblers' output object file is an ascii file containing
+ *     the information needed by the linker  to  bind  multiple  object
+ *     modules into a complete loadable memory image.  
+ *
+ *     The object module contains the following designators:  
+ *
+ *             [XDQ][HL]
+ *                     X        Hexadecimal radix
+ *                     D        Decimal radix
+ *                     Q        Octal radix
+ *     
+ *                     H        Most significant byte first
+ *                     L        Least significant byte first
+ *     
+ *             H        Header 
+ *             M        Module
+ *             A        Area
+ *             S        Symbol
+ *             T        Object code
+ *             R        Relocation information
+ *             P        Paging information
+ *
+ *
+ *     (1)     Radix Line
+ *
+ *     The  first  line  of  an object module contains the [XDQ][HL]
+ *     format specifier (i.e.  XH indicates  a  hexadecimal  file  with
+ *     most significant byte first) for the following designators.  
+ *
+ *
+ *     (2)     Header Line
+ *
+ *             H aa areas gg global symbols 
+ *
+ *     The  header  line  specifies  the number of areas(aa) and the
+ *     number of global symbols(gg) defined or referenced in  this  ob-
+ *     ject module segment.  
+ *
+ *
+ *     (3)     Module Line 
+ *
+ *             M name 
+ *
+ *     The  module  line  specifies  the module name from which this
+ *     header segment was assembled.  The module line will  not  appear
+ *     if the .module directive was not used in the source program.  
+ *
+ *
+ *     (4)     Symbol Line 
+ *
+ *             S string Defnnnn 
+ *
+ *                     or 
+ *
+ *             S string Refnnnn 
+ *
+ *     The  symbol line defines (Def) or references (Ref) the symbol
+ *     'string' with the value nnnn.  The defined value is relative  to
+ *     the  current area base address.  References to constants and ex-
+ *     ternal global symbols will always appear before the  first  area
+ *     definition.  References to external symbols will have a value of
+ *     zero.  
+ *
+ *
+ *     (5)     Area Line 
+ *
+ *             A label size ss flags ff 
+ *
+ *     The  area  line  defines the area label, the size (ss) of the
+ *     area in bytes, and the area flags (ff).  The area flags  specify
+ *     the ABS, REL, CON, OVR, and PAG parameters:  
+ *
+ *             OVR/CON (0x04/0x00 i.e.  bit position 2) 
+ *
+ *             ABS/REL (0x08/0x00 i.e.  bit position 3) 
+ *
+ *             PAG (0x10 i.e.  bit position 4) 
+ *
+ *
+ *     (6)     T Line 
+ *
+ *             T xx xx nn nn nn nn nn ...  
+ *
+ *     The  T  line contains the assembled code output by the assem-
+ *     bler with xx xx being the offset address from the  current  area
+ *     base address and nn being the assembled instructions and data in
+ *     byte format.  
+ *
+ *
+ *     (7)     R Line 
+ *
+ *             R 0 0 nn nn n1 n2 xx xx ...  
+ *
+ *     The R line provides the relocation information to the linker.
+ *     The nn nn value is the current area index, i.e.  which area  the
+ *     current  values  were  assembled.  Relocation information is en-
+ *     coded in groups of 4 bytes:  
+ *
+ *     1.  n1 is the relocation mode and object format 
+ *             1.  bit 0 word(0x00)/byte(0x01) 
+ *             2.  bit 1 relocatable area(0x00)/symbol(0x02) 
+ *             3.  bit 2 normal(0x00)/PC relative(0x04) relocation 
+ *             4.  bit  3  1-byte(0x00)/2-byte(0x08) object format for
+ *                 byte data 
+ *             5.  bit 4 signed(0x00)/unsigned(0x10) byte data 
+ *             6.  bit 5 normal(0x00)/page '0'(0x20) reference 
+ *             7.  bit 6 normal(0x00)/page 'nnn'(0x40) reference 
+ *             8.  bit 7 normal(0x00)/MSB of value
+ *
+ *     2.  n2  is  a byte index into the corresponding (i.e.  pre-
+ *             ceeding) T line data (i.e.  a pointer to the data to be
+ *             updated  by  the  relocation).   The T line data may be
+ *             1-byte or  2-byte  byte  data  format  or  2-byte  word
+ *             format.  
+ *
+ *     3.  xx xx  is the area/symbol index for the area/symbol be-
+ *             ing referenced.  the corresponding area/symbol is found
+ *             in the header area/symbol lists.  
+ *
+ *
+ *     The groups of 4 bytes are repeated for each item requiring relo-
+ *     cation in the preceeding T line.  
+ *
+ *
+ *     (8)     P Line 
+ *
+ *             P 0 0 nn nn n1 n2 xx xx 
+ *
+ *     The  P  line provides the paging information to the linker as
+ *     specified by a .setdp directive.  The format of  the  relocation
+ *     information is identical to that of the R line.  The correspond-
+ *     ing T line has the following information:  
+ *             T xx xx aa aa bb bb 
+ *
+ *     Where  aa aa is the area reference number which specifies the
+ *     selected page area and bb bb is the base address  of  the  page.
+ *     bb bb will require relocation processing if the 'n1 n2 xx xx' is
+ *     specified in the P line.  The linker will verify that  the  base
+ *     address is on a 256 byte boundary and that the page length of an
+ *     area defined with the PAG type is not larger than 256 bytes.  
+ *
+ *     The  linker  defaults any direct page references to the first
+ *     area defined in the input REL file.  All ASxxxx assemblers  will
+ *     specify the _CODE area first, making this the default page area. 
+ *
+ *
+ *     asout.c contains the following functions:
+ *             int     lobyte()
+ *             int     hibyte()
+ *             VOID    out()
+ *             VOID    outab()
+ *             VOID    outall()
+ *             VOID    outarea()
+ *             VOID    outaw()
+ *             VOID    outbuf()
+ *             VOID    outchk()
+ *             VOID    outdot()
+ *             VOID    outdp()
+ *             VOID    outgsd()
+ *             VOID    outrb()
+ *             VOID    outrw()
+ *             VOID    outsym()
+ *             VOID    out_lb()
+ *             VOID    out_lw()
+ *             VOID    out_rw()
+ *             VOID    out_tw()
+ *
+ *     The module asout.c contains the following local variables:
+ *             int     rel[]           relocation data for code/data array
+ *             int *   relp            pointer to rel array
+ *             int     txt[]           assembled code/data array
+ *             int *   txtp            pointer to txt array
+ */
+
+#define         NTXT   16
+#define         NREL   16
+
+char    txt[NTXT];
+char    rel[NREL];
+
+char   *txtp = { &txt[0] };
+char   *relp = { &rel[0] };
+
+/*)Function    VOID    outab(b)
+ *
+ *             int     b               assembler data word
+ *
+ *     The function outab() processes a single word of
+ *     assembled data in absolute format.
+ *
+ *     local variables:
+ *             int *   txtp            pointer to data word
+ *
+ *     global variables:
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *
+ *     functions called:
+ *             VOID    outchk()        asout.c
+ *             VOID    out_lb()        asout.c
+ *
+ *     side effects:
+ *             The current assembly address is incremented by 1.
+ */
+
+VOID
+outab(b)
+{
+       if (pass == 2) {
+               out_lb(b,0);
+               if (oflag) {
+                       outchk(1, 0);
+                       *txtp++ = lobyte(b);
+               }
+       }
+       ++dot.s_addr;
+}
+
+/*)Function    VOID    outaw(w)
+ *
+ *             int     w               assembler data word
+ *
+ *     The function outaw() processes a single word of
+ *     assembled data in absolute format.
+ *
+ *     local variables:
+ *             int *   txtp            pointer to data word
+ *
+ *     global variables:
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *
+ *     functions called:
+ *             VOID    outchk()        asout.c
+ *             VOID    out_lw()        asout.c
+ *
+ *     side effects:
+ *             The current assembly address is incremented by 2.
+ */
+
+VOID
+outaw(w)
+{
+       if (pass == 2) {
+               out_lw(w,0);
+               if (oflag) {
+                       outchk(2, 0);
+                       out_tw(w);
+               }
+       }
+       dot.s_addr += 2;
+}
+
+/*)Function    VOID    write_rmode(r)
+ *
+ *             int     r               relocation mode
+ *
+ *     write_rmode puts the passed relocation mode into the 
+ *     output relp buffer, escaping it if necessary.
+ *
+ *     global variables:
+ *             int *   relp            pointer to rel array
+ *
+ *     functions called:
+ *             VOID    rerr()          assubr.c
+ *
+ *     side effects:
+ *             relp is incremented appropriately.
+ */
+VOID
+write_rmode(int r)
+{
+    /* We need to escape the relocation mode if it is greater
+     * than a byte, or if it happens to look like an escape.
+     * (I don't think that the latter case is legal, but
+     * better safe than sorry).
+     */
+    if ((r > 0xff) || ((r & R_ESCAPE_MASK) == R_ESCAPE_MASK))
+    {
+       /* Hack in up to an extra 4 bits of flags with escape. */
+       if (r > 0xfff)
+       {
+            /* uh-oh.. we have more than 4 extra bits. */
+            fprintf(stderr, 
+                    "Internal error: relocation mode 0x%X too big.\n", 
+                    r);
+            rerr();
+       }
+       /* printf("escaping relocation mode\n"); */
+       *relp++ = R_ESCAPE_MASK | (r >> 8);
+       *relp++ = r & 0xff;
+    }
+    else
+    {
+       *relp++ = r;
+    }
+}
+
+/*)Function    VOID    outrb(esp, r)
+ *
+ *             expr *  esp             pointer to expr structure
+ *             int     r               relocation mode
+ *
+ *     The function outrb() processes a byte of generated code
+ *     in either absolute or relocatable format dependent upon
+ *     the data contained in the expr structure esp.  If the
+ *     .REL output is enabled then the appropriate information
+ *     is loaded into the txt and rel buffers.
+ *
+ *     local variables:
+ *             int     n               symbol/area reference number
+ *             int *   relp            pointer to rel array
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             sym     dot             defined as sym[0]
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *             
+ *     functions called:
+ *             VOID    aerr()          assubr.c
+ *             VOID    outchk()        asout.c
+ *             VOID    out_lb()        asout.c
+ *             VOID    out_rb()        asout.c
+ *             VOID    out_tb()        asout.c
+ *
+ *     side effects:
+ *             The current assembly address is incremented by 1.
+ */
+
+VOID
+outrb(struct expr *esp, int r)
+{
+       register int n;
+
+       if (pass == 2) {
+               if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+                       /* This is a constant; simply write the
+                        * const byte to the T line and don't
+                        * generate any relocation info.
+                        */
+                       out_lb(lobyte(esp->e_addr),0);
+                       if (oflag) {
+                               outchk(1, 0);
+                               *txtp++ = lobyte(esp->e_addr);
+                       }
+               } else {
+                       /* We are generating a single byte of relocatable
+                        * info.
+                        *
+                        * In 8051 mode, we generate a 16 bit address. The 
+                        * linker will later select a single byte based on
+                        * whether R_MSB is set.
+                        *
+                        * In flat24 mode, we generate a 24 bit address. The
+                        * linker will select a single byte based on 
+                        * whether R_MSB or R_HIB is set.
+                        */
+                       if (!flat24Mode)
+                       { 
+                           r |= R_BYTE | R_BYT2 | esp->e_rlcf;
+                           if (r & R_MSB) {
+                               out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
+                           } else {
+                               out_lb(lobyte(esp->e_addr),r|R_RELOC);
+                           }
+                           if (oflag) {
+                               outchk(2, 5);
+                               out_tw(esp->e_addr);
+                               if (esp->e_flag) {
+                                       n = esp->e_base.e_sp->s_ref;
+                                       r |= R_SYM;
+                               } else {
+                                       n = esp->e_base.e_ap->a_ref;
+                               }
+                               write_rmode(r);
+                               *relp++ = txtp - txt - 2;
+                               out_rw(n);
+                           }
+                       }
+                       else
+                       {
+                           /* 24 bit mode. */
+                           r |= R_BYTE | R_BYT3 | esp->e_rlcf;
+                           if (r & R_HIB)
+                           {
+                               /* Probably should mark this differently in the
+                                * listing file.
+                                */
+                               out_lb(byte3(esp->e_addr),r|R_RELOC|R_HIGH);
+                           }
+                           else if (r & R_MSB) {
+                               out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
+                           } else {
+                               out_lb(lobyte(esp->e_addr),r|R_RELOC);
+                           }
+                           if (oflag) {
+                               outchk(3, 5);
+                               out_t24(esp->e_addr);
+                               if (esp->e_flag) {
+                                       n = esp->e_base.e_sp->s_ref;
+                                       r |= R_SYM;
+                               } else {
+                                       n = esp->e_base.e_ap->a_ref;
+                               }
+                               write_rmode(r);
+                               *relp++ = txtp - txt - 3;
+                               out_rw(n);                          
+                           }
+                       }
+               }
+       }
+       ++dot.s_addr;
+}
+
+/*)Function    VOID    outrw(esp, r)
+ *
+ *             expr *  esp             pointer to expr structure
+ *             int     r               relocation mode
+ *
+ *     The function outrw() processes a word of generated code
+ *     in either absolute or relocatable format dependent upon
+ *     the data contained in the expr structure esp.  If the
+ *     .REL output is enabled then the appropriate information
+ *     is loaded into the txt and rel buffers.
+ *
+ *     local variables:
+ *             int     n               symbol/area reference number
+ *             int *   relp            pointer to rel array
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             sym     dot             defined as sym[0]
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *             
+ *     functions called:
+ *             VOID    aerr()          assubr.c
+ *             VOID    outchk()        asout.c
+ *             VOID    out_lw()        asout.c
+ *             VOID    out_rw()        asout.c
+ *             VOID    out_tw()        asout.c
+ *
+ *     side effects:
+ *             The current assembly address is incremented by 2.
+ */
+
+VOID
+outrw(struct expr *esp, int r)
+{
+       register int n;
+
+       if (pass == 2) {
+       
+               if (esp->e_addr > 0xffff)
+               {
+                   warnBanner();
+                   fprintf(stderr,
+                           "large constant 0x%x truncated to 16 bits\n",
+                           esp->e_addr);
+               }
+               if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+                       out_lw(esp->e_addr,0);
+                       if (oflag) {
+                               outchk(2, 0);
+                               out_tw(esp->e_addr);
+                       }
+               } else {
+                       r |= R_WORD | esp->e_rlcf;
+                       if (r & R_BYT2) {
+                               rerr();
+                               if (r & R_MSB) {
+                                       out_lw(hibyte(esp->e_addr),r|R_RELOC);
+                               } else {
+                                       out_lw(lobyte(esp->e_addr),r|R_RELOC);
+                               }
+                       } else {
+                               out_lw(esp->e_addr,r|R_RELOC);
+                       }
+                       if (oflag) {
+                               outchk(2, 5);
+                               out_tw(esp->e_addr);
+                               if (esp->e_flag) {
+                                       n = esp->e_base.e_sp->s_ref;
+                                       r |= R_SYM;
+                               } else {
+                                       n = esp->e_base.e_ap->a_ref;
+                               }
+                               
+                               if (IS_C24(r))
+                               {
+                                   /* If this happens, the linker will
+                                    * attempt to process this 16 bit field
+                                    * as 24 bits. That would be bad.
+                                    */
+                                   fprintf(stderr,
+                                           "***Internal error: C24 out in "
+                                           "outrw()\n");
+                                   rerr();
+                               }
+                               write_rmode(r);
+                               *relp++ = txtp - txt - 2;
+                               out_rw(n);
+                       }
+               }
+       }
+       dot.s_addr += 2;
+}
+
+/*)Function    VOID    outr24(esp, r)
+ *
+ *             expr *  esp             pointer to expr structure
+ *             int     r               relocation mode
+ *
+ *     The function outr24() processes 24 bits of generated code
+ *     in either absolute or relocatable format dependent upon
+ *     the data contained in the expr structure esp.  If the
+ *     .REL output is enabled then the appropriate information
+ *     is loaded into the txt and rel buffers.
+ *
+ *     local variables:
+ *             int     n               symbol/area reference number
+ *             int *   relp            pointer to rel array
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             sym     dot             defined as sym[0]
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *             
+ *     functions called:
+ *             VOID    aerr()          assubr.c
+ *             VOID    outchk()        asout.c
+ *             VOID    out_l24()       asout.c
+ *             VOID    out_rw()        asout.c
+ *             VOID    out_t24()       asout.c
+ *
+ *     side effects:
+ *             The current assembly address is incremented by 3.
+ */
+
+VOID
+outr24(struct expr *esp, int r)
+{
+       register int n;
+
+       if (pass == 2) {
+               if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+                       /* This is a constant expression. */
+                       out_l24(esp->e_addr,0);
+                       if (oflag) {
+                               outchk(3, 0);
+                               out_t24(esp->e_addr);
+                       }
+               } else {
+                       /* This is a symbol. */
+                       r |= R_WORD | esp->e_rlcf;
+                       if (r & R_BYT2) {
+                               /* I have no idea what this case is. */
+                               rerr();
+                               if (r & R_MSB) {
+                                       out_lw(hibyte(esp->e_addr),r|R_RELOC);
+                               } else {
+                                       out_lw(lobyte(esp->e_addr),r|R_RELOC);
+                               }
+                       } else {
+                               out_l24(esp->e_addr,r|R_RELOC);
+                       }
+                       if (oflag) {
+                               outchk(3, 5);
+                               out_t24(esp->e_addr);
+                               if (esp->e_flag) {
+                                       n = esp->e_base.e_sp->s_ref;
+                                       r |= R_SYM;
+                               } else {
+                                       n = esp->e_base.e_ap->a_ref;
+                               }
+                               
+                               if (r & R_BYTE)
+                               {
+                                   /* If this occurs, we cannot properly
+                                    * code the relocation data with the
+                                    * R_C24 flag. This means the linker
+                                    * will fail to do the 24 bit relocation.
+                                    * Which will suck.
+                                    */
+                                   fprintf(stderr,
+                                           "***Internal error: BYTE out in 24 "
+                                           "bit flat mode unexpected.\n");
+                                   rerr();
+                               }
+                               
+                               write_rmode(r | R_C24);
+                               *relp++ = txtp - txt - 3;
+                               out_rw(n);
+                       }
+               }
+       }
+       dot.s_addr += 3;
+}
+
+/*)Function    VOID    outdp(carea, esp)
+ *
+ *             area *  carea           pointer to current area strcuture
+ *             expr *  esp             pointer to expr structure
+ *
+ *     The function outdp() flushes the output buffer and
+ *     outputs paging information to the .REL file.
+ *
+ *     local variables:
+ *             int     n               symbol/area reference number
+ *             int     r               relocation mode
+ *             int *   relp            pointer to rel array
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *             
+ *     functions called:
+ *             VOID    outbuf()        asout.c
+ *             VOID    outchk()        asout.c
+ *             VOID    out_rw()        asout.c
+ *             VOID    out_tw()        asout.c
+ *
+ *     side effects:
+ *             Output buffer flushed to .REL fiel.
+ *             Paging information dumped to .REL file.
+ */
+
+VOID
+outdp(carea, esp)
+register struct area *carea;
+register struct expr *esp;
+{
+       register int n, r;
+
+       if (oflag && pass==2) {
+               outchk(HUGE,HUGE);
+               out_tw(carea->a_ref);
+               out_tw(esp->e_addr);
+               if (esp->e_flag || esp->e_base.e_ap!=NULL) {
+                       r = R_WORD;
+                       if (esp->e_flag) {
+                               n = esp->e_base.e_sp->s_ref;
+                               r |= R_SYM;
+                       } else {
+                               n = esp->e_base.e_ap->a_ref;
+                       }
+                       write_rmode(r);
+                       *relp++ = txtp - txt - 2;
+                       out_rw(n);
+               }
+               outbuf("P");
+       }
+}
+
+/*)Function    VOID    outall()
+ *
+ *     The function outall() will output any bufferred assembled
+ *     data and relocation information (during pass 2 if the .REL
+ *     output has been enabled).
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *
+ *     functions called:
+ *             VOID    outbuf()        asout.c
+ *
+ *     side effects:
+ *             assembled data and relocation buffers will be cleared.
+ */
+
+VOID
+outall()
+{
+       if (oflag && pass==2)
+               outbuf("R");
+}
+
+/*)Function    VOID    outdot()
+ *
+ *     The function outdot() outputs information about the
+ *     current program counter value (during pass 2 if the .REL
+ *     output has been enabled).
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int     oflag           -o, generate relocatable output flag
+ *             int     pass            assembler pass number
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    out()           asout.c
+ *
+ *     side effects:
+ *             assembled data and relocation buffers will be cleared.
+ */
+
+VOID
+outdot()
+{
+       if (oflag && pass==2) {
+               fprintf(ofp, "T");
+               out(txt,(int) (txtp-txt));
+               fprintf(ofp, "\n");
+               fprintf(ofp, "R");
+               out(rel,(int) (relp-rel));
+               fprintf(ofp, "\n");
+               txtp = txt;
+               relp = rel;
+       }
+}
+
+/*)Function    outchk(nt, nr)
+ *
+ *             int     nr              number of additional relocation words
+ *             int     nt              number of additional data words
+ *
+ *     The function outchk() checks the data and relocation buffers
+ *     for space to insert the nt data words and nr relocation words.
+ *     If space is not available then output the current data and
+ *     initialize the data buffers to receive the new data.
+ *
+ *     local variables:
+ *             area *  ap              pointer to an area structure
+ *             int *   relp            pointer to rel array
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             sym     dot             defined as sym[0]
+ *
+ *     functions called:
+ *             VOID    outbuf()        asout.c
+ *
+ *     side effects:
+ *             Data and relocation buffers may be emptied and initialized.
+ */
+
+VOID
+outchk(nt, nr)
+{
+       register struct area *ap;
+
+       if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) {
+               outbuf("R");
+       }
+       if (txtp == txt) {
+               out_tw(dot.s_addr);
+               if ((ap = dot.s_area) != NULL) {
+                       write_rmode(R_WORD|R_AREA);
+                       *relp++ = 0;
+                       out_rw(ap->a_ref);
+               }
+       }
+}
+
+/*)Function    VOID    outbuf()
+ *
+ *     The function outbuf() will output any bufferred data
+ *     and relocation information to the .REL file.  The output
+ *     buffer pointers and counters are initialized.
+ *
+ *     local variables:
+ *             int     rel[]           relocation data for code/data array
+ *             int *   relp            pointer to rel array
+ *             int     txt[]           assembled code/data array
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             FILE *  ofp             relocation output file handle
+ *
+ *     functions called:
+ *             VOID    out()           asout.c
+ *
+ *     side effects:
+ *             All bufferred data written to .REL file and
+ *             buffer pointers and counters initialized.
+ */
+
+VOID
+outbuf(s)
+char *s;
+{
+       if (txtp > &txt[2]) {
+               fprintf(ofp, "T");
+               out(txt,(int) (txtp-txt));
+               fprintf(ofp, "\n");
+               fprintf(ofp, "%s", s);
+               out(rel,(int) (relp-rel));
+               fprintf(ofp, "\n");
+       }
+       txtp = txt;
+       relp = rel;
+}
+
+/*)Function    VOID    outgsd()
+ *
+ *     The function outgsd() performs the following:
+ *     (1)     outputs the .REL file radix
+ *     (2)     outputs the header specifying the number
+ *             of areas and global symbols
+ *     (3)     outputs the module name
+ *     (4)     set the reference number and output a symbol line
+ *             for all external global variables and absolutes
+ *     (5)     output an area name, set reference number and output
+ *             a symbol line for all global relocatables in the area.
+ *             Repeat this proceedure for all areas.
+ *
+ *     local variables:
+ *             area *  ap              pointer to an area structure
+ *             sym *   sp              pointer to a sym structure
+ *             int     i               loop counter
+ *             int     j               loop counter
+ *             int     c               string character value
+ *             int     narea           number of code areas
+ *             char *  ptr             string pointer
+ *             int     nglob           number of global symbols
+ *             int     rn              symbol reference number
+ *
+ *     global variables:
+ *             area *  areap           pointer to an area structure
+ *             char    module[]        module name string
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    outarea()       asout.c
+ *             VOID    outsym()        asout.c
+ *             int     putc()          c_library
+ *
+ *     side effects:
+ *             All symbols are given reference numbers, all symbol
+ *             and area information is output to the .REL file.
+ */
+
+VOID
+outgsd()
+{
+       register struct area *ap;
+       register struct sym  *sp;
+       register int i, j;
+       char *ptr;
+       int c, narea, nglob, rn;
+
+       /*
+        * Number of areas
+        */
+       narea = areap->a_ref + 1;
+
+       /*
+        * Number of global references/absolutes
+        */
+       nglob = 0;
+       for (i = 0; i < NHASH; ++i) {
+               sp = symhash[i];
+               while (sp) {
+                       if (sp->s_flag&S_GBL)
+                               ++nglob;
+                       sp = sp->s_sp;
+               }
+       }
+
+       /*
+        * Output Radix and number of areas and symbols
+        */
+       if (xflag == 0) {
+               fprintf(ofp, "X%c\n", hilo ? 'H' : 'L');
+               fprintf(ofp, "H %X areas %X global symbols\n", narea, nglob);
+       } else
+       if (xflag == 1) {
+               fprintf(ofp, "Q%c\n", hilo ? 'H' : 'L');
+               fprintf(ofp, "H %o areas %o global symbols\n", narea, nglob);
+       } else
+       if (xflag == 2) {
+               fprintf(ofp, "D%c\n", hilo ? 'H' : 'L');
+               fprintf(ofp, "H %u areas %u global symbols\n", narea, nglob);
+       }               
+
+       /*
+        * Module name
+        */
+       if (module[0]) {
+               fprintf(ofp, "M ");
+               ptr = &module[0];
+               while (ptr < &module[NCPS]) {
+                       if ((c = *ptr++) != 0)
+                               putc(c, ofp);
+               }
+               putc('\n', ofp);
+       }
+
+    /*
+     * Sdcc compile options
+     */
+       if (strlen(optsdcc)) fprintf(ofp, "O %s\n", optsdcc);
+
+       /*
+        * Global references and absolutes.
+        */
+       rn = 0;
+       for (i=0; i<NHASH; ++i) {
+               sp = symhash[i];
+               while (sp) {
+                       if (sp->s_area==NULL && sp->s_flag&S_GBL) {
+                               sp->s_ref = rn++;
+                               outsym(sp);
+                       }
+                       sp = sp->s_sp;
+               }
+       }
+
+       /*
+        * Global relocatables.
+        */
+       for (i=0; i<narea; ++i) {
+               ap = areap;
+               while (ap->a_ref != i)
+                       ap = ap->a_ap;
+               outarea(ap);
+               for (j=0; j<NHASH; ++j) {
+                       sp = symhash[j];
+                       while (sp) {
+                               if (sp->s_area==ap && sp->s_flag&S_GBL) {
+                                       sp->s_ref = rn++;
+                                       outsym(sp);
+                               }
+                               sp = sp->s_sp;
+                       }
+               }
+       }
+}
+
+/*)Function    VOID    outarea(ap)
+ *
+ *             area *  ap              pointer to an area structure
+ *
+ *     The function outarea()  outputs the A line to the .REL
+ *     file.  The A line contains the area's name, size, and
+ *     attributes.
+ *
+ *     local variables:
+ *             char *  ptr             pointer to area id string
+ *             int     c               character value
+ *
+ *     global variables:
+ *             FILE *  ofp             relocation output file handle
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             int     putc()          c_library
+ *
+ *     side effects:
+ *             The A line is sent to the .REL file.
+ */
+
+VOID
+outarea(ap)
+register struct area *ap;
+{
+       register char *ptr;
+       register int c;
+
+       fprintf(ofp, "A ");
+       ptr = &ap->a_id[0];
+       while (ptr < &ap->a_id[NCPS]) {
+               if ((c = *ptr++) != 0)
+                       putc(c, ofp);
+       }
+       if (xflag == 0) {
+               fprintf(ofp, " size %X flags %X\n", ap->a_size, ap->a_flag);
+       } else
+       if (xflag == 1) {
+               fprintf(ofp, " size %o flags %o\n", ap->a_size, ap->a_flag);
+       } else
+       if (xflag == 2) {
+               fprintf(ofp, " size %u flags %u\n", ap->a_size, ap->a_flag);
+       }
+}
+
+/*)Function    VOID    outsym(sp)
+ *
+ *             sym *   sp              pointer to a sym structure
+ *
+ *     The function outsym() outputs the S line to the .REL
+ *     file.  The S line contains the symbols name and whether the
+ *     the symbol is defined or referenced.
+ *
+ *     local variables:
+ *             char *  ptr             pointer to symbol id string
+ *             int     c               character value
+ *
+ *     global variables:
+ *             FILE *  ofp             relocation output file handle
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             int     putc()          c_library
+ *
+ *     side effects:
+ *             The S line is sent to the .REL file.
+ */
+
+VOID
+outsym(sp)
+register struct sym *sp;
+{
+       register char *ptr;       
+
+       fprintf(ofp, "S ");
+       ptr = &sp->s_id[0];
+       fprintf(ofp, "%s", ptr );
+       fprintf(ofp, " %s", sp->s_type==S_NEW ? "Ref" : "Def");
+       if (xflag == 0) {
+               fprintf(ofp, "%04X\n", sp->s_addr);
+       } else
+       if (xflag == 1) {
+               fprintf(ofp, "%06o\n", sp->s_addr);
+       } else
+       if (xflag == 2) {
+               fprintf(ofp, "%05u\n", sp->s_addr);
+       }
+}
+
+/*)Function    VOID    out(p, n)
+ *
+ *             int     n               number of words to output
+ *             int *   p               pointer to data words
+ *
+ *     The function out() outputs the data words to the .REL file
+ *     int the specified radix.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             FILE *  ofp             relocation output file handle
+ *             int     xflag           -x, listing radix flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             Data is sent to the .REL file.
+ */
+
+VOID
+out(char *p, int n)
+{
+       while (n--) {
+               if (xflag == 0) {
+                       fprintf(ofp, " %02X", (*p++)&0xff);
+               } else
+               if (xflag == 1) {
+                       fprintf(ofp, " %03o", (*p++)&0xff);
+               } else
+               if (xflag == 2) {
+                       fprintf(ofp, " %03u", (*p++)&0xff);
+               }
+       }
+}
+
+/*)Function    VOID    out_lb(b, t)
+ *
+ *             int     b               assembled data
+ *             int     t               relocation type
+ *
+ *     The function out_lb() copies the assembled data and
+ *     its relocation type to the list data buffers.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int *   cp              pointer to assembler output array cb[]
+ *             int *   cpt             pointer to assembler relocation type
+ *                                     output array cbt[]
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             Pointers to data and relocation buffers incremented by 1.
+ */
+
+VOID
+out_lb(b,t)
+register int b,t;
+{
+       if (cp < &cb[NCODE]) {
+               *cp++ = b;
+               *cpt++ = t;
+       }
+}
+
+/*)Function    VOID    out_lw(n, t)
+ *
+ *             int     n               assembled data
+ *             int     t               relocation type
+ *
+ *     The function out_lw() copies the assembled data and
+ *     its relocation type to the list data buffers.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int *   cp              pointer to assembler output array cb[]
+ *             int *   cpt             pointer to assembler relocation type
+ *                                     output array cbt[]
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             Pointers to data and relocation buffers incremented by 2.
+ */
+
+VOID
+out_lw(n,t)
+register int n,t;
+{
+       if (hilo) {
+               out_lb(hibyte(n),t ? t|R_HIGH : 0);
+               out_lb(lobyte(n),t);
+       } else {
+               out_lb(lobyte(n),t);
+               out_lb(hibyte(n),t ? t|R_HIGH : 0);
+       }
+}
+
+/*)Function    VOID    out_l24(n, t)
+ *
+ *             int     n               assembled data
+ *             int     t               relocation type
+ *
+ *     The function out_l24() copies the assembled data and
+ *     its relocation type to the list data buffers.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int *   cp              pointer to assembler output array cb[]
+ *             int *   cpt             pointer to assembler relocation type
+ *                                     output array cbt[]
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             Pointers to data and relocation buffers incremented by 3.
+ */
+
+VOID
+out_l24(int n, int t)
+{
+       if (hilo) {
+               out_lb(byte3(n),t ? t|R_HIGH : 0);
+               out_lb(hibyte(n),t);
+               out_lb(lobyte(n),t);
+       } else {
+               out_lb(lobyte(n),t);
+               out_lb(hibyte(n),t);
+               out_lb(byte3(n),t ? t|R_HIGH : 0);
+       }
+}
+
+/*)Function    VOID    out_rw(n)
+ *
+ *             int     n               data word
+ *
+ *     The function out_rw() outputs the relocation (R)
+ *     data word as two bytes ordered according to hilo.
+ *
+ *     local variables:
+ *             int *   relp            pointer to rel array
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             int     lobyte()        asout.c
+ *             int     hibyte()        asout.c
+ *
+ *     side effects:
+ *             Pointer to relocation buffer incremented by 2.
+ */
+
+VOID
+out_rw(n)
+register int n;
+{
+       if (hilo) {
+               *relp++ = hibyte(n);
+               *relp++ = lobyte(n);
+       } else {
+               *relp++ = lobyte(n);
+               *relp++ = hibyte(n);
+       }
+}
+
+/*)Function    VOID    out_tw(n)
+ *
+ *             int     n               data word
+ *
+ *     The function out_tw() outputs the text (T)
+ *     data word as two bytes ordered according to hilo.
+ *
+ *     local variables:
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             int     lobyte()        asout.c
+ *             int     hibyte()        asout.c
+ *
+ *     side effects:
+ *             Pointer to relocation buffer incremented by 2.
+ */
+
+VOID
+out_tw(n)
+register int n;
+{
+       if (hilo) {
+               *txtp++ = hibyte(n);
+               *txtp++ = lobyte(n);
+       } else {
+               *txtp++ = lobyte(n);
+               *txtp++ = hibyte(n);
+       }
+}
+
+/*)Function    VOID    out_t24(n)
+ *
+ *             int     n               data word
+ *
+ *     The function out_t24() outputs the text (T)
+ *     data word as three bytes ordered according to hilo.
+ *
+ *     local variables:
+ *             int *   txtp            pointer to txt array
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             int     lobyte()        asout.c
+ *             int     hibyte()        asout.c
+ *
+ *     side effects:
+ *             Pointer to relocation buffer incremented by 3.
+ */
+
+VOID
+out_t24(int n)
+{
+       if (hilo) {
+               *txtp++ = byte3(n);
+               *txtp++ = hibyte(n);
+               *txtp++ = lobyte(n);
+       } else {
+               *txtp++ = lobyte(n);
+               *txtp++ = hibyte(n);
+               *txtp++ = byte3(n);
+       }
+}
+
+/*)Function    int     lobyte(n)
+ *
+ *             int     n               data word
+ *
+ *     The function lobyte() returns the lower byte of
+ *     integer n.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+int
+lobyte(n)
+{
+       return (n&0377);
+}
+
+/*)Function    int     hibyte(n)
+ *
+ *             int     n               data word
+ *
+ *     The function hibyte() returns the higher byte of
+ *     integer n.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+int
+hibyte(n)
+{
+       return ((n>>8)&0377);
+}
+
+/*)Function    int     byte3(n)
+ *
+ *             int     n               24 bit data
+ *
+ *     The function byte3() returns the MSB of the
+ *     24 bit integer n.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+int
+byte3(int n)
+{
+       return ((n >> 16) & 0xff);
+}
+
+/*
+ * JLH: Output relocatable 11 bit jump/call
+ *
+ * This function is derived from outrw(), adding the parameter for the
+ * 11 bit address.  This form of address is used only on the 8051 and 8048.
+ */
+VOID
+outr11(esp, op, r)
+register struct expr *esp;
+int op;
+int r;
+{
+       register int n;
+
+       if (pass == 2) {
+               if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+                       /* equated absolute destination.  Assume value
+                         * relative to current area */
+                        esp->e_base.e_ap = dot.s_area;
+               }
+
+                /* Relocatable destination.  Build THREE
+                 * byte output: relocatable word, followed
+                 * by op-code.  Linker will combine them.
+                 * Listing shows only the address.
+                 */
+               r |= R_WORD | esp->e_rlcf;
+                out_lw(esp->e_addr,r|R_RELOC);
+                if (oflag) {
+                        outchk(3, 5);
+                        out_tw(esp->e_addr);
+                        *txtp++ = op;
+
+                        if (esp->e_flag) {
+                                n = esp->e_base.e_sp->s_ref;
+                                r |= R_SYM;
+                        } else {
+                                n = esp->e_base.e_ap->a_ref;
+                        }
+                        write_rmode(r);
+                        *relp++ = txtp - txt - 3;
+                        out_rw(n);
+                }
+       }
+       dot.s_addr += 2;
+}
+
+/*
+ * Output relocatable 19 bit jump/call
+ *
+ * This function is derived from outrw(), adding the parameter for the
+ * 19 bit address.  This form of address is used only in the DS80C390
+ * Flat24 mode.
+ */
+VOID
+outr19(struct expr * esp, int op, int r)
+{
+       register int n;
+
+       if (pass == 2) {
+               if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+                       /* equated absolute destination.  Assume value
+                         * relative to current area */
+                        esp->e_base.e_ap = dot.s_area;
+               }
+
+                /* Relocatable destination.  Build FOUR
+                 * byte output: relocatable 24-bit entity, followed
+                 * by op-code.  Linker will combine them.
+                 * Listing shows only the address.
+                 */
+               r |= R_WORD | esp->e_rlcf;
+                out_l24(esp->e_addr,r|R_RELOC);
+                if (oflag) {
+                        outchk(4, 5);
+                        out_t24(esp->e_addr);
+                        *txtp++ = op;
+                        
+                        if (esp->e_flag) {
+                                n = esp->e_base.e_sp->s_ref;
+                                r |= R_SYM;
+                        } else {
+                                n = esp->e_base.e_ap->a_ref;
+                        }
+                        write_rmode(r);
+                        *relp++ = txtp - txt - 4;
+                        out_rw(n);
+                }
+       }
+       dot.s_addr += 3;
+}
diff --git a/as/hc08/asstore.c b/as/hc08/asstore.c
new file mode 100644 (file)
index 0000000..947c7b8
--- /dev/null
@@ -0,0 +1,44 @@
+/* strstore.c */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*
+ * Allocate space for "str", copy str into new space
+ * Return a pointer to the allocated name, or NULL if out of memory
+ */
+char *StoreString( char *str )
+{
+   /* To avoid wasting memory headers on small allocations, we
+   /  allocate a big chunk and parcel it out as required.
+   /  These static variables remember our hunk
+   */
+   #define STR_STORE_HUNK 2000
+   static char *pNextFree = NULL;
+   static int  bytesLeft = 0;
+   
+   int  length;
+   char *pStoredString;
+   
+   length = strlen( str ) + 1; /* what we need, including null */
+
+   if (length > bytesLeft)
+   {
+      /* no space.  Allocate a new hunk.  We lose the pointer to any
+      /  old hunk.  We don't care, as the names are never deleted.
+      */
+      pNextFree = (char*)new( STR_STORE_HUNK );
+      bytesLeft = STR_STORE_HUNK;
+   }
+
+   /* Copy the name and terminating null into the name store */
+   pStoredString = pNextFree;
+   memcpy( pStoredString, str, length );
+
+   pNextFree += length;
+   bytesLeft -= length;
+
+   return pStoredString;
+}
diff --git a/as/hc08/assubr.c b/as/hc08/assubr.c
new file mode 100644 (file)
index 0000000..1751c29
--- /dev/null
@@ -0,0 +1,275 @@
+/* assubr.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module      assubr.c
+ *
+ *     The module assubr.c contains the error
+ *     processing routines.
+ *
+ *     assubr.c contains the following functions:
+ *             VOID    aerr()
+ *             VOID    diag()
+ *             VOID    err()
+ *             VOID    qerr()
+ *             VOID    rerr()
+ *
+ *     assubr.c contains the local array of *error[]
+ */
+
+/*)Function    VOID    err(c)
+ *
+ *             int     c               error type character
+ *
+ *     The function err() logs the error code character
+ *     suppressing duplicate errors.  If the error code
+ *     is 'q' then the parse of the current assembler-source
+ *     text line is terminated.
+ *
+ *     local variables:
+ *             char *  p               pointer to the error array
+ *
+ *     global variables:
+ *             char    eb[]            array of generated error codes
+ *
+ *     functions called:
+ *             VOID    longjmp()       c_library
+ *
+ *     side effects:
+ *             The error code may be inserted into the
+ *             error code array eb[] or the parse terminated.
+ */
+
+VOID
+err(c)
+register int c;
+{
+       register char *p;
+
+       aserr++;
+       p = eb;
+       while (p < ep)
+               if (*p++ == c)
+                       return;
+       if (p < &eb[NERR]) {
+               *p++ = c;
+               ep = p;
+       }
+       if (c == 'q')
+               longjmp(jump_env, -1);
+}
+
+/*)Function    VOID    diag()
+ *
+ *     The function diag() prints any error codes and
+ *     the source line number to the stderr output device.
+ *
+ *     local variables:
+ *             char *  p               pointer to error code array eb[]
+ *
+ *     global variables:
+ *             int     cfile           current source file index
+ *             char    eb[]            array of generated error codes
+ *             char *  ep              pointer into error list
+ *             int     incfile         current include file index
+ *             char    incfn[]         array of include file names
+ *             int     incline[]       array of include line numbers
+ *             char    srcfn[]         array of source file names
+ *             int     srcline[]       array of source line numbers
+ *             FILE *  stderr          c_library
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             char *  geterr()        assubr.c
+ *
+ *     side effects:
+ *             none
+ */
+
+extern int fatalErrors;
+
+VOID
+diag()
+{
+       register char *p,*errstr;
+
+       if (eb != ep) {
+               fatalErrors++;
+               p = eb;
+               fprintf(stderr, "?ASxxxx-Error-<");
+               while (p < ep) {
+                       fprintf(stderr, "%c", *p++);
+               }
+               fprintf(stderr, "> in line ");
+               if (incfil >= 0) {
+                       fprintf(stderr, "%d", incline[incfil]);
+                       fprintf(stderr, " of %s\n", incfn[incfil]);
+               } else {
+                       fprintf(stderr, "%d", srcline[cfile]);
+                       fprintf(stderr, " of %s\n", srcfn[cfile]);
+               }
+               p = eb;
+               while (p < ep) {
+                       if ((errstr = geterr(*p++)) != NULL) {
+                               fprintf(stderr, "              %s\n", errstr);
+                       }
+               }
+       }
+}
+
+/*)Function    VOID    warnBanner()
+ *
+ *     The function warnBanner() prints a generic warning message
+ *     header (including the current source file/line) and positions
+ *     the output for a more specific warning message.
+ *
+ *     It is assumed that the call to warnBanner will be followed with
+ *     a fprintf to stderr (or equivalent) with the specific warning
+ *     text.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int     cfile           current source file index
+ *             int     incfile         current include file index
+ *             char    incfn[]         array of include file names
+ *             int     incline[]       array of include line numbers
+ *             char    srcfn[]         array of source file names
+ *             int     srcline[]       array of source line numbers
+ *             FILE *  stderr          c_library
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             none
+ */
+VOID
+warnBanner(void)
+{
+       fprintf(stderr, "?ASxxxx-Warning in line ");
+       if (incfil >= 0) {
+               fprintf(stderr, "%d", incline[incfil]);
+               fprintf(stderr, " of %s\n", incfn[incfil]);
+       } else {
+               fprintf(stderr, "%d", srcline[cfile]);
+               fprintf(stderr, " of %s\n", srcfn[cfile]);
+       }
+       fprintf(stderr, "               ");
+}      
+
+/*)Functions:  VOID    aerr()
+ *             VOID    qerr()
+ *             VOID    rerr()
+ *
+ *     The functions aerr(), qerr(), and rerr() report their
+ *     respective error type.  These are included only for
+ *     convenience.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             VOID    err()           assubr.c
+ *
+ *     side effects:
+ *             The appropriate error code is inserted into the
+ *             error array and the parse may be terminated.
+ */
+
+/*
+ * Note an 'r' error.
+ */
+VOID
+rerr()
+{
+       err('r');
+}
+
+/*
+ * Note an 'a' error.
+ */
+VOID
+aerr()
+{
+       err('a');
+}
+
+/*
+ * Note a 'q' error.
+ */
+VOID
+qerr()
+{
+       err('q');
+}
+
+/*
+ * ASxxxx assembler errors
+ */
+char *errors[] = {
+       "<.> use \". = . + <arg>\" not \". = <arg>\"",
+       "<a> machine specific addressing or addressing mode error",
+       "<b> direct page boundary error",
+       "<d> direct page addressing error",
+       "<i> .include file error or an .if/.endif mismatch",
+       "<m> multiple definitions error",
+       "<o> .org in REL area or directive / mnemonic error",
+       "<p> phase error: label location changing between passes 2 and 3",
+       "<q> missing or improper operators, terminators, or delimiters",
+       "<r> relocation error",
+       "<u> undefined symbol encountered during assembly",
+       NULL
+};
+       
+/*)Function:   char    *getarr(c)
+ *
+ *             int     c               the error code character
+ *
+ *     The function geterr() scans the list of errors returning the
+ *     error string corresponding to the input error character.
+ *
+ *     local variables:
+ *             int     i               error index counter
+ *
+ *     global variables:
+ *             char    *errors[]       array of pointers to the
+ *                                     error strings
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             A pointer to the appropriate
+ *             error code string is returned.
+ */
+char *
+geterr(c)
+int c;
+{
+       int     i;
+
+       for (i=0; errors[i]!=NULL; i++) {
+               if (c == errors[i][1]) {
+                       return(errors[i]);
+               }
+       }
+       return(NULL);
+}
+
diff --git a/as/hc08/assym.c b/as/hc08/assym.c
new file mode 100644 (file)
index 0000000..6f504de
--- /dev/null
@@ -0,0 +1,441 @@
+/* assym.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - lookup: Use StoreString for sym construction
+ *          - change symeq() to do length-independent string compare
+ *          - change hash() to do length-independent hash calculation
+ * 29-Oct-97 JLH:
+ *           - make mnemonics case insensitive ALWAYS
+ *           - make hash() case-insensitive always
+ *           - replace symeq() call in mlookup with strcmpi
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <alloc.h>
+#endif
+#include "asm.h"
+#include "strcmpi.h"
+
+/*)Module      assym.c
+ *
+ *     The module assym.c contains the functions that operate
+ *     on the mnemonic/directive and symbol structures.
+ *
+ *     assym.c contains the following functions:
+ *             VOID    allglob()
+ *             area *  alookup()
+ *             int     hash()
+ *             sym *   lookup()
+ *             mne *   mlookup()
+ *             VOID *  new()
+ *             int     symeq()
+ *             VOID    syminit()
+ *             VOID    symglob()
+ *
+ *     assym.c contains no local/static variables.
+ */
+
+/*)Function    VOID    syminit()
+ *
+ *     The function syminit() is called early in the game
+ *     to set up the hashtables.  First all buckets in a
+ *     table are cleared.  Then a pass is made through
+ *     the respective symbol lists, linking them into
+ *     their hash buckets.  Finally the base area pointer
+ *     is set to 'dca'.
+ *
+ *     local variables:
+ *             int     h               computed hash value
+ *             mne *   mp              pointer to a mne structure
+ *             mne **  mpp             pointer to an array of
+ *                                     mne structure pointers
+ *             sym *   sp              pointer to a sym structure
+ *             sym **  spp             pointer to an array of
+ *                                     sym structure pointers
+ *
+ *     global variables:
+ *             area    area[]          single elememt area array
+ *             area    dca             defined as area[0]
+ *             mne * mnehash[]         array of pointers to NHASH
+ *                                     linked mnemonic/directive lists
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             (1)     The symbol hash tables are initialized,
+ *                     the only defined symbol is '.'.
+ *             (2)     The mnemonic/directive hash tables are
+ *                     initialized with the assembler directives
+ *                     and mnemonics found in the machine dependent
+ *                     file ___pst.c.
+ *             (3)     The area pointer is initialized to dca (area[0]).
+ */
+
+VOID
+syminit()
+{
+       register struct mne  *mp;
+       struct mne **mpp;
+       register struct sym  *sp;
+       struct sym **spp;
+       register int h;
+
+       mpp = &mnehash[0];
+       while (mpp < &mnehash[NHASH])
+               *mpp++ = NULL;
+       mp = &mne[0];
+       for (;;) {
+               h = hash(mp->m_id);
+               mp->m_mp = mnehash[h];
+               mnehash[h] = mp;
+               if (mp->m_flag&S_END)
+                       break;
+               ++mp;
+       }
+
+       spp = &symhash[0];
+       while (spp < &symhash[NHASH])
+               *spp++ = NULL;
+       sp = &sym[0];
+       for (;;) {
+               h = hash(sp->s_id);
+               sp->s_sp = symhash[h];
+               symhash[h] = sp;
+               if (sp->s_flag&S_END)
+                       break;
+               ++sp;
+       }
+
+       areap = &dca;
+}
+
+/*)Function    area *  alookup(id)
+ *
+ *             char *  id              area name string
+ *
+ *     The function alookup() searches the area list for a
+ *     match with id.  If the area is defined then a pointer
+ *     to this area is returned else a NULL is returned.
+ *
+ *     local variables:
+ *             area *  ap              pointer to area structure
+ *
+ *     global variables:
+ *             area *  areap           pointer to an area structure
+ *
+ *     functions called:
+ *             int     symeq()         assym.c
+ *
+ *     side effects:
+ *             none
+ */
+
+struct area *
+alookup(id)
+char *id;
+{
+       register struct area *ap;
+
+       ap = areap;
+       while (ap) {
+               if (symeq(id, ap->a_id)) {
+                       return (ap);
+               }
+               ap = ap->a_ap;
+       }
+       return(NULL);
+}
+
+/*)Function    mne *   mlookup(id)
+ *
+ *             char *  id              mnemonic/directive name string
+ *
+ *     The function mlookup() searches the mnemonic/directive
+ *     hash tables for a match returning a pointer to the
+ *     mne structure else it returns a NULL.
+ *
+ *     local variables:
+ *             mne *   mp              pointer to mne structure
+ *             int     h               calculated hash value
+ *
+ *     global variables:
+ *             mne * mnehash[]         array of pointers to NHASH
+ *                                     linked mnemonic/directive lists
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+struct mne *
+mlookup(id)
+char *id;
+{
+       register struct mne *mp;
+       register int h;
+
+       h = hash(id);
+       mp = mnehash[h];
+       while (mp) {
+               if (as_strcmpi(id, mp->m_id) == 0)      /* JLH: case insensitive */
+                       return (mp);
+               mp = mp->m_mp;
+       }
+       return (NULL);
+}
+
+/*)Function    sym *   lookup(id)
+ *
+ *             char *  id              symbol name string
+ *
+ *     The function lookup() searches the symbol hash tables for
+ *     a symbol name match returning a pointer to the sym structure.
+ *     If the symbol is not found then a sym structure is created,
+ *     initialized, and linked to the appropriate hash table.
+ *     A pointer to this new sym structure is returned.
+ *
+ *     local variables:
+ *             int     h               computed hash value
+ *             sym *   sp              pointer to a sym structure
+ *
+ *     global varaibles:
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             int     hash()          assym.c
+ *             VOID *  new()           assym.c
+ *             int     symeq()         assym.c
+ *
+ *     side effects:
+ *             If the function new() fails to allocate space
+ *             for the new sym structure the assembly terminates.
+ */
+
+struct sym *
+lookup(id)
+char *id;
+{
+       register struct sym *sp;
+       register int h;
+
+       h = hash(id);
+       sp = symhash[h];
+       while (sp) {
+               if (symeq(id, sp->s_id))
+                       return (sp);
+               sp = sp->s_sp;
+       }
+       sp = (struct sym *) new (sizeof(struct sym));
+       sp->s_sp = symhash[h];
+       symhash[h] = sp;
+       sp->s_tsym = NULL;
+       sp->s_id = StoreString( id ); /* JLH */
+       sp->s_type = S_NEW;
+       sp->s_flag = 0;
+       sp->s_area = NULL;
+       sp->s_ref = 0;
+       sp->s_addr = 0;
+       return (sp);
+}
+
+/*)Function    VOID    symglob()
+ *
+ *     The function symglob() will mark all symbols of
+ *     type S_NEW as global.  Called at the beginning of pass 1
+ *     if the assembly option -g was specified.
+ *
+ *     local variables:
+ *             sym *   sp              pointer to a sym structure
+ *             int     i               loop index
+ *
+ *     global variables:
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             Symbol types changed.
+ */
+
+VOID
+symglob()
+{
+       register struct sym *sp;
+       register int i;
+
+       for (i=0; i<NHASH; ++i) {
+               sp = symhash[i];
+               while (sp != NULL) {
+                       if (sp->s_type == S_NEW)
+                               sp->s_flag |= S_GBL;
+                       sp = sp->s_sp;
+               }
+       }
+}
+
+/*)Function    VOID    allglob()
+ *
+ *     The function allglob() will mark all symbols of
+ *     type S_USER as global.  Called at the beginning of pass 1
+ *     if the assembly option -a was specified.
+ *
+ *     local variables:
+ *             sym *   sp              pointer to a sym structure
+ *             int     i               loop index
+ *
+ *     global variables:
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             Symbol types changed.
+ */
+
+VOID
+allglob()
+{
+       register struct sym *sp;
+       register int i;
+
+       for (i=0; i<NHASH; ++i) {
+               sp = symhash[i];
+               while (sp != NULL) {
+                       if (sp != &dot && sp->s_type == S_USER)
+                               sp->s_flag |= S_GBL;
+                       sp = sp->s_sp;
+               }
+       }
+}
+
+/*)Function    int     symeq(p1, p2)
+ *
+ *             char *  p1              name string
+ *             char *  p2              name string
+ *
+ *     The function symeq() compares the two name strings for a match.
+ *     The return value is 1 for a match and 0 for no match.
+ *
+ *     local variables:
+ *             int     h               loop counter
+ *
+ *     global variables:
+ *             char    ccase[]         an array of characters which
+ *                                     perform the case translation function
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ *
+ */
+
+int
+symeq(p1, p2)
+register char *p1, *p2;
+{
+#if    CASE_SENSITIVE
+               return (strcmp( p1, p2 ) == 0);
+#else
+               return (as_strcmpi( p1, p2 ) == 0);
+#endif
+}
+
+/*)Function    int     hash(p)
+ *
+ *             char *  p               pointer to string to hash
+ *
+ *     The function hash() computes a hash code using the sum
+ *     of all characters mod table size algorithm.
+ *
+ *     local variables:
+ *             int     h               accumulated character sum
+ *             int     n               loop counter
+ *
+ *     global variables:
+ *             char    ccase[]         an array of characters which
+ *                                     perform the case translation function
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+int
+hash(p)
+register char *p;
+{
+       register int h;
+
+       h = 0;
+       while (*p) {
+               /* JLH: case insensitive hash:  Doesn't much affect
+                 * hashing, and allows same function for mnemonics and symbols
+                 */
+               h += ccase[(int)*p++];
+       }
+       return (h&HMASK);
+}
+
+/*)Function    VOID *  new(n)
+ *
+ *             unsigned int    n       allocation size in bytes
+ *
+ *     The function new() allocates n bytes of space and returns
+ *     a pointer to this memory.  If no space is available the
+ *     assembly is terminated.
+ *
+ *     local variables:
+ *             VOID *  p               a general pointer
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             VOID    asexit()        asmain.c
+ *             int     fprintf()       c_library
+ *             VOID *  malloc()        c_library
+ *
+ *     side effects:
+ *             Memory is allocated, if allocation fails
+ *             the assembly is terminated.
+ */
+
+VOID *
+new(n)
+unsigned int n;
+{
+       register VOID *p;
+
+       if ((p = (VOID *) malloc(n)) == NULL) {
+               fprintf(stderr, "Out of space!\n");
+               asexit(1);
+       }
+       return (p);
+}
diff --git a/as/hc08/clean.mk b/as/hc08/clean.mk
new file mode 100644 (file)
index 0000000..27e35fa
--- /dev/null
@@ -0,0 +1,26 @@
+# Deleting all files created by building the program
+# --------------------------------------------------
+include ../../Makefile.common
+PRJDIR = ../..
+
+clean:
+       rm -f *core *[%~] *.[oa]
+       rm -f .[a-z]*~
+       rm -f $(PRJDIR)/bin/as-hc08$(EXEEXT) $(PRJDIR)/bin/link-hc08$(EXEEXT) as-hc08$(EXEEXT) link-hc08$(EXEEXT)
+
+
+# Deleting all files created by configuring or building the program
+# -----------------------------------------------------------------
+distclean: clean
+       rm -f Makefile *.dep
+
+
+# Like clean but some files may still exist
+# -----------------------------------------
+mostlyclean: clean
+
+
+# Deleting everything that can reconstructed by this Makefile. It deletes
+# everything deleted by distclean plus files created by bison, etc.
+# -----------------------------------------------------------------------
+realclean: distclean
diff --git a/as/hc08/conf.mk b/as/hc08/conf.mk
new file mode 100644 (file)
index 0000000..879e9bc
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile targets to remake configuration
+#
+
+freshconf: Makefile
+
+Makefile: $(srcdir)/Makefile.in $(PRJDIR)/configure.in
+       cd $(PRJDIR) && $(SHELL) ./config.status
+
+# End of conf.mk
diff --git a/as/hc08/lkaomf51.c b/as/hc08/lkaomf51.c
new file mode 100644 (file)
index 0000000..fa009e7
--- /dev/null
@@ -0,0 +1,980 @@
+/*-------------------------------------------------------------------------
+  lkaomf51.c - Create an absolute object memory format 51 file
+
+   Written By -  Jesus Calvino-Fraga, jesusc@ieee.org (2002)
+
+   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.
+-------------------------------------------------------------------------*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+#define EQ(A,B) !strcmp((A),(B))
+#define MEMSIZE 0x10000
+//#define DODUMP 1
+
+typedef struct
+{
+       char PathName[PATH_MAX];
+       char ModuleName[PATH_MAX];
+} _infn;
+
+int numin=0;
+_infn * infn=NULL;
+
+char ihxFileName[PATH_MAX];
+char aomf51FileName[PATH_MAX];
+
+typedef struct
+{
+   char name[0x100];
+   int FileNameNumber;
+   int Procedure;//If the symbol belongs to a function
+   int Static; //If the symbol is only public on its file
+   int Address;
+   int UsageType;
+} _symbol;
+
+int numsym=0;
+_symbol * symbol=NULL;
+
+typedef struct
+{
+   char name[0x100];
+   int FileNameNumber;
+   int BeginAdd;
+   int EndAdd;
+} _procedure;
+
+int numproc=0;
+_procedure * procedure=NULL;
+
+typedef struct
+{
+   int Number;
+   int Address;
+   int Procedure;
+   int FileNameNumber;
+} _linenum;
+
+int numlinenum=0;
+_linenum * linenum=NULL;
+
+typedef struct
+{
+       char * name;
+       int usage;
+}
+_UsageType;
+
+_UsageType UsageType[]=
+{
+       {"CSEG",                0},
+       {"GSINIT",              0},
+       {"GSFINAL",             0},
+       {"HOME",                0},
+       {"XINIT",               0},
+       {"XSEG",                1},
+       {"XISEG",               1},
+       {"REG_BANK_0",  2},
+       {"REG_BANK_1",  2},
+       {"REG_BANK_2",  2},
+       {"REG_BANK_3",  2},
+       {"DSEG",                2},
+       {"OSEG",                2},
+       {"SSEG",                2},
+       {"ISEG",                3},
+       {"BSEG",                4},
+       {"",                    5} /*A typeless number?*/
+};
+
+char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"};
+int AddNumber;
+unsigned char * ihxBuff=NULL;
+FILE * aomf51out;
+int GlobalChkSum=0;
+int HexSize, HexBegin=0x10000;
+
+
+void GetName(char * filepath, char * name)
+{
+       int j, k;
+       for(j=strlen(filepath); j>0; j--)
+               if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break;
+       for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++)
+               name[k]=filepath[j];
+       name[k]=0;
+}
+
+void SaveLinkedFilePath(char * filepath) 
+{
+       int j;
+
+       if((dflag) && (!rflag))
+       {
+               infn=realloc(infn, sizeof(_infn)*(numin+1));
+
+               strcpy(infn[numin].PathName, filepath);
+               j=strlen(infn[numin].PathName);
+               
+               /*If there is an extension remove it*/
+               if(j>=4)
+               {
+                       if(EQ(&infn[numin].PathName[j-4], ".rel"))
+                       {
+                               infn[numin].PathName[j-4]=0;
+                       }
+               }
+
+               /*Get the module name=filename, no drive, no dir, no ext*/
+               GetName(infn[numin].PathName, infn[numin].ModuleName);
+               //printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName);
+               
+               /*Check if this filename is already in*/
+               for(j=0; j<numin; j++)
+               {
+                       if(EQ(infn[numin].PathName, infn[j].PathName)) break;
+               }
+               if(j==numin) numin++;
+       }
+}
+
+void FreeAll(void)
+{
+       if(infn!=NULL)
+       {
+               free(infn);
+               numin=0;
+               infn=NULL;
+       }
+
+       if(symbol!=NULL)
+       {
+               free(symbol);
+               numsym=0;
+               symbol=NULL;
+       }
+
+       if(procedure!=NULL)
+       {
+               free(procedure);
+               numproc=0;
+               procedure=NULL;
+
+       }
+       if(linenum!=NULL)
+       {
+               free(linenum);
+               numlinenum=0;
+               linenum=NULL;
+       }
+
+       if(ihxBuff!=NULL)
+       {
+               free(ihxBuff);
+               ihxBuff=NULL;
+       }
+}
+
+void OutputByte(unsigned char value)
+{
+       GlobalChkSum+=value;
+       fwrite( &value, 1, 1, aomf51out );
+}
+
+void OutputWord(int value)
+{
+       OutputByte((unsigned char)(value%0x100));
+       OutputByte((unsigned char)(value/0x100));
+}
+
+void OutputName(char * name)
+{
+       int k;
+       OutputByte((unsigned char)strlen(name));
+       for(k=0; name[k]!=0; k++)
+               OutputByte((unsigned char)toupper(name[k]));
+}
+
+void OutputChkSum(void)
+{
+       OutputByte((unsigned char)(0x100-(GlobalChkSum%0x100)));
+       GlobalChkSum=0;
+}
+
+#ifdef DODUMP
+void DumpForDebug (void)
+{
+       char DumpFileName[PATH_MAX];
+       FILE * DumpFile;
+       int j, k;
+
+       strcpy(DumpFileName, infn[0].PathName);
+       strcat(DumpFileName, ".d51");
+
+       DumpFile=fopen(DumpFileName, "wb");
+       if(DumpFile==NULL)
+       {
+               printf("Couldn't create file %s\n", DumpFileName);
+               return;
+       }
+
+       fprintf(DumpFile,"SYMBOLS:\n");
+
+       for(j=0; j<numsym; j++)
+       {
+               k=symbol[j].UsageType&0xf;
+               fprintf(DumpFile, "%s, %s, %s, 0x%04x, %s\n",
+                       symbol[j].name,
+                       infn[symbol[j].FileNameNumber].PathName,
+                       (symbol[j].Procedure>=0)?procedure[symbol[j].Procedure].name:"GLOBAL",
+                       symbol[j].Address,
+                       k<6?UsageTypeName[k]:"???");
+       }
+       
+       fprintf(DumpFile,"\nPROCEDURES:\n");
+       for(j=0; j<numproc; j++)
+       {
+               fprintf(DumpFile, "%s, %s, 0x%04x-0x%04x\n",
+                       procedure[j].name,
+                       infn[procedure[j].FileNameNumber].PathName,
+                       procedure[j].BeginAdd,
+                       procedure[j].EndAdd);
+       }
+
+       fprintf(DumpFile,"\nLINE NUMBERS:\n");
+       for(j=0; j<numlinenum; j++)
+       {
+               fprintf(DumpFile, "%d:0x%04x, %s -> %s\n",
+                       linenum[j].Number,
+                       linenum[j].Address,
+                       infn[linenum[j].FileNameNumber].PathName,
+                       (linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know");
+       }
+
+       fclose(DumpFile);
+}
+#endif
+
+void OutputAOEMF51(void)
+{
+       int i, j, k, recsize;
+       char MHRname[0x100], Mname[0x100];
+
+       strcpy(aomf51FileName, infn[0].PathName);
+
+       aomf51out=fopen(aomf51FileName, "wb");
+       if(aomf51out==NULL)
+       {
+               printf("Couldn't create file %s\n", aomf51FileName);
+               return;
+       }
+
+       GetName(infn[0].PathName, MHRname);
+       GlobalChkSum=0;
+       
+       /*Module header record*/
+       OutputByte(0x02);/*REC TYPE*/
+       OutputWord((strlen(MHRname)+1)+3);/*Record Length*/
+       OutputName(MHRname);/*Module Name*/
+       OutputByte(0xff);/*TRN ID: RL51?*/
+       OutputByte(0x00);
+       OutputChkSum();
+
+       for(j=0; j<numin; j++)
+       {
+               GetName(infn[j].PathName, Mname);
+
+               /*Scope Definition record: begin module block*/
+               OutputByte(0x10);/*REC TYPE*/
+               OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+               OutputByte(0x00);/*BLK TYP: module block*/
+               OutputName(Mname);/*Module Name*/
+               OutputChkSum();
+
+               /*Public symbols defined in this module*/
+               recsize=2;
+               for(k=0; k<numsym; k++)/*Compute the record length*/
+                       if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+                                (symbol[k].Procedure==-1) &&
+                                (symbol[k].Static==-1) ) recsize+=((strlen(symbol[k].name)+1)+5);
+
+               if(recsize>2) /*If there are any symbols*/
+               {
+                       OutputByte(0x12);       /*REC TYPE*/
+                       OutputWord(recsize);/*Record Length*/
+                       OutputByte(0x01);       /*DEF TYPE: Public symbols*/
+                       for(k=0; k<numsym; k++)
+                       {
+                               if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+                                        (symbol[k].Procedure==-1) &&
+                                        (symbol[k].Static==-1) )
+                               {
+                                       OutputByte(0x00);/*SEG ID*/
+                                       OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
+                                       OutputWord(symbol[k].Address);/*Offset*/
+                                       OutputByte(0x00);
+                                       OutputName(symbol[k].name);/*Symbol name*/
+                               }
+                       }
+                       OutputChkSum();
+               }
+
+               /*Local symbols defined in this module*/
+               recsize=2;
+               for(k=0; k<numsym; k++)/*Compute the record length*/
+                       if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+                                (symbol[k].Procedure==-1) &&
+                                (symbol[k].Static==j) ) recsize+=((strlen(symbol[k].name)+1)+5);
+
+               if(recsize>2) /*If there are any symbols*/
+               {
+                       OutputByte(0x12);       /*REC TYPE*/
+                       OutputWord(recsize);/*Record Length*/
+                       OutputByte(0x00);       /*DEF TYPE: Local symbols*/
+                       for(k=0; k<numsym; k++)
+                       {
+                               if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+                                        (symbol[k].Procedure==-1) &&
+                                        (symbol[k].Static==j) )
+                               {
+                                       OutputByte(0x00);/*SEG ID*/
+                                       OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
+                                       OutputWord(symbol[k].Address);/*Offset*/
+                                       OutputByte(0x00);
+                                       OutputName(symbol[k].name);/*Symbol name*/
+                               }
+                       }
+                       OutputChkSum();
+               }
+
+               /*Output the procedures of this module*/
+
+               for(k=0; k<numproc; k++)
+               {
+                       if(procedure[k].FileNameNumber==j)
+                       {
+                               /*Scope Definition record: begin PROCEDURE block*/
+                               OutputByte(0x10);/*REC TYPE*/
+                               OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
+                               OutputByte(0x02);/*BLK TYP: PROCEDURE block*/
+                               OutputName(procedure[k].name);/*Module Name*/
+                               OutputChkSum();
+
+                               /*Content Record*/
+                               OutputByte(0x06);/*REC TYPE*/
+                               if(procedure[k].EndAdd==-1) procedure[k].EndAdd=HexSize;
+                               recsize=procedure[k].EndAdd-procedure[k].BeginAdd+1+4;
+                               OutputWord(recsize);/*Record Length*/
+                               OutputByte(0x00);/*SEG ID*/
+                               OutputWord(procedure[k].BeginAdd); /*Offset*/
+                               for(i=procedure[k].BeginAdd; i<=procedure[k].EndAdd; i++)
+                                       OutputByte(ihxBuff[i]);
+                               OutputChkSum();
+
+                               /*Local Symbols*/
+                               
+                               recsize=2;
+                               for(i=0; i<numsym; i++)/*Get the record length*/
+                                       if(symbol[i].Procedure==k)
+                                               recsize+=((strlen(symbol[i].name)+1)+5);
+
+                               if(recsize>2) /*If there are any symbols*/
+                               {
+                                       OutputByte(0x12);       /*REC TYPE*/
+                                       OutputWord(recsize);/*Record Length*/
+                                       OutputByte(0x00);       /*DEF TYPE: Local symbols*/
+                                       for(i=0; i<numsym; i++)
+                                       {
+                                               if ( (symbol[i].Procedure==k) )
+                                               {
+                                                       OutputByte(0x00);/*SEG ID*/
+                                                       OutputByte((unsigned char)symbol[i].UsageType);/*SYM INFO*/
+                                                       OutputWord(symbol[i].Address);/*Offset*/
+                                                       OutputByte(0x00);
+                                                       OutputName(symbol[i].name);/*Symbol name*/
+                                               }
+                                       }
+                                       OutputChkSum();
+                               }
+
+                               /*Line Numbers*/
+                               recsize=2;
+                               for(i=0; i<numlinenum; i++)/*Get the record length*/
+                                       if(linenum[i].Procedure==k) recsize+=5;
+                               
+                               if(recsize>2) /*If there are any line numbers*/
+                               {
+                                       OutputByte(0x12);       /*REC TYPE*/
+                                       OutputWord(recsize);/*Record Length*/
+                                       OutputByte(0x03);       /*DEF TYPE: Line numbers*/
+                                       for(i=0; i<numlinenum; i++)
+                                       {
+                                               if ( (linenum[i].Procedure==k) )
+                                               {
+                                                       OutputByte(0x00);/*SEG ID*/
+                                                       OutputWord(linenum[i].Address);/*Offset*/
+                                                       OutputWord(linenum[i].Number);/*Line Number*/
+                                               }
+                                       }
+                                       OutputChkSum();
+                               }
+                       
+                               /*Scope Definition record: end PROCEDURE block*/
+                               OutputByte(0x10);/*REC TYPE*/
+                               OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
+                               OutputByte(0x05);/*BLK TYP: PROCEDURE end block*/
+                               OutputName(procedure[k].name);/*Module Name*/
+                               OutputChkSum();
+                       }
+               }
+
+               /*Scope Definition record: end module block*/
+               OutputByte(0x10);/*REC TYPE*/
+               OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+               OutputByte(0x03);/*BLK TYP: module end*/
+               OutputName(Mname);/*Module Name*/
+               OutputChkSum();
+       }
+
+       /*Content records for everything that is not in the above procedures*/
+       strcpy(Mname, "OTHER_SDCC_STUF");
+
+       /*Scope Definition record: begin module block*/
+       OutputByte(0x10);/*REC TYPE*/
+       OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+       OutputByte(0x00);/*BLK TYP: module block*/
+       OutputName(Mname);/*Module Name*/
+       OutputChkSum();
+
+       for(j=-1; j<numproc; j++)
+       {
+               if(numproc)
+               {
+                       if(j==-1)
+                       {
+                               i=HexBegin;
+                               k=procedure[0].BeginAdd;
+                       }
+                       else if(j==(numproc-1))
+                       {
+                               i=procedure[j].EndAdd+1;
+                               k=HexSize;
+                       }
+                       else
+                       {
+                               i=procedure[j].EndAdd+1;
+                               k=procedure[j+1].BeginAdd;
+                       }
+               }
+               else /*What, no procedures??? Ok, here it is the whole hex file*/
+               {
+                       i=HexBegin;
+                       k=HexSize;
+               }
+
+               if(i<k)
+               {
+                       /*Content Record*/
+                       OutputByte(0x06);/*REC TYPE*/
+                       OutputWord(k-i+4);/*Record Length*/
+                       OutputByte(0x00);/*SEG ID*/
+                       OutputWord(i); /*Offset*/
+                       for(; i<k; i++) OutputByte(ihxBuff[i]);
+                       OutputChkSum();
+               }
+       }
+       
+       /*Scope Definition record: end module block*/
+       OutputByte(0x10);/*REC TYPE*/
+       OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+       OutputByte(0x03);/*BLK TYP: module end*/
+       OutputName(Mname);/*Module Name*/
+       OutputChkSum();
+
+       /*Module end record*/
+       OutputByte(0x04);/*REC TYPE*/
+       OutputWord((strlen(MHRname)+1)+5);/*Record Length*/
+       OutputName(MHRname);/*Module Name*/
+       OutputWord(0x00);
+       OutputByte(0x0f);/*REG MSK: All the register banks?*/
+       OutputByte(0x00);
+       OutputChkSum();
+
+       fclose(aomf51out);
+}
+
+void CollectInfoFromCDB(void)
+{
+       int i, j, k, CurrentModule;
+       FILE * CDBin;
+       char buff[0x1000];
+       char SourceName[PATH_MAX];
+
+       //"S:{G|F<filename>|L<functionName>}$<name>$<level>$<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>"
+       char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s";
+       char c;
+       char scope[0x100];
+       char name[0x100];
+       char level[0x100];
+       char block[0x100];
+       char Bfmt[]="%[^)] %c %c %c %c %d %c %d";
+       char TypeInfo[0x100];
+       char AddressSpace;
+       int OnStack;
+       int StackOffset;
+       int Address, CLine;
+       
+       if(numin==0) return;
+
+       if (dfp != NULL)
+       {
+               fclose(dfp);
+               dfp=NULL;
+       }
+
+       /*Build the source filename*/
+       strcpy(SourceName, infn[0].PathName);
+       strcat(SourceName, ".cdb");
+       CDBin=fopen(SourceName, "r");
+       if(CDBin==NULL)
+       {
+               printf("Couldn't open file '%s'\n", SourceName);
+               lkexit(1);
+       }
+
+       CurrentModule=0; /*Set the active module as the first one*/
+       while(!feof(CDBin))
+       {
+               fgets(buff, sizeof(buff)-1, CDBin);
+
+               if(!feof(CDBin)) switch(buff[0])
+               {
+                       /*Example: "M:adq"*/
+                       case 'M':
+                               sscanf(&buff[2], "%s", name);
+                               for(j=0; j<numin; j++)
+                                       if(EQ(infn[j].ModuleName, name)) break;
+                               if(j<numin) CurrentModule=j;
+                       break;
+
+                       /* Example:
+                       "S:G$actual$0$0({7}ST__00010000:S),E,0,0"
+                       "S:Lmain$j$1$1({2}SI:S),E,0,0"
+                       "S:G$DS1306_Reset_SPI$0$0({2}DF,SV:S),C,0,0"
+                       "S:G$main$0$0({2}DF,SV:S),C,0,0"
+                       */
+
+                       case 'S':
+                               sscanf(buff, Sfmt,
+                                       scope, &c,
+                                       name, &c,
+                                       level, &c,
+                                       block);
+                               
+                               /*<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>*/
+                               sscanf(block, Bfmt,
+                                          TypeInfo, &c, &c,
+                                          &AddressSpace, &c,
+                                          &OnStack, &c, 
+                                          &StackOffset);
+
+                               i=-1; k=-1;
+                               switch(scope[2])
+                               {
+                                       case 'G': /*Global symbol*/
+                                       break;
+                                       case 'L': /*Local symbol of a procedure*/
+                                               for(j=0; j<numproc; j++)
+                                               {
+                                                       if(EQ(&scope[3], procedure[j].name)) break;
+                                               }
+                                               if(j<numproc) k=j; /*Local symbol*/
+                                       break;
+                                       case 'F': /*Local symbol to a module*/
+                                               for(j=0; j<numin; j++)
+                                               {
+                                                       if(EQ(&scope[3], infn[j].ModuleName)) break;
+                                               }
+                                               if(j<numin) i=j;
+                                       break;
+                               }
+
+                               /*This symbol may have been already defined*/
+                               for(j=0; j<numsym; j++)
+                               {
+                                       if( EQ(name, symbol[j].name) && 
+                                               (symbol[j].Procedure==k) &&
+                                               (symbol[j].Static==i) ) break;
+                               }
+                               if(j==numsym) /*New symbol*/
+                               {
+                                       symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
+                                       symbol[numsym].FileNameNumber=CurrentModule;
+                                       strcpy(symbol[numsym].name, name);
+                                       symbol[numsym].Procedure=k;
+                                       symbol[numsym].Static=i;
+                                       symbol[numsym].Address=-1;/*Collected later*/
+
+                                       switch(AddressSpace)
+                                       {
+                                               case 'C': /*Code*/ 
+                                               case 'D': /*Code/static segment*/ 
+                                               case 'Z': /*Functions and undefined code space*/ 
+                                                       symbol[numsym].UsageType=0x40;
+                                               break;
+
+                                               case 'F': /*External ram*/ 
+                                               case 'A': /*External stack*/
+                                                       symbol[numsym].UsageType=0x41;
+                                               break;
+
+                                               case 'E': /*Internal ram (lower 128) bytes*/ 
+                                               case 'I': /*SFR space*/ 
+                                               case 'R': /*Register Space*/ 
+                                                       symbol[numsym].UsageType=0x42;
+                                               break;
+
+                                               case 'B': /*Internal stack*/ 
+                                               case 'G': /*Internal ram*/ 
+                                                       symbol[numsym].UsageType=0x43;
+                                               break;
+
+                                               case 'H': /*Bit addressable*/ 
+                                               case 'J': /*SBIT space*/ 
+                                                       symbol[numsym].UsageType=0x44;
+                                               break;
+                                               
+                                               default:
+                                                       printf("Unknown scope information for: %s, AddressSpace:%c\n", symbol[numsym].name, AddressSpace);
+                                               break;
+                                       }
+                                       numsym++;
+                               }
+                       break;
+
+                       /*Examples:
+                       F:G$AsciiToHex$0$0({2}DF,SC:U),C,0,0,0,0,0
+                       F:G$main$0$0({2}DF,SV:S),C,0,0,0,0,0   */
+
+                       case 'F':
+                               sscanf(buff, "%[^$] %c %[^$]", scope, &c, name);
+                               /*The same may have been already defined */
+                               for(j=0; j<numproc; j++)
+                               {
+                                       if(EQ(name, procedure[j].name)) break;
+                               }
+                               if(j==numproc)
+                               {
+                                       procedure=realloc(procedure, sizeof(_procedure)*(numproc+1));
+                                       strcpy(procedure[numproc].name, name);
+                                       procedure[numproc].FileNameNumber=CurrentModule;
+                                       procedure[numproc].BeginAdd=-1;/*To be collected latter*/
+                                       procedure[numproc].EndAdd=-1;/*To be collected latter*/
+                                       numproc++;
+                               }
+                               
+                               /*This function name is also a global symbol*/
+                               for(j=0; j<numsym; j++)/*A global symbol may have been already defined*/
+                               {
+                                       if( EQ(name, symbol[j].name) && (symbol[j].Procedure==-1) ) break;
+                               }
+                               if(j==numsym)
+                               {
+                                       symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
+                                       symbol[numsym].FileNameNumber=CurrentModule;
+                                       strcpy(symbol[numsym].name, name);
+                                       symbol[numsym].UsageType=0x00;/*A procedure name symbol*/
+                                       symbol[numsym].Procedure=-1; /*Global symbol*/
+                                       symbol[numsym].Address=-1;/*Collected later*/
+                                       numsym++;
+                               }
+                       break;
+
+                       case 'L':
+                               switch(buff[2])
+                               {
+                                       case 'G': /*Example L:G$P0$0$0:80*/
+                                               sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
+                                                       scope, &c, name, &c, level, &c, &Address);
+
+                                               for(j=0; j<numsym; j++)
+                                               {
+                                                       if(EQ(symbol[j].name, name))
+                                                       {
+                                                               if( (symbol[j].Address==-1) && (symbol[j].Procedure==-1) )
+                                                               {
+                                                                       symbol[j].Address=Address;
+                                                               }
+                                                               
+                                                               /*If the symbol is the name of a procedure, the address is also
+                                                               the begining of such procedure*/
+                                                               if((symbol[j].UsageType&0x0f)==0x00)
+                                                               {
+                                                                       for(k=0; k<numproc; k++)
+                                                                       {
+                                                                               if(EQ(symbol[j].name, procedure[k].name))
+                                                                               {
+                                                                                       if(procedure[k].BeginAdd==-1)
+                                                                                               procedure[k].BeginAdd=Address;
+                                                                                       break;
+                                                                               }
+                                                                       }
+                                                               }
+                                                               
+                                                               break;
+                                                       }
+                                               }
+                                       break;
+                                       
+                                       case 'F': /*Example L:Fadq$_str_2$0$0:57A*/
+                                               sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
+                                                       scope, &c, name, &c, level, &c, &Address);
+                                               
+                                               for(j=0; j<numsym; j++)
+                                               {
+                                                       if(EQ(symbol[j].name, name))
+                                                       {
+                                                               if( (symbol[j].Address==-1) ) symbol[j].Address=Address;
+                                                               break;
+                                                       }
+                                               }
+                                               
+                                               /*It could be also a static function*/
+                                               for(j=0; j<numproc; j++)
+                                               {
+                                                       if(EQ(procedure[j].name, name))
+                                                       {
+                                                               if( (procedure[j].BeginAdd==-1) ) procedure[j].BeginAdd=Address;
+                                                               break;
+                                                       }
+                                               }
+
+                                       break;
+                                       
+                                       case 'L': /*Example L:Lmain$j$1$1:29*/
+
+                                               /*
+                                               L:LDS1306_Write$Value$1$1:34
+                                               L:LDS1306_Burst_Read$count$1$1:35
+                                               L:LDS1306_Burst_Read$address$1$1:36
+                                               L:LDS1306_Burst_Write$count$1$1:37
+                                               L:LDS1306_Burst_Write$address$1$1:38
+                                               */
+                                               sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
+                                                       scope, &c, name, &c, level, &c, &Address);
+                                               
+                                               for(k=0; k<numproc; k++)
+                                               {
+                                                       if(EQ(procedure[k].name, scope)) break;
+                                               }
+                                               
+                                               if(k<numproc) for(j=0; j<numsym; j++)
+                                               {
+                                                       if( EQ(symbol[j].name, name) && (symbol[j].Procedure==k) )
+                                                       {
+                                                               if(symbol[j].Address==-1) symbol[j].Address=Address;
+                                                               break;
+                                                       }
+                                               }
+                                       break;
+                                       
+                                       /*Line Numbers*/
+                                       case 'C': /*Example L:C$adq.c$38$1$1:3E*/  /*L:C$hwinit.c$29$1$1:7AD*/
+                                               sscanf(&buff[4], "%[^.] %[^$] %c %d %[^:] %c %x",
+                                                       name, level, &c, &CLine, level, &c, &Address);
+
+                                               for(j=0; j<numin; j++)
+                                                       if(EQ(infn[j].ModuleName, name)) break;
+                                               if(j<numin)
+                                               {
+                                                       /*Check if this line is already defined*/
+                                                       for(k=0; k<numlinenum; k++)
+                                                       {
+                                                               if( (linenum[k].Number==CLine) &&
+                                                                       (linenum[k].FileNameNumber==j) )break;
+                                                       }
+                                                       if(k==numlinenum) /*New line number*/
+                                                       {
+                                                               linenum=realloc(linenum, sizeof(_linenum)*(numlinenum+1));
+                                                               linenum[numlinenum].Number=CLine;
+                                                               linenum[numlinenum].FileNameNumber=j;
+                                                               linenum[numlinenum].Procedure=-1;/*To be asigned later*/
+                                                               linenum[numlinenum].Address=Address;
+                                                               numlinenum++;
+                                                       }
+                                               }
+                                       break;
+                                       
+                                       case 'A': /*Example L:A$adq$424:40*/
+                                               /*No use for this one*/
+                                       break;
+                                       
+                                       /*The end of a procedure*/
+                                       case 'X': /*Example L:XG$AsciiToHex$0$0:88*/
+                                               sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
+                                                       scope, &c, name, &c, level, &c, &Address);
+
+                                               for(k=0; k<numproc; k++)
+                                               {
+                                                       if(EQ(procedure[k].name, name))
+                                                       {
+                                                               if(procedure[k].EndAdd==-1) procedure[k].EndAdd=Address;
+                                                               break;
+                                                       }
+                                               }
+                                       break;
+                               }
+                       break;
+
+                       default:
+                       break;
+               }
+       }
+
+       /*Make sure each procedure has an end*/
+       for(k=0; k<(numproc-1); k++)
+       {
+               if (procedure[k].EndAdd==-1) procedure[k].EndAdd=procedure[k+1].BeginAdd-1;
+       }
+       /*Asign each line number to a procedure*/
+       for(j=0; j<numlinenum; j++)
+       {
+               for(k=0; k<numproc; k++)
+               {
+                       if ( (linenum[j].Address>=procedure[k].BeginAdd) &&
+                                (linenum[j].Address<=procedure[k].EndAdd) &&
+                                (linenum[j].FileNameNumber==procedure[k].FileNameNumber) )
+                       {
+                               linenum[j].Procedure=k;
+                       }
+               }
+       }
+
+       fclose(CDBin);
+}
+
+int hex2dec (char hex_digit)
+{
+   int j;
+   j=toupper(hex_digit)-'0';
+   if (j>9) j -= 7;
+   return j;
+}
+
+unsigned char GetByte(char * buffer)
+{
+       return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]);
+}
+
+unsigned short GetWord(char * buffer)
+{
+       return  hex2dec(buffer[0])*0x1000+
+                       hex2dec(buffer[1])*0x100+
+                       hex2dec(buffer[2])*0x10+
+                       hex2dec(buffer[3]);
+}
+
+int ReadHexFile(int * Begin)
+{
+       char buffer[1024];
+       FILE * filein;
+       int j;
+       unsigned char linesize, recordtype, rchksum, value;
+       unsigned short address;
+       int MaxAddress=0;
+       int chksum;
+
+       /*If the hexfile is already open, close it*/
+       if(ofp!=NULL)
+       {
+               fclose(ofp);
+               ofp=NULL;
+       }
+       
+       strcpy(ihxFileName, infn[0].PathName);
+       strcat(ihxFileName, ".ihx");
+
+       if ( (filein=fopen(ihxFileName, "r")) == NULL )
+       {
+          printf("Error: Can't open file `%s`.\r\n", ihxFileName);
+          return 0;
+       }
+   
+       ihxBuff=calloc(MEMSIZE, sizeof(unsigned char));
+       if(ihxBuff==NULL)
+       {
+               printf("Insufficient memory\n");
+               fclose(filein);
+               return -1;
+       }
+
+       for(j=0; j<MEMSIZE; j++) ihxBuff[j]=0xff;
+
+    while(1)
+    {
+               if(fgets(buffer, sizeof(buffer), filein)==NULL)
+               {
+                       printf("Error reading file '%s'\n", ihxFileName);
+                       break;
+               }
+       if(buffer[0]==':')
+       {
+                       linesize = GetByte(&buffer[1]);
+                       address = GetWord(&buffer[3]);
+                       recordtype = GetByte(&buffer[7]);
+                       rchksum = GetByte(&buffer[9]+(linesize*2));
+                       chksum=linesize+(address/0x100)+(address%0x100)+recordtype+rchksum;
+
+                       if (recordtype==1) break; /*End of record*/
+
+                       for(j=0; j<linesize; j++)
+                       {
+                               value=GetByte(&buffer[9]+(j*2));
+                               chksum+=value;
+                               ihxBuff[address+j]=value;
+                       }
+                       if(MaxAddress<(address+linesize-1)) MaxAddress=(address+linesize-1);
+                       if(address<*Begin) *Begin=address;
+
+                       if((chksum%0x100)!=0)
+                       {
+                               printf("ERROR: Bad checksum in file %s\n", ihxFileName);
+                               fclose(filein);
+                               return -1;
+                       }
+               }
+    }
+    fclose(filein);
+       
+    return MaxAddress;
+}
+
+void CreateAOMF51(void)
+{
+       if((dflag) && (!rflag))
+       {
+               CollectInfoFromCDB();
+               #ifdef DODUMP
+               DumpForDebug();
+               #endif
+               HexSize=ReadHexFile(&HexBegin)+1;
+               OutputAOEMF51();
+               FreeAll();
+       }
+}
diff --git a/as/hc08/lkarea.c b/as/hc08/lkarea.c
new file mode 100644 (file)
index 0000000..d13f104
--- /dev/null
@@ -0,0 +1,476 @@
+/* lkarea.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ *  3-Nov-97 JLH: 
+ *           - change lkparea to use a_type == 0 as "virgin area" flag
+ * 02-Apr-98 JLH: add code to link 8051 data spaces
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lkarea.c
+ *
+ *     The module lkarea.c contains the functions which
+ *     create and link together all area definitions read
+ *     from the .rel file(s).
+ *
+ *     lkarea.c contains the following functions:
+ *             VOID    lnkarea()
+ *             VOID    lnksect()
+ *             VOID    lkparea()
+ *             VOID    newarea()
+ *
+ *     lkarea.c contains no global variables.
+ */
+
+/*)Function    VOID    newarea()
+ * 
+ *     The function newarea() creates and/or modifies area
+ *     and areax structures for each A directive read from
+ *     the .rel file(s).  The function lkparea() is called
+ *     to find tha area structure associated with this name.
+ *     If the area does not yet exist then a new area
+ *     structure is created and linked to any existing
+ *     linked area structures. The area flags are copied
+ *     into the area flag variable.  For each occurence of
+ *     an A directive an areax structure is created and
+ *     linked to the areax structures associated with this
+ *     area.  The size of this area section is placed into
+ *     the areax structure.  The flag value for all subsequent
+ *     area definitions for the same area are compared and
+ *     flagged as an error if they are not identical.
+ *     The areax structure created for every occurence of
+ *     an A directive is loaded with a pointer to the base
+ *     area structure and a pointer to the associated
+ *     head structure.  And finally, a pointer to this
+ *     areax structure is loaded into the list of areax
+ *     structures in the head structure.  Refer to lkdata.c
+ *     for details of the structures and their linkage.
+ *
+ *     local variables:
+ *             areax **halp            pointer to an array of pointers
+ *             int     i               counter, loop variable, value
+ *             char    id[]            id string
+ *             int     narea           number of areas in this head structure
+ *             areax * taxp            pointer to an areax structure
+ *                                     to areax structures
+ *
+ *     global variables:
+ *             area    *ap             Pointer to the current
+ *                                     area structure
+ *             areax   *axp            Pointer to the current
+ *                                     areax structure
+ *             head    *hp             Pointer to the current
+ *                                     head structure
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             Addr_T  eval()          lkeval.c
+ *             VOID    exit()          c_library
+ *             int     fprintf()       c_library
+ *             VOID    getid()         lklex.c
+ *             VOID    lkparea()       lkarea.c
+ *             VOID    skip()          lklex.c
+ *
+ *     side effects:
+ *             The area and areax structures are created and
+ *             linked with the appropriate head structures.
+ *             Failure to allocate area or areax structure
+ *             space will terminate the linker.  Other internal
+ *             errors most likely caused by corrupted .rel
+ *             files will also terminate the linker.
+ */
+
+/*
+ * Create an area entry.
+ *
+ * A xxxxxx size nnnn flags mm
+ *   |           |          |
+ *   |           |          `--  ap->a_flag
+ *   |           `------------- axp->a_size
+ *   `-------------------------  ap->a_id
+ *
+ */
+VOID
+newarea()
+{
+       register int i, narea;
+       struct areax *taxp;
+       struct areax **halp;
+       char id[NCPS];
+
+       /*
+        * Create Area entry
+        */
+       getid(id, -1);
+       lkparea(id);
+       /*
+        * Evaluate area size
+        */
+       skip(-1);
+       axp->a_size = eval();
+       /*
+        * Evaluate flags
+        */
+       skip(-1);
+       i = 0;
+       taxp = ap->a_axp;
+       while (taxp->a_axp) {
+               ++i;
+               taxp = taxp->a_axp;
+       }
+       if (i == 0) {
+               ap->a_flag = eval();
+       } else {
+               i = eval();
+/*             if (i && (ap->a_flag != i)) { */
+/*                 fprintf(stderr, "Conflicting flags in area %8s\n", id); */
+/*                 lkerr++; */
+/*             } */
+       }
+       /*
+        * Place pointer in header area list
+        */
+       if (headp == NULL) {
+               fprintf(stderr, "No header defined\n");
+               lkexit(1);
+       }
+       narea = hp->h_narea;
+       halp = hp->a_list;
+       for (i=0; i < narea ;++i) {
+               if (halp[i] == NULL) {
+                       halp[i] = taxp;
+                       return;
+               }
+       }
+       fprintf(stderr, "Header area list overflow\n");
+       lkexit(1);
+}
+
+/*)Function    VOID    lkparea(id)
+ *
+ *             char *  id              pointer to the area name string
+ *
+ *     The function lkparea() searches the linked area structures
+ *     for a name match.  If the name is not found then an area
+ *     structure is created.  An areax structure is created and
+ *     appended to the areax structures linked to the area structure.
+ *     The associated base area and head structure pointers are
+ *     loaded into the areax structure.
+ *
+ *     local variables:
+ *             area *  tap             pointer to an area structure
+ *             areax * taxp            pointer to an areax structure
+ *
+ *     global variables:
+ *             area    *ap             Pointer to the current
+ *                                     area structure
+ *             area    *areap          The pointer to the first
+ *                                     area structure of a linked list
+ *             areax   *axp            Pointer to the current
+ *                                     areax structure
+ *
+ *     functions called:
+ *             VOID *  new()           lksym()
+ *             char *  strcpy()        c_library
+ *             int     symeq()         lksym.c
+ *
+ *     side effects:
+ *             Area and/or areax structures are created.
+ *             Failure to allocate space for created structures
+ *             will terminate the linker.
+ */
+
+VOID
+lkparea(id)
+char *id;
+{
+       register struct area *tap;
+       register struct areax *taxp;
+
+       ap = areap;
+       axp = (struct areax *) new (sizeof(struct areax));
+       while (ap) {
+               if (symeq(id, ap->a_id)) {
+                       taxp = ap->a_axp;
+                       while (taxp->a_axp)
+                               taxp = taxp->a_axp;
+                       taxp->a_axp = axp;
+                       axp->a_bap = ap;
+                       axp->a_bhp = hp;
+                       return;
+               }
+               ap = ap->a_ap;
+       }
+       ap = (struct area *) new (sizeof(struct area));
+       if (areap == NULL) {
+               areap = ap;
+       } else {
+               tap = areap;
+               while (tap->a_ap)
+                       tap = tap->a_ap;
+               tap->a_ap = ap;
+       }
+       ap->a_axp = axp;
+       axp->a_bap = ap;
+       axp->a_bhp = hp;
+       strncpy(ap->a_id, id, NCPS);
+        ap->a_addr = 0;
+}
+
+/*)Function    VOID    lnkarea()
+ *
+ *     The function lnkarea() resolves all area addresses.
+ *     The function evaluates each area structure (and all
+ *     the associated areax structures) in sequence.  The
+ *     linking process supports four (4) possible area types:
+ *
+ *     ABS/OVR -       All sections (each individual areax
+ *                     section) starts at the identical base
+ *                     area address overlaying all other
+ *                     areax sections for this area.  The
+ *                     size of the area is largest of the area
+ *                     sections.
+ *
+ *     ABS/CON -       All sections (each individual areax
+ *                     section) are concatenated with the
+ *                     first section starting at the base
+ *                     area address.  The size of the area
+ *                     is the sum of the section sizes.
+ *
+ *     NOTE:   Multiple absolute (ABS) areas are
+ *                     never concatenated with each other,
+ *                     thus absolute area A and absolute area
+ *                     B will overlay each other if they begin
+ *                     at the same location (the default is
+ *                     always address 0 for absolute areas).
+ *
+ *     REL/OVR -       All sections (each individual areax
+ *                     section) starts at the identical base
+ *                     area address overlaying all other
+ *                     areax sections for this area.  The
+ *                     size of the area is largest of the area
+ *                     sections.
+ *
+ *     REL/CON -       All sections (each individual areax
+ *                     section) are concatenated with the
+ *                     first section starting at the base
+ *                     area address.  The size of the area
+ *                     is the sum of the section sizes.
+ *
+ *     NOTE:   Relocatable (REL) areas ae always concatenated
+ *                     with each other, thus relocatable area B
+ *                     (defined after area A) will follow
+ *                     relocatable area A independent of the
+ *                     starting address of area A.  Within a
+ *                     specific area each areax section may be
+ *                     overlayed or concatenated with other
+ *                     areax sections.
+ *
+ *
+ *     If a base address for an area is specified then the
+ *     area will start at that address.  Any relocatable
+ *     areas defined subsequently will be concatenated to the
+ *     previous relocatable area if it does not have a base
+ *     address specified.
+ *
+ *     The names s_<areaname> and l_<areaname> are created to
+ *     define the starting address and length of each area.
+ *
+ *     local variables:
+ *             Addr_T  rloc            ;current relocation address
+ *             char    temp[]          ;temporary string
+ *             struct symbol   *sp     ;symbol structure
+ *
+ *     global variables:
+ *             area    *ap                     Pointer to the current
+ *                                                     area structure
+ *             area    *areap          The pointer to the first
+ *                                                     area structure of a linked list
+ *
+ *     functions called:
+ *             int             fprintf()       c_library
+ *             VOID    lnksect()       lkarea.c
+ *             symbol *lkpsym()        lksysm.c
+ *             char *  strncpy()       c_library
+ *             int             symeq()         lksysm.c
+ *
+ *     side effects:
+ *             All area and areax addresses and sizes are
+ *             determined and saved in their respective
+ *             structures.
+ */
+
+/*
+ * Resolve all area addresses.
+ */
+VOID
+lnkarea()
+{
+       Addr_T rloc[4];
+       int  locIndex;
+       char temp[NCPS];
+       struct sym *sp;
+       /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
+       struct area *ta[5];
+       int j;
+
+       rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
+       ap = areap;
+       while (ap) {
+               if (ap->a_flag&A_ABS) {
+                       /*
+                        * Absolute sections
+                        */
+                       lnksect(ap);
+               } else {
+                       /* Determine memory space */
+            locIndex = 0;
+            if (ap->a_flag & A_CODE) {
+                locIndex = 1;
+            }
+            if (ap->a_flag & A_XDATA) {
+                locIndex = 2;
+            }
+            if (ap->a_flag & A_BIT) {
+                locIndex = 3;
+            }
+                       /*
+                        * Relocatable sections
+                        */
+                       if (ap->a_type == 0) {  /* JLH */
+                               ap->a_addr = rloc[ locIndex ];
+                               ap->a_type = 1;
+                       }
+                       lnksect(ap);
+                       rloc[ locIndex ] = ap->a_addr + ap->a_size;
+               }
+
+               /*
+                * Create symbols called:
+                *      s_<areaname>    the start address of the area
+                *      l_<areaname>    the length of the area
+                */
+
+               if (! symeq(ap->a_id, _abs_)) {
+                       strncpy(temp+2,ap->a_id,NCPS-2);
+                       *(temp+1) = '_';
+
+                       *temp = 's';
+                       sp = lkpsym(temp, 1);
+                       sp->s_addr = ap->a_addr ;
+                       /* sp->s_axp = ap->a_axp;  JLH: was NULL; */
+                       sp->s_type |= S_DEF;
+
+                       *temp = 'l';
+                       sp = lkpsym(temp, 1);
+                       sp->s_addr = ap->a_size;
+                       sp->s_axp = NULL;
+                       sp->s_type |= S_DEF;
+
+               }
+               
+               /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
+               to compute the byte size of BSEG_BYTES: */
+               if (!strcmp(ap->a_id, "BSEG")) {
+                       ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
+               }
+               else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
+               else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
+               else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
+               else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
+               else if (!strcmp(ap->a_id, "BSEG_BYTES"))
+               {
+                       ta[4]=ap;
+                       for(j=4; j>1; j--)
+                       {
+                               /*If upper register banks are not used roll back the rellocation counter*/
+                               if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
+                               {
+                                       rloc[0]-=8;
+                               }
+                               else break;
+                       }
+               }
+               ap = ap->a_ap;
+       }
+}
+
+/*)Function    VOID    lnksect()
+ *
+ *             area *  tap             pointer to an area structure
+ *
+ *     The function lnksect() is the function called by
+ *     lnkarea() to resolve the areax addresses.  Refer
+ *     to the function lnkarea() for more detail. Pageing
+ *     boundary and length errors will be reported by this
+ *     function.
+ *
+ *     local variables:
+ *             Addr_T  size            size of area
+ *             Addr_T  addr            address of area
+ *             areax * taxp            pointer to an areax structure
+ *
+ *     global variables:
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             All area and areax addresses and sizes area determined
+ *             and linked into the structures.
+ */
+
+VOID
+lnksect(tap)
+register struct area *tap;
+{
+       register Addr_T size, addr;
+       register struct areax *taxp;
+
+       size = 0;
+       addr = tap->a_addr;
+       if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
+           fprintf(stderr,
+           "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+           lkerr++;
+       }
+       taxp = tap->a_axp;
+       if (tap->a_flag&A_OVR) {
+               /*
+                * Overlayed sections
+                */
+               while (taxp) {
+                       taxp->a_addr = addr;
+                       if (taxp->a_size > size)
+                               size = taxp->a_size;
+                       taxp = taxp->a_axp;
+               }
+       } else {
+               /*
+                * Concatenated sections
+                */
+               while (taxp) {
+                       taxp->a_addr = addr;
+                       addr += taxp->a_size;
+                       size += taxp->a_size;
+                       taxp = taxp->a_axp;
+               }
+       }
+       tap->a_size = size;
+       if ((tap->a_flag&A_PAG) && (size > 256)) {
+           fprintf(stderr,
+           "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
+           lkerr++;
+       }
+}
diff --git a/as/hc08/lkdata.c b/as/hc08/lkdata.c
new file mode 100644 (file)
index 0000000..d6a3517
--- /dev/null
@@ -0,0 +1,491 @@
+/* lkdata.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - change s_id from [NCPS] to pointer (comment)
+ * 31-Oct-97 JLH: 
+ *           - add jflag and jfp for NoICE output
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lkdata.c
+ *
+ *     The module lkdata contains the global variables
+ *     and structures used in the linker aslink.
+ */
+
+/*
+ *     Definitions for all Global Variables
+ */
+
+char   *_abs_  = { ".  .ABS." };
+
+int    lkerr;          /*      Linker error flag
+                        */
+char   *ip;            /*      Pointer into the REL file text line in ib[]
+                        */
+char   ib[NINPUT];     /*      REL file text line
+                        */
+char   *rp;            /*      pointer into the LST file
+                        *      text line in rb[]
+                        */
+char   rb[NINPUT];     /*      LST file text line being
+                        *      address relocated
+                        */
+
+char sdccopt[NINPUT]="";
+char sdccopt_module[NINPUT]="";
+char curr_module[NINPUT]="";
+
+int     dflag;          /*      Debug information output flag
+                        */
+int    oflag;          /*      Output file type flag
+                        */
+int    mflag;          /*      Map output flag
+                        */
+int    sflag;          /*      JCF: Memory usage output flag
+                        */
+int    aflag;          /*      Overlapping area warning flag
+                        */
+int    jflag;          /*      NoICE output flag
+                        */
+int    xflag;          /*      Map file radix type flag
+                        */
+int    pflag;          /*      print linker command file flag
+                        */
+int    uflag;          /*      Listing relocation flag
+                        */
+int    rflag;          /*      Extended linear address record flag.
+                        */
+int    radix;          /*      current number conversion radix:
+                        *      2 (binary), 8 (octal), 10 (decimal),
+                        *      16 (hexadecimal)
+                        */
+int    line;           /*      current line number
+                        */
+int    page;           /*      current page number
+                        */
+int    lop;            /*      current line number on page
+                        */
+int    pass;           /*      linker pass number
+                        */
+int    rtcnt;          /*      count of elements in the
+                        *      rtval[] and rtflg[] arrays
+                        */
+Addr_T rtval[NTXT];    /*      data associated with relocation
+                        */
+int    rtflg[NTXT];    /*      indicates if rtval[] value is
+                        *      to be sent to the output file.
+                        *      (always set in this linker)
+                        */
+int    hilo;           /*      REL file byte ordering
+                        */
+int    gline;          /*      LST file relocation active
+                        *      for current line
+                        */
+int    gcntr;          /*      LST file relocation active
+                        *      counter
+                        */
+Addr_T iram_size;      /*      internal ram size
+                        */
+long   xram_size=-1;   /*      external ram size
+                        */
+long   code_size=-1;   /*      code size
+                        */
+
+/*
+ *     The structure lfile contains a pointer to a
+ *     file specification string, the file type, and
+ *     a link to the next lfile structure.
+ *
+ *     struct  lfile
+ *     {
+ *             struct  lfile   *f_flp;         lfile link
+ *             int     f_type;                 File type
+ *             char    *f_idp;                 Pointer to file spec
+ *     };
+ */
+struct lfile   *filep; /*      The pointers (lfile *) filep,
+                        *      (lfile *) cfp, and (FILE *) sfp
+                        *      are used in conjunction with
+                        *      the routine getline() to read
+                        *      asmlnk commands from
+                        *      (1) the standard input or
+                        *      (2) or a command file
+                        *      and to read the REL files
+                        *      sequentially as defined by the
+                        *      asmlnk input commands.
+                        *
+                        *      The pointer *filep points to the
+                        *      beginning of a linked list of
+                        *      lfile structures.
+                        */
+struct lfile   *cfp;   /*      The pointer *cfp points to the
+                        *      current lfile structure
+                        */
+struct lfile   *startp;/*      asmlnk startup file structure
+                        */
+struct lfile   *linkp; /*      pointer to first lfile structure
+                        *      containing an input REL file
+                        *      specification
+                        */
+struct lfile   *lfp;   /*      pointer to current lfile structure
+                        *      being processed by parse()
+                        */
+FILE   *ofp;           /*      Output file handle
+                        *      for word formats
+                        */
+FILE   *mfp;           /*      Map output file handle
+                        */
+FILE   *jfp;           /*      NoICE output file handle
+                        */
+FILE   *rfp;           /*      File handle for output
+                        *      address relocated ASxxxx
+                        *      listing file
+                        */
+FILE   *sfp;           /*      The file handle sfp points to the
+                        *      currently open file
+                        */
+FILE   *tfp;           /*      File handle for input
+                        *      ASxxxx listing file
+                        */
+FILE    *dfp = NULL ;   /*
+                        *      File handle for debug
+                        *      information output file
+                        */
+/*
+ *     The structures of head, area, areax, and sym are created
+ *     as the REL files are read during the first pass of the
+ *     linker.  The struct head is created upon encountering a
+ *     H directive in the REL file.  The structure contains a
+ *     link to a link file structure (struct lfile) which describes
+ *     the file containing the H directive, the number of data/code
+ *     areas contained in this header segment, the number of
+ *     symbols referenced/defined in this header segment, a pointer
+ *     to an array of pointers to areax structures (struct areax)
+ *     created as each A directive is read, and a pointer to an
+ *     array of pointers to symbol structures (struct sym) for
+ *     all referenced/defined symbols.  As H directives are read
+ *     from the REL files a linked list of head structures is
+ *     created by placing a link to the new head structure
+ *     in the previous head structure.
+ *
+ *     struct  head
+ *     {
+ *             struct  head   *h_hp;           Header link
+ *             struct  lfile  *h_lfile;        Associated file
+ *             int     h_narea;                # of areas
+ *             struct  areax **a_list;         Area list
+ *             int     h_nglob;                # of global symbols
+ *             struct  sym   **s_list;         Global symbol list
+ *             char    m_id[NCPS];             Module name
+ *     };
+ */
+struct head    *headp; /*      The pointer to the first
+                        *      head structure of a linked list
+                        */
+struct head    *hp;    /*      Pointer to the current
+                        *      head structure
+                        */
+
+/*
+ *     A structure area is created for each 'unique' data/code
+ *     area definition found as the REL files are read.  The
+ *     struct area contains the name of the area, a flag byte
+ *     which contains the area attributes (REL/CON/OVR/ABS),
+ *     an area subtype (not used in this assembler), and the
+ *     area base address and total size which will be filled
+ *     in at the end of the first pass through the REL files.
+ *     As A directives are read from the REL files a linked
+ *     list of unique area structures is created by placing a
+ *     link to the new area structure in the previous area structure.
+ *
+ *     struct  area
+ *     {
+ *             struct  area    *a_ap;          Area link
+ *             struct  areax   *a_axp;         Area extension link
+ *             Addr_T  a_addr;                 Beginning address of area
+ *             Addr_T  a_size;                 Total size of the area
+ *             char    a_type;                 Area subtype
+ *             char    a_flag;                 Flag byte
+ *             char    a_id[NCPS];             Name
+ *     };
+ */
+struct area    *areap; /*      The pointer to the first
+                        *      area structure of a linked list
+                        */
+struct area    *ap;    /*      Pointer to the current
+                        *      area structure
+                        */
+
+/*
+ *     An areax structure is created for every A directive found
+ *     while reading the REL files.  The struct areax contains a
+ *     link to the 'unique' area structure referenced by the A
+ *     directive and to the head structure this area segment is
+ *     a part of.  The size of this area segment as read from the
+ *     A directive is placed in the areax structure.  The beginning
+ *     address of this segment will be filled in at the end of the
+ *     first pass through the REL files.  As A directives are read
+ *     from the REL files a linked list of areax structures is
+ *     created for each unique area.  The final areax linked
+ *     list has at its head the 'unique' area structure linked
+ *     to the linked areax structures (one areax structure for
+ *     each A directive for this area).
+ *
+ *     struct  areax
+ *     {
+ *             struct  areax   *a_axp;         Area extension link
+ *             struct  area    *a_bap;         Base area link
+ *             struct  head    *a_bhp;         Base header link
+ *             Addr_T  a_addr;                 Beginning address of section
+ *             Addr_T  a_size;                 Size of the area in section
+ *     };
+ */
+struct areax   *axp;   /*      Pointer to the current
+                        *      areax structure
+                        */
+
+/*
+ *     A sym structure is created for every unique symbol
+ *     referenced/defined while reading the REL files.  The
+ *     struct sym contains the symbol's name, a flag value
+ *     (not used in this linker), a symbol type denoting
+ *     referenced/defined, and an address which is loaded
+ *     with the relative address within the area in which
+ *     the symbol was defined.  The sym structure also
+ *     contains a link to the area where the symbol was defined.
+ *     The sym structures are linked into linked lists using
+ *     the symbol link element.
+ *
+ *     struct  sym
+ *     {
+ *             struct  sym     *s_sp;          Symbol link
+ *             struct  areax   *s_axp;         Symbol area link
+ *             char    s_type;                 Symbol subtype
+ *             char    s_flag;                 Flag byte
+ *             Addr_T  s_addr;                 Address
+ *             char    *s_id;                  Name (JLH)
+ *     };
+ */
+struct sym *symhash[NHASH]; /* array of pointers to NHASH
+                             * linked symbol lists
+                             */
+/*
+ *     The struct base contains a pointer to a
+ *     base definition string and a link to the next
+ *     base structure.
+ *
+ *     struct  base
+ *     {
+ *             struct  base  *b_base;          Base link
+ *             char          *b_strp;          String pointer
+ *     };
+ */
+struct base    *basep; /*      The pointer to the first
+                        *      base structure
+                        */
+struct base    *bsp;   /*      Pointer to the current
+                        *      base structure
+                        */
+
+/*
+ *     The struct globl contains a pointer to a
+ *     global definition string and a link to the next
+ *     global structure.
+ *
+ *     struct  globl
+ *     {
+ *             struct  globl *g_globl;         Global link
+ *             char          *g_strp;          String pointer
+ *     };
+ */
+struct globl   *globlp;/*      The pointer to the first
+                        *      globl structure
+                        */
+struct globl   *gsp;   /*      Pointer to the current
+                        *      globl structure
+                        */
+
+/*
+ *     A structure sdp is created for each 'unique' paged
+ *     area definition found as the REL files are read.
+ *     As P directives are read from the REL files a linked
+ *     list of unique sdp structures is created by placing a
+ *     link to the new sdp structure in the previous area structure.
+ *
+ *     struct  sdp
+ *     {
+ *             struct  area  *s_area;  Paged Area link
+ *             struct  areax *s_areax; Paged Area Extension Link
+ *             Addr_T  s_addr;         Page address offset
+ *     };
+ */
+struct sdp     sdp;    /* Base Page Structure */
+
+/*
+ *     The structure rerr is loaded with the information
+ *     required to report an error during the linking
+ *     process.  The structure contains an index value
+ *     which selects the areax structure from the header
+ *     areax structure list, a mode value which selects
+ *     symbol or area relocation, the base address in the
+ *     area section, an area/symbol list index value, and
+ *     an area/symbol offset value.
+ *
+ *     struct  rerr
+ *     {
+ *             int     aindex;         Linking area
+ *             int     mode;           Relocation mode
+ *             Addr_T  rtbase;         Base address in section
+ *             int     rindex;         Area/Symbol reloaction index
+ *             Addr_T  rval;           Area/Symbol offset value
+ *     };
+ */
+struct rerr    rerr;   /*      Structure containing the
+                        *      linker error information
+                        */
+
+/*
+ *     The structure lbpath is created for each library
+ *     path specification input by the -k option.  The
+ *     lbpath structures are linked into a list using
+ *     the next link element.
+ *
+ *     struct lbpath {
+ *             struct  lbpath  *next;
+ *             char            *path;
+ *     };
+ */
+struct lbpath  *lbphead;       /*      pointer to the first
+                                *      library path structure
+                                */
+
+/*
+ *     The structure lbname is created for all combinations of the
+ *     library path specifications (input by the -k option) and the
+ *     library file specifications (input by the -l option) that
+ *     lead to an existing file.  The element path points to
+ *     the path string, element libfil points to the library
+ *     file string, and the element libspc is the concatenation
+ *     of the valid path and libfil strings.
+ *
+ *     The lbpath structures are linked into a list
+ *     using the next link element.
+ *
+ *     Each library file contains a list of object files
+ *     that are contained in the particular library. e.g.:
+ *
+ *             \iolib\termio
+ *             \inilib\termio
+ *
+ *     Only one specification per line is allowed.
+ *
+ *     struct lbname {
+ *             struct  lbname  *next;
+ *             char            *path;
+ *             char            *libfil;
+ *             char            *libspc;
+ *     };
+ */
+struct lbname  *lbnhead;       /*      pointer to the first
+                                *      library name structure
+                                */
+
+/*
+ *     The function fndsym() searches through all combinations of the
+ *     library path specifications (input by the -k option) and the
+ *     library file specifications (input by the -l option) that
+ *     lead to an existing file for a symbol definition.
+ *
+ *     The structure lbfile is created for the first library
+ *     object file which contains the definition for the
+ *     specified undefined symbol.
+ *
+ *     The element libspc points to the library file path specification
+ *     and element relfil points to the object file specification string.
+ *     The element filspc is the complete path/file specification for
+ *     the library file to be imported into the linker.  The
+ *     file specicifation may be formed in one of two ways:
+ *
+ *     (1)     If the library file contained an absolute
+ *             path/file specification then this becomes filspc.
+ *             (i.e. C:\...)
+ *
+ *     (2)     If the library file contains a relative path/file
+ *             specification then the concatenation of the path
+ *             and this file specification becomes filspc.
+ *             (i.e. \...)
+ *
+ *     The lbpath structures are linked into a list
+ *     using the next link element.
+ *
+ *     struct lbfile {
+ *             struct  lbfile  *next;
+ *             char            *libspc;
+ *             char            *relfil;
+ *             char            *filspc;
+ *     };
+ */
+struct lbfile  *lbfhead;       /*      pointer to the first
+                                *      library file structure
+                                */
+
+/*
+ *     array of character types, one per
+ *     ASCII character
+ */
+unsigned char  ctype[128] = {
+/*NUL*/        ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,
+/*BS*/ ILL,    SPACE,  ILL,    ILL,    SPACE,  ILL,    ILL,    ILL,
+/*DLE*/        ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,
+/*CAN*/        ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,    ILL,
+/*SPC*/        SPACE,  ETC,    ETC,    ETC,    LETTER, BINOP,  BINOP,  ETC,
+/*(*/  ETC,    ETC,    BINOP,  BINOP,  ETC,    BINOP,  LETTER, BINOP,
+/*0*/  DGT2,   DGT2,   DGT8,   DGT8,   DGT8,   DGT8,   DGT8,   DGT8,
+/*8*/  DGT10,  DGT10,  ETC,    ETC,    BINOP,  ETC,    BINOP,  ETC,
+/*@*/  ETC,    LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LETTER,
+/*H*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*P*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*X*/  LETTER, LETTER, LETTER, ETC,    ETC,    ETC,    BINOP,  LETTER,
+/*`*/  ETC,    LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LTR16,  LETTER,
+/*h*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*p*/  LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*x*/  LETTER, LETTER, LETTER, ETC,    BINOP,  ETC,    ETC,    ETC
+};
+
+/*
+ *     an array of characters which
+ *     perform the case translation function
+ */
+#if    CASE_SENSITIVE
+#else
+char   ccase[128] = {
+/*NUL*/        '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+/*DLE*/        '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+/*CAN*/        '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+/*SPC*/        '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+/*(*/  '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+/*0*/  '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+/*8*/  '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+/*@*/  '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*H*/  '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*P*/  '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*X*/  '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+/*`*/  '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*h*/  '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*p*/  '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*x*/  '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177'
+};     
+#endif
diff --git a/as/hc08/lkeval.c b/as/hc08/lkeval.c
new file mode 100644 (file)
index 0000000..90df003
--- /dev/null
@@ -0,0 +1,396 @@
+/* lkeval.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lkeval.c
+ *
+ *     The module lkeval.c contains the routines to evaluate
+ *     arithmetic/numerical expressions.  The functions in
+ *     lkeval.c perform a recursive evaluation of the arithmetic
+ *     expression read from the input text line.
+ *     The expression may include binary/unary operators, brackets,
+ *     symbols, labels, and constants in hexadecimal, decimal, octal
+ *     and binary.  Arithmetic operations are prioritized and
+ *     evaluated by normal arithmetic conventions.
+ *
+ *     lkeval.c contains the following functions:
+ *             int     digit()
+ *             Addr_T  eval()
+ *             Addr_T  expr()
+ *             int     oprio()
+ *             Addr_T  term()
+ *
+ *     lkeval.c contains no local/static variables
+ */
+
+/*)Function    Addr_T  eval()
+ *
+ *     The function eval() evaluates a character string to a
+ *     numerical value.
+ *
+ *     local variables:
+ *             int     c               character from input string
+ *             int     v               value of character in current radix
+ *             Addr_T  n               evaluation value
+ *
+ *     global variables:
+ *             int     radix           current number conversion radix
+ *
+ *     functions called:
+ *             int     digit()         lkeval.c
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             Input test is scanned and evaluated to a
+ *             numerical value.
+ */
+
+Addr_T
+eval()
+{
+       register int c, v;
+       register Addr_T n;
+
+       c = getnb();
+       n = 0;
+       while ((v = digit(c, radix)) >= 0) {
+               n = n*radix + v;
+               c = get();
+       }
+       unget(c);
+       return(n);
+}
+
+/*)Function    Addr_T  expr(n)
+ *
+ *             int     n               a firewall priority; all top
+ *                                     level calls (from the user)
+ *                                     should be made with n set to 0.
+ *
+ *     The function expr() evaluates an expression and
+ *     returns the value.
+ *
+ *     local variables:
+ *             int     c               current input text character
+ *             int     p               current operator priority
+ *             Addr_T  v               value returned by term()
+ *             Addr_T  ve              value returned by a
+ *                                     recursive call to expr()
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *             int     lkerr           error flag
+ *             FILE *  stderr          c_library
+ *
+ *     functions called:
+ *             VOID    expr()          lkeval.c
+ *             int     fprintf()       c_library
+ *             int     getnb()         lklex.c
+ *             int     oprio()         lkeval.c
+ *             VOID    term()          lkeval.c
+ *             VOID    unget()         lklex.c
+ *
+ *
+ *     side effects:
+ *             An expression is evaluated by scanning the input
+ *             text string.
+ */
+
+Addr_T
+expr (n)
+{
+       register int c, p;
+       register Addr_T v, ve;
+
+       v = term();
+       while (ctype[c = getnb()] & BINOP) {
+               if ((p = oprio(c)) <= n)
+                       break;
+               if ((c == '>' || c == '<') && c != get()) {
+                       fprintf(stderr, "Invalid expression");
+                       lkerr++;
+                       return(v);
+               }
+               ve = expr(p);
+               if (c == '+') {
+                       v += ve;
+               } else
+               if (c == '-') {
+                       v -= ve;
+               } else {
+                       switch (c) {
+
+                       case '*':
+                               v *= ve;
+                               break;
+
+                       case '/':
+                               v /= ve;
+                               break;
+
+                       case '&':
+                               v &= ve;
+                               break;
+
+                       case '|':
+                               v |= ve;
+                               break;
+
+                       case '%':
+                               v %= ve;
+                               break;
+
+                       case '^':
+                               v ^= ve;
+                               break;
+
+                       case '<':
+                               v <<= ve;
+                               break;
+
+                       case '>':
+                               v >>= ve;
+                               break;
+                       }
+               }
+       }
+       unget(c);
+       return(v);
+}
+
+/*)Function    Addr_T  term()
+ *
+ *     The function term() evaluates a single constant
+ *     or symbol value prefaced by any unary operator
+ *     ( +, -, ~, ', ", >, or < ).
+ *
+ *     local variables:
+ *             int     c               current character
+ *             char    id[]            symbol name
+ *             int     n               value of digit in current radix
+ *             int     r               current evaluation radix
+ *             sym *   sp              pointer to a sym structure
+ *             Addr_T  v               evaluation value
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             int     digit()         lkeval.c
+ *             VOID    expr()          lkeval.c
+ *             int     fprintf()       c_library
+ *             int     get()           lklex.c
+ *             VOID    getid()         lklex.c
+ *             int     getmap()        lklex.c
+ *             int     getnb()         lklex.c
+ *             sym *   lkpsym()        lksym.c
+ *             Addr_T  symval()        lksym.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             An arithmetic term is evaluated by scanning input text.
+ */
+
+Addr_T
+term()
+{
+       register int c, r, n;
+       register Addr_T v;
+       struct sym *sp;
+       char id[NCPS];
+
+       c = getnb();
+       if (c == '#') { c = getnb(); }
+       if (c == '(') {
+               v = expr(0);
+               if (getnb() != ')') {
+                       fprintf(stderr, "Missing delimiter");
+                       lkerr++;
+               }
+               return(v);
+       }
+       if (c == '-') {
+               return(0-expr(100));
+       }
+       if (c == '~') {
+               return(~expr(100));
+       }
+       if (c == '\'') {
+               return(getmap(-1)&0377);
+       }
+       if (c == '\"') {
+               if (hilo) {
+                       v  = (getmap(-1)&0377)<<8;
+                       v |=  getmap(-1)&0377;
+               } else {
+                       v  =  getmap(-1)&0377;
+                       v |= (getmap(-1)&0377)<<8;
+               }
+               return(v);
+       }
+       if (c == '>' || c == '<') {
+               v = expr(100);
+               if (c == '>')
+                       v >>= 8;
+               return(v&0377);
+       }
+       if (ctype[c] & DIGIT) {
+               r = 10;
+               if (c == '0') {
+                       c = get();
+                       switch (c) {
+                       case 'b':
+                       case 'B':
+                               r = 2;
+                               c = get();
+                               break;
+                       case '@':
+                       case 'o':
+                       case 'O':
+                       case 'q':
+                       case 'Q':
+                               r = 8;
+                               c = get();
+                               break;
+                       case 'd':
+                       case 'D':
+                               r = 10;
+                               c = get();
+                               break;
+                       case 'h':
+                       case 'H':
+                       case 'x':
+                       case 'X':
+                               r = 16;
+                               c = get();
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               v = 0;
+               while ((n = digit(c, r)) >= 0) {
+                       v = r*v + n;
+                       c = get();
+               }
+               unget(c);
+               return(v);
+       }
+       if (ctype[c] & LETTER) {
+               getid(id, c);
+               if ((sp = lkpsym(id, 0)) == NULL) {
+                       fprintf(stderr, "Undefined symbol %8s\n", id);
+                       lkerr++;
+                       return(0);
+               } else {
+                       return(symval(sp));
+               }
+       }
+       return(0);
+}
+
+/*)Function    int     digit(c, r)
+ *
+ *             int     c               digit character
+ *             int     r               current radix
+ *
+ *     The function digit() returns the value of c
+ *     in the current radix r.  If the c value is not
+ *     a number of the current radix then a -1 is returned.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+int
+digit(c, r)
+register int c, r;
+{
+       if (r == 16) {
+               if (ctype[c] & RAD16) {
+                       if (c >= 'A' && c <= 'F')
+                               return (c - 'A' + 10);
+                       if (c >= 'a' && c <= 'f')
+                               return (c - 'a' + 10);
+                       return (c - '0');
+               }
+       } else
+       if (r == 10) {
+               if (ctype[c] & RAD10)
+                       return (c - '0');
+       } else
+       if (r == 8) {
+               if (ctype[c] & RAD8)
+                       return (c - '0');
+       } else
+       if (r == 2) {
+               if (ctype[c] & RAD2)
+                       return (c - '0');
+       }
+       return (-1);
+}
+
+/*)Function    int     oprio(c)
+ *
+ *             int     c               operator character
+ *
+ *     The function oprio() returns a relative priority
+ *     for all valid unary and binary operators.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+int
+oprio(c)
+register int c;
+{
+       if (c == '*' || c == '/' || c == '%')
+               return (10);
+       if (c == '+' || c == '-')
+               return (7);
+       if (c == '<' || c == '>')
+               return (5);
+       if (c == '^')
+               return (4);
+       if (c == '&')
+               return (3);
+       if (c == '|')
+               return (1);
+       return (0);
+}
diff --git a/as/hc08/lkhead.c b/as/hc08/lkhead.c
new file mode 100644 (file)
index 0000000..1cd390a
--- /dev/null
@@ -0,0 +1,153 @@
+/* lkhead.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*Module       lkhead.c
+ *
+ *     The module lkhead.c contains the function newhead() which
+ *     creates a head structure and the function module() which
+ *     loads the module name into the current head structure.
+ *
+ *     lkhead.c contains the following functions:
+ *             VOID    newhead()
+ *             VOID    module()
+ *
+ *     lkhead.c contains no local variables.
+ */
+
+/*)Function    VOID    newhead()
+ *
+ *     The function newhead() creates a head structure.  All head
+ *     structures are linked to form a linked list of head structures
+ *     with the current head structure at the tail of the list.
+ *
+ *     local variables:
+ *             int     i               evaluation value
+ *             head *  thp             temporary pointer
+ *                                     to a header structure
+ *
+ *     global variables:
+ *             area    *ap             Pointer to the current
+ *                                     area structure
+ *             lfile   *cfp            The pointer *cfp points to the
+ *                                     current lfile structure
+ *             head    *headp          The pointer to the first
+ *                                     head structure of a linked list
+ *             head    *hp             Pointer to the current
+ *                                     head structure
+ *
+ *     functions called:
+ *             Addr_T  expr()          lkeval.c
+ *             VOID *  new()           lksym.c
+ *             VOID    lkparea()       lkarea.c
+ *
+ *     side effects:
+ *             A new head structure is created and linked to any
+ *             existing linked head structure.  The head structure
+ *             parameters of file handle, number of areas, and number
+ *             of global symbols are loaded into the structure.
+ *             The default area "_abs_" is created when the first
+ *             head structure is created and an areax structure is
+ *             created for every head structure called.
+ */
+
+/*
+ * Create a new header entry.
+ *
+ * H n areas n global symbols
+ *   |       |
+ *   |       `---- hp->h_nglob
+ *   `------------ hp->h_narea
+ *
+ */
+VOID
+newhead()
+{
+       register int i;
+       struct head *thp;
+
+       hp = (struct head *) new (sizeof(struct head));
+       if (headp == NULL) {
+               headp = hp;
+       } else {
+               thp = headp;
+               while (thp->h_hp)
+                       thp = thp->h_hp;
+               thp->h_hp = hp;
+       }
+       /*
+        * Set file pointer
+        */
+       hp->h_lfile = cfp;
+       /*
+        * Evaluate and build Area pointer list
+        */
+       i = hp->h_narea = eval();
+       if (i)
+               hp->a_list = (struct areax **) new (i*sizeof(struct areax *));
+       /*
+        * Evaluate and build Global symbol pointer list
+        */
+       skip(-1);
+       i = hp->h_nglob = eval();
+       if (i)
+               hp->s_list = (struct sym **) new (i*sizeof(struct sym *));
+       /*
+        * Setup Absolute DEF linkage.
+        */
+       lkparea(_abs_);
+       ap->a_flag = A_ABS|A_OVR;
+}
+
+/*)Function    VOID    module()
+ *
+ *     The function module() copies the module name into
+ *     the current head structure.
+ *
+ *     local variables:
+ *             char    id[]            module id string
+ *
+ *     global variables:
+ *             head    *headp          The pointer to the first
+ *                                     head structure of a linked list
+ *             head    *hp             Pointer to the current
+ *                                     head structure
+ *             int     lkerr           error flag
+ *             FILE *  stderr          c_library
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    getid()         lklex.c
+ *             char *  strncpy()       c_library
+ *
+ *     side effects:
+ *             The module name is copied into the head structure.
+ */
+
+/*
+ * Module Name
+ */
+VOID
+module()
+{
+       char id[NCPS];
+
+       if (headp) {
+               getid(id, -1);
+               strncpy(hp->m_id, id, NCPS);
+       } else {
+               fprintf(stderr, "No header defined\n");
+               lkerr++;
+       }
+}
diff --git a/as/hc08/lkihx.c b/as/hc08/lkihx.c
new file mode 100644 (file)
index 0000000..c5890cd
--- /dev/null
@@ -0,0 +1,260 @@
+/* lkihx.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lkihx.c
+ *
+ *     The module lkihx.c contains the function to
+ *     output the relocated object code in the
+ *     Intel Hex format.
+ *
+ *     lkihx.c contains the following functions:
+ *             VOID    hexRecord(addr, rtvalIndex)
+ *             VOID    ihx(i)
+ *             VOID    ihxEntendedLinearAddress(a)
+ *
+ *     local variables: hexPageOverrun, lastHexAddr
+ */
+
+/*Intel Hex Format
+ *      Record Mark Field    -  This  field  signifies  the  start  of a
+ *                              record, and consists of an  ascii  colon
+ *                              (:).  
+ *
+ *      Record Length Field  -  This   field   consists   of  two  ascii
+ *                              characters which indicate the number  of
+ *                              data   bytes   in   this   record.   The
+ *                              characters are the result of  converting
+ *                              the  number  of  bytes  in binary to two
+ *                              ascii characters, high digit first.   An
+ *                              End  of  File  record contains two ascii
+ *                              zeros in this field.  
+ *
+ *      Load Address Field   -  This  field  consists  of the four ascii
+ *                              characters which result from  converting
+ *                              the  the  binary value of the address in
+ *                              which to begin loading this record.  The
+ *                              order is as follows:  
+ *
+ *                                  High digit of high byte of address. 
+ *                                  Low digit of high byte of address.  
+ *                                  High digit of low byte of address.  
+ *                                  Low digit of low byte of address.  
+ *
+ *                              In an End of File record this field con-
+ *                              sists of either four ascii zeros or  the
+ *                              program  entry  address.   Currently the
+ *                              entry address option is not supported.  
+ *
+ *      Record Type Field    -  This  field  identifies the record type,
+ *                              which is either 0 for data records or  1
+ *                              for  an End of File record.  It consists
+ *                              of two ascii characters, with  the  high
+ *                              digit of the record type first, followed
+ *                              by the low digit of the record type.  
+ *
+ *      Data Field           -  This  field consists of the actual data,
+ *                              converted to two ascii characters,  high
+ *                              digit first.  There are no data bytes in
+ *                              the End of File record.  
+ *
+ *      Checksum Field       -  The  checksum  field is the 8 bit binary
+ *                              sum of the record length field, the load
+ *                              address  field,  the  record type field,
+ *                              and the data field.  This  sum  is  then
+ *                              negated  (2's  complement) and converted
+ *                              to  two  ascii  characters,  high  digit
+ *                              first.  
+ */
+
+/* Static variable which holds the count of hex page overruns
+ * (crossings of the 64kB boundary). Cleared at explicit extended
+ * address output.
+ */
+static int hexPageOverrun = 0;
+
+/* Global which holds the last (16 bit) address of hex record.
+ * Cleared at begin of new area or when the extended address is output.
+ */
+unsigned int lastHexAddr = 0;
+
+
+/*)Function    hexRecord(addr, rtvalIndex)
+ *
+ *             unsigned addr   starting address of hex record
+ *             int rtvalIndex  starting index into the rtval[] array
+ *
+ *     The function hexRecord() outputs the relocated data
+ *     in the standard Intel Hex format (with inserting
+ *     the extended address record if necessary).
+ *
+ *     local variables:
+ *             Addr_T  chksum          byte checksum
+ *             int             i                       index for loops
+ *             int             overrun         temporary storage for hexPageOverrun
+ *             int             bytes           counter for bytes written
+ *
+ *     global variables:
+ *             FILE *  ofp             output file handle
+ *             int     rtcnt           count of data words
+ *             int     rtflg[]         output the data flag
+ *             Addr_T  rtval[]         relocated data
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             ihxEntendedLinearAddress()      lkihx.c
+ *             hexRecord()             lkihx.c         (recursion)
+ *
+ *     side effects:
+ *             hexPageOverrun is eventually incremented,
+ *             lastHexAddr is updated
+ */
+
+VOID
+hexRecord(unsigned addr, int rtvalIndex)
+{
+       Addr_T chksum;
+       int i, overrun, bytes;
+
+       for (i = rtvalIndex, chksum = 0; i < rtcnt; i++) {
+               if (rtflg[i]) {
+                       if (addr + ++chksum > 0xffff)
+                               break;
+               }
+       }
+       if (chksum == 0)
+               return;                 // nothing to output
+
+       if (lastHexAddr > addr) {
+               overrun = hexPageOverrun + 1;
+               ihxEntendedLinearAddress(lastExtendedAddress + overrun);
+               hexPageOverrun = overrun;
+               hexRecord(addr, rtvalIndex);
+               return;
+       }
+
+       lastHexAddr = addr;
+       fprintf(ofp, ":%02X%04X00", chksum, addr);
+       chksum += (addr >> 8) + (addr & 0xff);
+       for (i = rtvalIndex, bytes = 0; i < rtcnt; i++) {
+               if (rtflg[i]) {
+                   fprintf(ofp, "%02X", rtval[i]);
+                   chksum += rtval[i];
+#if 0
+                       if (addr + ++bytes > 0xffff) {
+                               if (rflag) {
+                                       fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
+                                       overrun = hexPageOverrun + 1;
+                                       ihxEntendedLinearAddress(lastExtendedAddress + overrun);
+                                       hexPageOverrun = overrun;
+                                       hexRecord(0, i + 1);
+                                       return;
+                               } else {
+                                       fprintf(stderr, 
+                                               "warning: extended linear address encountered; "
+                                               "you probably want the -r flag.\n");
+                               }
+                       }
+#endif
+               }
+       }
+       fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
+}
+
+/*)Function    ihx(i)
+ *
+ *             int     i               0 - process data
+ *                                     1 - end of data
+ *
+ *     The function ihx() calls the hexRecord() function for processing data
+ *     or writes the End of Data record to the file defined by ofp.
+ *
+ *     local variables:
+ *             Addr_T  n               auxiliary variable
+ *
+ *     global variables:
+ *             int     hilo            byte order
+ *             FILE *  ofp             output file handle
+ *             Addr_T  rtval[]         relocated data
+ *
+ *     functions called:
+ *             VOID hexRecord()        lkihx.c
+ *             int     fprintf()               c_library
+ *
+ *     side effects:
+ *             The sequence of rtval[0], rtval[1] is eventually changed.
+ */
+
+VOID
+ihx(i)
+{
+       Addr_T n;
+       if (i) {
+               if (hilo == 0) {
+                       n = rtval[0];
+                       rtval[0] = rtval[1];
+                       rtval[1] = n;
+               }
+               hexRecord((rtval[0]<<8) + rtval[1], 2);
+       } else {
+               fprintf(ofp, ":00000001FF\n");
+       }
+}
+
+/*)Function    newArea(i)
+ * The function newArea() is called when processing of new area is started.
+ * It resets the value of lastHexAddr.
+ */ 
+
+VOID
+newArea()
+{
+       lastHexAddr = 0;
+}
+
+/*)Function    ihxEntendedLinearAddress(i)
+ *
+ *             Addr_T  i               16 bit extended linear address.
+ *
+ *     The function ihxEntendedLinearAddress() writes an extended
+ *     linear address record (type 04) to the output file.
+ *
+ *     local variables:
+ *             Addr_T  chksum          byte checksum
+ *
+ *     global variables:
+ *             FILE *  ofp             output file handle
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             The data is output to the file defined by ofp.
+ *             hexPageOverrun and lastHexAddr is cleared
+ */
+VOID
+ihxEntendedLinearAddress(Addr_T a)
+{
+    Addr_T     chksum;
+  
+    /* The checksum is the complement of the bytes in the
+     * record: the 2 is record length, 4 is the extended linear
+     * address record type, plus the two address bytes.
+     */ 
+    chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff);    
+    
+    fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (0-chksum) & 0xff);
+       hexPageOverrun = 0;
+       lastHexAddr = 0;
+}
diff --git a/as/hc08/lklex.c b/as/hc08/lklex.c
new file mode 100644 (file)
index 0000000..daaa4f3
--- /dev/null
@@ -0,0 +1,637 @@
+/* lklex.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lklex.c
+ *
+ *     The module lklex.c contains the general lexical analysis
+ *     functions used to scan the text lines from the .rel files.
+ *
+ *     lklex.c contains the fllowing functions:
+ *             char    endline()
+ *             char    get()
+ *             VOID    getfid()
+ *             VOID    getid()
+ *             VOID    getSid()
+ *             int     getline()
+ *             int     getmap()
+ *             char    getnb()
+ *             int     more()
+ *             VOID    skip()
+ *             VOID    unget()
+ *
+ *     lklex.c contains no local variables.
+ */
+
+/*)Function    VOID    getid(id,c)
+ *
+ *             char *  id              a pointer to a string of
+ *                                     maximum length NCPS
+ *             int     c               mode flag
+ *                                     >=0     this is first character to
+ *                                             copy to the string buffer
+ *                                     <0      skip white space
+ *
+ *     The function getid() scans the current input text line
+ *     from the current position copying the next LETTER | DIGIT string
+ *     into the external string buffer (id).  The string ends when a non
+ *     LETTER or DIGIT character is found. The maximum number of
+ *     characters copied is NCPS.  If the input string is larger than
+ *     NCPS characters then the string is truncated, if the input string
+ *     is shorter than NCPS characters then the string is NULL filled.
+ *     If the mode argument (c) is >=0 then (c) is the first character
+ *     copied to the string buffer, if (c) is <0 then intervening white
+ *     space (SPACES and TABS) are skipped.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of getnb(), get(), and unget() updates the
+ *             global pointer ip the position in the current
+ *             input text line.
+ */
+
+VOID
+getid(id, c)
+register int c;
+char *id;
+{
+       register char *p;
+
+       if (c < 0) {
+               c = getnb();
+       }
+       p = id;
+       do {
+               if (p < &id[NCPS])
+                       *p++ = c;
+       } while (ctype[c=get()] & (LETTER|DIGIT));
+       unget(c);
+       while (p < &id[NCPS])
+               *p++ = 0;
+}
+
+/*)Function    VOID    getSid (char *id)
+ *
+ *             char *  id              a pointer to a string of
+ *                                     maximum length NCPS
+ *
+ *  getSid is derived from getid. It is called from newsym()
+ *  in lksym.c, when an S-record has to be scanned. getSid accepts
+ *  much more characters than getid, which is necessary for SDCC.
+ * 
+ *     The function getSid() scans the current input text line
+ *     from the current position copying the next string
+ *     into the external string buffer (id).  The string ends when a space
+ *  character (space, tab, \0) is found. The maximum number of
+ *     characters copied is NCPS.  If the input string is larger than
+ *     NCPS characters then the string is truncated, if the input string
+ *     is shorter than NCPS characters then the string is NULL filled.
+ *     Intervening white space (SPACES and TABS) are skipped.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of getnb(), get(), and unget() updates the
+ *             global pointer ip the position in the current
+ *             input text line.
+ */
+
+VOID
+getSid (id)
+char *id;
+{
+  register int c;
+       register char *p;
+
+  c = getnb();
+       p = id;
+       do {
+               if (p < &id[NCPS])
+                       *p++ = c;
+               c = get();
+       } while (c != '\0' && c != ' ' && c != '\t');
+       unget(c);
+       while (p < &id[NCPS])
+               *p++ = 0;
+}
+
+/*)Function    VOID    getfid(fid,c)
+ *
+ *             char *  str             a pointer to a string of
+ *                                     maximum length PATH_MAX
+ *             int     c               this is first character to
+ *                                     copy to the string buffer
+ *
+ *     The function getfid() scans the current input text line from
+ *     the current position copying the next string into the external
+ *     string buffer (str).  The string ends when end of line is found.
+ *     Trailing spacers are removed. The maximum number of characters
+ *     copied is PATH_MAX. If the input string is larger than PATH_MAX
+ *     characters then the string is truncated. The string is NULL
+ *     terminated.
+ *
+ *     local variables:
+ *             char *  p               pointer to external string buffer
+ *             int     c               current character value
+ *
+ *     global variables:
+ *             char    ctype[]         a character array which defines the
+ *                                     type of character being processed.
+ *                                     This index is the character
+ *                                     being processed.
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip
+ *             the position in the current input text line.
+ */
+
+VOID
+getfid(str, c)
+register int c;
+char *str;
+{
+       register char *p;
+
+       p = str;
+       do
+       {
+               if (p < &str[PATH_MAX-1])
+                       *p++ = c;
+               c = get();
+       } while (c);
+       /* trim trailing spaces */
+       --p;
+       while (p >= str && ctype[(int)*p] == SPACE)
+               --p;
+       /* terminate the string */
+       *(++p) = '\0';
+}
+
+/*)Function    char    getnb()
+ *
+ *     The function getnb() scans the current input text
+ *     line returning the first character not a SPACE or TAB.
+ *
+ *     local variables:
+ *             int     c               current character from input
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip, the position
+ *             in the current input text line
+ */
+
+char
+getnb()
+{
+       register int c;
+
+       while ((c=get())==' ' || c=='\t')
+               ;
+       return (c);
+}
+
+/*)Function    VOID    skip()
+ *
+ *     The function skip() scans the input text skipping all
+ *     letters and digits.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                     ASCII character
+ *             
+ *     functions called:
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             Input letters and digits are skipped.
+ */
+
+VOID
+skip(c)
+register int c;
+{
+       if (c < 0)
+               c = getnb();
+       while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
+       unget(c);
+}
+
+/*)Function    char    get()
+ *
+ *     The function get() returns the next character in the
+ *     input text line, at the end of the line a
+ *     NULL character is returned.
+ *
+ *     local variables:
+ *             int     c               current character from
+ *                                     input text line
+ *
+ *     global variables:
+ *             char *  ip              pointer into the current
+ *                                     input text line
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             updates ip to the next character position in the
+ *             input text line.  If ip is at the end of the
+ *             line, ip is not updated.
+ */
+
+char
+get()
+{
+       register int c;
+
+       if ((c = *ip) != 0)
+               ++ip;
+       return (c);
+}
+
+/*)Function    VOID    unget(c)
+ *
+ *             int     c               value of last character
+ *                                     read from input text line
+ *
+ *     If (c) is not a NULL character then the global pointer ip
+ *     is updated to point to the preceeding character in the
+ *     input text line.
+ *
+ *     NOTE:   This function does not push the character (c)
+ *             back into the input text line, only
+ *             the pointer ip is changed.
+ *
+ *     local variables:
+ *             int     c               last character read
+ *                                     from input text line
+ *
+ *     global variables:
+ *             char *  ip              position into the current
+ *                                     input text line
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             ip decremented by 1 character position
+ */
+
+VOID
+unget(c)
+{
+       if (c != 0)
+               --ip;
+}
+
+/*)Function    int     getmap(d)
+ *
+ *             int     d               value to compare with the
+ *                                     input text line character
+ *
+ *     The function getmap() converts the 'C' style characters \b, \f,
+ *     \n, \r, and \t to their equivalent ascii values and also
+ *     converts 'C' style octal constants '\123' to their equivalent
+ *     numeric values.  If the first character is equivalent to (d) then
+ *     a (-1) is returned, if the end of the line is detected then
+ *     a 'q' error terminates the parse for this line, or if the first
+ *     character is not a \ then the character value is returned.
+ *
+ *     local variables:
+ *             int     c               value of character
+ *                                     from input text line
+ *             int     n               looping counter
+ *             int     v               current value of numeric conversion
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    get()           lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of get() updates the global pointer ip the position
+ *             in the current input text line
+ */
+
+int
+getmap(d)
+{
+       register int c, n, v;
+
+       if ((c = get()) == '\0')
+               return (-1);
+       if (c == d)
+               return (-1);
+       if (c == '\\') {
+               c = get();
+               switch (c) {
+
+               case 'b':
+                       c = '\b';
+                       break;
+
+               case 'f':
+                       c = '\f';
+                       break;
+
+               case 'n':
+                       c = '\n';
+                       break;
+
+               case 'r':
+                       c = '\r';
+                       break;
+
+               case 't':
+                       c = '\t';
+                       break;
+
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                       n = 0;
+                       v = 0;
+                       while (++n<=3 && c>='0' && c<='7') {
+                               v = (v<<3) + c - '0';
+                               c = get();
+                       }
+                       unget(c);
+                       c = v;
+                       break;
+               }
+       }
+       return (c);
+}
+
+/*)Function    int     getline()
+ *
+ *     The function getline() reads a line of input text from a
+ *     .rel source text file, a .lnk command file or from stdin.
+ *     Lines of text are processed from a single .lnk file or
+ *     multiple .rel files until all files have been read.
+ *     The input text line is copied into the global string ib[]
+ *     and converted to a NULL terminated string.  The function
+ *     getline() returns a (1) after succesfully reading a line
+ *     or a (0) if all files have been read.
+ *     This function also opens each input .lst file and output
+ *     .rst file as each .rel file is processed.
+ *
+ *     local variables:
+ *             int     i               string length
+ *             int     ftype           file type
+ *             char *  fid             file name
+ *
+ *     global variables:
+ *             lfile   *cfp            The pointer *cfp points to the
+ *                                     current lfile structure
+ *             lfile   *filep          The pointer *filep points to the
+ *                                     beginning of a linked list of
+ *                                     lfile structures.
+ *             int     gline           get a line from the LST file
+ *                                     to translate for the RST file
+ *             char    ib[NINPUT]      REL file text line
+ *             int     pass            linker pass number
+ *             int     pflag           print linker command file flag
+ *             FILE    *rfp            The file handle to the current
+ *                                     output RST file
+ *             FILE    *sfp            The file handle sfp points to the
+ *                                     currently open file
+ *             FILE *  stdin           c_library
+ *             FILE *  stdout          c_library
+ *             FILE    *tfp            The file handle to the current
+ *                                     LST file being scanned
+ *             int     uflag           update listing flag
+ *
+ *     called functions:
+ *             FILE *  afile()         lkmain.c
+ *             int     fclose()        c_library
+ *             char *  fgets()         c_library
+ *             int     fprintf()       c_library
+ *             VOID    lkulist()       lklist.c
+ *             VOID    lkexit()        lkmain.c
+ *             int     strlen()        c_library
+ *
+ *     side effects:
+ *             The input stream is scanned.  The .rel files will be
+ *             opened and closed sequentially scanning each in turn.
+ */
+
+int
+getline()
+{
+       register int ftype;
+       register char *fid;
+
+loop:  if (pflag && cfp && cfp->f_type == F_STD)
+               fprintf(stdout, "ASlink >> ");
+
+       if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
+               if (sfp) {
+                       fclose(sfp);
+                       sfp = NULL;
+                       lkulist(0);
+               }
+               if (cfp == NULL) {
+                       cfp = filep;
+               } else {
+                       cfp = cfp->f_flp;
+               }
+               if (cfp) {
+                       ftype = cfp->f_type;
+                       fid = cfp->f_idp;
+                       if (ftype == F_STD) {
+                               sfp = stdin;
+                       } else
+                       if (ftype == F_LNK) {
+                               sfp = afile(fid, "lnk", 0);
+                       } else
+                       if (ftype == F_REL) {
+                               sfp = afile(fid, "rel", 0);
+                               /* if a .cdb file exists then copy it over */
+                               if (dflag && sfp && dfp && pass == 0) {
+                                   FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002
+                                   if (xfp) {
+                                       copyfile(dfp,xfp);
+                                       fclose(xfp);
+                                   }
+                               }
+                               if (uflag && pass != 0) {
+                                SaveLinkedFilePath(fid); //Save the linked path for aomf51
+                                if ((tfp = afile(fid, "lst", 0)) != NULL) {
+                                 if ((rfp = afile(fid, "rst", 1)) == NULL) {
+                                       fclose(tfp);
+                                       tfp = NULL;
+                                 }
+                                }
+                               }
+                               gline = 1;
+                       } else {
+                               fprintf(stderr, "Invalid file type\n");
+                               lkexit(1);
+                       }
+                       if (sfp == NULL) {
+                               lkexit(1);
+                       }
+                       goto loop;
+               } else {
+                       filep = NULL;
+                       return(0);
+               }
+       }
+       chop_crlf(ib);
+       return (1);
+}
+
+/*)Function    int     more()
+ *
+ *     The function more() scans the input text line
+ *     skipping white space (SPACES and TABS) and returns a (0)
+ *     if the end of the line or a comment delimeter (;) is found,
+ *     or a (1) if their are additional characters in the line.
+ *
+ *     local variables:
+ *             int     c               next character from
+ *                                     the input text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             use of getnb() and unget() updates the global pointer ip
+ *             the position in the current input text line
+ */
+
+int
+more()
+{
+       register int c;
+
+       c = getnb();
+       unget(c);
+       return( (c == '\0' || c == ';') ? 0 : 1 );
+}
+
+/*)Function    char    endline()
+ *
+ *     The function endline() scans the input text line
+ *     skipping white space (SPACES and TABS) and returns the next
+ *     character or a (0) if the end of the line is found or a
+ *     comment delimiter (;) is found.
+ *
+ *     local variables:
+ *             int     c               next character from
+ *                                     the input text line
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             char    getnb()         lklex.c
+ *
+ *     side effects:
+ *             Use of getnb() updates the global pointer ip the
+ *             position in the current input text line.
+ */
+
+char
+endline()
+{
+       register int c;
+
+       c = getnb();
+       return( (c == '\0' || c == ';') ? 0 : c );
+}
+
+/*)Function    VOID    chop_crlf(str)
+ *
+ *             char    *str            string to chop
+ *
+ *     The function chop_crlf() removes trailing LF or CR/LF from
+ *     str, if present.
+ *
+ *     local variables:
+ *             int     i               string length
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+VOID
+chop_crlf(str)
+char *str;
+{
+       register int i;
+
+       i = strlen(str);
+       if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
+       if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;
+}
diff --git a/as/hc08/lklibr.c b/as/hc08/lklibr.c
new file mode 100644 (file)
index 0000000..8ca4504
--- /dev/null
@@ -0,0 +1,870 @@
+/* lklibr.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * With contributions for the
+ * object libraries from
+ * Ken Hornstein
+ * kenh@cmf.nrl.navy.mil
+ *
+ */
+
+#define EQ(A,B) !strcmp((A),(B))
+#define MAXLINE 254 /*when using fgets*/
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <sys/types.h>
+#include <sys/malloc.h>
+#else
+#include <malloc.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lklibr.c
+ *
+ *     The module lklibr.c contains the functions which
+ *     (1) specify the path(s) to library files [.LIB]
+ *     (2) specify the library file(s) [.LIB] to search
+ *     (3) search the library files for specific symbols
+ *         and link the module containing this symbol
+ *
+ *     lklibr.c contains the following functions:
+ *             VOID    addpath()
+ *             VOID    addlib()
+ *             VOID    addfile()
+ *             VOID    search()
+ *             VOID    fndsym()
+ *             VOID    library()
+ *             VOID    loadfile()
+ *
+ */
+
+/*)Function    VOID    addpath()
+ *
+ *     The function addpath() creates a linked structure containing
+ *     the paths to various object module library files.
+ *
+ *     local variables:
+ *             lbpath  *lbph           pointer to new path structure
+ *             lbpath  *lbp            temporary pointer
+ *
+ *     global variables:
+ *             lbpath  *lbphead        The pointer to the first
+ *                                     path structure
+ *
+ *      functions called:
+ *             char    getnb()         lklex.c
+ *             VOID *  new()           lksym.c
+ *             int     strlen()        c_library
+ *             char *  strcpy()        c_library
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             An lbpath structure may be created.
+ */
+
+VOID
+addpath()
+{
+       struct lbpath *lbph, *lbp;
+
+       lbph = (struct lbpath *) new (sizeof(struct lbpath));
+       if (lbphead == NULL) {
+               lbphead = lbph;
+       } else {
+               lbp = lbphead;
+               while (lbp->next)
+                       lbp = lbp->next;
+               lbp->next = lbph;
+       }
+       unget(getnb());
+       lbph->path = (char *) new (strlen(ip)+1);
+       strcpy(lbph->path, ip);
+}
+
+/*)Function    VOID    addlib()
+ *
+ *     The function addlib() tests for the existance of a
+ *     library path structure to determine the method of
+ *     adding this library file to the library search structure.
+ *
+ *     This function calls the function addfile() to actually
+ *     add the library file to the search list.
+ *
+ *     local variables:
+ *             lbpath  *lbph           pointer to path structure
+ *
+ *     global variables:
+ *             lbpath  *lbphead        The pointer to the first
+ *                                     path structure
+ *      ip a pointer to the library name
+ *
+ *      functions called:
+ *             VOID    addfile()       lklibr.c
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             The function addfile() may add the file to
+ *             the library search list.
+ */
+
+VOID
+addlib()
+{
+       struct lbpath *lbph;
+    int foundcount=0;
+
+       unget(getnb());
+
+       if (lbphead == NULL)
+    {
+               foundcount=addfile(NULL, ip);
+       }
+    else
+    {
+           for (lbph=lbphead; lbph; lbph=lbph->next)
+        {
+                   foundcount+=addfile(lbph->path, ip);
+           }
+    }
+    if(foundcount == 0)
+    {
+        printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
+    }
+}
+
+/*)Function    int     addfile(path,libfil)
+ *
+ *             char    *path           library path specification
+ *             char    *libfil         library file specification
+ *
+ *     The function addfile() searches for the library file
+ *     by concatenating the path and libfil specifications.
+ *     if the library is found, an lbname structure is created
+ *     and linked to any previously defined structures.  This
+ *     linked list is used by the function fndsym() to attempt
+ *     to find any undefined symbols.
+ *
+ *     The function does not give report an error on invalid
+ *     path / file specifications or if the file is not found.
+ *
+ *     local variables:
+ *             lbname  *lbnh           pointer to new name structure
+ *             lbname  *lbn            temporary pointer
+ *
+ *     global variables:
+ *             lbname  *lbnhead        The pointer to the first
+ *                                     path structure
+ *
+ *      functions called:
+ *             char    getnb()         lklex.c
+ *             VOID *  new()           lksym.c
+ *             int     strlen()        c_library
+ *             char *  strcpy()        c_library
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             An lbname structure may be created.
+ *
+ *  return:
+ *      1: the library was found
+ *      0: the library was not found
+ */
+
+int addfile(char * path, char * libfil)
+{
+       FILE *fp;
+       char *str;
+       struct lbname *lbnh, *lbn;
+#ifdef OTHERSYSTEM
+    int libfilinc=0;
+#endif
+
+       if (path != NULL)
+    {
+               str = (char *) new (strlen(path) + strlen(libfil) + 6);
+               strcpy(str,path);
+#ifdef OTHERSYSTEM
+               if (str[strlen(str)-1] != '/')
+        {
+                       strcat(str,"/");
+               }
+#endif
+       }
+    else
+    {
+               str = (char *) new (strlen(libfil) + 5);
+       }
+
+#ifdef OTHERSYSTEM
+       if (libfil[0] == '/')
+    {
+        libfil++;
+        libfilinc=1;
+    }
+#endif
+       
+    strcat(str, libfil);
+       if(strchr(libfil, FSEPX) == NULL)
+    {
+               sprintf(&str[strlen(str)], "%clib", FSEPX);
+       }
+
+    fp=fopen(str, "r");
+    if(fp == NULL)
+    {
+        /*Ok, that didn't work.  Try with the 'libfil' name only*/
+#ifdef OTHERSYSTEM
+        if(libfilinc) libfil--;
+#endif
+        fp=fopen(libfil, "r");
+        if(fp != NULL) 
+        {
+            /*Bingo!  'libfil' is the absolute path of the library*/
+            strcpy(str, libfil);
+            path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
+        }
+    }
+
+    if(path==NULL)
+    {
+        /*'path' can not be null since it is needed to find the '.rel' files associated with
+        the library.  So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
+        That way putting 'path' and 'libfil' together will result into the original filepath
+        as contained in 'str'.*/
+        int j;
+        path = (char *) new (strlen(str));
+        strcpy(path, str);
+        for(j=strlen(path)-1; j>=0; j--)
+        {
+            if((path[j]=='\\')||(path[j]=='/'))
+            {
+                strcpy(libfil, &path[j+1]);
+                path[j+1]=0;
+                break;
+            }
+        }
+        if(j<=0) path[0]=0;
+    }
+
+       if (fp != NULL)
+    {
+               fclose(fp);
+               lbnh = (struct lbname *) new (sizeof(struct lbname));
+               if (lbnhead == NULL)
+        {
+                       lbnhead = lbnh;
+               }
+        else
+        {
+                       lbn = lbnhead;
+                       while (lbn->next)
+                               lbn = lbn->next;
+                       lbn->next = lbnh;
+               }
+               
+        lbnh->path = path;
+               lbnh->libfil = (char *) new (strlen(libfil) + 1);
+               strcpy(lbnh->libfil,libfil);
+               lbnh->libspc = str;
+        return 1;
+       } 
+    else 
+    {
+               free(str);
+        return 0;
+       }
+}
+
+/*)Function    VOID    search()
+ *
+ *     The function search() looks through all the symbol tables
+ *     at the end of pass 1.  If any undefined symbols are found
+ *     then the function fndsym() is called. Function fndsym()
+ *     searches any specified library files to automagically
+ *     import the object modules containing the needed symbol.
+ *
+ *     After a symbol is found and imported by the function
+ *     fndsym() the symbol tables are again searched.  The
+ *     symbol tables are search until no more symbols can be
+ *     resolved within the library files.  This ensures that
+ *     back references from one library module to another are
+ *     also resolved.
+ *
+ *     local variables:
+ *             int     i               temporary counter
+ *             sym     *sp             pointer to a symbol structure
+ *             int     symfnd          found a symbol flag
+ *
+ *     global variables:
+ *             sym     *symhash[]      array of pointers to symbol tables
+ *
+ *      functions called:
+ *             int     fndsym()        lklibr.c
+ *
+ *     side effects:
+ *             If a symbol is found then the library object module
+ *             containing the symbol will be imported and linked.
+ */
+
+VOID
+search()
+{
+       register struct sym *sp;
+       register int i,symfnd;
+
+       /*
+        * Look for undefined symbols.  Keep
+        * searching until no more symbols are resolved.
+        */
+       symfnd = 1;
+       while (symfnd) {
+               symfnd = 0;
+               /*
+                * Look through all the symbols
+                */
+               for (i=0; i<NHASH; ++i) {
+                       sp = symhash[i];
+                       while (sp) {
+                               /* If we find an undefined symbol
+                                * (one where S_DEF is not set), then
+                                * try looking for it.  If we find it
+                                * in any of the libraries then
+                                * increment symfnd.  This will force
+                                * another pass of symbol searching and
+                                * make sure that back references work.
+                                */
+                               if ((sp->s_type & S_DEF) == 0) {
+                                       if (fndsym(sp->s_id)) {
+                                               symfnd++;
+                                       }
+                               }
+                               sp = sp->s_sp;
+                       }
+               }
+       }
+}
+
+/*Load a .rel file embedded in a sdcclib file*/
+void LoadRel(FILE * libfp, char * ModName)
+{
+       char str[NINPUT+2];
+       int state=0;
+
+       while (fgets(str, NINPUT, libfp) != NULL)
+       {
+               str[NINPUT+1] = '\0';
+               chop_crlf(str);
+               switch(state)
+               {
+                       case 0:
+                               if(EQ(str, "<FILE>"))
+                               {
+                                       fgets(str, NINPUT, libfp);
+                                       str[NINPUT+1] = '\0';
+                                       chop_crlf(str);
+                                       if(EQ(str, ModName)) state=1;
+                                       else
+                                       {
+                                               printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
+                                               lkexit(1);
+                                       }
+                               }
+                       break;
+                       case 1:
+                               if(EQ(str, "<REL>")) state=2;
+                       break;
+                       case 2:
+                               if(EQ(str, "</REL>")) return;
+                               ip = str;
+                               link_main();
+                       break;
+               }
+       }
+}
+
+/*Load an .adb file embedded in a sdcclib file.  If there is
+something between <ADB> and </ADB> returns 1, otherwise returns 0.
+This way the aomf51 will not have uselless empty modules. */
+
+int LoadAdb(FILE * libfp)
+{
+       char str[MAXLINE+1];
+       int state=0;
+       int ToReturn=0;
+
+       while (fgets(str, MAXLINE, libfp) != NULL)
+       {
+               str[NINPUT+1] = '\0';
+               chop_crlf(str);
+               switch(state)
+               {
+                       case 0:
+                               if(EQ(str, "<ADB>")) state=1;
+                       break;
+                       case 1:
+                               if(EQ(str, "</ADB>")) return ToReturn;
+                               fprintf(dfp, "%s\n", str);
+                               ToReturn=1;
+                       break;
+               }
+       }
+       return ToReturn;
+}
+
+/*Check for a symbol in a SDCC library.  If found, add the embedded .rel and
+.adb files from the library.  The library must be created with the SDCC
+librarian 'sdcclib' since the linking process depends on the correct file offsets
+embedded in the library file.*/
+
+int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
+{
+       struct lbfile *lbfh, *lbf;
+       char ModName[NCPS]="";
+       char FLine[MAXLINE+1];
+       int state=0;
+       long IndexOffset=0, FileOffset;
+
+       while(!feof(libfp))
+    {
+        FLine[0]=0;
+        fgets(FLine, MAXLINE, libfp);
+        chop_crlf(FLine);
+
+        switch(state)
+        {
+            case 0:
+                if(EQ(FLine, "<INDEX>"))
+                {
+                                       /*The next line has the size of the index*/
+                    FLine[0]=0;
+                    fgets(FLine, MAXLINE, libfp);
+                    chop_crlf(FLine);
+                                       IndexOffset=atol(FLine);
+                                       state=1;
+                }
+            break;
+            case 1:
+                if(EQ(FLine, "<MODULE>"))
+                               {
+                                       /*The next line has the name of the module and the offset
+                                       of the corresponding embedded file in the library*/
+                    FLine[0]=0;
+                    fgets(FLine, MAXLINE, libfp);
+                    chop_crlf(FLine);
+                                       sscanf(FLine, "%s %ld", ModName, &FileOffset);
+                                       state=2;
+                               }
+                else if(EQ(FLine, "</INDEX>"))
+                               {
+                                       /*Reached the end of the index.  The symbol is not in this library.*/
+                                       return 0;
+                               }
+            break;
+            case 2:
+                if(EQ(FLine, "</MODULE>"))
+                               {
+                                       /*The symbol is not in this module, try the next one*/
+                    state=1;
+                               }
+                else
+                               {
+                                       /*Check if this is the symbol we are looking for.*/
+                                       if (strncmp(SymName, FLine, NCPS)==0)
+                                       {
+                                               /*The symbol is in this module.*/
+
+                                               /*As in the original library format, it is assumed that the .rel
+                                               files reside in the same directory as the lib files.*/
+                                               strcat(DirLib, ModName);
+                                       sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
+
+                                               /*If this module has been loaded already don't load it again.*/
+                                               lbf = lbfhead;
+                                               while (lbf)
+                                               {
+                                                       if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
+                                                       lbf=lbf->next;
+                                               }
+                                               
+                                               /*Add the embedded file to the list of files to be loaded in
+                                               the second pass.  That is performed latter by the function
+                                               library() below.*/
+                                               lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+                                               if (lbfhead == NULL)
+                                               {
+                                                       lbfhead = lbfh;
+                                               }
+                                               else
+                                               {
+                                                       lbf = lbfhead;
+                                                       while (lbf->next)
+                                                       lbf = lbf->next;
+                                                       lbf->next = lbfh;
+                                               }
+
+                                               lbfh->libspc = PathLib;
+                                               lbfh->filspc = DirLib;
+                                               lbfh->relfil = (char *) new (strlen(ModName) + 1);
+                                               strcpy(lbfh->relfil, ModName);
+                                               /*Library embedded file, so lbfh->offset must be >=0*/
+                                               lbfh->offset = IndexOffset+FileOffset;
+                                               
+                                               /*Jump to where the .rel begins and load it.*/
+                                               fseek(libfp, lbfh->offset, SEEK_SET);
+                                               LoadRel(libfp, ModName);
+
+                                               /* if cdb information required & .adb file present */
+                                               if (dflag && dfp)
+                                               {
+                                                       if(LoadAdb(libfp))
+                                                               SaveLinkedFilePath(DirLib);
+                                               }
+                                               return 1; /*Found the symbol, so success!*/
+                                       }
+                               }
+            break;
+                       
+                       default:
+                               return 0; /*It should never reach this point, but just in case...*/
+                       break;
+        }
+    }
+
+       return 0; /*The symbol is not in this library*/
+}
+
+/*)Function    VOID    fndsym(name)
+ *
+ *             char    *name           symbol name to find
+ *
+ *     The function fndsym() searches through all combinations of the
+ *     library path specifications (input by the -k option) and the
+ *     library file specifications (input by the -l option) that
+ *     lead to an existing file.
+ *
+ *     The file specicifation may be formed in one of two ways:
+ *
+ *     (1)     If the library file contained an absolute
+ *             path/file specification then this becomes filspc.
+ *             (i.e. C:\...)
+ *
+ *     (2)     If the library file contains a relative path/file
+ *             specification then the concatenation of the path
+ *             and this file specification becomes filspc.
+ *             (i.e. \...)
+ *
+ *     The structure lbfile is created for the first library
+ *     object file which contains the definition for the
+ *     specified undefined symbol.
+ *
+ *     If the library file [.LIB] contains file specifications for
+ *     non existant files, no errors are returned.
+ *
+ *     local variables:
+ *             char    buf[]           [.REL] file input line
+ *             char    c               [.REL] file input character
+ *             FILE    *fp             file handle for object file
+ *             lbfile  *lbf            temporary pointer
+ *             lbfile  *lbfh           pointer to lbfile structure
+ *             FILE    *libfp          file handle for library file
+ *             lbname  *lbnh           pointer to lbname structure
+ *             char    *path           file specification path
+ *             char    relfil[]        [.REL] file specification
+ *             char    *str            combined path and file specification
+ *             char    symname[]       [.REL] file symbol string
+ *
+ *     global variables:
+ *             lbname  *lbnhead        The pointer to the first
+ *                                     name structure
+ *             lbfile  *lbfhead        The pointer to the first
+ *                                     file structure
+ *
+ *      functions called:
+ *             int     fclose()        c_library
+ *             int     fgets()         c_library
+ *             FILE    *fopen()        c_library
+ *             VOID    free()          c_library
+ *             char    getnb()         lklex.c
+ *             VOID    lkexit()        lkmain.c
+ *             VOID    loadfile()      lklibr.c
+ *             VOID *  new()           lksym.c
+ *             char *  sprintf()       c_library
+ *             int     sscanf()        c_library
+ *             char *  strcat()        c_library
+ *             char *  strchr()        c_library
+ *             char *  strcpy()        c_library
+ *             int     strlen()        c_library
+ *             int     strncmp()       c_library
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             If the symbol is found then a new lbfile structure
+ *             is created and added to the linked list of lbfile
+ *             structures.  The file containing the found symbol
+ *             is linked.
+ */
+
+int
+fndsym(name)
+char *name;
+{
+       FILE *libfp, *fp;
+       struct lbname *lbnh;
+       struct lbfile *lbfh, *lbf;
+       char relfil[NINPUT+2];
+       char buf[NINPUT+2];
+       char symname[NINPUT];
+       char *path,*str;
+       char c;
+       int result;
+
+       /*
+        * Search through every library in the linked list "lbnhead".
+        */
+
+       for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
+       {
+               if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
+               {
+                       fprintf(stderr, "Cannot open library file %s\n",
+                               lbnh->libspc);
+                       lkexit(1);
+               }
+               path = lbnh->path;
+
+               /*
+                * Read in a line from the library file.
+                * This is the relative file specification
+                * for a .REL file in this library.
+                */
+
+               while (fgets(relfil, NINPUT, libfp) != NULL)
+               {
+                   relfil[NINPUT+1] = '\0';
+                   chop_crlf(relfil);
+                   if (path != NULL)
+                       {
+                               str = (char *) new (strlen(path)+strlen(relfil)+6);
+                               strcpy(str,path);
+#ifdef OTHERSYSTEM
+                               if (str[strlen(str)-1] != '/')
+                               {
+                                       strcat(str,"/");
+                               }
+#endif
+                   }
+                       else
+                       {
+                               str = (char *) new (strlen(relfil) + 5);
+                   }
+
+                       if(strcmp(relfil, "<SDCCLIB>")==0)
+                       {
+                               result=SdccLib(lbnh->libspc, libfp, str, name);
+                               fclose(libfp);
+                               if(result) return(1); /*Found the symbol*/
+                               free(str);
+                               /*The symbol is not in the current library,
+                               check the next library in the list*/
+                               break; 
+                       }
+
+                       /*From here down is the support for libraries in the original format*/
+                       if (relfil[0] == '\\')
+                       {
+                               strcat(str,relfil+1);
+                   }
+                       else
+                       {
+                               strcat(str,relfil);
+                   }
+                   
+                       if(strchr(relfil, FSEPX) == NULL)
+                       {
+                               sprintf(&str[strlen(str)], "%crel", FSEPX);
+                   }
+
+                       if ((fp = fopen(str, "r")) != NULL)
+                       {
+
+                               /*
+                                * Read in the object file.  Look for lines that
+                                * begin with "S" and end with "D".  These are
+                                * symbol table definitions.  If we find one, see
+                                * if it is our symbol.  Make sure we only read in
+                                * our object file and don't go into the next one.
+                                */
+                       
+                               while (fgets(buf, NINPUT, fp) != NULL)
+                               {
+                                       buf[NINPUT+1] = '\0';
+                                       chop_crlf(buf);
+                                       /*
+                                        * Skip everything that's not a symbol record.
+                                        */
+                                       if (buf[0] != 'S') continue;
+
+                                       /*
+                                       * When a 'T line' is found terminate file scan.
+                                       * All 'S line's preceed 'T line's in .REL files.
+                                       */
+                                       if (buf[0] == 'T') break;
+
+                                       sscanf(buf, "S %s %c", symname, &c);
+
+                                       /*
+                                       * If we find a symbol definition for the
+                                       * symbol we're looking for, load in the
+                                       * file and add it to lbfhead so it gets
+                                       * loaded on pass number 2.
+                                       */
+                                       if (strncmp(symname, name, NCPS) == 0 && c == 'D')
+                                       {
+                                               lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+                                               if (lbfhead == NULL)
+                                               {
+                                                       lbfhead = lbfh;
+                                               }
+                                               else
+                                               {
+                                                       lbf = lbfhead;
+                                                       while (lbf->next)
+                                                       lbf = lbf->next;
+                                                       lbf->next = lbfh;
+                                               }
+
+                                               lbfh->libspc = lbnh->libspc;
+                                               lbfh->filspc = str;
+                                               lbfh->relfil = (char *) new (strlen(relfil) + 1);
+                                               lbfh->offset = -1; /*Stand alone rel file*/
+                                               strcpy(lbfh->relfil,relfil);
+                                               fclose(fp);
+                                               fclose(libfp);                 
+                       
+                                               /* if cdb information required & adb file present */
+                                               if (dflag && dfp)
+                                               {
+                                                       FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
+                                                       if (xfp)
+                                                       {
+                                                               SaveLinkedFilePath(str);
+                                                               copyfile(dfp,xfp);
+                                                               fclose(xfp);
+                                                       }
+                                               }
+                                               loadfile(str);
+                                               return (1);
+                                       }
+                               }
+                               fclose(fp);
+                       }
+                       free(str);
+               }
+               fclose(libfp);
+       }
+       return(0);
+}
+
+void loadfile_SdccLib(char * libspc, char * module, long offset)
+{
+       FILE *fp;
+
+       if ((fp = fopen(libspc,"r")) != NULL)
+       {
+               fseek(fp, offset, SEEK_SET);
+               LoadRel(fp, module);
+               fclose(fp);
+       }
+}
+
+/*)Function    VOID    library()
+ *
+ *     The function library() links all the library object files
+ *     contained in the lbfile structures.
+ *
+ *     local variables:
+ *             lbfile  *lbfh           pointer to lbfile structure
+ *
+ *     global variables:
+ *             lbfile  *lbfhead        pointer to first lbfile structure
+ *
+ *      functions called:
+ *             VOID    loadfile        lklibr.c
+ *
+ *     side effects:
+ *             Links all files contained in the lbfile structures.
+ */
+
+VOID
+library()
+{
+       struct lbfile *lbfh;
+
+       for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
+       {
+               if(lbfh->offset<0)
+               {
+                       /*Stand alone rel file (original lib format)*/
+                       loadfile(lbfh->filspc);
+               }
+               else
+               {
+                       /*rel file embedded in lib (new lib format)*/
+                       loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+               }
+       }
+}
+
+/*)Function    VOID    loadfile(filspc)
+ *
+ *             char    *filspc         library object file specification
+ *
+ *     The function loadfile() links the library object module.
+ *
+ *     local variables:
+ *             FILE    *fp             file handle
+ *             int     i               input line length
+ *             char    str[]           file input line
+ *
+ *     global variables:
+ *             char    *ip             pointer to linker input string
+ *
+ *      functions called:
+ *             int     fclose()        c_library
+ *             int     fgets()         c_library
+ *             FILE *  fopen()         c_library
+ *             VOID    link_main()     lkmain.c
+ *             int     strlen()        c_library
+ *
+ *     side effects:
+ *             If file exists it is linked.
+ */
+
+VOID
+loadfile(filspc)
+char *filspc;
+{
+       FILE *fp;
+       char str[NINPUT+2];
+
+       if ((fp = fopen(filspc,"r")) != NULL) {
+               while (fgets(str, NINPUT, fp) != NULL) {
+                       str[NINPUT+1] = '\0';
+                       chop_crlf(str);
+                       ip = str;
+                       link_main();
+               }
+               fclose(fp);
+       }
+}
diff --git a/as/hc08/lklist.c b/as/hc08/lklist.c
new file mode 100644 (file)
index 0000000..5325ec8
--- /dev/null
@@ -0,0 +1,1099 @@
+/* lklist.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *           - lstarea: show s_id as string rather than array [NCPS]
+ *           - lstarea: show a_id as string rather than array [NCPS]
+ * 31-Oct-97 JLH: add NoICE output file genration in lstarea
+ * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+/*)Module      lklist.c
+ *
+ *     The module lklist.c contains the functions which
+ *     output the linker .map file and produce a relocated
+ *     listing .rst file.
+ *
+ *     lklist.c contains the following functions:
+ *             int     dgt()
+ *             VOID    lstarea()
+ *             VOID    lkulist()
+ *             VOID    lkalist()
+ *             VOID    lkglist()
+ *             VOID    newpag()
+ *             VOID    slew()
+ *
+ *     lklist.c contains no local variables.
+ */
+
+/*)Function    VOID    slew(fp)
+ *
+ *             FILE *  fp              output file handle
+ *
+ *     The function slew() increments the page line counter.
+ *     If the number of lines exceeds the maximum number of
+ *     lines per page then a page skip and a page header are
+ *     output.
+ *
+ *     local variables:
+ *             int     i               loop counter
+ *
+ *     global variables:
+ *             int     lop             current line number on page
+ *             int     xflag           Map file radix type flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    newpag()        lklist.c
+ *
+ *     side effects:
+ *             The page line and the page count may be updated.
+ */
+
+VOID
+slew(fp)
+FILE *fp;
+{
+       register int i;
+
+       if (lop++ >= NLPP) {
+               newpag(fp);
+               if (xflag == 0) {
+                       fprintf(fp, "Hexadecimal\n\n");
+               } else
+               if (xflag == 1) {
+                       fprintf(fp, "Octal\n\n");
+               } else
+               if (xflag == 2) {
+                       fprintf(fp, "Decimal\n\n");
+               }
+               fprintf(fp, "Area       Addr   Size");
+               fprintf(fp, "   Decimal Bytes (Attributes)\n");
+               for(i=0;i<4;++i)
+                       fprintf(fp, "      Value--Global");
+               fprintf(fp, "\n\n");
+               lop += 6;
+       }
+}
+
+/*)Function    VOID    newpag()
+ *
+ *     The function newpag() outputs a page skip, writes the
+ *     first page header line, sets the line count to 1, and
+ *     increments the page counter.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             int     lop             current line number on page
+ *             int     page            current page number
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             The page and line counters are updated.
+ */
+
+VOID
+newpag(fp)
+FILE *fp;
+{
+       fprintf(fp, "\fASxxxx Linker %s,  page %u.\n", VERSION, ++page);
+       lop = 1;
+}
+
+/* Used for qsort call in lstsym */
+static int _cmpSymByAddr(const void *p1, const void *p2)
+{
+    struct sym **s1 = (struct sym **)(p1);
+    struct sym **s2 = (struct sym **)(p2);
+    int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) -
+               ((*s2)->s_addr + (*s2)->s_axp->a_addr);
+
+    /* Sort first by address, then by name. */
+    if (delta)
+    {
+       return delta;
+    }
+    return strcmp((*s1)->s_id,(*s2)->s_id);    
+}
+
+
+#if    NCPS-8
+
+/* NCPS != 8 */
+/*)Function    VOID    lstarea(xp)
+ *
+ *             area *  xp              pointer to an area structure
+ *
+ *     The function lstarea() creates the linker map output for
+ *     the area specified by pointer xp.  The generated output
+ *     area header includes the area name, starting address,
+ *     size of area, number of words (in decimal), and the
+ *     area attributes.  The symbols defined in this area are
+ *     sorted by ascending address and output one per line
+ *     in the selected radix.
+ *
+ *     local variables:
+ *             areax * oxp             pointer to an area extension structure
+ *             int     c               character value
+ *             int     i               loop counter
+ *             int     j               bubble sort update status
+ *             char *  ptr             pointer to an id string
+ *             int     nmsym           number of symbols in area
+ *             Addr_T  a0              temporary
+ *             Addr_T  ai              temporary
+ *             Addr_T  aj              temporary
+ *             sym *   sp              pointer to a symbol structure
+ *             sym **  p               pointer to an array of
+ *                                     pointers to symbol structures
+ *
+ *     global variables:
+ *             FILE    *mfp            Map output file handle
+ *             sym *symhash[NHASH]     array of pointers to NHASH
+ *                                     linked symbol lists
+ *             int     xflag           Map file radix type flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    free()          c_library
+ *             char *  malloc()        c_library
+ *             char    putc()          c_library
+ *             VOID    slew()          lklist.c
+ *
+ *     side effects:
+ *             Map output generated.
+ */
+
+VOID
+lstarea(xp)
+struct area *xp;
+{
+       register struct areax *oxp;
+       register int i;
+       /* int j; */
+       register char *ptr;
+       int nmsym;
+       /* Addr_T a0; */
+       Addr_T     ai, aj;
+       struct sym *sp;
+       struct sym **p;
+       int memPage;
+
+       putc('\n', mfp);
+       if (xflag == 0) {
+               fprintf(mfp, "Hexadecimal\n\n");
+       } else
+       if (xflag == 1) {
+               fprintf(mfp, "Octal\n\n");
+       } else
+       if (xflag == 2) {
+               fprintf(mfp, "Decimal\n\n");
+       }
+       fprintf(mfp, "Area                               ");
+       fprintf(mfp, "Addr   Size   Decimal %s (Attributes)\n",
+               (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/
+       fprintf(mfp, "--------------------------------   ");
+       fprintf(mfp, "----   ----   ------- ----- ------------\n");
+       /*
+        * Output Area Header
+        */
+       ptr = &xp->a_id[0];
+       fprintf(mfp, "%-32s", ptr );    /* JLH: width matches --- above */
+       ai = xp->a_addr;
+       aj = xp->a_size;
+       if (xflag == 0) {
+               fprintf(mfp, "   %04X   %04X", ai, aj);
+       } else
+       if (xflag == 1) {
+               fprintf(mfp, " %06o %06o", ai, aj);
+       } else
+       if (xflag == 2) {
+               fprintf(mfp, "  %05u  %05u", ai, aj);
+       }
+       fprintf(mfp, " = %6u. %s ", aj,
+               (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/
+       if (xp->a_flag & A_ABS) {
+               fprintf(mfp, "(ABS");
+       } else {
+               fprintf(mfp, "(REL");
+       }
+       if (xp->a_flag & A_OVR) {
+               fprintf(mfp, ",OVR");
+       } else {
+               fprintf(mfp, ",CON");
+       }
+       if (xp->a_flag & A_PAG) {
+               fprintf(mfp, ",PAG");
+       }
+
+       memPage = 0x00;
+       if (xp->a_flag & A_CODE) {
+               fprintf(mfp, ",CODE");
+               memPage = 0x0C;
+       }
+       if (xp->a_flag & A_XDATA) {
+               fprintf(mfp, ",XDATA");
+               memPage = 0x0D;
+       }
+       if (xp->a_flag & A_BIT) {
+               fprintf(mfp, ",BIT");
+               memPage = 0x0B;
+       }
+       fprintf(mfp, ")");
+       if (xp->a_flag & A_PAG) {
+               ai = (ai & 0xFF);
+               aj = (aj > 256);
+               if (ai || aj) { fprintf(mfp, "  "); }
+               if (ai)      { fprintf(mfp, " Boundary"); }
+               if (ai & aj)  { fprintf(mfp, " /"); }
+               if (aj)      { fprintf(mfp, " Length"); }
+               if (ai || aj) { fprintf(mfp, " Error"); }
+       }
+
+       /*
+        * Find number of symbols in area
+        */
+       nmsym = 0;
+       oxp = xp->a_axp;
+       while (oxp) {
+               for (i=0; i<NHASH; i++) {
+                       sp = symhash[i];
+                       while (sp != NULL) {
+                               if (oxp == sp->s_axp)
+                                       ++nmsym;
+                               sp = sp->s_sp;
+                       }
+               }
+               oxp = oxp->a_axp;
+       }
+       if (nmsym == 0) {
+               putc('\n', mfp);
+               return;
+       }
+
+       /*
+        * Allocate space for an array of pointers to symbols
+        * and load array.
+        */
+       if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
+               == NULL) {
+               fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
+               return;
+       }
+       nmsym = 0;
+       oxp = xp->a_axp;
+       while (oxp) {
+               for (i=0; i<NHASH; i++) {
+                       sp = symhash[i];
+                       while (sp != NULL) {
+                               if (oxp == sp->s_axp) {
+                                       p[nmsym++] = sp;
+                               }
+                               sp = sp->s_sp;
+                       }
+               }
+               oxp = oxp->a_axp;
+       }
+
+#if 0
+       /*
+        * Bubble Sort of Addresses in Symbol Table Array
+        */
+       j = 1;
+       while (j) {
+               j = 0;
+               sp = p[0];
+               a0 = sp->s_addr + sp->s_axp->a_addr;
+               for (i=1; i<nmsym; ++i) {
+                       sp = p[i];
+                       ai = sp->s_addr + sp->s_axp->a_addr;
+                       if (a0 > ai) {
+                               j = 1;
+                               p[i] = p[i-1];
+                               p[i-1] = sp;
+                       }
+                       a0 = ai;
+               }
+       }
+#else
+       qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
+#endif 
+
+       /*
+        * Symbol Table Output
+        */
+
+       i = 0;
+       fprintf(mfp, "\n\n");
+       fprintf(mfp, "      Value  Global\n");
+       fprintf(mfp, "   --------  --------------------------------");
+       while (i < nmsym) {
+               fprintf(mfp, "\n");
+               if (memPage != 0) 
+                       fprintf(mfp, "  %02X:", memPage);
+               else
+                       fprintf(mfp, "     ");
+
+               sp = p[i];
+               aj = sp->s_addr + sp->s_axp->a_addr;
+               if (xflag == 0) {
+                       fprintf(mfp, "%04X    ", aj);
+               } else
+               if (xflag == 1) {
+                       fprintf(mfp, "%06o  ", aj);
+               } else
+               if (xflag == 2) {
+                       fprintf(mfp, "%05u   ", aj);
+               }
+               ptr = &sp->s_id[0];
+               fprintf(mfp, "%s", ptr );
+               
+               /* if cdb flag set the output cdb Information 
+                  and the symbol has a '$' sign in it then */
+               if (dflag &&
+                   strchr(ptr,'$'))
+                   fprintf(dfp,"L:%s:%X\n",ptr,aj);
+
+               /* NoICE output of symbol */
+               if (jflag) DefineNoICE( ptr, aj, memPage );
+
+               i++;
+       }
+       putc('\n', mfp);
+       free(p);
+}
+
+#else
+
+/* NCPS == 8 */
+/*)Function    VOID    lstarea(xp)
+ *
+ *             area *  xp              pointer to an area structure
+ *
+ *     The function lstarea() creates the linker map output for
+ *     the area specified by pointer xp.  The generated output
+ *     area header includes the area name, starting address,
+ *     size of area, number of words (in decimal), and the
+ *     area attributes.  The symbols defined in this area are
+ *     sorted by ascending address and output four per line
+ *     in the selected radix.
+ *
+ *     local variables:
+ *             areax * oxp             pointer to an area extension structure
+ *             int     c               character value
+ *             int     i               loop counter
+ *             int     j               bubble sort update status
+ *             char *  ptr             pointer to an id string
+ *             int     nmsym           number of symbols in area
+ *             Addr_T  a0              temporary
+ *             Addr_T  ai              temporary
+ *             Addr_T  aj              temporary
+ *             sym *   sp              pointer to a symbol structure
+ *             sym **  p               pointer to an array of
+ *                                     pointers to symbol structures
+ *
+ *     global variables:
+ *             FILE    *mfp            Map output file handle
+ *             sym *symhash[NHASH]     array of pointers to NHASH
+ *                                     linked symbol lists
+ *             int     xflag           Map file radix type flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID    free()          c_library
+ *             char *  malloc()        c_library
+ *             char    putc()          c_library
+ *             VOID    slew()          lklist.c
+ *
+ *     side effects:
+ *             Map output generated.
+ */
+
+VOID
+lstarea(xp)
+struct area *xp;
+{
+       register struct areax *oxp;
+       register c, i, j;
+       register char *ptr;
+       int nmsym;
+       Addr_T a0, ai, aj;
+       struct sym *sp;
+       struct sym **p;
+        int page;
+
+       putc('\n', mfp);
+       slew(mfp);
+       /*
+        * Output Area Header
+        */
+       ptr = &xp->a_id[0];
+       while (ptr < &xp->a_id[NCPS]) {
+               if ((c = *ptr++) != 0) {
+                       putc(c, mfp);
+               } else {
+                       putc(' ', mfp);
+               }
+       }
+       ai = xp->a_addr;
+       aj = xp->a_size;
+       if (xflag == 0) {
+               fprintf(mfp, "   %04X   %04X", ai, aj);
+       } else
+       if (xflag == 1) {
+               fprintf(mfp, " %06o %06o", ai, aj);
+       } else
+       if (xflag == 2) {
+               fprintf(mfp, "  %05u  %05u", ai, aj);
+       }
+       fprintf(mfp, " = %6u. bytes ", aj);
+       if (xp->a_flag & A_ABS) {
+               fprintf(mfp, "(ABS");
+       } else {
+               fprintf(mfp, "(REL");
+       }
+       if (xp->a_flag & A_OVR) {
+               fprintf(mfp, ",OVR");
+       } else {
+               fprintf(mfp, ",CON");
+       }
+       if (xp->a_flag & A_PAG) {
+               fprintf(mfp, ",PAG");
+       }
+
+       page = 0x00;
+       if (xp->a_flag & A_CODE) {
+               fprintf(mfp, ",CODE");
+               memPage = 0x0C;
+       }
+       if (xp->a_flag & A_XDATA) {
+               fprintf(mfp, ",XDATA");
+               memPage = 0x0D;
+       }
+       if (xp->a_flag & A_BIT) {
+               fprintf(mfp, ",BIT");
+               memPage = 0x0B;
+       }
+       fprintf(mfp, ")");
+       if (xp->a_flag & A_PAG) {
+               ai = (ai & 0xFF);
+               aj = (aj > 256);
+               if (ai || aj) { fprintf(mfp, "  "); }
+               if (ai)      { fprintf(mfp, " Boundary"); }
+               if (ai & aj)  { fprintf(mfp, " /"); }
+               if (aj)      { fprintf(mfp, " Length"); }
+               if (ai || aj) { fprintf(mfp, " Error"); }
+       }
+
+       /*
+        * Find number of symbols in area
+        */
+       nmsym = 0;
+       oxp = xp->a_axp;
+       while (oxp) {
+               for (i=0; i<NHASH; i++) {
+                       sp = symhash[i];
+                       while (sp != NULL) {
+                               if (oxp == sp->s_axp)
+                                       ++nmsym;
+                               sp = sp->s_sp;
+                       }
+               }
+               oxp = oxp->a_axp;
+       }
+       if (nmsym == 0) {
+               putc('\n', mfp);
+               slew(mfp);
+               return;
+       }
+
+       /*
+        * Allocate space for an array of pointers to symbols
+        * and load array.
+        */
+       if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
+               == NULL) {
+               fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
+               slew(mfp);
+               return;
+       }
+       nmsym = 0;
+       oxp = xp->a_axp;
+       while (oxp) {
+               for (i=0; i<NHASH; i++) {
+                       sp = symhash[i];
+                       while (sp != NULL) {
+                               if (oxp == sp->s_axp) {
+                                       p[nmsym++] = sp;
+                               }
+                               sp = sp->s_sp;
+                       }
+               }
+               oxp = oxp->a_axp;
+       }
+
+#if 0
+       /*
+        * Bubble Sort of Addresses in Symbol Table Array
+        */
+       j = 1;
+       while (j) {
+               j = 0;
+               sp = p[0];
+               a0 = sp->s_addr + sp->s_axp->a_addr;
+               for (i=1; i<nmsym; ++i) {
+                       sp = p[i];
+                       ai = sp->s_addr + sp->s_axp->a_addr;
+                       if (a0 > ai) {
+                               j = 1;
+                               p[i] = p[i-1];
+                               p[i-1] = sp;
+                       }
+                       a0 = ai;
+               }
+       }
+#else
+       qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
+#endif 
+
+       /*
+        * Symbol Table Output
+        */
+       i = 0;
+       while (i < nmsym) {
+               fprintf(mfp, "\n");
+               slew(mfp);
+               fprintf(mfp, "     ");
+               sp = p[i];
+               aj = sp->s_addr + sp->s_axp->a_addr;
+               if (xflag == 0) {
+                       fprintf(mfp, "  %04X  ", aj);
+               } else
+               if (xflag == 1) {
+                       fprintf(mfp, "%06o  ", aj);
+               } else
+               if (xflag == 2) {
+                       fprintf(mfp, " %05u  ", aj);
+               }
+               ptr = &sp->s_id[0];
+               fprintf(mfp, "%s", ptr );
+
+               /* NoICE output of symbol */
+               if (jflag) DefineNoICE( ptr, aj, memPage );
+       }
+       putc('\n', mfp);
+       free(p);
+       slew(mfp);
+}
+#endif
+
+/*)Function    VOID    lkulist(i)
+ *
+ *             int     i       i # 0   process LST to RST file
+ *                             i = 0   copy remainder of LST file
+ *                                     to RST file and close files
+ *
+ *     The function lkulist() creates a relocated listing (.rst)
+ *     output file from the ASxxxx assembler listing (.lst)
+ *     files.  The .lst file's program address and code bytes
+ *     are changed to reflect the changes made by ASlink as
+ *     the .rel files are combined into a single relocated
+ *     output file.
+ *
+ *     local variables:
+ *             Addr_T  pc              current program counter address
+ *
+ *     global variables:
+ *             int     hilo            byte order
+ *             int     gline           get a line from the LST file
+ *                                     to translate for the RST file
+ *             char    rb[]            read listing file text line
+ *             FILE    *rfp            The file handle to the current
+ *                                     output RST file
+ *             int     rtcnt           count of data words
+ *             int     rtflg[]         output the data flag
+ *             Addr_T  rtval[]         relocated data
+ *             FILE    *tfp            The file handle to the current
+ *                                     LST file being scanned
+ *
+ *     functions called:
+ *             int     fclose()        c_library
+ *             int     fgets()         c_library
+ *             int     fprintf()       c_library
+ *             VOID    lkalist()       lklist.c
+ *             VOID    lkglist()       lklist.c
+ *
+ *     side effects:
+ *             A .rst file is created for each available .lst
+ *             file associated with a .rel file.
+ */
+
+VOID
+lkulist(i)
+int i;
+{
+       Addr_T pc;
+
+       /*
+        * Exit if listing file is not open
+        */
+       if (tfp == NULL)
+               return;
+
+       /*
+        * Normal processing of LST to RST
+        */
+       if (i) {
+               /*
+                * Evaluate current code address
+                */
+               if (hilo == 0) {
+                       pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
+               } else {
+                       pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
+               }
+
+               /*
+                * Line with only address
+                */
+               if (rtcnt == 2) {
+                       lkalist(pc);
+
+               /*
+                * Line with address and code
+                */
+               } else {
+                       for (i=2; i < rtcnt; i++) {
+                               if (rtflg[i]) {
+                                       lkglist(pc++, rtval[i] & 0xFF);
+                               }
+                       }
+               }
+
+       /*
+        * Copy remainder of LST to RST
+        */
+       } else {
+               if (gline == 0)
+                       fprintf(rfp, "%s", rb);
+
+               while (fgets(rb, sizeof(rb), tfp) != 0) {
+                       fprintf(rfp, "%s", rb);
+               }
+               fclose(tfp);
+               tfp = NULL;
+               fclose(rfp);
+               rfp = NULL;
+       }
+}
+
+/*)Function    VOID    lkalist(pc)
+ *
+ *             int     pc              current program counter value
+ *
+ *     The function lkalist() performs the following functions:
+ *
+ *     (1)     if the value of gline = 0 then the current listing
+ *             file line is copied to the relocated listing file output.
+ *
+ *     (2)     the listing file is read line by line and copied to
+ *             the relocated listing file until a valid source
+ *             line number and a program counter value of the correct
+ *             radix is found.  The new relocated pc value is substituted
+ *             and the line is written to the RST file.
+ *
+ *     local variables:
+ *             int     i               loop counter
+ *             char    str[]           temporary string
+ *
+ *     global variables:
+ *             int     gcntr           data byte counter
+ *             int     gline           get a line from the LST file
+ *                                     to translate for the RST file
+ *             char    rb[]            read listing file text line
+ *             char    *rp             pointer to listing file text line
+ *             FILE    *rfp            The file handle to the current
+ *                                     output RST file
+ *             FILE    *tfp            The file handle to the current
+ *                                     LST file being scanned
+ *
+ *     functions called:
+ *             int     dgt()           lklist.c
+ *             int     fclose()        c_library
+ *             int     fgets()         c_library
+ *             int     fprintf()       c_library
+ *             int     sprintf()       c_library
+ *             char *  strncpy()       c_library
+ *
+ *     side effects:
+ *             Lines of the LST file are copied to the RST file,
+ *             the last line copied has the code address
+ *             updated to reflect the program relocation.
+ */
+
+VOID
+lkalist(pc)
+Addr_T pc;
+{
+       char str[8];
+       int i;
+
+       /*
+        * Exit if listing file is not open
+        */
+loop:  if (tfp == NULL)
+               return;
+
+       /*
+        * Copy current LST to RST
+        */
+       if (gline == 0) {
+               fprintf(rfp, "%s", rb);
+               gline = 1;
+       }
+
+       /*
+        * Clear text line buffer
+        */
+       for (i=0,rp=rb; i<sizeof(rb); i++) {
+               *rp++ = 0;
+       }
+
+       /*
+        * Get next LST text line
+        */
+       if (fgets(rb, sizeof(rb), tfp) == NULL) {
+               fclose(tfp);
+               tfp = NULL;
+               fclose(rfp);
+               rfp = NULL;
+               return;
+       }
+
+       /*
+        * Must have an ASxxxx Listing line number
+        */
+       if (!dgt(RAD10, &rb[30], 1)) {
+               fprintf(rfp, "%s", rb);
+               goto loop;
+       }
+
+       /*
+        * Must have an address in the expected radix
+        */
+       if (radix == 16) {
+               if (!dgt(RAD16, &rb[3], 4)) {
+                       fprintf(rfp, "%s", rb);
+                       goto loop;
+               }
+               sprintf(str, "%04X", pc);
+               strncpy(&rb[3], str, 4);
+       } else
+       if (radix == 10) {
+               if (!dgt(RAD10, &rb[3], 5)) {
+                       fprintf(rfp, "%s", rb);
+                       goto loop;
+               }
+               sprintf(str, "%05d", pc);
+               strncpy(&rb[3], str, 5);
+       } else
+       if (radix == 8) {
+               if (!dgt(RAD8, &rb[3], 6)) {
+                       fprintf(rfp, "%s", rb);
+                       goto loop;
+               }
+               sprintf(str, "%06o", pc);
+               strncpy(&rb[3], str, 6);
+       }
+
+       /*
+        * Copy updated LST text line to RST
+        */
+       fprintf(rfp, "%s", rb);
+       gcntr = 0;
+}
+
+/*)Function    VOID    lkglist(pc,v)
+ *
+ *             int     pc              current program counter value
+ *             int     v               value of byte at this address
+ *
+ *     The function lkglist() performs the following functions:
+ *
+ *     (1)     if the value of gline = 1 then the listing file
+ *             is read line by line and copied to the
+ *             relocated listing file until a valid source
+ *             line number and a program counter value of the correct
+ *             radix is found.
+ *
+ *     (2)     The new relocated values and code address are
+ *             substituted and the line may be written to the RST file.
+ *
+ *     local variables:
+ *             int     i               loop counter
+ *             char    str[]           temporary string
+ *
+ *     global variables:
+ *             int     gcntr           data byte counter
+ *                                     set to -1 for a continuation line
+ *             int     gline           get a line from the LST file
+ *                                     to translate for the RST file
+ *             char    rb[]            read listing file text line
+ *             char    *rp             pointer to listing file text line
+ *             FILE    *rfp            The file handle to the current
+ *                                     output RST file
+ *             FILE    *tfp            The file handle to the current
+ *                                     LST file being scanned
+ *
+ *     functions called:
+ *             int     dgt()           lklist.c
+ *             int     fclose()        c_library
+ *             int     fgets()         c_library
+ *             int     fprintf()       c_library
+ *             int     sprintf()       c_library
+ *             char *  strncpy()       c_library
+ *
+ *     side effects:
+ *             Lines of the LST file are copied to the RST file
+ *             with updated data values and code addresses.
+ */
+
+VOID
+lkglist(pc,v)
+Addr_T pc;
+int v;
+{
+       char str[8];
+       int i;
+
+       /*
+        * Exit if listing file is not open
+        */
+loop:  if (tfp == NULL)
+               return;
+
+       /*
+        * Get next LST text line
+        */
+       if (gline) {
+               /*
+                * Clear text line buffer
+                */
+               for (i=0,rp=rb; i<sizeof(rb); i++) {
+                       *rp++ = 0;
+               }
+
+               /*
+                * Get next LST text line
+                */
+               if (fgets(rb, sizeof(rb), tfp) == NULL) {
+                       fclose(tfp);
+                       tfp = NULL;
+                       fclose(rfp);
+                       rfp = NULL;
+                       return;
+               }
+
+               /*
+                * Check for a listing line number if required
+                */
+               if (gcntr != -1) {
+                       if (!dgt(RAD10, &rb[30], 1)) {
+                               fprintf(rfp, "%s", rb);
+                               goto loop;
+                       }
+                       gcntr = 0;
+               }
+               gline = 0;
+       }
+
+       /*
+        * Hex Listing
+        */
+       if (radix == 16) {
+               /*
+                * Data Byte Pointer
+                */
+               if (gcntr == -1) {
+                       rp = &rb[8];
+               } else {
+                       rp = &rb[8 + (3 * gcntr)];
+               }
+               /*
+                * Number must be of proper radix
+                */
+               if (!dgt(RAD16, rp, 2)) {
+                       fprintf(rfp, "%s", rb);
+                       gline = 1;
+                       goto loop;
+               }
+               /*
+                * Output new data value, overwrite relocation codes
+                */
+               sprintf(str, " %02X", v);
+               strncpy(rp-1, str, 3);
+               if (gcntr == -1) {
+                       gcntr = 0;
+               }
+               /*
+                * Output relocated code address
+                */
+               if (gcntr == 0) {
+                       if (dgt(RAD16, &rb[3], 4)) {
+                               sprintf(str, "%04X", pc);
+                               strncpy(&rb[3], str, 4);
+                       }
+               }
+               /*
+                * Output text line when updates finished
+                */
+               if (++gcntr == 6) {
+                       fprintf(rfp, "%s", rb);
+                       gline = 1;
+                       gcntr = -1;
+               }
+       } else
+       /*
+        * Decimal Listing
+        */
+       if (radix == 10) {
+               /*
+                * Data Byte Pointer
+                */
+               if (gcntr == -1) {
+                       rp = &rb[9];
+               } else {
+                       rp = &rb[9 + (3 * gcntr)];
+               }
+               /*
+                * Number must be of proper radix
+                */
+               if (!dgt(RAD10, rp, 3)) {
+                       fprintf(rfp, "%s", rb);
+                       gline = 1;
+                       goto loop;
+               }
+               /*
+                * Output new data value, overwrite relocation codes
+                */
+               sprintf(str, " %03d", v);
+               strncpy(rp-1, str, 4);
+               if (gcntr == -1) {
+                       gcntr = 0;
+               }
+               /*
+                * Output relocated code address
+                */
+               if (gcntr == 0) {
+                       if (dgt(RAD10, &rb[3], 5)) {
+                               sprintf(str, "%05d", pc);
+                               strncpy(&rb[3], str, 5);
+                       }
+               }
+               /*
+                * Output text line when updates finished
+                */
+               if (++gcntr == 4) {
+                       fprintf(rfp, "%s", rb);
+                       gline = 1;
+                       gcntr = -1;
+               }
+       } else
+       /*
+        * Octal Listing
+        */
+       if (radix == 8) {
+               /*
+                * Data Byte Pointer
+                */
+               if (gcntr == -1) {
+                       rp = &rb[10];
+               } else {
+                       rp = &rb[10 + (3 * gcntr)];
+               }
+               /*
+                * Number must be of proper radix
+                */
+               if (!dgt(RAD8, rp, 3)) {
+                       fprintf(rfp, "%s", rb);
+                       gline = 1;
+                       goto loop;
+               }
+               /*
+                * Output new data value, overwrite relocation codes
+                */
+               sprintf(str, " %03o", v);
+               strncpy(rp-1, str, 4);
+               if (gcntr == -1) {
+                       gcntr = 0;
+               }
+               /*
+                * Output relocated code address
+                */
+               if (gcntr == 0) {
+                       if (dgt(RAD8, &rb[3], 6)) {
+                               sprintf(str, "%06o", pc);
+                               strncpy(&rb[3], str, 6);
+                       }
+               }
+               /*
+                * Output text line when updates finished
+                */
+               if (++gcntr == 4) {
+                       fprintf(rfp, "%s", rb);
+                       gline = 1;
+                       gcntr = -1;
+               }
+       }
+}
+
+/*)Function    int     dgt(rdx,str,n)
+ *
+ *             int     rdx             radix bit code
+ *             char    *str            pointer to the test string
+ *             int     n               number of characters to check
+ *
+ *     The function dgt() verifies that the string under test
+ *     is of the specified radix.
+ *
+ *     local variables:
+ *             int     i               loop counter
+ *
+ *     global variables:
+ *             ctype[]                 array of character types
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+int
+dgt(rdx, str, n)
+int rdx, n;
+char *str;
+{
+       int i;
+
+       for (i=0; i<n; i++) {
+               if ((ctype[(int)*str++] & rdx) == 0)
+                       return(0);
+       }
+       return(1);
+}
diff --git a/as/hc08/lkmain.c b/as/hc08/lkmain.c
new file mode 100644 (file)
index 0000000..548a44f
--- /dev/null
@@ -0,0 +1,1378 @@
+/* lkmain.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 31-Oct-97 JLH:
+ *           - add jflag and jfp to control NoICE output file genration
+ *  3-Nov-97 JLH: 
+ *           - use a_type == 0 as "virgin area" flag: set == 1 if -b
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+#ifdef WIN32T
+#include <time.h>
+
+void Timer(int action, char * message)
+{
+       static double start, end, total=0.0;
+    static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+
+    if(action==0) start=clock()*secs_per_tick;
+    else if(action==1)
+    {
+       end=clock() * secs_per_tick;
+               printf("%s \t%f seconds.\n", message, (end-start));
+               total+=end-start;
+    }
+    else
+    {
+               printf("Total time: \t%f seconds.\n", total);
+               total=0.0;
+    }
+}
+#endif
+
+/* yuck - but including unistd.h causes problems on Cygwin by redefining
+ * Addr_T.
+ */
+extern int unlink(const char *);
+
+/*)Module      lkmain.c
+ *
+ *     The module lkmain.c contains the functions which
+ *     (1) input the linker options, parameters, and specifications
+ *     (2) perform a two pass link
+ *     (3) produce the appropriate linked data output and/or
+ *         link map file and/or relocated listing files.
+ *
+ *     lkmain.c contains the following functions:
+ *             FILE *  afile(fn,ft,wf)
+ *             VOID    bassav()
+ *             VOID    gblsav()
+  *            VOID    link_main()
+ *             VOID    lkexit()
+ *             VOID    main(argc,argv)
+ *             VOID    map()
+ *             int     parse()
+ *             VOID    setbas()
+ *             VOID    setgbl()
+ *             VOID    usage()
+ *
+ *     lkmain.c contains the following local variables:
+ *             char *  usetext[]       array of pointers to the
+ *                                     command option tect lines
+ *
+ */
+
+/*JCF:         Creates some of the default areas so they are allocated in the right order.*/
+void Areas51 (void)
+{
+       char * rel[]={
+               "XH",
+               "H 7 areas 0 global symbols",
+               "A _CODE size 0 flags 0",               /*Each .rel has one, so...*/
+               "A REG_BANK_0 size 0 flags 4",  /*Register banks are overlayable*/
+               "A REG_BANK_1 size 0 flags 4",
+               "A REG_BANK_2 size 0 flags 4",
+               "A REG_BANK_3 size 0 flags 4",
+               "A BSEG size 0 flags 80",               /*BSEG must be just before BITS*/
+               "A BSEG_BYTES size 0 flags 0",  /*Size will be obtained from BSEG in lnkarea()*/
+               ""
+       };
+       int j;
+
+       for (j=0; rel[j][0]!=0; j++)
+       {
+               ip=rel[j];
+               link_main();
+       }
+       
+       /*Set the start address of the default areas:*/
+       for(ap=areap; ap; ap=ap->a_ap)
+       {
+               /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr=0x00; ap->a_type=1; }
+               else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr=0x08; ap->a_type=1; }
+               else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; }
+               else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; }
+               else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; }
+       }
+}
+
+/*)Function    VOID    main(argc,argv)
+ *
+ *             int     argc            number of command line arguments + 1
+ *             char *  argv[]          array of pointers to the command line
+ *                                     arguments
+ *
+ *     The function main() evaluates the command line arguments to
+ *     determine if the linker parameters are to input through 'stdin'
+ *     or read from a command file.  The functiond getline() and parse()
+ *     are to input and evaluate the linker parameters.  The linking process
+ *     proceeds by making the first pass through each .rel file in the order
+ *     presented to the linker.  At the end of the first pass the setbase(),
+ *     lnkarea(), setgbl(), and symdef() functions are called to evaluate
+ *     the base address terms, link all areas, define global variables,
+ *     and look for undefined symbols.  Following these routines a linker
+ *     map file may be produced and the linker output files may be opened.
+ *     The second pass through the .rel files will output the linked data
+ *     in one of the four supported formats.
+ *
+ *     local variables:
+ *             char *  p               pointer to an argument string
+ *             int     c               character from argument string
+ *             int     i               loop counter
+ *
+ *     global variables:
+ *                                             text line in ib[]
+ *             lfile   *cfp            The pointer *cfp points to the
+ *                                             current lfile structure
+ *             char    ctype[]         array of character types, one per
+ *                                             ASCII character
+ *             lfile   *filep                  The pointer *filep points to the
+ *                                             beginning of a linked list of
+ *                                             lfile structures.
+ *             head    *hp             Pointer to the current
+ *                                             head structure
+ *             char    ib[NINPUT]      .rel file text line
+ *             char    *ip             pointer into the .rel file
+ *             lfile   *linkp          pointer to first lfile structure
+ *                                             containing an input .rel file
+ *                                             specification
+ *             int     lkerr           error flag
+ *             int     mflag           Map output flag
+ *             int     oflag           Output file type flag
+ *             FILE    *ofp            Output file handle
+ *                                             for word formats
+ *             FILE    *ofph           Output file handle
+ *                                             for high byte format
+ *             FILE    *ofpl           Output file handle
+ *                                             for low byte format
+ *             int     pass            linker pass number
+ *             int     pflag           print linker command file flag
+ *             int     radix           current number conversion radix
+ *             FILE    *sfp            The file handle sfp points to the
+ *                                             currently open file
+ *             lfile   *startp         asmlnk startup file structure
+ *             FILE *  stdin           c_library
+ *             FILE *  stdout          c_library
+ *
+ *     functions called:
+ *             FILE *  afile()         lkmain.c
+ *             int     fclose()        c_library
+ *             int     fprintf()       c_library
+ *             int     getline()       lklex.c
+ *             VOID    library()       lklibr.c
+ *             VOID    link_main()     lkmain.c
+ *             VOID    lkexit()        lkmain.c
+ *             VOID    lnkarea()       lkarea.c
+ *             VOID    map()           lkmain.c
+ *             VOID    new()           lksym.c
+ *             int     parse()         lkmain.c
+ *             VOID    reloc()         lkreloc.c
+ *             VOID    search()        lklibr.c
+ *             VOID    setbas()        lkmain.c
+ *             VOID    setgbl()        lkmain.c
+ *             VOID    symdef()        lksym.c
+ *             VOID    usage()         lkmain.c
+ *
+ *     side effects:
+ *             Completion of main() completes the linking process
+ *             and may produce a map file (.map) and/or a linked
+ *             data files (.ihx or .s19) and/or one or more
+ *             relocated listing files (.rst).
+ */
+
+int
+main(argc, argv)
+char *argv[];
+{
+       register char *p;
+       register int c, i;
+
+#ifdef WIN32T
+    Timer(0, "");
+#endif
+
+       startp = (struct lfile *) new (sizeof (struct lfile));
+
+       pflag = 1;
+       for (i=1; i<argc; ++i) {
+               p = argv[i];
+               if (*p == '-') {
+                       while (ctype[c = *(++p)] & LETTER) {
+                               switch(c) {
+
+                               case 'c':
+                               case 'C':
+                                       startp->f_type = F_STD;
+                                       break;
+
+                               case 'f':
+                               case 'F':
+                                       startp->f_type = F_LNK;
+                                       break;
+       
+                               case 'n':
+                               case 'N':
+                                       pflag = 0;
+                                       break;
+
+                               case 'p':
+                               case 'P':
+                                       pflag = 1;
+                                       break;
+
+                               default:
+                                       usage();
+                               }
+                       }
+               } else {
+                       if (startp->f_type == F_LNK) {
+                               startp->f_idp = p;
+                       }
+               }
+       }
+       if (startp->f_type == 0)
+               usage();
+       if (startp->f_type == F_LNK && startp->f_idp == NULL)
+               usage();
+
+       cfp = NULL;
+       sfp = NULL;
+       filep = startp;
+       while (1) {
+               ip = ib;
+               if (getline() == 0)
+                       break;
+               if (pflag && sfp != stdin)
+                       fprintf(stdout, "%s\n", ip);
+               if (*ip == '\0' || parse())
+                       break;
+       }
+
+       if (sfp) {
+           fclose(sfp);
+           sfp = NULL;
+       }
+
+       if (linkp == NULL)
+               usage();
+
+       syminit();
+       
+       if (dflag){
+           //dfp = afile("temp", "cdb", 1);
+               SaveLinkedFilePath(linkp->f_idp); //Must be the first one... 
+               dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002
+           if (dfp == NULL) 
+               lkexit(1);
+       }
+
+       for (pass=0; pass<2; ++pass) {
+               cfp = NULL;
+               sfp = NULL;
+               filep = linkp;
+               hp = NULL;
+               radix = 10;
+               
+               Areas51(); /*JCF: Create the default 8051 areas in the right order*/
+
+               while (getline()) {
+                       ip = ib;
+
+                        /* pass any "magic comments" to NoICE output */
+                        if ((ip[0] == ';') && (ip[1] == '!') && jfp) {
+                               fprintf( jfp, "%s\n", &ip[2] );
+                        }
+                       link_main();
+               }
+               if (pass == 0) {
+                       /*
+                        * Search libraries for global symbols
+                        */
+                       search();
+                       /*
+                        * Set area base addresses.
+                        */
+                       setbas();
+                       /*
+                        * Link all area addresses.
+                        */
+                       lnkarea();
+                       /*
+                        * Process global definitions.
+                        */
+                       setgbl();
+                       /*
+                        * Check for undefined globals.
+                        */
+                       symdef(stderr);
+
+                       /* Open NoICE output file if requested */
+                       if (jflag) {
+                               jfp = afile(linkp->f_idp, "NOI", 1);
+                               if (jfp == NULL) {
+                                       lkexit(1);
+                               }
+                       }
+
+                       /*
+                        * Output Link Map if requested,
+                        * or if NoICE output requested (since NoICE
+                         * file is generated in part by map() processing)
+                        */
+                       if (mflag || jflag)
+                               map();
+
+                       if (sflag) /*JCF: memory usage summary output*/
+                               if(summary(areap))lkexit(1);
+
+                       if (iram_size)
+                               iramcheck();
+
+                       /*
+                        * Open output file
+                        */
+                       if (oflag == 1) {
+                               ofp = afile(linkp->f_idp, "ihx", 1);
+                               if (ofp == NULL) {
+                                       lkexit(1);
+                               }
+                               /* include NoICE command to load hex file */
+                               if (jfp) fprintf( jfp, "LOAD %s.IHX\n", linkp->f_idp );
+
+                       } else
+                       if (oflag == 2) {
+                               ofp = afile(linkp->f_idp, "S19", 1);
+                               if (ofp == NULL) {
+                                       lkexit(1);
+                               }
+                               /* include NoICE command to load hex file */
+                               if (jfp) fprintf( jfp, "LOAD %s.S19\n", linkp->f_idp );
+                       }
+               } else {
+                       /*
+                        * Link in library files
+                        */
+                       library();
+                       reloc('E');
+               }
+       }
+       //JCF:
+       CreateAOMF51();
+
+#ifdef WIN32T
+    Timer(1, "Linker execution time");
+#endif
+
+       lkexit(lkerr);
+       return 0;
+}
+
+/*)Function    VOID    lkexit(i)
+ *
+ *                     int     i       exit code
+ *
+ *     The function lkexit() explicitly closes all open
+ *     files and then terminates the program.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             FILE *  mfp             file handle for .map
+ *             FILE *  ofp             file handle for .ihx/.s19
+ *             FILE *  rfp             file hanlde for .rst
+ *             FILE *  sfp             file handle for .rel
+ *             FILE *  tfp             file handle for .lst
+ *
+ *     functions called:
+ *             int     fclose()        c_library
+ *             VOID    exit()          c_library
+ *
+ *     side effects:
+ *             All files closed. Program terminates.
+ */
+
+VOID
+lkexit(i)
+int i;
+{
+       if (mfp != NULL) fclose(mfp);
+       if (jfp != NULL) fclose(jfp);
+       if (ofp != NULL) fclose(ofp);
+       if (rfp != NULL) fclose(rfp);
+       if (sfp != NULL) fclose(sfp);
+       if (tfp != NULL) fclose(tfp);
+       if (dfp != NULL) fclose(dfp);
+       /*if (dfp != NULL)
+           FILE *xfp = afile(linkp->f_idp,"cdb",1);
+           dfp = freopen("temp.cdb","r",dfp);
+           copyfile(xfp,dfp);
+           fclose(xfp);
+           fclose(dfp);
+           unlink("temp.cdb");
+       }*/
+       exit(i);
+}
+
+/*)Function    link_main()
+ *
+ *     The function link_main() evaluates the directives for each line of
+ *     text read from the .rel file(s).  The valid directives processed
+ *     are:
+ *             X, D, Q, H, M, A, S, T, R, and P.
+ *
+ *     local variables:
+ *             int     c               first non blank character of a line
+ *
+ *     global variables:
+ *             head    *headp          The pointer to the first
+ *                                             head structure of a linked list
+ *             head    *hp             Pointer to the current
+ *                                             head structure
+ *             int     pass            linker pass number
+ *             int     radix           current number conversion radix
+ *
+ *     functions called:
+ *             char    endline()       lklex.c
+ *             VOID    module()        lkhead.c
+ *             VOID    newarea()       lkarea.c
+ *             VOID    newhead()       lkhead.c
+ *             sym *   newsym()        lksym.c
+ *             VOID    reloc()         lkreloc.c
+ *
+ *     side effects:
+ *             Head, area, and symbol structures are created and
+ *             the radix is set as the .rel file(s) are read.
+ */
+
+VOID
+link_main()
+{
+       register int c;
+
+       if ((c=endline()) == 0) { return; }
+       switch (c) {
+
+    case 'O': /*For some important sdcc options*/
+        if (pass == 0)
+        {
+            if(strlen(sdccopt)==0)
+            {
+                strcpy(sdccopt, &ip[1]);
+                strcpy(sdccopt_module, curr_module);
+            }
+            else
+            {
+                if(strcmp(sdccopt, &ip[1])!=0)
+                {
+                                   fprintf(stderr,
+                                   "?ASlink-Warning-Conflicting sdcc options:\n"
+                    "   \"%s\" in module \"%s\" and\n"
+                    "   \"%s\" in module \"%s\".\n",
+                    sdccopt, sdccopt_module, &ip[1], curr_module);
+                                   lkerr++;
+                }
+            }
+        }
+               break;
+
+       case 'X':
+               radix = 16;
+               break;
+
+       case 'D':
+               radix = 10;
+               break;
+
+       case 'Q':
+               radix = 8;
+               break;
+
+       case 'H':
+               if (pass == 0) {
+                       newhead();
+               } else {
+                       if (hp == 0) {
+                               hp = headp;
+                       } else {
+                               hp = hp->h_hp;
+                       }
+               }
+               sdp.s_area = NULL;
+               sdp.s_areax = NULL;
+               sdp.s_addr = 0;
+               break;
+
+       case 'M':
+               if (pass == 0)
+        {
+            strcpy(curr_module, &ip[1]);
+                       module();
+        }
+               break;
+
+       case 'A':
+               if (pass == 0)
+                       newarea();
+               if (sdp.s_area == NULL) {
+                       sdp.s_area = areap;
+                       sdp.s_areax = areap->a_axp;
+                       sdp.s_addr = 0;
+               }
+               break;
+
+       case 'S':
+               if (pass == 0)
+                       newsym();
+               break;
+
+       case 'T':
+       case 'R':
+       case 'P':
+               if (pass == 0)
+                       break;
+               reloc(c);
+               break;
+
+       default:
+               break;
+       }
+       if (c == 'X' || c == 'D' || c == 'Q') {
+               if ((c = get()) == 'H') {
+                       hilo = 1;
+               } else
+               if (c == 'L') {
+                       hilo = 0;
+               }
+       }
+}
+
+
+/*)Function    VOID    map()
+ *
+ *     The function map() opens the output map file and calls the various
+ *     routines to
+ *     (1) output the variables in each area,
+ *     (2) list the files processed with module names,
+ *     (3) list the libraries file processed,
+ *     (4) list base address definitions,
+ *     (5) list global variable definitions, and
+ *     (6) list any undefined variables.
+ *
+ *     local variables:
+ *             int             i               counter
+ *             head *  hdp             pointer to head structure
+ *             lbfile *lbfh            pointer to library file structure
+ *
+ *     global variables:
+ *             area    *ap             Pointer to the current
+ *                                             area structure
+ *             area    *areap          The pointer to the first
+ *                                             area structure of a linked list
+ *             base    *basep          The pointer to the first
+ *                                             base structure
+ *             base    *bsp            Pointer to the current
+ *                                             base structure
+ *             lfile   *filep                  The pointer *filep points to the
+ *                                             beginning of a linked list of
+ *                                             lfile structures.
+ *             globl   *globlp         The pointer to the first
+ *                                             globl structure
+ *             globl   *gsp            Pointer to the current
+ *                                             globl structure
+ *             head    *headp          The pointer to the first
+ *                                             head structure of a linked list
+ *             lbfile  *lbfhead        The pointer to the first
+ *                                     lbfile structure of a linked list
+ *             lfile   *linkp          pointer to first lfile structure
+ *                                             containing an input REL file
+ *                                             specification
+ *             int     lop             current line number on page
+ *             FILE    *mfp            Map output file handle
+ *             int     page            current page number
+ *
+ *     functions called:
+ *             FILE *  afile()         lkmain.c
+ *             int     fprintf()       c_library
+ *             VOID    lkexit()        lkmain.c
+ *             VOID    lstarea()       lklist.c
+ *             VOID    newpag()        lklist.c
+ *             VOID    symdef()        lksym.c
+ *
+ *     side effects:
+ *             The map file is created.
+ */
+
+VOID
+map()
+{
+       register int i;
+       register struct head *hdp;
+       register struct lbfile *lbfh;
+
+       /*
+        * Open Map File
+        */
+       mfp = afile(linkp->f_idp, "map", 1);
+       if (mfp == NULL) {
+               lkexit(1);
+       }
+
+       /*
+        * Output Map Area Lists
+        */
+       page = 0;
+       lop  = NLPP;
+       ap = areap;
+       while (ap) {
+               lstarea(ap);
+               ap = ap->a_ap;
+       }
+       /*
+        * List Linked Files
+        */
+       newpag(mfp);
+       fprintf(mfp, "\nFiles Linked      [ module(s) ]\n\n");
+       hdp = headp;
+       filep = linkp;
+       while (filep) {
+               fprintf(mfp, "%-16s", filep->f_idp);
+               i = 0;
+               while ((hdp != NULL) && (hdp->h_lfile == filep)) {
+                       if (i % 5) {
+                           fprintf(mfp, ", %8.8s", hdp->m_id);
+                       } else {
+                           if (i) {
+                               fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
+                           } else {
+                               fprintf(mfp, "  [ %8.8s", hdp->m_id);
+                           }
+                       }
+                       hdp = hdp->h_hp;
+                       i++;
+               }
+               if (i)
+                       fprintf(mfp, " ]");
+               fprintf(mfp, "\n");
+               filep = filep->f_flp;
+       }
+       /*
+        * List Linked Libraries
+        */
+       if (lbfhead != NULL) {
+               fprintf(mfp,
+       "\nLibraries Linked                    [   object  file   ]\n\n");
+               for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
+                       fprintf(mfp, "%-32s    [ %16.16s ]\n",
+                               lbfh->libspc, lbfh->relfil);
+               }
+               fprintf(mfp, "\n");
+       }
+       /*
+        * List Base Address Definitions
+        */
+       if (basep) {
+               newpag(mfp);
+               fprintf(mfp, "\nUser Base Address Definitions\n\n");
+               bsp = basep;
+               while (bsp) {
+                       fprintf(mfp, "%s\n", bsp->b_strp);
+                       bsp = bsp->b_base;
+               }
+       }
+       /*
+        * List Global Definitions
+        */
+       if (globlp) {
+               newpag(mfp);
+               fprintf(mfp, "\nUser Global Definitions\n\n");
+               gsp = globlp;
+               while (gsp) {
+                       fprintf(mfp, "%s\n", gsp->g_strp);
+                       gsp = gsp->g_globl;
+               }
+       }
+       fprintf(mfp, "\n\f");
+       symdef(mfp);
+}
+
+/*)Function    int     parse()
+ *
+ *     The function parse() evaluates all command line or file input
+ *     linker directives and updates the appropriate variables.
+ *
+ *     local variables:
+ *             int     c               character value
+ *             char    fid[]           file id string
+ *
+ *     global variables:
+ *             char    ctype[]         array of character types, one per
+ *                                             ASCII character
+ *             lfile   *lfp            pointer to current lfile structure
+ *                                             being processed by parse()
+ *             lfile   *linkp          pointer to first lfile structure
+ *                                             containing an input REL file
+ *                                             specification
+ *             int     mflag           Map output flag
+ *             int     oflag           Output file type flag
+ *             int     pflag           print linker command file flag
+ *             FILE *  stderr          c_library
+ *             int     uflag           Relocated listing flag
+ *             int     xflag           Map file radix type flag
+ *
+ *     Functions called:
+ *             VOID    addlib()        lklibr.c
+ *             VOID    addpath()       lklibr.c
+ *             VOID    bassav()        lkmain.c
+ *             int     fprintf()       c_library
+ *             VOID    gblsav()        lkmain.c
+ *             VOID    getfid()        lklex.c
+ *             char    getnb()         lklex.c
+ *             VOID    lkexit()        lkmain.c
+ *             char *  strcpy()        c_library
+ *             int     strlen()        c_library
+ *
+ *     side effects:
+ *             Various linker flags are updated and the linked
+ *             structure lfile is created.
+ */
+
+int
+parse()
+{
+       register int c;
+       char fid[NINPUT];
+
+       while ((c = getnb()) != 0) {
+               if ( c == '-') {
+                       while (ctype[c=get()] & LETTER) {
+                               switch(c) {
+
+                               case 'i':
+                               case 'I':
+                                       oflag = 1;
+                                       break;
+
+                               case 's':
+                               case 'S':
+                                       oflag = 2;
+                                       break;
+
+                               case 'm':
+                               case 'M':
+                                       ++mflag;
+                                       break;
+
+                               case 'y': /*JCF: memory usage summary output*/
+                               case 'Y':
+                                       ++sflag;
+                                       break;
+
+                               case 'j':
+                               case 'J':
+                                       jflag = 1;
+                                       break;
+
+                               case 'u':
+                               case 'U':
+                                       uflag = 1;
+                                       break;
+                               case 'r':
+                               case 'R':
+                                       rflag = 1;
+                                       break;
+                               case 'x':
+                               case 'X':
+                                       xflag = 0;
+                                       break;
+
+                               case 'q':
+                               case 'Q':
+                                       xflag = 1;
+                                       break;
+
+                               case 'd':
+                               case 'D':
+                                       xflag = 2;
+                                       break;
+
+                               case 'e':
+                               case 'E':
+                                       return(1);
+
+                               case 'n':
+                               case 'N':
+                                       pflag = 0;
+                                       break;
+
+                               case 'p':
+                               case 'P':
+                                       pflag = 1;
+                                       break;
+
+                               case 'b':
+                               case 'B':
+                                       bassav();
+                                       return(0);
+
+                               case 'g':
+                               case 'G':
+                                       gblsav();
+                                       return(0);
+
+                               case 'k':
+                               case 'K':
+                                       addpath();
+                                       return(0);
+
+                               case 'l':
+                               case 'L':
+                                       addlib();
+                                       return(0);
+
+                               case 'a':
+                               case 'A':
+                                       iramsav();
+                                       return(0);
+
+                               case 'v':
+                               case 'V':
+                                       xramsav();
+                                       return(0);
+
+                               case 'w':
+                               case 'W':
+                                       codesav();
+                                       return(0);
+
+                               case 'z':
+                                case 'Z':
+                                       dflag = 1;                                      
+                                       return(0);
+                               default:
+                                       fprintf(stderr, "Invalid option\n");
+                                       lkexit(1);
+                               }
+                       }
+               } else
+               if (ctype[c] & ILL) {
+                       fprintf(stderr, "Invalid input");
+                       lkexit(1);
+               } else {
+                       if (linkp == NULL) {
+                               linkp = (struct lfile *)
+                                       new (sizeof (struct lfile));
+                               lfp = linkp;
+                       } else {
+                               lfp->f_flp = (struct lfile *)
+                                               new (sizeof (struct lfile));
+                               lfp = lfp->f_flp;
+                       }
+                       getfid(fid, c);
+                       lfp->f_idp = (char *) new (strlen(fid)+1);
+                       strcpy(lfp->f_idp, fid);
+                       lfp->f_type = F_REL;
+               }
+       }
+       return(0);
+}
+
+/*)Function    VOID    bassav()
+ *
+ *     The function bassav() creates a linked structure containing
+ *     the base address strings input to the linker.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             base    *basep          The pointer to the first
+ *                                             base structure
+ *             base    *bsp            Pointer to the current
+ *                                             base structure
+ *             char    *ip             pointer into the REL file
+ *                                             text line in ib[]
+ *
+ *      functions called:
+ *             char    getnb()         lklex.c
+ *             VOID *  new()           lksym.c
+ *             int     strlen()        c_library
+ *             char *  strcpy()        c_library
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             The basep structure is created.
+ */
+
+VOID
+bassav()
+{
+       if (basep == NULL) {
+               basep = (struct base *)
+                       new (sizeof (struct base));
+               bsp = basep;
+       } else {
+               bsp->b_base = (struct base *)
+                               new (sizeof (struct base));
+               bsp = bsp->b_base;
+       }
+       unget(getnb());
+       bsp->b_strp = (char *) new (strlen(ip)+1);
+       strcpy(bsp->b_strp, ip);
+}
+
+/*)Function    VOID    setbas()
+ *
+ *     The function setbas() scans the base address lines in hte
+ *     basep structure, evaluates the arguments, and sets beginning
+ *     address of the specified areas.
+ *
+ *     local variables:
+ *             int     v               expression value
+ *             char    id[]            base id string
+ *
+ *     global variables:
+ *             area    *ap             Pointer to the current
+ *                                             area structure
+ *             area    *areap          The pointer to the first
+ *                                             area structure of a linked list
+ *             base    *basep          The pointer to the first
+ *                                             base structure
+ *             base    *bsp            Pointer to the current
+ *                                             base structure
+ *             char    *ip             pointer into the REL file
+ *                                             text line in ib[]
+ *             int     lkerr           error flag
+ *
+ *      functions called:
+ *             Addr_T  expr()          lkeval.c
+ *             int     fprintf()       c_library
+ *             VOID    getid()         lklex.c
+ *             char    getnb()         lklex.c
+ *             int     symeq()         lksym.c
+ *
+ *     side effects:
+ *             The base address of an area is set.
+ */
+
+VOID
+setbas()
+{
+       register int v;
+       char id[NCPS];
+
+       bsp = basep;
+       while (bsp) {
+               ip = bsp->b_strp;
+               getid(id, -1);
+               if (getnb() == '=') {
+                       v = expr(0);
+                       for (ap = areap; ap != NULL; ap = ap->a_ap) {
+                               if (symeq(id, ap->a_id))
+                                       break;
+                       }
+                       if (ap == NULL) {
+                               fprintf(stderr,
+                               "ASlink-Warning-No definition of area %s\n", id);
+                               lkerr++;
+                       } else {
+                               ap->a_addr = v;
+                                ap->a_type = 1;        /* JLH: value set */
+                       }
+               } else {
+                       fprintf(stderr, "ASlink-Warning-No '=' in base expression");
+                       lkerr++;
+               }
+               bsp = bsp->b_base;
+       }
+}
+
+/*)Function    VOID    gblsav()
+ *
+ *     The function gblsav() creates a linked structure containing
+ *     the global variable strings input to the linker.
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             globl   *globlp         The pointer to the first
+ *                                             globl structure
+ *             globl   *gsp            Pointer to the current
+ *                                             globl structure
+ *             char    *ip             pointer into the REL file
+ *                                             text line in ib[]
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             char    getnb()         lklex.c
+ *             VOID *  new()           lksym.c
+ *             int     strlen()        c_library
+ *             char *  strcpy()        c_library
+ *             VOID    unget()         lklex.c
+ *
+ *     side effects:
+ *             The globlp structure is created.
+ */
+
+VOID
+gblsav()
+{
+       if (globlp == NULL) {
+               globlp = (struct globl *)
+                       new (sizeof (struct globl));
+               gsp = globlp;
+       } else {
+               gsp->g_globl = (struct globl *)
+                               new (sizeof (struct globl));
+               gsp = gsp->g_globl;
+       }
+       unget(getnb());
+       gsp->g_strp = (char *) new (strlen(ip)+1);
+       strcpy(gsp->g_strp, ip);
+}
+       
+/*)Function    VOID    setgbl()
+ *
+ *     The function setgbl() scans the global variable lines in hte
+ *     globlp structure, evaluates the arguments, and sets a variable
+ *     to this value.
+ *
+ *     local variables:
+ *             int     v               expression value
+ *             char    id[]            base id string
+ *             sym *   sp              pointer to a symbol structure
+ *
+ *     global variables:
+ *             char    *ip             pointer into the REL file
+ *                                             text line in ib[]
+ *             globl   *globlp         The pointer to the first
+ *                                             globl structure
+ *             globl   *gsp            Pointer to the current
+ *                                             globl structure
+ *             FILE *  stderr          c_library
+ *             int     lkerr           error flag
+ *
+ *      functions called:
+ *             Addr_T  expr()          lkeval.c
+ *             int     fprintf()       c_library
+ *             VOID    getid()         lklex.c
+ *             char    getnb()         lklex.c
+ *             sym *   lkpsym()        lksym.c
+ *
+ *     side effects:
+ *             The value of a variable is set.
+ */
+
+VOID
+setgbl()
+{
+       register int v;
+       register struct sym *sp;
+       char id[NCPS];
+
+       gsp = globlp;
+       while (gsp) {
+               ip = gsp->g_strp;
+               getid(id, -1);
+               if (getnb() == '=') {
+                       v = expr(0);
+                       sp = lkpsym(id, 0);
+                       if (sp == NULL) {
+                               fprintf(stderr,
+                               "No definition of symbol %s\n", id);
+                               lkerr++;
+                       } else {
+                               if (sp->s_flag & S_DEF) {
+                                       fprintf(stderr,
+                                       "Redefinition of symbol %s\n", id);
+                                       lkerr++;
+                                       sp->s_axp = NULL;
+                               }
+                               sp->s_addr = v;
+                               sp->s_type |= S_DEF;
+                       }
+               } else {
+                       fprintf(stderr, "No '=' in global expression");
+                       lkerr++;
+               }
+               gsp = gsp->g_globl;
+       }
+}
+
+/*)Function    FILE *  afile(fn,, ft, wf)
+ *
+ *             char *  fn              file specification string
+ *             char *  ft              file type string
+ *             int     wf              read(0)/write(1) flag
+ *
+ *     The function afile() opens a file for reading or writing.
+ *             (1)     If the file type specification string ft
+ *                     is not NULL then a file specification is
+ *                     constructed with the file path\name in fn
+ *                     and the extension in ft.
+ *             (2)     If the file type specification string ft
+ *                     is NULL then the file specification is
+ *                     constructed from fn.  If fn does not have
+ *                     a file type then the default .rel file
+ *                     type is appended to the file specification.
+ *
+ *     afile() returns a file handle for the opened file or aborts
+ *     the assembler on an open error.
+ *
+ *     local variables:
+ *             char    fb[]            constructed file specification string
+ *             FILE *  fp              filehandle for opened file
+ *
+ *     global variables:
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             FILE *  fopen()         c_library
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             File is opened for read or write.
+ */
+
+FILE *
+afile(fn, ft, wf)
+char *fn;
+char *ft;
+{
+       FILE *fp;
+       char fb[PATH_MAX];
+       char *omode = (wf ? (wf == 2 ? "a" : "w") : "r");
+       int i;
+
+       /*Look backward the name path and get rid of the extension, if any*/
+       i=strlen(fn);
+       for(; (fn[i]!='.')&&(fn[i]!='\\')&&(fn[i]!='/')&&(i>=0); i--);
+       if( (fn[i]=='.') && strcmp(ft, "lnk") )
+       {
+               strncpy(fb, fn, i);
+               fb[i]=0;
+       }
+       else
+       {
+               strcpy(fb, fn);
+       }
+
+       /*Add the extension*/
+       strcat(fb, ".");
+       strcat(fb, strlen(ft)?ft:"rel");
+       
+       fp = fopen(fb, omode);
+       if (fp==NULL)
+       {
+           if (strcmp(ft,"adb"))/*Do not complaint for optional adb files*/
+               {
+                       fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
+                       lkerr++;
+           }
+       }
+       return (fp);
+}
+
+/*)Function    VOID    iramsav()
+ *
+ *     The function iramsav() stores the size of the chip's internal RAM.
+ *     This is used after linking to check that variable assignment to this
+ *     dataspace didn't overflow into adjoining segments.  Variables in the
+ *     DSEG, OSEG, and ISEG are assigned to this dataspace.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             char    *ip             pointer into the REL file
+ *                                             text line in ib[]
+ *             unsigned int            size of chip's internal
+ *                     iram_size               RAM segment
+ *
+ *      functions called:
+ *             char    getnb()         lklex.c
+ *             VOID    unget()         lklex.c
+ *             Addr_T  expr()          lkeval.c
+ *
+ *     side effects:
+ *             The iram_size may be modified.
+ */
+
+VOID
+iramsav()
+{
+  unget(getnb());
+  if (ip && *ip)
+    //iram_size = atoi(ip);
+    iram_size = expr(0);       /* evaluate size expression */
+  else
+    iram_size = 128;           /* Default is 128 (0x80) bytes */
+}
+
+/*Similar to iramsav but for xram memory*/
+VOID
+xramsav()
+{
+  unget(getnb());
+  if (ip && *ip)
+    xram_size = expr(0);       /* evaluate size expression */
+  else
+       xram_size = rflag?0x1000000:0x10000;
+}
+
+/*Similar to iramsav but for code memory*/
+VOID
+codesav()
+{
+  unget(getnb());
+  if (ip && *ip)
+    code_size = expr(0);       /* evaluate size expression */
+  else
+       code_size = rflag?0x1000000:0x10000;
+}
+
+
+/*)Function    VOID    iramcheck()
+ *
+ *     The function iramcheck() is used at the end of linking to check that
+ *     the internal RAM area wasn't overflowed by too many variable
+ *     assignments.  Variables in the DSEG, ISEG, and OSEG are assigned to
+ *     the chip's internal RAM.
+ *
+ *     local variables:
+ *             none
+ *
+ *     global variables:
+ *             unsigned int            size of chip's internal
+ *                     iram_size               RAM segment
+ *             struct area             linked list of memory
+ *                     *areap                  areas
+ *
+ *      functions called:
+ *
+ *     side effects:
+ */
+
+VOID
+iramcheck()
+{
+  register unsigned int last_addr;
+  register struct area *ap;
+
+  for (ap = areap; ap; ap=ap->a_ap) {
+    if ((ap->a_size != 0) &&
+        (!strcmp(ap->a_id, "DSEG") ||
+         !strcmp(ap->a_id, "OSEG") ||
+         !strcmp(ap->a_id, "ISEG")
+        )
+       )
+    {
+      last_addr = ap->a_addr + ap->a_size - 1;
+      if (last_addr >= iram_size)
+       fprintf(stderr,
+               "\nWARNING! Segment %s extends past the end\n"
+               "         of internal RAM.  Check map file.\n",
+               ap->a_id);
+    }
+  }
+}
+
+char *usetxt[] = {
+       "Startup:",
+       "  -c   Command line input",
+       "  -f   file[LNK] File input",
+       "  -p   Prompt and echo of file[LNK] to stdout (default)",
+       "  -n   No echo of file[LNK] to stdout",
+/*     "Usage: [-Options] file [file ...]", */
+       "Libraries:",
+       "  -k   Library path specification, one per -k",
+       "  -l   Library file specification, one per -l",
+       "Relocation:",
+       "  -b   area base address = expression",
+       "  -g   global symbol = expression",
+       "Map format:",
+       "  -m   Map output generated as file[MAP]",
+       "  -x   Hexadecimal (default),  -d  Decimal,  -q  Octal",
+       "Output:",
+       "  -i   Intel Hex as file[IHX]",
+       "  -s   Motorola S19 as file[S19]",
+       "  -j   Produce NoICE debug as file[NOI]",
+       "  -z   Produce SDCdb debug as file[cdb]",
+/*     "List:", */
+       "  -u   Update listing file(s) with link data as file(s)[.RST]",
+       "Miscellaneous:\n"
+       "  -a   [iram-size] Check for internal RAM overflow",
+       "  -v   [xram-size] Check for external RAM overflow",
+       "  -w   [code-size] Check for code overflow",
+       "End:",
+       "  -e   or null line terminates input",
+       0
+};
+
+/*)Function    VOID    usage()
+ *
+ *     The function usage() outputs to the stderr device the
+ *     assembler name and version and a list of valid assembler options.
+ *
+ *     local variables:
+ *             char ** dp              pointer to an array of
+ *                                     text string pointers.
+ *
+ *     global variables:
+ *             FILE *  stderr          c_library
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             none
+ */
+
+VOID
+usage()
+{
+       register char   **dp;
+
+       fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
+       for (dp = usetxt; *dp; dp++)
+               fprintf(stderr, "%s\n", *dp);
+       lkexit(1);
+}
+
+/*)Function    VOID    copyfile()
+ *             
+ *             FILE    *dest           destination file
+ *             FILE    *src            source file
+ *
+ *      function will copy source file to destination file
+ *
+ *
+ *     functions called:
+ *             int     fgetc()         c_library
+ *              int     fputc()         c_library
+ *
+ *     side effects:
+ *             none
+ */
+VOID copyfile (dest,src)
+FILE *src,*dest ;
+{    
+    int ch;
+    while ((ch = fgetc(src)) != EOF) {
+
+       fputc(ch,dest);
+    }
+}
diff --git a/as/hc08/lkmem.c b/as/hc08/lkmem.c
new file mode 100644 (file)
index 0000000..db9a2cd
--- /dev/null
@@ -0,0 +1,361 @@
+/*-------------------------------------------------------------------------
+  lkmem.c - Create a memory summary file with extension .mem
+
+   Written By -  Jesus Calvino-Fraga, jesusc@ieee.org (2002)
+
+   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.
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+#include "strcmpi.h"
+
+int summary(struct area * areap) 
+{
+       #define EQ(A,B) !as_strcmpi((A),(B))
+       #define MIN_STACK 16
+       #define REPORT_ERROR(A, H) \
+       {\
+               fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
+               fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
+               toreturn=1; \
+       }
+
+       #define REPORT_WARNING(A, H) \
+       { \
+               fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
+               fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
+       }
+
+       char buff[128];
+       int j, toreturn=0;
+       unsigned int Total_Last=0, k; 
+
+       struct area * xp;
+       FILE * of;
+       
+       /*Artifacts used for printing*/
+       char start[15], end[15], size[15], max[15];
+       char format[]="   %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
+       char line[]="---------------------";
+
+       typedef struct
+       {
+               unsigned long Start;
+               unsigned long Size;
+               unsigned long Max;
+               char Name[NCPS];
+               unsigned long flag;
+       } _Mem;
+
+       unsigned int dram[0x100];
+       _Mem Ram[]={
+               {0,     0,      0,       "REG_BANK_0", 0x0001},
+               {0x0,   0,      0,       "REG_BANK_1", 0x0002},
+               {0x0,   0,      0,       "REG_BANK_2", 0x0004},
+               {0x0,   0,      0,       "REG_BANK_3", 0x0008},
+               {0x0,   0,      0,       "BSEG_BYTES", 0x0010},
+               {0,     0,      256,    "UNUSED",     0x0000},
+               {0xff,  0,      256,    "DATA",       0x0020},
+               {0,             0,      256, "TOTAL:",     0x0000}
+       };
+       
+       _Mem IRam= {0xff,   0,     0, "INDIRECT RAM",           0x0080};
+       _Mem Stack={0xff,   0,     1, "STACK",                          0x0000};
+       _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM",           0x0100};
+       _Mem Rom=  {0xffff, 0, 65536, "ROM/EPROM/FLASH",        0x0200};
+       
+#if 0
+       if(rflag) /*For the DS390*/
+       {
+               XRam.Max=0x1000000; /*24 bits*/
+               XRam.Start=0xffffff;
+               Rom.Max=0x1000000;
+               Rom.Start=0xffffff;
+       }
+
+       if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
+       {
+               Ram[5].Max=0x80;
+               Ram[6].Max=0x80;
+               Ram[7].Max=0x80;
+               IRam.Max=0x80;
+               iram_size=0x100;
+       }
+       else if(iram_size<0x80)
+       {
+               Ram[5].Max=iram_size;
+               Ram[6].Max=iram_size;
+               Ram[7].Max=iram_size;
+               IRam.Max=0;
+       }
+       else
+       {
+               Ram[5].Max=0x80;
+               Ram[6].Max=0x80;
+               Ram[7].Max=0x80;
+               IRam.Max=iram_size-0x80;
+       }
+#endif
+
+       for(j=0; j<(int)iram_size; j++) dram[j]=0;
+       for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
+
+       /* Open Memory Summary File*/
+       of = afile(linkp->f_idp, "mem", 1);
+       if (of == NULL)
+       {
+               lkexit(1);
+       }
+
+       xp=areap;
+       while (xp)
+       {
+               /**/ if (EQ(xp->a_id, "REG_BANK_0"))
+               {
+                       Ram[0].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "REG_BANK_1"))
+               {
+                       Ram[1].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "REG_BANK_2"))
+               {
+                       Ram[2].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "REG_BANK_3"))
+               {
+                       Ram[3].Size=xp->a_size;
+               }
+               else if (EQ(xp->a_id, "BSEG_BYTES"))
+               {
+                       Ram[4].Size=xp->a_size;
+               }
+               else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") )
+               {
+                       Ram[6].Size+=xp->a_size;
+                       if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
+               }
+
+               else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
+                                EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
+               {
+                       Rom.Size+=xp->a_size;
+                       if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
+               }
+               
+               else if (EQ(xp->a_id, "SSEG"))
+               {
+                       Stack.Size+=xp->a_size;
+                       if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
+               }
+
+               else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG")) 
+               {
+                       XRam.Size+=xp->a_size;
+                       if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
+               }
+
+               else if (EQ(xp->a_id, "ISEG"))
+               {
+                       IRam.Size+=xp->a_size;
+                       if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
+               }
+               xp=xp->a_ap;
+       }
+
+       for(j=0; j<7; j++)
+               for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
+                       dram[k]|=Ram[j].flag; /*Mark as used*/
+       
+#if 0
+       for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
+               dram[k]|=IRam.flag; /*Mark as used*/
+#endif
+
+       /*Compute the amount of unused memory in direct data Ram.  This is the
+       gap between the last register bank or bit segment and the data segment.*/
+       for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
+       Ram[5].Start=k+1;
+       Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
+
+       /*Compute the data Ram totals*/
+       for(j=0; j<7; j++)
+       {
+               if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
+               Ram[7].Size+=Ram[j].Size;
+       }
+       Total_Last=Ram[6].Size+Ram[6].Start-1;
+
+       /*Report the Ram totals*/
+       fprintf(of, "Direct Internal RAM:\n");
+       fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+
+       for(j=0; j<8; j++)
+       {
+               if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
+               if((j!=5) || (Ram[j].Size>0))
+               {
+                       sprintf(start, "0x%02lx", Ram[j].Start);
+                       if(Ram[j].Size==0)
+                               end[0]=0;/*Empty string*/
+                       else
+                               sprintf(end,  "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
+                       sprintf(size, "%5lu", Ram[j].Size);
+                       sprintf(max, "%5lu", Ram[j].Max);
+                       fprintf(of, format, Ram[j].Name, start, end, size, max);
+               }
+       }
+
+#if 0
+       for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
+       {
+               if(dram[k]!=Ram[6].flag)
+               {
+                       sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
+                       REPORT_ERROR(buff, 1);
+                       break;
+               }
+       }
+
+       if(Ram[4].Size>Ram[4].Max)
+       {
+               k=Ram[4].Size-Ram[4].Max;
+               sprintf(buff, "Insufficient bit addressable memory.  "
+                                       "%d byte%s short.\n", k, (k==1)?"":"s");
+               REPORT_ERROR(buff, 1);
+       }
+
+       if(Ram[5].Size!=0)
+       {
+               sprintf(buff, "%ld bytes in data memory wasted.  "
+                           "SDCC link could use: --data-loc 0x%02lx\n",
+                                       Ram[5].Size, Ram[6].Start-Ram[5].Size);
+               REPORT_WARNING(buff, 1);
+       }
+
+       if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
+       {
+               k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
+               sprintf(buff, "Insufficient space in data memory.   "
+                                       "%d byte%s short.\n", k, (k==1)?"":"s");
+               REPORT_ERROR(buff, 1);
+       }
+#endif
+       /*Report the position of the begining of the stack*/
+       fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
+               rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1);
+
+#if 0
+       /*Check that the stack pointer is landing in a safe place:*/
+       if( (dram[Stack.Start] & 0x8000) == 0x8000 )
+       {
+               fprintf(of, ".\n");
+               sprintf(buff, "Stack set to unavailable memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+       else if(dram[Stack.Start])
+       {
+               fprintf(of, ".\n");
+               sprintf(buff, "Stack overlaps area ");
+               REPORT_ERROR(buff, 1);
+               for(j=0; j<7; j++)
+               {
+                               if(dram[Stack.Start]&Ram[j].flag)
+                       {
+                               sprintf(buff, "'%s'\n", Ram[j].Name);
+                               break;
+                       }
+               }
+               if(dram[Stack.Start]&IRam.flag)
+               {
+                       sprintf(buff, "'%s'\n", IRam.Name);
+               }
+               REPORT_ERROR(buff, 0);
+       }
+       else
+       {
+               for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
+               fprintf(of, " with %d bytes available\n", k);
+               if (k<MIN_STACK)
+               {
+                       sprintf(buff, "Only %d byte%s available for stack.\n",
+                               k, (k==1)?"":"s");
+                       REPORT_WARNING(buff, 1);
+               }
+       }
+#endif
+
+       fprintf(of, "\nOther memory:\n");
+       fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+       fprintf(of, format, line, line, line, line, line);
+
+       /*Report IRam totals:*/
+       sprintf(start, "0x%02lx", IRam.Start);
+       if(IRam.Size==0)
+               end[0]=0;/*Empty string*/
+       else
+               sprintf(end,  "0x%02lx", IRam.Size+IRam.Start-1);
+       sprintf(size, "%5lu", IRam.Size);
+       sprintf(max, "%5lu", IRam.Max);
+       fprintf(of, format, IRam.Name, start, end, size, max);
+
+       /*Report XRam totals:*/
+       sprintf(start, "0x%04lx", XRam.Start);
+       if(XRam.Size==0)
+               end[0]=0;/*Empty string*/
+       else
+               sprintf(end,  "0x%04lx", XRam.Size+XRam.Start-1);
+       sprintf(size, "%5lu", XRam.Size);
+       sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
+       fprintf(of, format, XRam.Name, start, end, size, max);
+
+       /*Report Rom/Flash totals:*/
+       sprintf(start, "0x%04lx", Rom.Start);
+       if(Rom.Size==0)
+               end[0]=0;/*Empty string*/
+       else
+               sprintf(end,  "0x%04lx", Rom.Size+Rom.Start-1);
+       sprintf(size, "%5lu", Rom.Size);
+       sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
+       fprintf(of, format, Rom.Name, start, end, size, max);
+
+       /*Report any excess:*/
+#if 0
+       if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
+       {
+               sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+#endif
+       if( ((XRam.Start+XRam.Size)>XRam.Max) ||
+               (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
+       {
+               sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+       if( ((Rom.Start+Rom.Size)>Rom.Max) ||
+               (((int)Rom.Size>code_size)&&(code_size>=0)) )
+       {
+               sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
+               REPORT_ERROR(buff, 1);
+       }
+
+       fclose(of);
+       return toreturn;                
+}
diff --git a/as/hc08/lknoice.c b/as/hc08/lknoice.c
new file mode 100644 (file)
index 0000000..2cd6a91
--- /dev/null
@@ -0,0 +1,246 @@
+/* lknoice.c */
+
+/*
+ * Extensions to CUG 292 linker ASLINK to produce NoICE debug files
+ *
+ * 31-Oct-1997 by John Hartman
+ * 30-Jan-98 JLH add page to DefineNoICE for 8051
+ *  2-Feb-98 JLH Allow optional .nest on local vars - C scoping rules...
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "aslink.h"
+#include "strcmpi.h"
+
+static void DefineGlobal( char *name, Addr_T value, int page );
+static void DefineScoped( char *name, Addr_T value, int page );
+static void DefineFile( char *name, Addr_T value, int page );
+static void DefineFunction( char *name, Addr_T value, int page );
+static void DefineStaticFunction( char *name, Addr_T value, int page );
+static void DefineEndFunction( Addr_T value, int page );
+static void DefineLine( char *lineString, Addr_T value, int page );
+static void PagedAddress( Addr_T value, int page );
+
+/*
+ * Called from lstarea in lklist.c for each symbol.
+ *
+ * Generates appropriate NoICE commands into output file, if any is open
+ *
+ */
+void DefineNoICE( char *name, Addr_T value, int page )
+{
+       char token1[NCPS];                      /* parse for file.function.symbol */
+       char token2[NCPS];
+       char token3[NCPS];
+       //      char token4[NCPS];
+       char sep1, sep2;
+       int  j, level;
+
+       /* no output if file is not open */
+       if (jfp == NULL) return;
+
+        j = sscanf( name, "%[^.]%c%[^.]%c%s",
+                   token1, &sep1, token2, &sep2, token3 );
+        switch (j)
+       {
+               /* file.function.symbol, or file.function..SPECIAL */
+               case 5:
+                       DefineFile( token1, 0, 0 );
+                       if (token3[0] == '.')
+                       {
+                               if (strcmp( token3, ".FN" ) == 0)
+                               {
+                                       /* Global function */
+                                        DefineFunction( token2, value, page );
+                               }
+                               else if (strcmp( token3, ".SFN" ) == 0)
+                               {
+                                       /* Static (file-scope) function */
+                                       DefineStaticFunction( token2, value, page );
+                               }
+                               else if (strcmp( token3, ".EFN" ) == 0)
+                               {
+                                       /* End of function */
+                                        DefineEndFunction( value, page );
+                                }
+                       }
+                       else
+                       {
+                               /* Function-scope var. */
+                               DefineFunction( token2, 0, 0 );
+
+                                /* Look for optional level integer */
+                               j = sscanf( token3, "%[^.]%c%u", token1, &sep1, &level );
+                                if ((j == 3) && (level != 0))
+                                {
+                                       sprintf( &token1[ strlen(token1) ], "_%u", level );
+                               }
+                                       DefineScoped( token1, value, page );
+                        }
+                       break;
+
+               /* file.func. is illegal */
+               case 4:
+                       break;
+
+               /* either file.symbol or file.line# */
+               case 3:
+                       DefineFile( token1, 0, 0 );
+                       if ((token2[0] >= '0') && (token2[0] <= '9'))
+                       {
+                               /* Line number */
+                                DefineLine( token2, value, page );
+                        }
+                       else
+                       {
+                               /* File-scope symbol.  (Kill any function) */
+                               DefineEndFunction( 0, 0 );
+                                DefineScoped( token2, value, page );
+                        }
+                       break;
+
+               /* symbol. is illegal */
+               case 2:
+                       break;
+
+               /* just a symbol */
+               case 1:
+                        DefineGlobal( token1, value, page );
+                        break;
+       }
+}
+
+static char currentFile[NCPS];
+static char currentFunction[NCPS];
+
+/*
+ * static function:
+ * Define "name" as a global symbol
+ */
+void DefineGlobal( char *name, Addr_T value, int page )
+{
+       fprintf( jfp, "DEF %s ", name );
+       PagedAddress( value, page );
+}
+
+/*
+ * static function:
+ * Define "name" as a static (scoped) symbol
+ */
+void DefineScoped( char *name, Addr_T value, int page )
+{
+       fprintf( jfp, "DEFS %s ", name );
+       PagedAddress( value, page );
+}
+
+/*
+ * static function:
+ * Define "name" as the current file
+ */
+void DefineFile( char *name, Addr_T value, int page )
+{
+       if (as_strcmpi( name, currentFile ) != 0)
+       {
+               strcpy( currentFile, name );
+               if (value != 0)
+               {
+                       fprintf( jfp, "FILE %s ", name );
+                       PagedAddress( value, page );
+               }
+               else
+               {
+                       fprintf( jfp, "FILE %s\n", name );
+               }
+       }
+}
+
+/*
+ * static function:
+ * Define "name" as the current function
+ */
+void DefineFunction( char *name, Addr_T value, int page )
+{
+       if (as_strcmpi( name, currentFunction ) != 0)
+       {
+               strcpy( currentFunction, name );
+                if (value != 0)
+                {
+                        fprintf( jfp, "DEF %s ", name );
+                       PagedAddress( value, page );
+                        fprintf( jfp, "FUNC %s ", name );
+                       PagedAddress( value, page );
+                }
+                else
+                {
+                        fprintf( jfp, "FUNC %s\n", name );
+               }
+       }
+}
+
+/*
+ * static function:
+ * Define "name" as the current static (scoped) function
+ */
+void DefineStaticFunction( char *name, Addr_T value, int page )
+{
+       if (as_strcmpi( name, currentFunction ) != 0)
+       {
+               strcpy( currentFunction, name );
+               if (value != 0)
+               {
+                        fprintf( jfp, "DEFS %s ", name );
+                       PagedAddress( value, page );
+                       fprintf( jfp, "SFUNC %s ", name );
+                       PagedAddress( value, page );
+               }
+               else
+               {
+                       fprintf( jfp, "SFUNC %s\n", name );
+               }
+       }
+}
+
+/*
+ * static function:
+ * Define the end of the current function
+ */
+void DefineEndFunction( Addr_T value, int page )
+{
+       if (currentFunction[0] != 0)
+       {
+               if (value != 0)
+               {
+                       fprintf( jfp, "ENDF " );
+                       PagedAddress( value, page );
+               }
+               else
+               {
+                       fprintf( jfp, "ENDF\n" );
+               }
+
+               currentFunction[0] = 0;
+       }
+}
+
+/*
+ * static function:
+ * Define "lineNumber" as a line in the current file
+ */
+void DefineLine( char *lineString, Addr_T value, int page )
+{
+       int indigit, lineNumber = 0;
+
+       while( (indigit=digit( *lineString++, 10 )) >= 0)
+       {
+               lineNumber = 10*lineNumber + indigit;
+       }
+       fprintf( jfp, "LINE %u ", lineNumber );
+        PagedAddress( value, page );
+}
+
+void PagedAddress( Addr_T value, int page )
+{
+       fprintf( jfp, "%X:0x%X\n", page, value );
+}
diff --git a/as/hc08/lkrloc.c b/as/hc08/lkrloc.c
new file mode 100644 (file)
index 0000000..cf76102
--- /dev/null
@@ -0,0 +1,1473 @@
+/* lkrloc.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 29-Oct-97 JLH:
+ *              - errdmp: show s_id as string rather than array [NCPS]
+ *              - relr: add support for 11 bit 8051 addressing
+ * 02-Apr-98 JLH: don't output empty hex records
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lkrloc.c
+ *
+ *     The module lkrloc.c contains the functions which
+ *     perform the relocation calculations.
+ *
+ *     lkrloc.c contains the following functions:
+ *             Addr_T  adb_b()
+ *             Addr_T  adb_lo()
+ *             Addr_T  adb_hi()
+ *             Addr_T  adw_w()
+ *             Addr_T  adw_lo()
+ *             Addr_T  adw_hi()
+ *             VOID    erpdmp()
+ *             VOID    errdmp()
+ *             Addr_T  evword()
+ *             VOID    prntval()
+ *             VOID    rele()
+ *             VOID    relerr()
+ *             VOID    relerp()
+ *             VOID    reloc()
+ *             VOID    relp()
+ *             VOID    relr()
+ *             VOID    relt()
+ *
+ *     lkrloc.c the local variable errmsg[].
+ *
+ */
+
+/* Global which holds the upper 16 bits of the last 32 bit area adress
+ * output. Useful only for iHex mode.
+ */
+int    lastExtendedAddress=-1;
+
+/* Static variable which holds the index of last processed area.
+ * Useful only for iHex mode.
+ */
+static int lastAreaIndex = -1;
+
+/*)Function    VOID    reloc(c)
+ *
+ *                     char c          process code
+ *
+ *     The function reloc() calls a particular relocation
+ *     function determined by the process code.
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             int     lkerr           error flag
+ *
+ *     called functions:
+ *             int     fprintf()       c_library
+ *             VOID    rele()          lkrloc.c
+ *             VOID    relp()          lkrloc.c
+ *             VOID    relr()          lkrloc.c
+ *             VOId    relt()          lkrloc.c
+ *
+ *     side effects:
+ *             Refer to the called relocation functions.
+ *
+ */
+
+VOID
+reloc(c)
+char c;
+{
+       switch(c) {
+
+       case 'T':
+               relt();
+               break;
+
+       case 'R':
+               relr();
+               break;
+
+       case 'P':
+               relp();
+               break;
+
+       case 'E':
+               rele();
+               break;
+
+       default:
+               fprintf(stderr, "Undefined Relocation Operation\n");
+               lkerr++;
+               break;
+
+       }
+}
+
+
+/*)Function    VOID    relt()
+ *
+ *     The function relt() evaluates a T line read by
+ *     the linker. Each byte value read is saved in the
+ *     rtval[] array, rtflg[] is set, and the number of
+ *     evaluations is maintained in rtcnt.
+ *
+ *             T Line
+ *
+ *             T xx xx nn nn nn nn nn ...
+ *
+ *
+ *             In:     "T n0 n1 n2 n3 ... nn"
+ *
+ *             Out:     0   1    2        ..  rtcnt
+ *                       +----+----+----+----+----+
+ *             rtval | n0 | n1 | n2 | .. | nn |
+ *                   +----+----+----+----+----+
+ *             rtflag|  1 |  1 |  1 |  1 |  1 |
+ *            +----+----+----+----+----+
+ *
+ *     The T line contains the assembled code output by the assem-
+ *     bler with xx xx being the offset address from the current area
+ *     base address and nn being the assembled instructions and data in
+ *     byte format.
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             int     rtcnt           number of values evaluated
+ *             int     rtflg[]         array of evaluation flags
+ *             int     rtval[]         array of evaluation values
+ *
+ *     called functions:
+ *             int     eval()          lkeval.c
+ *             int     more()          lklex.c
+ *
+ *     side effects:
+ *             Linker input T line evaluated.
+ *
+ */
+
+VOID
+relt()
+{
+       rtcnt = 0;
+       while (more()) {
+               if (rtcnt < NTXT) {
+                       rtval[rtcnt] = eval();
+                       rtflg[rtcnt] = 1;
+                       rtcnt++;
+               }
+       }
+}
+
+/*)Function    VOID    relr()
+ *
+ *     The function relr() evaluates a R line read by
+ *     the linker.  The R line data is combined with the
+ *     previous T line data to perform the relocation of
+ *     code and data bytes.  The S19 / IHX output and
+ *     translation of the LST files to RST files may be
+ *     performed.
+ *
+ *             R Line
+ *
+ *             R 0 0 nn nn n1 n2 xx xx ...
+ *
+ *             The R line provides the relocation information to the linker.
+ *     The nn nn value is the current area index, i.e.  which area  the
+ *     current  values  were  assembled.  Relocation information is en-
+ *     coded in groups of 4 bytes:
+ *
+ *     1.      n1 is the relocation mode and object format
+ *                     1.      bit 0 word(0x00)/byte(0x01)
+ *                     2.      bit 1 relocatable area(0x00)/symbol(0x02)
+ *                     3.      bit 2 normal(0x00)/PC relative(0x04) relocation
+ *                     4.      bit  3  1-byte(0x00)/2-byte(0x08) object format for
+ *                     byte data
+ *                     5.      bit 4 signed(0x00)/unsigned(0x10) byte data
+ *                     6.      bit 5 normal(0x00)/page '0'(0x20) reference
+ *                     7.      bit 6 normal(0x00)/page 'nnn'(0x40) reference
+ *
+ *     2.      n2      is      a byte index into the corresponding (i.e.  pre-
+ *                     ceeding) T line data (i.e.      a pointer to the data to be
+ *                     updated  by  the  relocation).   The T line data may be
+ *                     1-byte or  2-byte  byte  data  format  or  2-byte  word
+ *                     format.
+ *
+ *     3.      xx xx  is the area/symbol index for the area/symbol be-
+ *                     ing referenced.  the corresponding area/symbol is found
+ *             in the header area/symbol lists.
+ *
+ *     The groups of 4 bytes are repeated for each item requiring relo-
+ *     cation in the preceeding T line.
+ *
+ *     local variable:
+ *             areax   **a             pointer to array of area pointers
+ *             int     aindex          area index
+ *             char    *errmsg[]       array of pointers to error strings
+ *             int     error           error code
+ *             int     lkerr           error flag
+ *             int     mode            relocation mode
+ *             adrr_t  paga            paging base area address
+ *             Addr_T  pags            paging symbol address
+ *             Addr_T  pc              relocated base address
+ *             Addr_T  r               PCR relocation value
+ *             Addr_T  reli            relocation initial value
+ *             Addr_T  relv            relocation final value
+ *             int     rindex          symbol / area index
+ *             Addr_T  rtbase          base code address
+ *             Addr_T  rtofst          rtval[] index offset
+ *             int     rtp             index into T data
+ *             sym     **s             pointer to array of symbol pointers
+ *
+ *     global variables:
+ *             head    *hp             pointer to the head structure
+ *             rerr    rerr            linker error structure
+ *             FILE    *stderr         standard error device
+ *
+ *     called functions:
+ *             Addr_T  adb_b()         lkrloc.c
+ *             Addr_T  adb_lo()        lkrloc.c
+ *             Addr_T  adb_hi()        lkrloc.c
+ *             Addr_T  adw_w()         lkrloc.c
+ *             Addr_T  evword()        lkrloc.c
+ *             int     eval()          lkeval.c
+ *             int     fprintf()       c_library
+ *             VOID    ihx()           lkihx.c
+ *             int     lkulist         lklist.c
+ *             int     more()          lklex.c
+ *             VOID    relerr()        lkrloc.c
+ *             VOID    s19()           lks19.c
+ *             int     symval()        lksym.c
+ *
+ *     side effects:
+ *             The R and T lines are combined to produce
+ *             relocated code and data.  Output S19 / IHX
+ *             and relocated listing files may be produced.
+ *
+ */
+
+VOID
+relr()
+{
+       register int mode;
+       register Addr_T reli, relv;
+       int aindex, rindex, rtp, error;
+       Addr_T r, rtbase, rtofst, paga, pags, pc;
+       struct areax **a;
+       struct sym **s;
+
+       /*
+        * Get area and symbol lists
+        */
+       a = hp->a_list;
+       s = hp->s_list;
+
+       /*
+        * Verify Area Mode
+        */
+       if (eval() != (R_WORD | R_AREA) || eval()) {
+               fprintf(stderr, "R input error\n");
+               lkerr++;
+       }
+
+       /*
+        * Get area pointer
+        */
+       aindex = evword();
+       if (aindex >= hp->h_narea) {
+               fprintf(stderr, "R area error\n");
+               lkerr++;
+               return;
+       }
+
+       /*
+        * Base values
+        */
+       rtbase = adw_w(0, 0);
+       rtofst = 2;
+
+       /*
+        * Relocate address
+        */
+       pc = adw_w(a[aindex]->a_addr, 0);
+
+       #if 0
+       printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex, 
+               a[aindex]->a_addr, a[aindex]->a_size, rtbase);
+       #endif
+       /*
+        * Do remaining relocations
+        */
+       while (more()) {
+               error = 0;
+               mode = eval();
+               
+               if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK)
+               {
+                   mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval();
+                   /* printf("unescaping rmode\n"); */
+               }
+               
+               rtp = eval();
+               rindex = evword();
+
+               /*
+                * R_SYM or R_AREA references
+                */
+               if (mode & R_SYM) {
+                       if (rindex >= hp->h_nglob) {
+                               fprintf(stderr, "R symbol error\n");
+                               lkerr++;
+                               return;
+                       }
+                       reli = symval(s[rindex]);
+               } else {
+                       if (rindex >= hp->h_narea) {
+                               fprintf(stderr, "R area error\n");
+                               lkerr++;
+                               return;
+                       }
+                       reli = a[rindex]->a_addr;
+               }
+
+               /*
+                * R_PCR addressing
+                */
+               if (mode & R_PCR) {
+                       if (mode & R_BYTE) {
+                               reli -= (pc + (rtp-rtofst) + 1);
+                       } else {
+                               reli -= (pc + (rtp-rtofst) + 2);
+                       }
+               }
+
+               /*
+                * R_PAG0 or R_PAG addressing
+                */
+               if (mode & (R_PAG0 | R_PAG)) {
+                       paga  = sdp.s_area->a_addr;
+                       pags  = sdp.s_addr;
+                       reli -= paga + pags;
+               }
+
+               /*
+                * R_BYTE or R_WORD operation
+                */
+               if (mode & R_BYTE) {
+                       if (mode & R_BYT3)
+                       {
+                               /* This is a three byte address, of which 
+                                * we will select one byte.
+                                */
+                               if (mode & R_HIB)
+                               {
+                                       /* printf("24 bit address selecting hi byte.\n"); */
+                                       relv = adb_24_hi(reli, rtp);
+                               }               
+                               else if (mode & R_MSB)
+                               {
+                                       /* Note that in 24 bit mode, R_MSB
+                                        * is really the middle byte, not
+                                        * the most significant byte.
+                                        *
+                                        * This is ugly and I can only apologize
+                                        * for any confusion.
+                                        */
+                                       /* printf("24 bit address selecting middle byte.\n"); */
+                                       relv = adb_24_mid(reli, rtp);                           
+                               }
+                               else
+                               {
+                                       /* printf("24 bit address selecting lo byte.\n"); */
+                                       relv = adb_24_lo(reli, rtp);                            
+                               }
+                       }
+                       else if (mode & R_BYT2) {
+                               /* This is a two byte address, of
+                                * which we will select one byte.
+                                */
+                               if (mode & R_MSB) {
+                                       relv = adb_hi(reli, rtp);
+                               } else {
+                                       relv = adb_lo(reli, rtp);
+                               }
+                       } else {
+                               relv = adb_b(reli, rtp);
+                       }
+               } else if (IS_R_J11(mode)) {
+                       /* JLH: 11 bit jump destination for 8051.  Forms
+                       /  two byte instruction with op-code bits
+                       /  in the MIDDLE!
+                       /  rtp points at 3 byte locus: first two
+                       /  will get the instructiion. third one
+                       /  has raw op-code.
+                       */
+       
+                       /* Calculate absolute destination
+                       /  relv must be on same 2K page as pc
+                       */
+                       relv = adw_w(reli, rtp);
+
+            if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
+                    error = 2;
+            }
+
+            /* Merge MSB (byte 0) with op-code, ignoring
+            /  top 5 bits of address.  Then hide the op-code
+            */
+            rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
+            rtflg[rtp+2] = 0;
+                       rtofst += 1;
+               }
+               else if (IS_R_J19(mode)) {
+                       /* 19 bit jump destination for DS80C390.  Forms
+                       /  three byte instruction with op-code bits
+                       /  in the MIDDLE!
+                       /  rtp points at 4 byte locus: first three
+                       /  will get the instructiion. fourth one
+                       /  has raw op-code.
+                        */
+       
+                       /* Calculate absolute destination
+                       /  relv must be on same 512K page as pc
+                       */
+                       relv = adw_24(reli, rtp);
+
+            if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) {
+                    error = 2;
+                               }
+
+            /* Merge MSB (byte 0) with op-code, ignoring
+            /  top 5 bits of address.  Then hide the op-code
+            */
+            rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3];
+            rtflg[rtp+3] = 0;
+                       rtofst += 1;
+               }                
+               else if (IS_C24(mode))
+               {
+                       /* 24 bit address */
+                       relv = adw_24(reli, rtp);
+                       }
+               else
+               {
+                       /* 16 bit address. */
+                       relv = adw_w(reli, rtp);
+               }
+
+               /*
+                * R_BYTE with R_BYT2 offset adjust
+                */
+               if (mode & R_BYTE) {
+                       if (mode & R_BYT2) {
+                               rtofst += 1;
+                       }
+               }
+
+               /*
+                * Unsigned Byte Checking
+                */
+               if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
+                       error = 1;
+
+               /*
+                * PCR Relocation Error Checking
+                */
+               if (mode & R_PCR && mode & R_BYTE) {
+                       r = relv & ~0x7F;
+                       if (r != (Addr_T) ~0x7F && r != 0)
+                               error = 2; 
+               }
+
+               /*
+                * Page Relocation Error Checking
+                */
+               /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
+                       error = 3;*/
+               if (mode & R_PAG  && (relv & ~0xFF))
+                       error = 4;
+
+               /*
+                * Error Processing
+                */
+               if (error) {
+                       rerr.aindex = aindex;
+                       rerr.mode = mode;
+                       rerr.rtbase = rtbase + rtp - rtofst - 1;
+                       rerr.rindex = rindex;
+                       rerr.rval = relv - reli;
+                       relerr(errmsg[error-1]);
+               }
+       }
+       if (uflag != 0) {
+               lkulist(1);
+       }
+
+
+       /* JLH: output only if data (beyond two byte address) */
+       if ((oflag == 1) && (rtcnt > 2)) {
+               int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff;
+               
+               /* Boy, is this a hack: for ABS sections, the
+                * base address is stored as zero, and the T records
+                * indicate the offset from zero.
+                *
+                * Since T records can only indicate a 16 bit offset, this
+                * obviously creates a problem for ABS segments located
+                * above 64K (this is only meaningful in flat24 mode).
+                *
+                * However, the size of an ABS area is stored as
+                * base address + section size (I suspect this is a bug,
+                * but it's a handy one right now). So the upper 8 bits of
+                * the 24 bit address are stored in the size record.
+                * Thus we add it in.
+                *
+                * This is another reason why we can't have areas greater
+                * than 64K yet, even in flat24 mode.
+                */
+       //      extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff);
+       //      commented out by jr 
+               
+               if (lastAreaIndex != aindex) {
+                       lastAreaIndex = aindex;
+                       newArea();
+               }
+               
+#if 0
+               if (extendedAddress != lastExtendedAddress)
+               {
+               
+                   if (lastExtendedAddress!=-1) {
+                     printf("output extended linear address record 0x%x 0x%x\n",
+                            extendedAddress, lastExtendedAddress);
+                   }
+                   
+                   if (rflag)
+                   {
+                       ihxEntendedLinearAddress(extendedAddress);
+                   }
+                   else if (extendedAddress)
+                   {
+                       /* Not allowed to generate extended address records,
+                        * but one is called for here...
+                        */
+                       fprintf(stderr, 
+                               "warning: extended linear address encountered; "
+                               "you probably want the -r flag.\n");
+                   }
+                   lastExtendedAddress = extendedAddress;
+               }
+#endif
+               ihx(1);
+       } else
+       if ((oflag == 2) && (rtcnt > 2)) {
+               s19(1);
+       }
+}
+
+char *errmsg[] = {
+       "Unsigned Byte error",
+       "Byte PCR relocation error",
+       "Page0 relocation error",
+       "Page Mode relocation error"
+};
+
+
+/*)Function    VOID    relp()
+ *
+ *     The function relp() evaluates a P line read by
+ *     the linker.  The P line data is combined with the
+ *     previous T line data to set the base page address
+ *     and test the paging boundary and length.
+ *
+ *             P Line
+ *
+ *             P 0 0 nn nn n1 n2 xx xx
+ *
+ *     The P line provides the paging information to the linker as
+ *     specified by a .setdp directive.  The format of the relocation
+ *     information is identical to that of the R line.  The correspond-
+ *     ing T line has the following information:
+ *             T xx xx aa aa bb bb
+ *
+ *     Where aa aa is the area reference number which specifies the
+ *     selected page area and bb bb is the base address of the page.
+ *     bb bb will require relocation processing if the 'n1 n2 xx xx' is
+ *     specified in the P line.  The linker will verify that the base
+ *     address is on a 256 byte boundary and that the page length of an
+ *     area defined with the PAG type is not larger than 256 bytes.
+ *
+ *     local variable:
+ *             areax   **a             pointer to array of area pointers
+ *             int     aindex          area index
+ *             int     mode            relocation mode
+ *             Addr_T  relv    relocation value
+ *             int     rindex          symbol / area index
+ *             int     rtp                     index into T data
+ *             sym     **s                     pointer to array of symbol pointers
+ *
+ *     global variables:
+ *             head *hp                pointer to the head structure
+ *             int     lkerr           error flag
+ *             sdp     sdp                     base page structure
+ *             FILE *stderr    standard error device
+ *
+ *     called functions:
+ *             Addr_T adw_w()  lkrloc.c
+ *             Addr_T evword() lkrloc.c
+ *             int     eval()          lkeval.c
+ *             int     fprintf()       c_library
+ *             int     more()          lklex.c
+ *             int     symval()        lksym.c
+ *
+ *     side effects:
+ *             The P and T lines are combined to set
+ *             the base page address and report any
+ *             paging errors.
+ *
+ */
+
+VOID
+relp()
+{
+       register int aindex, rindex;
+       int mode, rtp;
+       Addr_T relv;
+       struct areax **a;
+       struct sym **s;
+
+       /*
+        * Get area and symbol lists
+        */
+       a = hp->a_list;
+       s = hp->s_list;
+
+       /*
+        * Verify Area Mode
+        */
+       if (eval() != (R_WORD | R_AREA) || eval()) {
+               fprintf(stderr, "P input error\n");
+               lkerr++;
+       }
+
+       /*
+        * Get area pointer
+        */
+       aindex = evword();
+       if (aindex >= hp->h_narea) {
+               fprintf(stderr, "P area error\n");
+               lkerr++;
+               return;
+       }
+
+       /*
+        * Do remaining relocations
+        */
+       while (more()) {
+               mode = eval();
+               rtp = eval();
+               rindex = evword();
+
+               /*
+                * R_SYM or R_AREA references
+                */
+               if (mode & R_SYM) {
+                       if (rindex >= hp->h_nglob) {
+                               fprintf(stderr, "P symbol error\n");
+                               lkerr++;
+                               return;
+                       }
+                       relv = symval(s[rindex]);
+               } else {
+                       if (rindex >= hp->h_narea) {
+                               fprintf(stderr, "P area error\n");
+                               lkerr++;
+                               return;
+                       }
+                       relv = a[rindex]->a_addr;
+               }
+               adw_w(relv, rtp);
+       }
+
+       /*
+        * Paged values
+        */
+       aindex = adw_w(0,2);
+       if (aindex >= hp->h_narea) {
+               fprintf(stderr, "P area error\n");
+               lkerr++;
+               return;
+       }
+       sdp.s_areax = a[aindex];
+       sdp.s_area = sdp.s_areax->a_bap;
+       sdp.s_addr = adw_w(0,4);
+       if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
+               relerp("Page Definition Boundary Error");
+}
+
+/*)Function    VOID    rele()
+ *
+ *     The function rele() closes all open output files
+ *     at the end of the linking process.
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             int     oflag           output type flag
+ *             int     uflag           relocation listing flag
+ *
+ *     called functions:
+ *             VOID    ihx()           lkihx.c
+ *             VOID    lkulist()       lklist.c
+ *             VOID    s19()           lks19.c
+ *
+ *     side effects:
+ *             All open output files are closed.
+ *
+ */
+
+VOID
+rele()
+{
+       if (uflag != 0) {
+               lkulist(0);
+       }
+       if (oflag == 1) {
+               ihx(0);
+       } else
+       if (oflag == 2) {
+               s19(0);
+       }
+}
+
+/*)Function    Addr_T          evword()
+ *
+ *     The function evword() combines two byte values
+ *     into a single word value.
+ *
+ *     local variable:
+ *             Addr_T  v               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             int     eval()          lkeval.c
+ *
+ *     side effects:
+ *             Relocation text line is scanned to combine
+ *             two byte values into a single word value.
+ *
+ */
+
+Addr_T
+evword()
+{
+       register Addr_T v;
+
+       if (hilo) {
+               v =  (eval() << 8);
+               v +=  eval();
+       } else {
+               v =   eval();
+               v += (eval() << 8);
+       }
+       return(v);
+}
+
+/*)Function    Addr_T          adb_b(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adb_b() adds the value of v to
+ *     the single byte value contained in rtval[i].
+ *     The new value of rtval[i] is returned.
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             none
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *
+ */
+
+Addr_T
+adb_b(v, i)
+register Addr_T v;
+register int i;
+{
+       return(rtval[i] += v);
+}
+
+/*)Function    Addr_T          adb_lo(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adb_lo() adds the value of v to the
+ *     double byte value contained in rtval[i] and rtval[i+1].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The MSB rtflg[] is cleared.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The rtflg[] value corresponding to the
+ *             MSB of the word value is cleared to reflect
+ *             the fact that the LSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_lo(v, i)
+Addr_T v;
+int    i;
+{
+       register Addr_T j;
+
+       j = adw_w(v, i);
+       /*
+        * Remove Hi byte
+        */
+       if (hilo) {
+               rtflg[i] = 0;
+       } else {
+               rtflg[i+1] = 0;
+       }
+       return (j);
+}
+
+/*)Function    Addr_T          adb_hi(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adb_hi() adds the value of v to the
+ *     double byte value contained in rtval[i] and rtval[i+1].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The LSB rtflg[] is cleared.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The rtflg[] value corresponding to the
+ *             LSB of the word value is cleared to reflect
+ *             the fact that the MSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_hi(v, i)
+Addr_T v;
+int    i;
+{
+       register Addr_T j;
+
+       j = adw_w(v, i);
+       /*
+        * Remove Lo byte
+        */
+       if (hilo) {
+               rtflg[i+1] = 0;
+       } else {
+               rtflg[i] = 0;
+       }
+       return (j);
+}
+
+/*)Function    Addr_T          adb_24_hi(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adb_24_hi() adds the value of v to the
+ *     24 bit value contained in rtval[i] - rtval[i+2].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The LSB & middle byte rtflg[] is cleared.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The rtflg[] value corresponding to the
+ *             LSB & middle byte of the word value is cleared to
+ *             reflect the fact that the MSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_24_hi(Addr_T v, int i)
+{
+       register Addr_T j;
+
+       j = adw_24(v, i);
+
+       /* Remove the lower two bytes. */
+       if (hilo)
+       {
+           rtflg[i+2] = 0;
+       }
+       else
+       {
+           rtflg[i] = 0;
+       }
+       rtflg[i+1] = 0;
+
+       return (j);
+}
+
+/*)Function    Addr_T          adb_24_mid(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adb_24_mid() adds the value of v to the
+ *     24 bit value contained in rtval[i] - rtval[i+2].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The LSB & MSB byte rtflg[] is cleared.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The rtflg[] value corresponding to the
+ *             LSB & MSB of the 24 bit value is cleared to reflect
+ *             the fact that the middle byte is the selected byte.
+ *
+ */
+
+Addr_T
+adb_24_mid(Addr_T v, int i)
+{
+       register Addr_T j;
+
+       j = adw_24(v, i);
+
+       /* remove the MSB & LSB. */
+       rtflg[i+2] = 0;
+       rtflg[i] = 0;
+
+       return (j);
+}
+
+/*)Function    Addr_T          adb_24_lo(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adb_24_lo() adds the value of v to the
+ *     24 bit value contained in rtval[i] - rtval[i+2].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The MSB & middle byte rtflg[] is cleared.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The rtflg[] value corresponding to the
+ *             MSB & middle byte  of the word value is cleared to
+ *             reflect the fact that the LSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_24_lo(Addr_T v, int i)
+{
+       register Addr_T j;
+
+       j = adw_24(v, i);
+
+       /* Remove the upper two bytes. */
+       if (hilo)
+       {
+           rtflg[i] = 0;
+       }
+       else
+       {
+           rtflg[i+2] = 0;
+       }
+       rtflg[i+1] = 0;
+
+       return (j);
+}
+
+/*)Function    Addr_T          adw_w(v, i)
+ *
+ *             int     v               value to add to word
+ *             int     i               rtval[] index
+ *
+ *     The function adw_w() adds the value of v to the
+ *     word value contained in rtval[i] and rtval[i+1].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The word value of rtval[] is changed.
+ *
+ */
+
+Addr_T
+adw_w(v, i)
+register Addr_T v;
+register int i;
+{
+       register Addr_T j;
+
+       if (hilo) {
+               j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
+               rtval[i] = (j >> 8) & 0xff;
+               rtval[i+1] = j & 0xff;
+       } else {
+               j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
+               rtval[i] = j & 0xff;
+               rtval[i+1] = (j >> 8) & 0xff;
+       }
+       return(j);
+}
+
+/*)Function    Addr_T          adw_24(v, i)
+ *
+ *             int     v               value to add to word
+ *             int     i               rtval[] index
+ *
+ *     The function adw_w() adds the value of v to the
+ *     24 bit value contained in rtval[i] - rtval[i+2].
+ *     The new value of rtval[i] - rtval[i+2] is returned.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The word value of rtval[] is changed.
+ *
+ */
+Addr_T
+adw_24(Addr_T v, int i)
+{
+       register Addr_T j;
+
+       if (hilo) {
+               j = v + ((rtval[i] & 0xff) << 16) 
+                     + ((rtval[i+1] & 0xff) << 8)
+                     + (rtval[i+2] & 0xff);
+               rtval[i] = (j >> 16) & 0xff;
+               rtval[i+1] = (j >> 8) & 0xff;
+               rtval[i+2] = j & 0xff;
+       } else {
+               j = v + (rtval[i] & 0xff) 
+                     + ((rtval[i+1] & 0xff) << 8)
+                     + ((rtval[i+2] & 0xff) << 16);
+               rtval[i] = j & 0xff;
+               rtval[i+1] = (j >> 8) & 0xff;
+               rtval[i+2] = (j >> 16) & 0xff;
+       }
+       return(j);
+}
+
+/*)Function    Addr_T          adw_lo(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adw_lo() adds the value of v to the
+ *     double byte value contained in rtval[i] and rtval[i+1].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The MSB rtval[] is zeroed.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The MSB of the word value is cleared to reflect
+ *             the fact that the LSB is the selected byte.
+ *
+ */
+
+Addr_T
+adw_lo(v, i)
+Addr_T v;
+int    i;
+{
+       register Addr_T j;
+
+       j = adw_w(v, i);
+       /*
+        * Clear Hi byte
+        */
+       if (hilo) {
+               rtval[i] = 0;
+       } else {
+               rtval[i+1] = 0;
+       }
+       return (j);
+}
+
+/*)Function    Addr_T          adw_hi(v, i)
+ *
+ *             int     v               value to add to byte
+ *             int     i               rtval[] index
+ *
+ *     The function adw_hi() adds the value of v to the
+ *     double byte value contained in rtval[i] and rtval[i+1].
+ *     The new value of rtval[i] / rtval[i+1] is returned.
+ *     The MSB and LSB values are interchanged.
+ *     The MSB rtval[] is zeroed.
+ *
+ *     local variable:
+ *             Addr_T  j               temporary evaluation variable
+ *
+ *     global variables:
+ *             hilo                    byte ordering parameter
+ *
+ *     called functions:
+ *             none
+ *
+ *     side effects:
+ *             The value of rtval[] is changed.
+ *             The MSB and LSB values are interchanged and
+ *             then the MSB cleared.
+ *
+ */
+
+Addr_T
+adw_hi(v, i)
+Addr_T v;
+int    i;
+{
+       register Addr_T j;
+
+       j = adw_w(v, i);
+       /*
+        * LSB = MSB, Clear MSB
+        */
+       if (hilo) {
+               rtval[i+1] = rtval[i];
+               rtval[i] = 0;
+       } else {
+               rtval[i] = rtval[i+1];
+               rtval[i+1] = 0;
+       }
+       return (j);
+}
+
+/*)Function    VOID    relerr(str)
+ *
+ *             char    *str            error string
+ *
+ *     The function relerr() outputs the error string to
+ *     stderr and to the map file (if it is open).
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             FILE    *mfp            handle for the map file
+ *
+ *     called functions:
+ *             VOID    errdmp()        lkrloc.c
+ *
+ *     side effects:
+ *             Error message inserted into map file.
+ *
+ */
+
+VOID
+relerr(str)
+char *str;
+{
+       errdmp(stderr, str);
+       if (mfp)
+               errdmp(mfp, str);
+}
+
+/*)Function    VOID    errdmp(fptr, str)
+ *
+ *             FILE    *fptr           output file handle
+ *             char    *str            error string
+ *
+ *     The function errdmp() outputs the error string str
+ *     to the device specified by fptr.  Additional information
+ *     is output about the definition and referencing of
+ *     the symbol / area error.
+ *
+ *     local variable:
+ *             int     mode            error mode
+ *             int     aindex          area index
+ *             int     lkerr           error flag
+ *             int     rindex          error index
+ *             sym     **s             pointer to array of symbol pointers
+ *             areax   **a             pointer to array of area pointers
+ *             areax   *raxp           error area extension pointer
+ *
+ *     global variables:
+ *             sdp     sdp             base page structure
+ *
+ *     called functions:
+ *             int     fprintf()       c_library
+ *             VOID    prntval()       lkrloc.c
+ *
+ *     side effects:
+ *             Error reported.
+ *
+ */
+
+VOID
+errdmp(fptr, str)
+FILE *fptr;
+char *str;
+{
+       int mode, aindex, rindex;
+       struct sym **s;
+       struct areax **a;
+       struct areax *raxp;
+
+       a = hp->a_list;
+       s = hp->s_list;
+
+       mode = rerr.mode;
+       aindex = rerr.aindex;
+       rindex = rerr.rindex;
+
+       /*
+        * Print Error
+        */
+       fprintf(fptr, "\n?ASlink-Warning-%s", str);
+       lkerr++;
+
+       /*
+        * Print symbol if symbol based
+        */
+       if (mode & R_SYM) {
+               fprintf(fptr, " for symbol %s\n",
+                       &s[rindex]->s_id[0]);
+       } else {
+               fprintf(fptr, "\n");
+       }
+
+       /*
+        * Print Ref Info
+        */
+       fprintf(fptr,
+               "         file        module      area        offset\n");
+       fprintf(fptr,
+               "  Refby  %-8.8s    %-8.8s    %-8.8s    ",
+                       hp->h_lfile->f_idp,
+                       &hp->m_id[0],
+                       &a[aindex]->a_bap->a_id[0]);
+       prntval(fptr, rerr.rtbase);
+
+       /*
+        * Print Def Info
+        */
+       if (mode & R_SYM) {
+               raxp = s[rindex]->s_axp;
+       } else {
+               raxp = a[rindex];
+       }
+       fprintf(fptr,
+               "  Defin  %-8.8s    %-8.8s    %-8.8s    ",
+                       raxp->a_bhp->h_lfile->f_idp,
+                       &raxp->a_bhp->m_id[0],
+                       &raxp->a_bap->a_id[0]);
+       if (mode & R_SYM) {
+               prntval(fptr, s[rindex]->s_addr);
+       } else {
+               prntval(fptr, rerr.rval);
+       }
+}
+
+/*)Function    VOID prntval(fptr, v)
+ *
+ *             FILE    *fptr   output file handle
+ *             Addr_T  v               value to output
+ *
+ *     The function prntval() outputs the value v, in the
+ *     currently selected radix, to the device specified
+ *     by fptr.
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             int     xflag           current radix
+ *
+ *     called functions:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             none
+ *
+ */
+
+VOID
+prntval(fptr, v)
+FILE *fptr;
+Addr_T v;
+{
+       if (xflag == 0) {
+               fprintf(fptr, "%04X\n", v);
+       } else
+       if (xflag == 1) {
+               fprintf(fptr, "%06o\n", v);
+       } else
+       if (xflag == 2) {
+               fprintf(fptr, "%05u\n", v);
+       }
+}
+
+/*)Function    VOID    relerp(str)
+ *
+ *             char    *str            error string
+ *
+ *     The function relerp() outputs the paging error string to
+ *     stderr and to the map file (if it is open).
+ *
+ *     local variable:
+ *             none
+ *
+ *     global variables:
+ *             FILE    *mfp            handle for the map file
+ *
+ *     called functions:
+ *             VOID    erpdmp()        lkrloc.c
+ *
+ *     side effects:
+ *             Error message inserted into map file.
+ *
+ */
+
+VOID
+relerp(str)
+char *str;
+{
+       erpdmp(stderr, str);
+       if (mfp)
+               erpdmp(mfp, str);
+}
+
+/*)Function    VOID    erpdmp(fptr, str)
+ *
+ *             FILE    *fptr           output file handle
+ *             char    *str            error string
+ *
+ *     The function erpdmp() outputs the error string str
+ *     to the device specified by fptr.
+ *
+ *     local variable:
+ *             head    *thp            pointer to head structure
+ *
+ *     global variables:
+ *             int             lkerr           error flag
+ *             sdp             sdp                     base page structure
+ *
+ *     called functions:
+ *             int     fprintf()               c_library
+ *             VOID    prntval()       lkrloc.c
+ *
+ *     side effects:
+ *             Error reported.
+ *
+ */
+
+VOID
+erpdmp(fptr, str)
+FILE *fptr;
+char *str;
+{
+       register struct head *thp;
+
+       thp = sdp.s_areax->a_bhp;
+
+       /*
+        * Print Error
+        */
+       fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
+       lkerr++;
+
+       /*
+        * Print PgDef Info
+        */
+       fprintf(fptr,
+               "         file        module      pgarea      pgoffset\n");
+       fprintf(fptr,
+               "  PgDef  %-8.8s    %-8.8s    %-8.8s    ",
+                       thp->h_lfile->f_idp,
+                       &thp->m_id[0],
+                       &sdp.s_area->a_id[0]);
+       prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);
+}
diff --git a/as/hc08/lks19.c b/as/hc08/lks19.c
new file mode 100644 (file)
index 0000000..26d8892
--- /dev/null
@@ -0,0 +1,122 @@
+/* lks19.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module      lks19.c
+ *
+ *     The module lks19.c contains the function to
+ *     output the relocated object code in the
+ *     Motorola S19 format.
+ *
+ *     lks19.c contains the following function:
+ *             VOID    s19(i)
+ *
+ *     lks19.c contains no local variables.
+ */
+
+/*)S19 Format
+ *      Record Type Field    -  This  field  signifies  the  start  of a
+ *                              record and  identifies  the  the  record
+ *                              type as follows:  
+ *
+ *                                  Ascii S1 - Data Record 
+ *                                  Ascii S9 - End of File Record 
+ *
+ *      Record Length Field  -  This  field  specifies the record length
+ *                              which includes the  address,  data,  and
+ *                              checksum   fields.   The  8  bit  record
+ *                              length value is converted to  two  ascii
+ *                              characters, high digit first.  
+ *
+ *      Load Address Field   -  This  field  consists  of the four ascii
+ *                              characters which result from  converting
+ *                              the  the  binary value of the address in
+ *                              which to begin loading this record.  The
+ *                              order is as follows:  
+ *
+ *                                  High digit of high byte of address. 
+ *                                  Low digit of high byte of address.  
+ *                                  High digit of low byte of address.  
+ *                                  Low digit of low byte of address.  
+ *
+ *                              In an End of File record this field con-
+ *                              sists of either four ascii zeros or  the
+ *                              program  entry  address.   Currently the
+ *                              entry address option is not supported.  
+ *
+ *      Data Field           -  This  field consists of the actual data,
+ *                              converted to two ascii characters,  high
+ *                              digit first.  There are no data bytes in
+ *                              the End of File record.  
+ *
+ *      Checksum Field       -  The  checksum  field is the 8 bit binary
+ *                              sum of the record length field, the load
+ *                              address field, and the data field.  This
+ *                              sum is then  complemented  (1's  comple-
+ *                              ment)   and   converted   to  two  ascii
+ *                              characters, high digit first.  
+ */
+
+/*)Function    s19(i)
+ *
+ *             int     i               0 - process data
+ *                                     1 - end of data
+ *
+ *     The function s19() outputs the relocated data
+ *     in the standard Motorola S19 format.
+ *
+ *     local variables:
+ *             Addr_T  chksum          byte checksum
+ *
+ *     global variables:
+ *             int     hilo            byte order
+ *             FILE *  ofp             output file handle
+ *             int     rtcnt           count of data words
+ *             int     rtflg[]         output the data flag
+ *             Addr_T  rtval[]         relocated data
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             The data is output to the file defined by ofp.
+ */
+
+VOID
+s19(i)
+{
+       register Addr_T chksum;
+
+       if (i) {
+               if (hilo == 0) {
+                       chksum = rtval[0];
+                       rtval[0] = rtval[1];
+                       rtval[1] = chksum;
+               }
+               for (i = 0, chksum = 1; i < rtcnt; i++) {
+                       if (rtflg[i])
+                               chksum++;
+               }
+               fprintf(ofp, "S1%02X", chksum);
+               for (i = 0; i < rtcnt ; i++) {
+                       if (rtflg[i]) {
+                               fprintf(ofp, "%02X", rtval[i]);
+                               chksum += rtval[i];
+                       }
+               }
+               fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff);
+       } else {
+               fprintf(ofp, "S9030000FC\n");
+       }
+}
diff --git a/as/hc08/lkstore.c b/as/hc08/lkstore.c
new file mode 100644 (file)
index 0000000..063e89c
--- /dev/null
@@ -0,0 +1,50 @@
+/* lkstore.c */
+
+/* 
+ * Allocated string storage module.
+ *
+ * 31-Oct-1997 by John Hartman
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "aslink.h"
+
+/*
+ * Allocate space for "str", copy str into new space
+ * Return a pointer to the allocated name, or NULL if out of memory
+ */
+char *StoreString( char *str )
+{
+   /* To avoid wasting memory headers on small allocations, we
+   /  allocate a big chunk and parcel it out as required.
+   /  These static variables remember our hunk
+   */
+   #define STR_STORE_HUNK 2000
+   static char *pNextFree = NULL;
+   static int  bytesLeft = 0;
+   
+   int  length;
+   char *pStoredString;
+   
+   length = strlen( str ) + 1; /* what we need, including null */
+
+   if (length > bytesLeft)
+   {
+      /* no space.  Allocate a new hunk.  We lose the pointer to any
+      /  old hunk.  We don't care, as the names are never deleted.
+      */
+      pNextFree = (char*)new( STR_STORE_HUNK );
+      bytesLeft = STR_STORE_HUNK;
+   }
+
+   /* Copy the name and terminating null into the name store */
+   pStoredString = pNextFree;
+   memcpy( pStoredString, str, length );
+
+   pNextFree += length;
+   bytesLeft -= length;
+
+   return pStoredString;
+}
diff --git a/as/hc08/lksym.c b/as/hc08/lksym.c
new file mode 100644 (file)
index 0000000..1ebc49c
--- /dev/null
@@ -0,0 +1,488 @@
+/* lksym.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 28-Oct-97 JLH: 
+ *          - lkpsym: Use StoreString for sym construction
+ *          - change symeq() to do length-independent string compare
+ *          - change hash() to do length-independent hash calculation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <alloc.h>
+#endif
+#include "aslink.h"
+
+/*)Module      lksym.c
+ *
+ *     The module lksym.c contains the functions that operate
+ *     on the symbol structures.
+ *
+ *     lksym.c contains the following functions:
+ *             int     hash()
+ *             sym *   lkpsym()
+ *             VOID *  new()
+ *             sym *   newsym()
+ *             VOID    symdef()
+ *             int     symeq()
+ *             VOID    syminit()
+ *             VOID    symmod()
+ *             Addr_T  symval()
+ *
+ *     lksym.c contains no local/static variables.
+ */
+
+/*)Function    VOID    syminit()
+ *
+ *     The function syminit() is called to clear the hashtable.
+ *
+ *     local variables:
+ *             int     h               computed hash value
+ *             sym **  spp             pointer to an array of
+ *                                     sym structure pointers
+ *
+ *     global variables:
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             (1)     The symbol hash tables are cleared
+ */
+
+VOID
+syminit()
+{
+    // register int h;
+       struct sym **spp;
+
+       spp = &symhash[0];
+       while (spp < &symhash[NHASH])
+               *spp++ = NULL;
+}
+
+/*)Function    sym *   newsym()
+ *
+ *     The function newsym() is called to evaluate the symbol
+ *     definition/reference directive from the .rel file(s).
+ *     If the symbol is not found in the symbol table a new
+ *     symbol structure is created.  Evaluation of the
+ *     directive determines if this is a reference or a definition.
+ *     Multiple definitions of the same variable will be flagged
+ *     as an error if the values are not identical.  A symbol
+ *     definition places the symbol value and area extension
+ *     into the symbols data structure.  And finally, a pointer
+ *     to the symbol structure is placed into the head structure
+ *     symbol list.  Refer to the description of the header, symbol,
+ *     area, and areax structures in lkdata.c for structure and
+ *     linkage details.
+ *
+ *     local variables:
+ *             int     c               character from input text
+ *             int     i               evaluation value
+ *             char    id[]            symbol name
+ *             int     nglob           number of symbols in this header
+ *             sym *   tsp             pointer to symbol structure
+ *             sym **  s               list of pointers to symbol structures
+ *
+ *     global variables:
+ *             areax   *axp            Pointer to the current
+ *                                     areax structure
+ *             head    *headp          The pointer to the first
+ *                                     head structure of a linked list
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             Addr_T  eval()          lkeval.c
+ *             VOID    exit()          c_library
+ *             int     fprintf()       c_library
+ *             char    getSid()        lklex.c
+ *             char    get()           lklex.c
+ *             char    getnb()         lklex.c
+ *             sym *   lkpsym()        lksym.c
+ *
+ *     side effects:
+ *             A symbol structure is created and/or modified.
+ *             If structure space allocation fails linker will abort.
+ *             Several severe errors (these are internal errors
+ *             indicating a corrupted .rel file or corrupted
+ *             assembler or linker) will terminated the linker.
+ */
+
+/*
+ * Find/Create a global symbol entry.
+ *
+ * S xxxxxx Defnnnn
+ *   |      |  |
+ *   |      |  `-- sp->s_addr
+ *   |      `----- sp->s_type
+ *   `------------ sp->s_id
+ *
+ */
+struct sym *
+newsym()
+{
+  register unsigned i ;
+  register unsigned nglob ;
+       register int c ;
+       struct sym *tsp;
+       struct sym **s;
+       char id[NCPS];
+
+       getSid(id);     // old: getid(id, -1);
+       tsp = lkpsym(id, 1);
+       c = getnb();get();get();
+       if (c == 'R') {
+               tsp->s_type |= S_REF;
+               if (eval()) {
+                       fprintf(stderr, "Non zero S_REF\n");
+                       lkerr++;
+               }
+       } else
+       if (c == 'D') {
+               i = eval();
+               if (tsp->s_type & S_DEF && tsp->s_addr != i) {
+                       fprintf(stderr, "Multiple definition of %8s\n", id);
+                       lkerr++;
+               }
+               tsp->s_type |= S_DEF;
+               /*
+                * Set value and area extension link.
+                */
+               tsp->s_addr = i;
+               tsp->s_axp = axp;
+       } else {
+               fprintf(stderr, "Invalid symbol type %c for %8s\n", c, id);
+               lkexit(1);
+       }
+       /*
+        * Place pointer in header symbol list
+        */
+       if (headp == NULL) {
+               fprintf(stderr, "No header defined\n");
+               lkexit(1);
+       }
+       nglob = hp->h_nglob;
+       s = hp->s_list;
+       for (i=0; i < nglob ;++i) {
+               if (s[i] == NULL) {
+                       s[i] = tsp;
+                       return(tsp);
+               }
+       }
+       fprintf(stderr, "Header symbol list overflow\n");
+       lkexit(1);
+       return(0);
+}
+
+/*)Function    sym *   lkpsym(id,f)
+ *
+ *             char *  id              symbol name string
+ *             int     f               f == 0, lookup only
+ *                                     f != 0, create if not found
+ *
+ *     The function lookup() searches the symbol hash tables for
+ *     a symbol name match returning a pointer to the sym structure.
+ *     If the symbol is not found then a sym structure is created,
+ *     initialized, and linked to the appropriate hash table if f != 0.
+ *     A pointer to this new sym structure is returned or a NULL
+ *     pointer is returned if f == 0.
+ *
+ *     local variables:
+ *             int     h               computed hash value
+ *             sym *   sp              pointer to a sym structure
+ *
+ *     global varaibles:
+ *             sym * symhash[]         array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             int     hash()          lksym.c
+ *             VOID *  new()           lksym.c
+ *             int     symeq()         lksym.c
+ *
+ *     side effects:
+ *             If the function new() fails to allocate space
+ *             for the new sym structure the linker terminates.
+ */
+
+struct sym *
+lkpsym(id, f)
+char *id;
+{
+       register struct sym *sp;
+       register int h;
+
+       h = hash(id);
+       sp = symhash[h];
+       while (sp != NULL) {
+               if (symeq(id, sp->s_id))
+                       return (sp);
+               sp = sp->s_sp;
+       }
+       if (f == 0)
+               return (NULL);
+       sp = (struct sym *) new (sizeof(struct sym));
+       sp->s_sp = symhash[h];
+       symhash[h] = sp;
+       sp->s_id = StoreString( id );   /* JLH */
+       return (sp);
+}
+
+/*)Function    Addr_T  symval(tsp)
+ *
+ *             sym *   tsp             pointer to a symbol structure
+ *
+ *     The function symval() returns the value of the
+ *     relocated symbol by adding the variable definition
+ *     value to the areax base address.
+ *
+ *     local variables:
+ *             Addr_T  val             relocated address value
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ */
+
+Addr_T
+symval(tsp)
+register struct sym *tsp;
+{
+       register Addr_T val;
+
+       val = tsp->s_addr;
+       if (tsp->s_axp) {
+               val += tsp->s_axp->a_addr;
+       }
+       return(val);
+}
+
+/*)Function    VOID    symdef(fp)
+ *
+ *             FILE *  fp              file handle for output
+ *
+ *     The function symdef() scans the hashed symbol table
+ *     searching for variables referenced but not defined.
+ *     Undefined variables are linked to the default
+ *     area "_CODE" and reported as referenced by the
+ *     appropriate module.
+ *
+ *     local variables:
+ *             int     i               hash table index loop variable
+ *             sym *   sp              pointer to linked symbol structure
+ *
+ *     global variables:
+ *             area    *areap          The pointer to the first
+ *                                     area structure of a linked list
+ *             sym *symhash[NHASH]     array of pointers to NHASH
+ *                                     linked symbol lists
+ *
+ *     functions called:
+ *             symmod()                lksym.c
+ *
+ *     side effects:
+ *             Undefined variables have their areas set to "_CODE".
+ */
+
+VOID
+symdef(fp)
+FILE *fp;
+{
+       register struct sym *sp;
+       register int i;
+
+       for (i=0; i<NHASH; ++i) {
+               sp = symhash[i];
+               while (sp) {
+                       if (sp->s_axp == NULL)
+                               sp->s_axp = areap->a_axp;
+                       if ((sp->s_type & S_DEF) == 0)
+                               symmod(fp, sp);
+                       sp = sp->s_sp;
+               }
+       }
+}
+
+/*)Function    VOID    symmod(fp,tsp)
+ *
+ *             FILE *  fp              output file handle
+ *             sym *   tsp             pointer to a symbol structure
+ *
+ *     The function symmod() scans the header structures
+ *     searching for a reference to the symbol structure
+ *     pointer to by tsp.  The function then generates an error
+ *     message whichs names the module having referenced the
+ *     undefined variable.
+ *
+ *     local variables:
+ *             int     i               loop counter
+ *             sym **  p               pointer to a list of pointers
+ *                                     to symbol structures
+ *
+ *     global variables:
+ *             head    *headp          The pointer to the first
+ *                                     head structure of a linked list
+ *             head    *hp             Pointer to the current
+ *                                     head structure
+ *             int     lkerr           error flag
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *
+ *     side effects:
+ *             Error output generated.
+ */
+
+VOID
+symmod(fp, tsp)
+FILE *fp;
+struct sym *tsp;
+{
+       register int i;
+       struct sym **p;
+
+       if ((hp = headp) != NULL) {
+           while(hp) {
+               p = hp->s_list;
+               for (i=0; i<hp->h_nglob; ++i) {
+                   if (p[i] == tsp) {
+                       fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id);
+                       fprintf(fp, "referenced by module '%s'\n", hp->m_id);
+                       lkerr++;
+                   }
+               }
+           hp = hp->h_hp;
+           }
+       }
+}
+
+/*)Function    int     symeq(p1, p2)
+ *
+ *             char *  p1              name string
+ *             char *  p2              name string
+ *
+ *     The function symeq() compares the two name strings for a match.
+ *     The return value is 1 for a match and 0 for no match.
+ *
+ *     local variables:
+ *             int     h               loop counter
+ *
+ *     global variables:
+ *             char    ccase[]         an array of characters which
+ *                                     perform the case translation function
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ *
+ */
+
+int
+symeq(p1, p2)
+register char *p1, *p2;
+{
+#if    CASE_SENSITIVE
+               return (strcmp( p1, p2 ) == 0);
+#else
+               return (as_strcmpi( p1, p2 ) == 0);
+#endif
+}
+
+/*)Function    int     hash(p)
+ *
+ *             char *  p               pointer to string to hash
+ *
+ *     The function hash() computes a hash code using the sum
+ *     of all characters mod table size algorithm.
+ *
+ *     local variables:
+ *             int     h               accumulated character sum
+ *             int     n               loop counter
+ *
+ *     global variables:
+ *             char    ccase[]         an array of characters which
+ *                                     perform the case translation function
+ *
+ *     functions called:
+ *             none
+ *
+ *     side effects:
+ *             none
+ *
+ */
+int
+hash(p)
+register char *p;
+{
+       register int h;
+
+       h = 0;
+       while (*p) {
+
+#if    CASE_SENSITIVE
+               h += *p++;
+#else
+               h += ccase[*p++];
+#endif
+
+       };
+       return (h&HMASK);
+}
+
+/*)Function    VOID *  new(n)
+ *
+ *             unsigned int    n       allocation size in bytes
+ *
+ *     The function new() allocates n bytes of space and returns
+ *     a pointer to this memory.  If no space is available the
+ *     linker is terminated.
+ *
+ *     local variables:
+ *             char *  p               a general pointer
+ *             char *  q               a general pointer
+ *
+ *     global variables:
+ *             none
+ *
+ *     functions called:
+ *             int     fprintf()       c_library
+ *             VOID *  malloc()        c_library
+ *
+ *     side effects:
+ *             Memory is allocated, if allocation fails
+ *             the linker is terminated.
+ */
+
+VOID *
+new(n)
+unsigned int n;
+{
+       register char *p;
+
+       if ((p = (char *) calloc(n, 1)) == NULL) {
+               fprintf(stderr, "Out of space!\n");
+               lkexit(1);
+       }
+       return (p);
+}
diff --git a/as/hc08/m08adr.c b/as/hc08/m08adr.c
new file mode 100644 (file)
index 0000000..61e10b4
--- /dev/null
@@ -0,0 +1,205 @@
+/* m08adr.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+int
+addr(esp)
+register struct expr *esp;
+{
+       register int c;
+       register struct area *espa;
+       register Addr_T espv;
+       char *tcp;
+
+       if ((c = getnb()) == '#') {
+               expr(esp, 0);
+               esp->e_mode = S_IMMED;
+       } else if (c == ',') {
+               switch(admode(axs)) {
+               default:
+                       aerr();
+
+               case S_X:
+                       c = S_IX;
+                       break;
+
+               case S_S:
+                       c = S_IS;
+                       break;
+
+               case S_XP:
+                       c = S_IXP;
+                       break;
+               }
+               esp->e_mode = c;
+       } else if (c == '*') {
+               expr(esp, 0);
+               esp->e_mode = S_DIR;
+               if (esp->e_addr & ~0xFF)
+                       err('d');
+               if (more()) {
+                       comma();
+                       tcp = ip;
+                       switch(admode(axs)) {
+                       case S_X:
+                               esp->e_mode = S_IX1;
+                               break;
+
+                       case S_S:
+                               esp->e_mode = S_SP1;
+                               break;
+
+                       case S_XP:
+                               esp->e_mode = S_IX1P;
+                               break;
+
+                       default:
+                               ip = --tcp;
+                       }
+               }
+       } else {
+               unget(c);
+               if ((esp->e_mode = admode(axs)) != 0) {
+                       ;
+               } else {
+                       expr(esp, 0);
+                       espa = esp->e_base.e_ap;
+                       espv = esp->e_addr;
+                       if (more()) {
+                               comma();
+                               c = admode(axs);
+                               if (esp->e_flag == 0 &&
+                                   espa == NULL &&
+                                   (espv & ~0xFF) == 0) {
+                                       switch(c) {
+                                       default:
+                                               aerr();
+
+                                       case S_X:
+                                               c = S_IX1;
+                                               break;
+
+                                       case S_S:
+                                               c = S_SP1;
+                                               break;
+
+                                       case S_XP:
+                                               c = S_IX1P;
+                                               break;
+                                       }
+                               } else {
+                                       switch(c) {
+                                       default:
+                                               aerr();
+
+                                       case S_X:
+                                               c = S_IX2;
+                                               break;
+
+                                       case S_S:
+                                               c = S_SP2;
+                                               break;
+
+                                       case S_XP:
+                                               c = S_IX2P;
+                                               break;
+                                       }
+                               }
+                               esp->e_mode = c;
+                       } else {
+                               esp->e_mode = S_EXT;
+                       }
+               }
+       }
+       return (esp->e_mode);
+}
+       
+/*
+ * Enter admode() to search a specific addressing mode table
+ * for a match. Return the addressing value on a match or
+ * zero for no match.
+ */
+int
+admode(sp)
+register struct adsym *sp;
+{
+       register char *ptr;
+       register int i;
+       register char *ips;
+
+       ips = ip;
+       unget(getnb());
+
+       i = 0;
+       while ( *(ptr = &sp[i].a_str[0]) ) {
+               if (srch(ptr)) {
+                       return(sp[i].a_val);
+               }
+               i++;
+       }
+       ip = ips;
+       return(0);
+}
+
+/*
+ *      srch --- does string match ?
+ */
+int
+srch(str)
+register char *str;
+{
+       register char *ptr;
+       ptr = ip;
+
+       while (*ptr && *str) {
+               if(ccase[*ptr & 0x007F] != ccase[*str & 0x007F])
+                       break;
+               ptr++;
+               str++;
+       }
+       if (ccase[*ptr & 0x007F] == ccase[*str & 0x007F]) {
+               ip = ptr;
+               return(1);
+       }
+
+       if (!*str)
+               if (any(*ptr," \t\n,];")) {
+                       ip = ptr;
+                       return(1);
+               }
+       return(0);
+}
+
+/*
+ *      any --- does str contain c?
+ */
+int
+any(c,str)
+int c;
+char*str;
+{
+       while (*str)
+               if(*str++ == c)
+                       return(1);
+       return(0);
+}
+
+struct adsym   axs[] = {       /* a, x, or s registers */
+    {  "a",    S_A     },
+    {  "x",    S_X     },
+    {  "s",    S_S     },
+    {  "x+",   S_XP    },
+    {  "",     0x00    }
+};
diff --git a/as/hc08/m08ext.c b/as/hc08/m08ext.c
new file mode 100644 (file)
index 0000000..8824731
--- /dev/null
@@ -0,0 +1,19 @@
+/* m08ext.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+char   *cpu    = "Motorola 68HC08";
+int    hilo    = 1;
+char   *dsft   = "asm";
diff --git a/as/hc08/m08mch.c b/as/hc08/m08mch.c
new file mode 100644 (file)
index 0000000..5c54496
--- /dev/null
@@ -0,0 +1,463 @@
+/* m08mch.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+/*
+ * Process a machine op.
+ */
+VOID
+machine(mp)
+struct mne *mp;
+{
+       register int op, t1, t2, type;
+       struct expr e1, e2, e3;
+       Addr_T espv;
+       struct area *espa;
+       char id[NCPS];
+       int c, v1;
+
+       clrexpr(&e1);
+       clrexpr(&e2);
+       clrexpr(&e3);
+       op = mp->m_valu;
+       type = mp->m_type;
+       switch (type) {
+
+       case S_SDP:
+               espa = NULL;
+               if (more()) {
+                       expr(&e1, 0);
+                       if (e1.e_flag == 0 && e1.e_base.e_ap == NULL) {
+                               if (e1.e_addr) {
+                                       err('b');
+                               }
+                       }
+                       if ((c = getnb()) == ',') {
+                               getid(id, -1);
+                               espa = alookup(id);
+                               if (espa == NULL) {
+                                       err('u');
+                               }
+                       } else {
+                               unget(c);
+                       }
+               }
+               if (espa) {
+                       outdp(espa, &e1);
+               } else {
+                       outdp(dot.s_area, &e1);
+               }
+               lmode = SLIST;
+               break;
+
+       case S_INH:
+               outab(op);
+               break;
+
+       case S_BRA:
+               expr(&e1, 0);
+               outab(op);
+               if (mchpcr(&e1)) {
+                       v1 = e1.e_addr - dot.s_addr - 1;
+                       if ((v1 < -128) || (v1 > 127))
+                               aerr();
+                       outab(v1);
+               } else {
+                       outrb(&e1, R_PCR);
+               }
+               if (e1.e_mode != S_USER)
+                       rerr();
+               break;
+
+       case S_TYP1:
+               t1 = addr(&e1);
+               if (t1 == S_A) {
+                       outab(op+0x10);
+                       break;
+               }
+               if (t1 == S_X) {
+                       outab(op+0x20);
+                       break;
+               }
+               if (t1 == S_DIR || t1 == S_EXT) {
+                       outab(op);
+                       outrb(&e1, R_PAG0);
+                       break;
+               }
+               if (t1 == S_IX) {
+                       outab(op+0x40);
+                       break;
+               }
+               if (t1 == S_IX1 || t1 == S_IX2) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(op+0x30);
+                       outrb(&e1, R_USGN);
+                       break;
+               }
+               if (t1 == S_SP1 || t1 == S_SP2) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(0x9e);
+                       outab(op+0x30);
+                       outrb(&e1, R_USGN);
+                       break;
+               }
+               aerr();
+               break;
+
+       case S_TYP2:
+               t1 = addr(&e1);
+               if (t1 == S_IMMED) {
+                       if ((op == 0xA7) || (op == 0xAC) ||
+                           (op == 0xAD) || (op == 0xAF))
+                               aerr();
+                       outab(op);
+                       outrb(&e1, 0);
+                       break;
+               }
+               if (t1 == S_DIR) {
+                       outab(op+0x10);
+                       outrb(&e1, R_PAG0);
+                       break;
+               }
+               if (t1 == S_EXT) {
+                       outab(op+0x20);
+                       outrw(&e1, 0);
+                       break;
+               }
+               if (t1 == S_IX) {
+                       outab(op+0x50);
+                       break;
+               }
+               if (t1 == S_IX1) {
+                       outab(op+0x40);
+                       outrb(&e1, R_USGN);
+                       break;
+               }
+               if (t1 == S_IX2) {
+                       outab(op+0x30);
+                       outrw(&e1, 0);
+                       break;
+               }
+               if (t1 == S_SP1) {
+                       if (op == 0xAC || op == 0xAD)
+                               aerr();
+                       outab(0x9e);
+                       outab(op+0x40);
+                       outrb(&e1, R_USGN);
+                       break;
+               }
+               if (t1 == S_SP2) {
+                       if (op == 0xAC || op == 0xAD)
+                               aerr();
+                       outab(0x9e);
+                       outab(op+0x30);
+                       outrw(&e1, 0);
+                       break;
+               }
+               aerr();
+               break;
+
+       case S_TYP3:
+               t1 = addr(&e1);
+               espv = e1.e_addr;
+               if (t1 != S_IMMED || espv & ~0x07)
+                       aerr();
+               comma();
+               t2 = addr(&e2);
+               if (t2 != S_DIR)
+                       aerr();
+               outab(op + 2*(espv&0x07));
+               outrb(&e2, R_PAG0);
+               break;
+
+       case S_TYP4:
+               t1 = addr(&e1);
+               espv = e1.e_addr;
+               if (t1 != S_IMMED || espv & ~0x07)
+                       aerr();
+               comma();
+               t2 = addr(&e2);
+               if (t2 != S_DIR)
+                       aerr();
+               comma();
+               expr(&e3, 0);
+               outab(op + 2*(espv&0x07));
+               outrb(&e2, R_PAG0);
+               if (mchpcr(&e3)) {
+                       v1 = e3.e_addr - dot.s_addr - 1;
+                       if ((v1 < -128) || (v1 > 127))
+                               aerr();
+                       outab(v1);
+               } else {
+                       outrb(&e3, R_PCR);
+               }
+               if (e3.e_mode != S_USER)
+                       rerr();
+               break;
+
+       case S_TYPAI:
+               t1 = addr(&e1);
+               if (t1 == S_IMMED) {
+                       outab(op);
+                       if (e1.e_flag == 0 && e1.e_base.e_ap == NULL) {
+                               v1 = e1.e_addr;
+                               if ((v1 < -128) || (v1 > 127))
+                                       aerr();
+                               outab(v1);
+                       } else {
+                               outrb(&e1, 0);
+                       }
+                       break;
+               }
+               aerr();
+               break;
+
+       case S_TYPHX:
+               t1 = addr(&e1);
+               if (t1 == S_IMMED) {
+                       if (op == 0x25)
+                               aerr();
+                       outab(op);
+                       outrw(&e1, 0);
+                       break;
+               }
+               if (t1 == S_DIR || t1 == S_EXT) {
+                       outab(op | 0x10);
+                       outrb(&e1, R_PAG0);
+                       break;
+               }
+               aerr();
+               break;
+
+       case S_CBEQ:
+               t1 = addr(&e1);
+               comma();
+               expr(&e2, 0);
+               if (t1 == S_IMMED) {
+                       outab(op);
+                       outrb(&e1, 0);
+               } else
+               if (t1 == S_DIR || t1 == S_EXT) {
+                       outab(op);
+                       outrb(&e1, R_PAG0);
+               } else
+               if (t1 == S_IXP) {
+                       outab(op+0x40);
+               } else
+               if (t1 == S_IX1P || t1 == S_IX2P) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(op+0x30);
+                       outrb(&e1, R_USGN);
+               } else
+               if (t1 == S_SP1 || t1 == S_SP2) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(0x9E);
+                       outab(op+0x30);
+                       outrb(&e1, R_USGN);
+               } else {
+                       aerr();
+                       break;
+               }
+               if (mchpcr(&e2)) {
+                       v1 = e2.e_addr - dot.s_addr - 1;
+                       if ((v1 < -128) || (v1 > 127))
+                               aerr();
+                       outab(v1);
+               } else {
+                       outrb(&e2, R_PCR);
+               }
+               if (e2.e_mode != S_USER)
+                       rerr();
+               break;
+
+       case S_CQAX:
+               t1 = addr(&e1);
+               if (t1 != S_IMMED)
+                       aerr();
+               comma();
+               expr(&e2, 0);
+               outab(op);
+               outrb(&e1, 0);
+               if (mchpcr(&e2)) {
+                       v1 = e2.e_addr - dot.s_addr - 1;
+                       if ((v1 < -128) || (v1 > 127))
+                               aerr();
+                       outab(v1);
+               } else {
+                       outrb(&e2, R_PCR);
+               }
+               if (e2.e_mode != S_USER)
+                       rerr();
+               break;
+
+       case S_DBNZ:
+               t1 = addr(&e1);
+               comma();
+               expr(&e2, 0);
+               if (t1 == S_DIR || t1 == S_EXT) {
+                       outab(op);
+                       outrb(&e1, R_PAG0);
+               } else
+               if (t1 == S_IX) {
+                       outab(op+0x40);
+               } else
+               if (t1 == S_IX1 || t1 == S_IX2) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(op+0x30);
+                       outrb(&e1, R_USGN);
+               } else
+               if (t1 == S_SP1 || t1 == S_SP2) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(0x9E);
+                       outab(op+0x30);
+                       outrb(&e1, R_USGN);
+               } else {
+                       aerr();
+                       break;
+               }
+               if (mchpcr(&e2)) {
+                       v1 = e2.e_addr - dot.s_addr - 1;
+                       if ((v1 < -128) || (v1 > 127))
+                               aerr();
+                       outab(v1);
+               } else {
+                       outrb(&e2, R_PCR);
+               }
+               if (e2.e_mode != S_USER)
+                       rerr();
+               break;
+
+       case S_DZAX:
+               expr(&e1, 0);
+               outab(op);
+               if (mchpcr(&e1)) {
+                       v1 = e1.e_addr - dot.s_addr - 1;
+                       if ((v1 < -128) || (v1 > 127))
+                               aerr();
+                       outab(v1);
+               } else {
+                       outrb(&e1, R_PCR);
+               }
+               if (e1.e_mode != S_USER)
+                       rerr();
+               break;
+
+       case S_MOV:
+               t1 = addr(&e1);
+               if (t1 == S_IX1P || t1 == S_IX2P) {
+                       if (chkindx(&e1))
+                               aerr();
+                       outab(op+0x10);
+                       outrb(&e1, R_PAG0);
+                       break;
+               }
+               comma();
+               t2 = addr(&e2);
+               if (t1 == S_IMMED) {
+                       if (t2 == S_DIR || t2 == S_EXT) {
+                               outab(op+0x20);
+                               outrb(&e1, 0);
+                               outrb(&e2, R_PAG0);
+                               break;
+                       }
+               }
+               if (t1 == S_DIR || t1 == S_EXT) {
+                       if (t2 == S_DIR || t2 == S_EXT) {
+                               outab(op);
+                               outrb(&e1, R_PAG0);
+                               outrb(&e2, R_PAG0);
+                               break;
+                       }
+               }
+               if (t1 == S_IXP) {
+                       if (t2 == S_DIR || t2 == S_EXT) {
+                               outab(op+0x30);
+                               outrb(&e2, R_PAG0);
+                               break;
+                       }
+               }
+               aerr();
+               break;
+
+       default:
+               err('o');
+       }
+}
+
+/*
+ * Check index byte
+ */
+int
+chkindx(exp)
+struct expr *exp;
+{
+       if (exp->e_flag == 0 && exp->e_base.e_ap == NULL) {
+               if (exp->e_addr & ~0xFF) {
+                       return(1);
+               }
+       }
+       return(0);
+}
+
+/*
+ * Branch/Jump PCR Mode Check
+ */
+int
+mchpcr(esp)
+register struct expr *esp;
+{
+       if (esp->e_base.e_ap == dot.s_area) {
+               return(1);
+       }
+       if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+               /*
+                * Absolute Destination
+                *
+                * Use the global symbol '.__.ABS.'
+                * of value zero and force the assembler
+                * to use this absolute constant as the
+                * base value for the relocation.
+                */
+               esp->e_flag = 1;
+               esp->e_base.e_sp = &sym[1];
+       }
+       return(0);
+}
+
+/*
+ * The next character must be a
+ * comma.
+ */
+int
+comma()
+{
+       if (getnb() != ',')
+               qerr();
+       return(1);
+}
+
+/*
+ * Machine specific initialization.
+ */
+VOID
+minit()
+{
+}
diff --git a/as/hc08/m08pst.c b/as/hc08/m08pst.c
new file mode 100644 (file)
index 0000000..54d725e
--- /dev/null
@@ -0,0 +1,195 @@
+/* m08pst.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+struct mne     mne[] = {
+
+       /* machine */
+
+    {  NULL,   ".setdp",       S_SDP,          0,      0       },
+
+       /* system */
+
+    {  NULL,   "CON",          S_ATYP,         0,      A_CON   },
+    {  NULL,   "OVR",          S_ATYP,         0,      A_OVR   },
+    {  NULL,   "REL",          S_ATYP,         0,      A_REL   },
+    {  NULL,   "ABS",          S_ATYP,         0,      A_ABS|A_OVR     },
+    {  NULL,   "NOPAG",        S_ATYP,         0,      A_NOPAG },
+    {  NULL,   "PAG",          S_ATYP,         0,      A_PAG   },
+
+    {  NULL,   ".byte",        S_BYTE,         0,      1       },
+    {  NULL,   ".db",          S_BYTE,         0,      1       },
+    {  NULL,   ".word",        S_WORD,         0,      2       },
+    {  NULL,   ".dw",          S_WORD,         0,      2       },
+    {  NULL,   ".ascii",       S_ASCII,        0,      0       },
+    {  NULL,   ".asciz",       S_ASCIZ,        0,      0       },
+    {  NULL,   ".blkb",        S_BLK,          0,      1       },
+    {  NULL,   ".ds",          S_BLK,          0,      1       },
+    {  NULL,   ".blkw",        S_BLK,          0,      2       },
+    {  NULL,   ".page",        S_PAGE,         0,      0       },
+    {  NULL,   ".title",       S_TITLE,        0,      0       },
+    {  NULL,   ".sbttl",       S_SBTL,         0,      0       },
+    {  NULL,   ".globl",       S_GLOBL,        0,      0       },
+    {  NULL,   ".area",        S_DAREA,        0,      0       },
+    {  NULL,   ".even",        S_EVEN,         0,      0       },
+    {  NULL,   ".odd",         S_ODD,          0,      0       },
+    {  NULL,   ".if",          S_IF,           0,      0       },
+    {  NULL,   ".else",        S_ELSE,         0,      0       },
+    {  NULL,   ".endif",       S_ENDIF,        0,      0       },
+    {  NULL,   ".include",     S_INCL,         0,      0       },
+    {  NULL,   ".radix",       S_RADIX,        0,      0       },
+    {  NULL,   ".org",         S_ORG,          0,      0       },
+    {  NULL,   ".module",      S_MODUL,        0,      0       },
+    {  NULL,   ".ascis",       S_ASCIS,        0,      0       },
+//    {        NULL,   ".assume",      S_ERROR,        0,      0       },
+//    {        NULL,   ".error",       S_ERROR,        0,      1       },
+
+       /* 68HC08 */
+
+    {  NULL,   "neg",          S_TYP1,         0,      0x30    },
+    {  NULL,   "com",          S_TYP1,         0,      0x33    },
+    {  NULL,   "lsr",          S_TYP1,         0,      0x34    },
+    {  NULL,   "ror",          S_TYP1,         0,      0x36    },
+    {  NULL,   "asr",          S_TYP1,         0,      0x37    },
+    {  NULL,   "asl",          S_TYP1,         0,      0x38    },
+    {  NULL,   "lsl",          S_TYP1,         0,      0x38    },
+    {  NULL,   "rol",          S_TYP1,         0,      0x39    },
+    {  NULL,   "dec",          S_TYP1,         0,      0x3A    },
+    {  NULL,   "inc",          S_TYP1,         0,      0x3C    },
+    {  NULL,   "tst",          S_TYP1,         0,      0x3D    },
+    {  NULL,   "clr",          S_TYP1,         0,      0x3F    },
+
+    {  NULL,   "sub",          S_TYP2,         0,      0xA0    },
+    {  NULL,   "cmp",          S_TYP2,         0,      0xA1    },
+    {  NULL,   "sbc",          S_TYP2,         0,      0xA2    },
+    {  NULL,   "cpx",          S_TYP2,         0,      0xA3    },
+    {  NULL,   "and",          S_TYP2,         0,      0xA4    },
+    {  NULL,   "bit",          S_TYP2,         0,      0xA5    },
+    {  NULL,   "lda",          S_TYP2,         0,      0xA6    },
+    {  NULL,   "sta",          S_TYP2,         0,      0xA7    },
+    {  NULL,   "eor",          S_TYP2,         0,      0xA8    },
+    {  NULL,   "adc",          S_TYP2,         0,      0xA9    },
+    {  NULL,   "ora",          S_TYP2,         0,      0xAA    },
+    {  NULL,   "add",          S_TYP2,         0,      0xAB    },
+    {  NULL,   "jmp",          S_TYP2,         0,      0xAC    },
+    {  NULL,   "jsr",          S_TYP2,         0,      0xAD    },
+    {  NULL,   "ldx",          S_TYP2,         0,      0xAE    },
+    {  NULL,   "stx",          S_TYP2,         0,      0xAF    },
+
+    {  NULL,   "bset",         S_TYP3,         0,      0x10    },
+    {  NULL,   "bclr",         S_TYP3,         0,      0x11    },
+
+    {  NULL,   "brset",        S_TYP4,         0,      0x00    },
+    {  NULL,   "brclr",        S_TYP4,         0,      0x01    },
+
+    {  NULL,   "ais",          S_TYPAI,        0,      0xA7    },
+    {  NULL,   "aix",          S_TYPAI,        0,      0xAF    },
+
+    {  NULL,   "sthx",         S_TYPHX,        0,      0x25    },
+    {  NULL,   "ldhx",         S_TYPHX,        0,      0x45    },
+    {  NULL,   "cphx",         S_TYPHX,        0,      0x65    },
+
+    {  NULL,   "cbeq",         S_CBEQ,         0,      0x31    },
+    {  NULL,   "cbeqa",        S_CQAX,         0,      0x41    },
+    {  NULL,   "cbeqx",        S_CQAX,         0,      0x51    },
+
+    {  NULL,   "dbnz",         S_DBNZ,         0,      0x3B    },
+    {  NULL,   "dbnza",        S_DZAX,         0,      0x4B    },
+    {  NULL,   "dbnzx",        S_DZAX,         0,      0x5B    },
+
+    {  NULL,   "mov",          S_MOV,          0,      0x4E    },
+
+    {  NULL,   "bra",          S_BRA,          0,      0x20    },
+    {  NULL,   "brn",          S_BRA,          0,      0x21    },
+    {  NULL,   "bhi",          S_BRA,          0,      0x22    },
+    {  NULL,   "bls",          S_BRA,          0,      0x23    },
+    {  NULL,   "bcc",          S_BRA,          0,      0x24    },
+    {  NULL,   "bhs",          S_BRA,          0,      0x24    },
+    {  NULL,   "bcs",          S_BRA,          0,      0x25    },
+    {  NULL,   "blo",          S_BRA,          0,      0x25    },
+    {  NULL,   "bne",          S_BRA,          0,      0x26    },
+    {  NULL,   "beq",          S_BRA,          0,      0x27    },
+    {  NULL,   "bhcc",         S_BRA,          0,      0x28    },
+    {  NULL,   "bhcs",         S_BRA,          0,      0x29    },
+    {  NULL,   "bpl",          S_BRA,          0,      0x2A    },
+    {  NULL,   "bmi",          S_BRA,          0,      0x2B    },
+    {  NULL,   "bmc",          S_BRA,          0,      0x2C    },
+    {  NULL,   "bms",          S_BRA,          0,      0x2D    },
+    {  NULL,   "bil",          S_BRA,          0,      0x2E    },
+    {  NULL,   "bih",          S_BRA,          0,      0x2F    },
+    {  NULL,   "bge",          S_BRA,          0,      0x90    },
+    {  NULL,   "blt",          S_BRA,          0,      0x91    },
+    {  NULL,   "bgt",          S_BRA,          0,      0x92    },
+    {  NULL,   "ble",          S_BRA,          0,      0x93    },
+    {  NULL,   "bsr",          S_BRA,          0,      0xAD    },
+
+    {  NULL,   "nega",         S_INH,          0,      0x40    },
+    {  NULL,   "mul",          S_INH,          0,      0x42    },
+    {  NULL,   "coma",         S_INH,          0,      0x43    },
+    {  NULL,   "lsra",         S_INH,          0,      0x44    },
+    {  NULL,   "rora",         S_INH,          0,      0x46    },
+    {  NULL,   "asra",         S_INH,          0,      0x47    },
+    {  NULL,   "asla",         S_INH,          0,      0x48    },
+    {  NULL,   "lsla",         S_INH,          0,      0x48    },
+    {  NULL,   "rola",         S_INH,          0,      0x49    },
+    {  NULL,   "deca",         S_INH,          0,      0x4A    },
+    {  NULL,   "inca",         S_INH,          0,      0x4C    },
+    {  NULL,   "tsta",         S_INH,          0,      0x4D    },
+    {  NULL,   "clra",         S_INH,          0,      0x4F    },
+
+    {  NULL,   "negx",         S_INH,          0,      0x50    },
+    {  NULL,   "div",          S_INH,          0,      0x52    },
+    {  NULL,   "comx",         S_INH,          0,      0x53    },
+    {  NULL,   "lsrx",         S_INH,          0,      0x54    },
+    {  NULL,   "rorx",         S_INH,          0,      0x56    },
+    {  NULL,   "asrx",         S_INH,          0,      0x57    },
+    {  NULL,   "aslx",         S_INH,          0,      0x58    },
+    {  NULL,   "lslx",         S_INH,          0,      0x58    },
+    {  NULL,   "rolx",         S_INH,          0,      0x59    },
+    {  NULL,   "decx",         S_INH,          0,      0x5A    },
+    {  NULL,   "incx",         S_INH,          0,      0x5C    },
+    {  NULL,   "tstx",         S_INH,          0,      0x5D    },
+    {  NULL,   "clrx",         S_INH,          0,      0x5F    },
+
+    {  NULL,   "nsa",          S_INH,          0,      0x62    },
+
+    {  NULL,   "daa",          S_INH,          0,      0x72    },
+
+    {  NULL,   "rti",          S_INH,          0,      0x80    },
+    {  NULL,   "rts",          S_INH,          0,      0x81    },
+    {  NULL,   "swi",          S_INH,          0,      0x83    },
+    {  NULL,   "tap",          S_INH,          0,      0x84    },
+    {  NULL,   "tpa",          S_INH,          0,      0x85    },
+    {  NULL,   "pula",         S_INH,          0,      0x86    },
+    {  NULL,   "psha",         S_INH,          0,      0x87    },
+    {  NULL,   "pulx",         S_INH,          0,      0x88    },
+    {  NULL,   "pshx",         S_INH,          0,      0x89    },
+    {  NULL,   "pulh",         S_INH,          0,      0x8A    },
+    {  NULL,   "pshh",         S_INH,          0,      0x8B    },
+    {  NULL,   "clrh",         S_INH,          0,      0x8C    },
+    {  NULL,   "stop",         S_INH,          0,      0x8E    },
+    {  NULL,   "wait",         S_INH,          0,      0x8F    },
+
+    {  NULL,   "txs",          S_INH,          0,      0x94    },
+    {  NULL,   "tsx",          S_INH,          0,      0x95    },
+    {  NULL,   "tax",          S_INH,          0,      0x97    },
+    {  NULL,   "clc",          S_INH,          0,      0x98    },
+    {  NULL,   "sec",          S_INH,          0,      0x99    },
+    {  NULL,   "cli",          S_INH,          0,      0x9A    },
+    {  NULL,   "sei",          S_INH,          0,      0x9B    },
+    {  NULL,   "rsp",          S_INH,          0,      0x9C    },
+    {  NULL,   "nop",          S_INH,          0,      0x9D    },
+    {  NULL,   "txa",          S_INH,          S_END,  0x9F    }
+};
diff --git a/as/hc08/m6808.h b/as/hc08/m6808.h
new file mode 100644 (file)
index 0000000..89929a4
--- /dev/null
@@ -0,0 +1,119 @@
+/* m6808.h */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ */
+
+/*)BUILD
+       $(PROGRAM) =    AS6808
+       $(INCLUDE) = {
+               ASM.H
+               M6808.H
+       }
+       $(FILES) = {
+               M08EXT.C
+               M08MCH.C
+               M08ADR.C
+               M08PST.C
+               ASMAIN.C
+               ASLEX.C
+               ASSYM.C
+               ASSUBR.C
+               ASEXPR.C
+               ASDATA.C
+               ASLIST.C
+               ASOUT.C
+       }
+       $(STACK) = 3000
+*/
+
+struct adsym
+{
+       char    a_str[4];       /* addressing string */
+       int     a_val;          /* addressing mode value */
+};
+
+/*
+ * Addressing types
+ */
+#define        S_IMMED 30
+#define        S_DIR   31
+#define        S_EXT   32
+#define        S_IX    33
+#define        S_IXP   34
+#define        S_IX1   35
+#define        S_IX1P  36
+#define        S_IX2   37
+#define        S_IX2P  38
+#define        S_IS    39
+#define        S_SP1   40
+#define        S_SP2   41
+#define        S_A     42
+#define        S_X     43
+#define        S_S     44
+#define        S_XP    45
+
+/*
+ * Instruction types
+ */
+#define        S_INH   60
+#define        S_BRA   61
+#define        S_TYP1  62
+#define        S_TYP2  63
+#define        S_TYP3  64
+#define        S_TYP4  65
+#define        S_TYPAI 66
+#define        S_TYPHX 67
+#define        S_CBEQ  68
+#define        S_CQAX  69
+#define        S_DBNZ  70
+#define        S_DZAX  71
+#define        S_MOV   72
+
+/*
+ * Set Direct Pointer
+ */
+#define        S_SDP   80
+
+
+       /* machine dependent functions */
+
+#ifdef OTHERSYSTEM
+       
+       /* m08adr.c */
+extern struct  adsym   axs[];
+extern int             addr(struct expr *esp);
+extern int             admode(struct adsym *sp);
+extern int             any(int c, char *str);
+extern int             srch(char *str);
+
+       /* m08mch.c */
+extern VOID            machine(struct mne *mp);
+extern int             chkindx(struct expr *exp);
+extern int             mchpcr(struct expr *esp);
+extern VOID            minit(void);
+extern int             comma(void);
+
+#else
+
+       /* m08adr.c */
+extern struct  adsym   axs[];
+extern int             addr();
+extern int             admode();
+extern int             any();
+extern int             srch();
+
+       /* m08mch.c */
+extern VOID            machine();
+extern int             chkindx();
+extern int             mchpcr();
+extern VOID            minit();
+extern int             comma();
+
+#endif
+
diff --git a/as/hc08/strcmpi.c b/as/hc08/strcmpi.c
new file mode 100644 (file)
index 0000000..434529c
--- /dev/null
@@ -0,0 +1,35 @@
+/* strcmpi.c */
+
+/*
+ * Compare two strings ignoring case.
+ *
+ * Taken from GLIBC 2.2.5. Original code is copyrighted "Free
+ * Software Foundation" and published under the GNU Lesser General
+ * Public License.
+ * 
+ */
+
+#include <ctype.h>
+#include "strcmpi.h"
+
+int as_strcmpi (const char *s1, const char *s2)
+{
+  const unsigned char *p1 = (const unsigned char *) s1;
+  const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  do
+    {
+      c1 = tolower (*p1++);
+      c2 = tolower (*p2++);
+      if (c1 == '\0')
+       break;
+    }
+  while (c1 == c2);
+  
+  return c1 - c2;
+}
+
diff --git a/as/hc08/strcmpi.h b/as/hc08/strcmpi.h
new file mode 100644 (file)
index 0000000..63c35c4
--- /dev/null
@@ -0,0 +1,3 @@
+/* strcmpi.h */
+
+int as_strcmpi (const char *s1, const char *s2);