+2006-09-15 Maarten Brock <sourceforge.brock AT dse.nl>
+
+ as/link/mcs51
+ as/aslink.dsp, as/link/mcs51/aslink.dsp,
+ as/link/mcs51/aslink.h, as/mcs51/aslink.h,
+ as/link/mcs51/aslink.mak, as/mcs51/aslink.mak,
+ as/link/mcs51/lkaomf51.c, as/mcs51/lkaomf51.c,
+ as/link/mcs51/lkarea.c, as/mcs51/lkarea.c,
+ as/link/mcs51/lkdata.c, as/mcs51/lkdata.c,
+ as/link/mcs51/lkeval.c, as/mcs51/lkeval.c,
+ as/link/mcs51/lkhead.c, as/mcs51/lkhead.c,
+ as/link/mcs51/lkihx.c, as/mcs51/lkihx.c,
+ as/link/mcs51/lklex.c, as/mcs51/lklex.c,
+ as/link/mcs51/lklibr.c, as/mcs51/lklibr.c,
+ as/link/mcs51/lklist.c, as/mcs51/lklist.c,
+ as/link/mcs51/lkmain.c, as/mcs51/lkmain.c,
+ as/link/mcs51/lkmem.c, as/mcs51/lkmem.c,
+ as/link/mcs51/lknoice.c, as/mcs51/lknoice.c,
+ as/link/mcs51/lkrloc.c, as/mcs51/lkrloc.c,
+ as/link/mcs51/lks19.c, as/mcs51/lks19.c,
+ as/link/mcs51/lkstore.c, as/mcs51/lkstore.c,
+ as/link/mcs51/lksym.c, as/mcs51/lksym.c,
+ as/link/mcs51/Makefile.aslink, as/mcs51/Makefile.aslink,
+ as/link/mcs51/alloc.h,
+ as/link/mcs51/clean.mk,
+ as/link/mcs51/conf.mk,
+ as/link/mcs51/Makefile.bcc,
+ as/link/mcs51/Makefile.in,
+ as/link/mcs51/readme.390,
+ as/link/mcs51/strcmpi.c,
+ as/link/mcs51/strcmpi.h,
+ as/mcs51/clean.mk,
+ as/mcs51/Makefile.bcc,
+ as/mcs51/Makefile.in,
+ configure,
+ Makefile.in,
+ sdcc.dsw: moved mcs51 linker to as/link/mcs51
+
2006-09-14 Maarten Brock <sourceforge.brock AT dse.nl>
* as/link,
endif
ifeq ($(OPT_DISABLE_MCS51), 0)
-SDCC_ASLINK += as/mcs51
+SDCC_ASLINK += as/mcs51 as/link/mcs51
SDCC_MISC += debugger/mcs51
endif
+++ /dev/null
-# Microsoft Developer Studio Project File - Name="aslink" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
-\r
-CFG=aslink - Win32 Release\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "aslink.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "aslink.mak" CFG="aslink - Win32 Release"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "aslink - Win32 Debug" (based on "Win32 (x86) Console Application")\r
-!MESSAGE "aslink - Win32 Release" (based on "Win32 (x86) Console Application")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF "$(CFG)" == "aslink - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "mcs51\Debug"\r
-# PROP BASE Intermediate_Dir "mcs51\Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "mcs51\Debug"\r
-# PROP Intermediate_Dir "mcs51\Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /FD /GZ /c\r
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /FD /GZ /c\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\bin_vc\aslink.exe" /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\bin_vc\aslink.exe" /pdbtype:sept\r
-\r
-!ELSEIF "$(CFG)" == "aslink - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "mcs51\Release"\r
-# PROP BASE Intermediate_Dir "mcs51\Release"\r
-# PROP BASE Ignore_Export_Lib 0\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "mcs51\Release"\r
-# PROP Intermediate_Dir "mcs51\Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c\r
-# ADD CPP /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# ADD RSC /l 0x409 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 /nologo /subsystem:console /machine:I386 /out:"..\bin_vc\aslink.exe" /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\bin_vc\aslink.exe" /pdbtype:sept\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "aslink - Win32 Debug"\r
-# Name "aslink - Win32 Release"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\lkaomf51.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkarea.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkdata.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkeval.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkhead.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkihx.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lklex.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lklibr.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lklist.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkmain.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\lkmem.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lknoice.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkrloc.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lks19.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lkstore.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=mcs51\lksym.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\strcmpi.c\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\alloc.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\aslink.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\asm.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\i8051.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\mcs51\string.h\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r
--- /dev/null
+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)
--- /dev/null
+# Makefile for Borland C++
+
+PRJDIR = ../..
+
+!include $(PRJDIR)/Bcc.inc
+
+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
+
+ASLINK = $(PRJDIR)/bin/aslink.exe
+
+all: $(ASLINK)
+
+$(ASLINK): $(LKOBJECTS)
+ $(CC) $(CFLAGS) -e$@ $(LKOBJECTS)
--- /dev/null
+#
+#
+#
+
+VERSION = @VERSION@
+VERSIONHI = @VERSIONHI@
+VERSIONLO = @VERSIONLO@
+VERSIONP = @VERSIONP@
+
+SHELL = /bin/sh
+CC = @CC@
+CPP = @CPP@
+INSTALL = @INSTALL@
+STRIP = @STRIP@
+
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+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@
+
+VPATH = @srcdir@
+
+CPPFLAGS = @CPPFLAGS@ -I. -I$(srcdir)
+CFLAGS = @CFLAGS@ -Wall -DINDEXLIB
+M_OR_MM = @M_OR_MM@
+LDFLAGS = @LDFLAGS@
+
+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))
+
+ASLINK = $(top_builddir)bin/aslink$(EXEEXT)
+
+transform = @program_transform_name@
+
+# Compiling entire program or any subproject
+# ------------------------------------------
+all: checkconf $(ASLINK)
+
+$(ASLINK): $(LKOBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LKOBJECTS)
+
+# Compiling and installing everything and running test
+# ----------------------------------------------------
+install: all installdirs
+ $(INSTALL) $(ASLINK) `echo $(DESTDIR)$(bindir)/aslink$(EXEEXT)|sed '$(transform)'`
+ $(STRIP) `echo $(DESTDIR)$(bindir)/aslink$(EXEEXT)|sed '$(transform)'`
+
+# Deleting all the installed files
+# --------------------------------
+uninstall:
+ rm -f $(DESTDIR)$(bindir)/aslink$(EXEEXT)
+
+
+# Performing self-test
+# --------------------
+check:
+
+
+# Performing installation test
+# ----------------------------
+installcheck:
+
+
+# Creating installation directories
+# ---------------------------------
+installdirs:
+ $(INSTALL) -d $(DESTDIR)$(bindir)
+
+
+# Creating dependencies
+# ---------------------
+dep: Makefile.dep
+
+Makefile.dep: $(LKSOURCES) $(srcdir)/*.h $(top_builddir)*.h $(top_srcdir)/*.h
+ $(CPP) $(CPPFLAGS) $(M_OR_MM) $(filter %.c,$^) >Makefile.dep
+
+ifeq "$(findstring $(MAKECMDGOALS),uninstall check installcheck installdirs \
+ clean distclean mostlyclean realclean)" ""
+ include Makefile.dep
+endif
+include $(srcdir)/clean.mk
+
+# My rules
+# --------
+.c.o:
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+
+# Remaking configuration
+# ----------------------
+checkconf:
+ @if [ -f $(top_builddir)devel ]; then\
+ $(MAKE) -f conf.mk srcdir="$(srcdir)" top_builddir="$(top_builddir)" freshconf;\
+ fi
+
+# End of Makefile
--- /dev/null
+/* alloc.h */
+/* DECUS C */
+
+#include <stdlib.h>
--- /dev/null
+# Microsoft Developer Studio Project File - Name="aslink" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=aslink - Win32 Release\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "aslink.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "aslink.mak" CFG="aslink - Win32 Release"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "aslink - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "aslink - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF "$(CFG)" == "aslink - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "mcs51\Debug"\r
+# PROP BASE Intermediate_Dir "mcs51\Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug"\r
+# PROP Intermediate_Dir "Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\aslink.exe" /pdbtype:sept\r
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\aslink.exe" /pdbtype:sept\r
+\r
+!ELSEIF "$(CFG)" == "aslink - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "mcs51\Release"\r
+# PROP BASE Intermediate_Dir "mcs51\Release"\r
+# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Release"\r
+# PROP Intermediate_Dir "Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c\r
+# ADD CPP /nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\aslink.exe" /pdbtype:sept\r
+# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\aslink.exe" /pdbtype:sept\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "aslink - Win32 Debug"\r
+# Name "aslink - Win32 Release"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\lkaomf51.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkarea.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkdata.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkeval.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkhead.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkihx.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklex.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklibr.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklist.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkmain.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkmem.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lknoice.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkrloc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lks19.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkstore.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lksym.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\strcmpi.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\alloc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\aslink.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\strcmpi.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
--- /dev/null
+/* 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_BIT 0x400 /* Linker will convert from byte-addressable
+ * space to bit-addressable space.
+ */
+
+#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 */
+ Addr_T a_unaloc; /* Total number of unalocated bytes, for error reporting */
+ 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 as_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 packflag; /* Pack data memory flag
+ */
+extern int stacksize; /* Pack data memory 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 as_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 lnkarea2();
+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(register Addr_T v, register int i);
+extern Addr_T adb_bit(register Addr_T v, register int i);
+extern Addr_T adb_hi(Addr_T v, int i);
+extern Addr_T adb_lo(Addr_T v, int i);
+extern Addr_T adb_24_bit(register Addr_T v, register int i);
+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(register Addr_T v, register int i);
+extern Addr_T adw_24(Addr_T v, int i);
+extern Addr_T adw_hi(Addr_T v, int i);
+extern Addr_T adw_lo(Addr_T v, int i);
+extern Addr_T evword(VOID);
+extern VOID rele(VOID);
+extern VOID reloc(char c);
+extern VOID relt(VOID);
+extern VOID relr(VOID);
+extern VOID relp(VOID);
+extern VOID relerr(char *str);
+extern char * errmsg[];
+extern VOID errdmp(FILE *fptr, char *str);
+extern VOID relerp(char *str);
+extern VOID erpdmp(FILE *fptr, char *str);
+extern VOID prntval(FILE *fptr, Addr_T v);
+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);
+extern int summary2(struct area * xp);
+
+/* JCF: lkaomf51.c */
+extern void SaveLinkedFilePath(char * filepath);
+extern void CreateAOMF51(void);
--- /dev/null
+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
+
+
+
+
--- /dev/null
+# Deleting all files created by building the program
+# --------------------------------------------------
+include $(top_builddir)Makefile.common
+
+clean:
+ rm -f *core *[%~] *.[oa]
+ rm -f .[a-z]*~
+ rm -f $(top_builddir)bin/aslink$(EXEEXT) aslink$(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
--- /dev/null
+#
+# Makefile targets to remake configuration
+#
+
+freshconf: Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_srcdir)/configure.in
+ cd $(top_prjdir) && $(SHELL) ./config.status
+
+# End of conf.mk
--- /dev/null
+/*-------------------------------------------------------------------------
+ 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;
+#if 0
+typedef struct
+{
+ char * name;
+ int usage;
+}
+_UsageType;
+
+_UsageType UsageType[]=
+{
+ {"CSEG", 0},
+ {"GSINIT", 0},
+ {"GSINIT0", 0},
+ {"GSINIT1", 0},
+ {"GSINIT2", 0},
+ {"GSINIT3", 0},
+ {"GSINIT4", 0},
+ {"GSINIT5", 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?*/
+};
+#endif
+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*/
+ symbol[numsym].Static=-1; // o_gloom
+ 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 (unsigned char hex_digit)
+{
+ if (isdigit (hex_digit))
+ return hex_digit-'0';
+ else
+ return toupper (hex_digit)-'A'+10;
+}
+
+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();
+ }
+}
--- /dev/null
+/* 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 the 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++; */
+/* } */
+ }
+ /*
+ * Evaluate area address
+ */
+ skip(-1);
+ axp->a_addr = eval();
+ /*
+ * 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(char *id)
+{
+ register struct area *tap;
+ register struct areax *taxp;
+
+ ap = areap;
+ axp = (struct areax *) new (sizeof(struct areax));
+ axp->a_addr = -1; /* default: no address yet */
+ 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 are 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() lksym.c
+ * char * strncpy() c_library
+ * int symeq() lksym.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 + 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 relocation 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(register struct area *tap)
+{
+ register Addr_T size, addr;
+ register struct areax *taxp;
+
+ size = 0;
+ addr = tap->a_addr;
+#if 0
+ if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+#endif
+ 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++;
+ }
+ if ((tap->a_flag&A_PAG) && (tap->a_size) &&
+ ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
+ {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+}
+
+Addr_T lnksect2 (struct area *tap, int locIndex);
+char idatamap[256];
+unsigned long codemap[524288];
+unsigned long xdatamap[131072];
+
+/*Modified version of the functions for packing variables in internal data memory*/
+VOID lnkarea2 (void)
+{
+ Addr_T rloc[4]={0, 0, 0, 0};
+ Addr_T gs_size = 0;
+ int locIndex;
+ char temp[NCPS];
+ struct sym *sp;
+ int j;
+ struct area *dseg_ap = NULL;
+ struct area *abs_ap = NULL;
+ struct area *gs0_ap = NULL;
+ struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
+
+ for(j=0; j<256; j++) idatamap[j]=' ';
+ memset(codemap, 0, sizeof(codemap));
+ memset(xdatamap, 0, sizeof(xdatamap));
+
+ /* first sort all absolute areas to the front */
+ ap = areap;
+ /* no need to check first area, it's in front anyway */
+ while (ap && ap->a_ap)
+ {
+ if (ap->a_ap->a_flag & A_ABS)
+ {/* next area is absolute, move it to front,
+ reversed sequence is no problem for absolutes */
+ abs_ap = ap->a_ap;
+ ap->a_ap = abs_ap->a_ap;
+ abs_ap->a_ap = areap;
+ areap = abs_ap;
+ }
+ else
+ {
+ ap = ap->a_ap;
+ }
+ }
+
+ /* next accumulate all GSINITx/GSFINAL area sizes
+ into GSINIT so they stay together */
+ ap = areap;
+ while (ap)
+ {
+ if (!strncmp(ap->a_id, "GS", 2))
+ {/* GSxxxxx area */
+ if (ap->a_size == 0)
+ {
+ axp = ap->a_axp;
+ while (axp)
+ {
+ ap->a_size += axp->a_size;
+ axp = axp->a_axp;
+ }
+ }
+ gs_size += ap->a_size;
+ if (!strcmp(ap->a_id, "GSINIT0"))
+ {/* GSINIT0 area */
+ gs0_ap = ap;
+ }
+ }
+ ap = ap->a_ap;
+ }
+ if (gs0_ap)
+ gs0_ap->a_size = gs_size;
+
+ ap = areap;
+ while (ap)
+ {
+ /* Determine memory space */
+ if (ap->a_flag & A_CODE) locIndex = 1;
+ else if (ap->a_flag & A_XDATA) locIndex = 2;
+ else if (ap->a_flag & A_BIT) locIndex = 3;
+ else locIndex = 0;
+
+ if (ap->a_flag & A_ABS) /* Absolute sections */
+ {
+ lnksect2(ap, locIndex);
+ }
+ else /* Relocatable sections */
+ {
+ if (ap->a_type == 0)
+ {
+ ap->a_addr = rloc[locIndex];
+ ap->a_type = 1;
+ }
+
+ rloc[locIndex] = lnksect2(ap, locIndex);
+ }
+
+ /*
+ * 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_type |= S_DEF;
+ if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
+
+ *temp = 'l';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_size;
+ sp->s_axp = NULL;
+ sp->s_type |= S_DEF;
+ if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
+ }
+
+ /*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 + ap->a_size + 7)/8); /*Bits to bytes*/
+ }
+ else if (!strcmp(ap->a_id, "DSEG"))
+ {
+ dseg_ap=ap; /*Need it later to set its correct size*/
+ }
+ ap = ap->a_ap;
+ }
+
+ /*Compute the size of DSEG*/
+ if(dseg_ap!=NULL)
+ {
+ dseg_ap->a_addr=0;
+ dseg_ap->a_size=0;
+ for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
+ }
+ if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
+ if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
+}
+
+static
+Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
+{
+ int i, j, k;
+ unsigned long mask, b;
+
+ while (1)
+ {
+ Addr_T a = start;
+ i = start >> 5;
+ j = (start + size) >> 5;
+ mask = -(1 << (start & 0x1F));
+
+ while (i < j)
+ {
+ if (map[i] & mask)
+ {
+ k = 32;
+ for (b=0x80000000; b!=0; b>>=1, k--)
+ {
+ if (map[i] & b)
+ break;
+ }
+ start = a + k;
+ break;
+ }
+ i++;
+ mask = 0xFFFFFFFF;
+ a += 32;
+ }
+ if (start > a)
+ continue;
+
+ mask &= (1 << ((start + size) & 0x1F)) - 1;
+ if (map[i] & mask)
+ {
+ k = 32;
+ for (b=0x80000000; b!=0; b>>=1, k--)
+ {
+ if (map[i] & b)
+ break;
+ }
+ start = (a & ~0x1F) + k;
+ }
+ if (start <= a)
+ break;
+ }
+ return start;
+}
+
+static
+Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
+{
+ int i, j;
+ unsigned long mask;
+ Addr_T a = start;
+ i = start >> 5;
+ j = (start + size) >> 5;
+ mask = -(1 << (start & 0x1F));
+
+ while (i < j)
+ {
+ if (map[i] & mask)
+ {
+ fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
+ }
+ map[i++] |= mask;
+ mask = 0xFFFFFFFF;
+ a += 32;
+ }
+ mask &= (1 << ((start + size) & 0x1F)) - 1;
+ if (map[i] & mask)
+ {
+ fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
+ }
+ map[i] |= mask;
+ return start;
+}
+
+Addr_T lnksect2 (struct area *tap, int locIndex)
+{
+ register Addr_T size, addr;
+ register struct areax *taxp;
+ int j, k, ramlimit;
+ char fchar=' ', dchar='a';
+ char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
+ " in internal RAM for area %s.\n";
+
+ tap->a_unaloc=0;
+
+ /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
+ if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
+ {
+ if((iram_size<=0)||(iram_size>0x100))
+ ramlimit=0x100;
+ else
+ ramlimit=iram_size;
+ }
+ else
+ {
+ if((iram_size<=0)||(iram_size>0x80))
+ ramlimit=0x80;
+ else
+ ramlimit=iram_size;
+ }
+
+ size = 0;
+ addr = tap->a_addr;
+#if 0
+ if ((tap->a_flag&A_PAG) && (addr & 0xFF))
+ {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+#endif
+ taxp = tap->a_axp;
+
+ /*Use a letter to identify each area in the internal RAM layout map*/
+ if (locIndex==0)
+ {
+ /**/ if(!strcmp(tap->a_id, "DSEG"))
+ fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
+ else if(!strcmp(tap->a_id, "ISEG"))
+ fchar='I';
+ else if(!strcmp(tap->a_id, "SSEG"))
+ fchar='S';
+ else if(!strcmp(tap->a_id, "OSEG"))
+ fchar='Q';
+ else if(!strcmp(tap->a_id, "REG_BANK_0"))
+ fchar='0';
+ else if(!strcmp(tap->a_id, "REG_BANK_1"))
+ fchar='1';
+ else if(!strcmp(tap->a_id, "REG_BANK_2"))
+ fchar='2';
+ else if(!strcmp(tap->a_id, "REG_BANK_3"))
+ fchar='3';
+ else if(!strcmp(tap->a_id, "BSEG_BYTES"))
+ fchar='B';
+ else if(!strcmp(tap->a_id, "BIT_BANK"))
+ fchar='T';
+ else
+ fchar=' ';/*???*/
+ }
+ else if (locIndex == 1)
+ {
+ /**/ if(!strcmp(tap->a_id, "GSINIT"))
+ fchar='G';
+ }
+ else if (locIndex == 2)
+ {
+ /**/ if(!strcmp(tap->a_id, "XSTK"))
+ fchar='K';
+ }
+
+ if (tap->a_flag&A_OVR) /* Overlayed sections */
+ {
+ while (taxp)
+ {
+ if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
+ {
+ addr=(fchar-'0')*8;
+ taxp->a_addr=addr;
+ size=taxp->a_size;
+ for(j=addr; (j<(int)(addr+taxp->a_size)) && (j<ramlimit); j++)
+ idatamap[j]=fchar;
+ }
+ else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
+ {
+ /*Find the size of the space currently used for this areax overlay*/
+ for(j=0, size=0; j<ramlimit; j++)
+ if(idatamap[j]==fchar) size++;
+
+ if( (fchar=='S') && (stacksize==0) )
+ {
+ /*Search for the largest space available and use it for stack*/
+ for(j=0, k=0, taxp->a_size=0; j<ramlimit; j++)
+ {
+ if(idatamap[j]==' ')
+ {
+ if((++k)>(int)taxp->a_size) taxp->a_size=k;
+ }
+ else
+ {
+ k=0;
+ }
+ }
+ stacksize=taxp->a_size;
+ }
+
+ /*If more space required, release the previously allocated areax in
+ internal RAM and search for a bigger one*/
+ if((int)taxp->a_size>size)
+ {
+ size=(int)taxp->a_size;
+
+ for(j=0; j<ramlimit; j++)
+ if(idatamap[j]==fchar) idatamap[j]=' ';
+
+ /*Search for a space large enough in data memory for this overlay areax*/
+ for(j=0, k=0; j<ramlimit; j++)
+ {
+ if(idatamap[j]==' ')
+ k++;
+ else
+ k=0;
+ if(k==(int)taxp->a_size) break;
+ }
+
+ if(k==(int)taxp->a_size)
+ {
+ taxp->a_addr = j-k+1;
+ if(addr<(unsigned int)ramlimit)
+ {
+ for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
+ if(j>=0) addr=j+1;
+ }
+ }
+
+ /*Mark the memory used for overlay*/
+ if(k==(int)taxp->a_size)
+ {
+ for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
+ idatamap[j]=fchar;
+
+ /*Set the new size of the data memory area*/
+ size=ramlimit-addr;
+ }
+ else /*Couldn't find a chunk big enough: report the problem.*/
+ {
+ tap->a_unaloc=taxp->a_size;
+ fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
+ lkerr++;
+ }
+ }
+
+ for(j=0; j<ramlimit; j++)
+ {
+ if (idatamap[j]==fchar)
+ {
+ addr=j;
+ tap->a_addr=addr;
+ taxp->a_addr=addr;
+ break;
+ }
+ }
+ }
+ else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
+ {
+ /*Find the size of the space currently used for this areax overlay*/
+ for(j=0x20, size=0; j<0x30; j++)
+ if(idatamap[j]==fchar) size++;
+
+ /*If more space required, release the previously allocated areax in
+ internal RAM and search for a bigger one*/
+ if((int)taxp->a_size>size)
+ {
+ size=(int)taxp->a_size;
+
+ for(j=0x20; j<0x30; j++)
+ if(idatamap[j]==fchar) idatamap[j]=' ';
+
+ /*Search for a space large enough in data memory for this overlay areax*/
+ for(j=0x20, k=0; j<0x30; j++)
+ {
+ if(idatamap[j]==' ')
+ k++;
+ else
+ k=0;
+ if(k==(int)taxp->a_size) break;
+ }
+
+ if(k==(int)taxp->a_size)
+ {
+ taxp->a_addr = j-k+1;
+ if(addr<(unsigned int)0x30)
+ {
+ for(j=0x2F; (j>=0x20)&&(idatamap[j]==' '); j--);
+ if(j>=0x20) addr=j+1;
+ }
+ }
+
+ /*Mark the memory used for overlay*/
+ if(k==(int)taxp->a_size)
+ {
+ for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
+ idatamap[j]=fchar;
+
+ /*Set the new size of the data memory area*/
+ size=ramlimit-addr;
+ }
+ else /*Couldn't find a chunk big enough: report the problem.*/
+ {
+ tap->a_unaloc=taxp->a_size;
+ fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
+ lkerr++;
+ }
+ }
+
+ for(j=0x20; j<0x30; j++)
+ {
+ if (idatamap[j]==fchar)
+ {
+ addr=j;
+ tap->a_addr=addr;
+ taxp->a_addr=addr;
+ break;
+ }
+ }
+ }
+ else /*Overlay areas not in internal ram*/
+ {
+ taxp->a_addr = addr;
+ if (taxp->a_size > size) size = taxp->a_size;
+ }
+ taxp = taxp->a_axp;
+ }
+ }
+ else if (tap->a_flag & A_ABS) /* Absolute sections */
+ {
+ while (taxp)
+ {
+ if (locIndex == 0)
+ {
+ for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
+ idatamap[j] = 'A';
+ }
+ if (locIndex == 1)
+ {
+ allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
+ }
+ if (locIndex == 2)
+ {
+ allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap);
+ }
+ taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
+ size += taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ }
+ else /* Concatenated sections */
+ {
+ if ((locIndex == 1) && tap->a_size)
+ {
+ addr = find_empty_space(addr, tap->a_size, codemap);
+ }
+ if ((locIndex == 2) && tap->a_size)
+ {
+ addr = find_empty_space(addr, tap->a_size, xdatamap);
+ }
+ while (taxp)
+ {
+ if( (fchar=='D') || (fchar=='I') )
+ {
+ if(taxp->a_size)
+ {
+ /*Search for a space large enough in internal RAM for this areax*/
+ for(j=0, k=0; j<ramlimit; j++)
+ {
+ if(idatamap[j]==' ')
+ k++;
+ else
+ k=0;
+ if(k==(int)taxp->a_size) break;
+ }
+
+ if(k==(int)taxp->a_size)
+ {
+ taxp->a_addr = j-k+1;
+ if(addr<(unsigned int)ramlimit)
+ {
+ for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
+ if(j>=0) addr=j+1;
+ size=ramlimit-addr;
+ }
+
+ for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
+ idatamap[j]=(fchar=='D')?dchar:fchar;
+ if((taxp->a_size>0)&&(fchar=='D'))dchar++;
+ if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
+ }
+ else /*We are in trouble, there is not enough memory for an areax chunk*/
+ {
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ tap->a_unaloc+=taxp->a_size;
+ fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
+ lkerr++;
+ }
+ }
+ taxp = taxp->a_axp;
+ }
+ else if(fchar=='B')
+ {
+ if(taxp->a_size!=0)
+ {
+ for(j=addr; j<((int)(addr+taxp->a_size)); j++)
+ idatamap[j]=fchar;
+ }
+
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ else /*For concatenated BIT, CODE, and XRAM areax's*/
+ {
+ if((fchar=='K') && (taxp->a_size == 1))
+ {
+ taxp->a_size = 256-(addr & 0xFF);
+ }
+ //find next unused address now
+ if ((locIndex == 1) && taxp->a_size)
+ {
+ addr = find_empty_space(addr, taxp->a_size, codemap);
+ allocate_space(addr, taxp->a_size, tap->a_id, codemap);
+ }
+ if ((locIndex == 2) && taxp->a_size)
+ {
+ addr = find_empty_space(addr, taxp->a_size, xdatamap);
+ allocate_space(addr, taxp->a_size, tap->a_id, xdatamap);
+ }
+ 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++;
+ }
+ if ((tap->a_flag&A_PAG) && (tap->a_size) &&
+ ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
+ {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+ return addr;
+}
--- /dev/null
+/* 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 packflag=0; /* JCF: Pack internal memory flag
+ */
+int stacksize=0; /* JCF: Stack size
+ */
+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 as_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, BINOP, 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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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;
+}
+
+/*)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++;
+ }
+}
--- /dev/null
+/* 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) && (rflag) ) {
+ 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 (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");
+ }
+ }
+ }
+ }
+ 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;
+}
--- /dev/null
+/* 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 as_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();
+ if (c == ';')
+ while (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 as_getline()
+ *
+ * The function as_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
+ * as_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
+as_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;
+}
--- /dev/null
+/* 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*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.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()
+ *
+ */
+
+#ifdef INDEXLIB
+typedef struct slibrarysymbol mlibrarysymbol;
+typedef struct slibrarysymbol *pmlibrarysymbol;
+
+struct slibrarysymbol {
+ char * name; /*Warning: allocate memory before using*/
+ pmlibrarysymbol next;
+};
+
+typedef struct slibraryfile mlibraryfile;
+typedef struct slibraryfile *pmlibraryfile;
+
+struct slibraryfile {
+ int loaded;
+ char * libspc;
+ char * relfil; /*Warning: allocate memory before using*/
+ char * filename; /*Warning: allocate memory before using*/
+ long offset; //if > 0, the embedded file offset in the library file libspc
+ pmlibrarysymbol symbols;
+ pmlibraryfile next;
+};
+
+/* First entry in the library object symbol cache */
+pmlibraryfile libr=NULL;
+
+int buildlibraryindex();
+void freelibraryindex (void);
+#endif /* INDEXLIB */
+
+/*)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)
+ {
+ fprintf(stderr, "?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 (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\'))
+ {
+ strcat(str,"/");
+ }
+#endif
+ }
+ else
+ {
+ str = (char *) new (strlen(libfil) + 5);
+ }
+
+#ifdef OTHERSYSTEM
+ if ((libfil[0] == '/') || (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) + 1);
+ 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(char * libfname, 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
+ {
+ fprintf(stderr, "?Aslink-Error-Bad offset in library file %s(%s)\n",
+ libfname, 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(PathLib, 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.
+ */
+
+#ifdef INDEXLIB
+
+int fndsym( char *name )
+{
+ struct lbfile *lbfh, *lbf;
+ pmlibraryfile ThisLibr;
+ pmlibrarysymbol ThisSym = NULL;
+
+ pmlibraryfile FirstFound;
+ int numfound=0;
+
+ /* Build the index if this is the first call to fndsym */
+ if (libr==NULL) buildlibraryindex();
+
+ /* Iterate through all library object files */
+ ThisLibr = libr;
+ FirstFound = libr; /*So gcc stops whining*/
+ while (ThisLibr)
+ {
+ /* Iterate through all symbols in an object file */
+ ThisSym = ThisLibr->symbols;
+
+ while (ThisSym)
+ {
+ if (!strcmp(ThisSym->name, name))
+ {
+ if ((!ThisLibr->loaded) && (numfound==0))
+ {
+ /* Object file is not loaded - add it to the list */
+ 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 = ThisLibr->libspc;
+ lbfh->filspc = ThisLibr->filename;
+ lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
+ strcpy(lbfh->relfil, ThisLibr->relfil);
+ lbfh->offset = ThisLibr->offset;
+ if(lbfh->offset>0)
+ { /*For an embedded object file in a library*/
+ void loadfile_SdccLib(char * libspc, char * module, long offset);
+ loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+ }
+ else
+ { /*For a stand alone object file*/
+ /* if cdb information required & adb file present */
+ if (dflag && dfp)
+ {
+ FILE *xfp = afile(lbfh->filspc, "adb",0);
+ if (xfp)
+ {
+ SaveLinkedFilePath(lbfh->filspc);
+ copyfile(dfp, xfp);
+ fclose(xfp);
+ }
+ }
+ loadfile(lbfh->filspc);
+ }
+ ThisLibr->loaded=1;
+ }
+
+ if(numfound==0)
+ {
+ numfound++;
+ FirstFound=ThisLibr;
+ }
+ else
+ {
+ char absPath1[PATH_MAX];
+ char absPath2[PATH_MAX];
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+ int j;
+
+ _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
+ _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
+ for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
+ for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
+#else
+ realpath(FirstFound->libspc, absPath1);
+ realpath(ThisLibr->libspc, absPath2);
+#endif
+ if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
+ {
+ if(numfound==1)
+ {
+ fprintf(stderr, "?Aslink-Warning-Definition of public symbol '%s'"
+ " found more than once:\n", name);
+ fprintf(stderr, " Library: '%s', Module: '%s'\n",
+ FirstFound->libspc, FirstFound->relfil);
+ }
+ fprintf(stderr, " Library: '%s', Module: '%s'\n",
+ ThisLibr->libspc, ThisLibr->relfil);
+ numfound++;
+ }
+ }
+ }
+ ThisSym=ThisSym->next; /* Next sym in library */
+ }
+ ThisLibr=ThisLibr->next; /* Next library in list */
+ }
+ return numfound;
+}
+
+pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
+{
+ char ModName[NCPS]="";
+ char FLine[MAXLINE+1];
+ char buff[PATH_MAX];
+ int state=0;
+ long IndexOffset=0, FileOffset;
+ pmlibrarysymbol ThisSym = NULL;
+
+ 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;
+
+ /*Create a new libraryfile object for this module*/
+ if(libr==NULL)
+ {
+ libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ }
+ else
+ {
+ This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ This=This->next;
+ }
+ This->next = NULL;
+ This->loaded=-1;
+ This->offset=FileOffset+IndexOffset;
+ This->libspc=PathLib;
+
+ This->relfil=(char *)new(strlen(ModName)+1);
+ strcpy(This->relfil, ModName);
+
+ sprintf(buff, "%s%s%crel", DirLib, ModName, FSEPX);
+ This->filename=(char *)new(strlen(buff)+1);
+ strcpy(This->filename, buff);
+
+ This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
+ }
+ else if(EQ(FLine, "</INDEX>"))
+ {
+ return This; /*Finish, get out of here*/
+ }
+ break;
+ case 2:
+ if(EQ(FLine, "</MODULE>"))
+ {
+ This->loaded=0;
+ /*Create the index for the next module*/
+ state=1;
+ }
+ else
+ {
+ /*Add the symbols*/
+ if(ThisSym==NULL) /*First symbol of the current module*/
+ {
+ ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ }
+ else
+ {
+ ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ ThisSym=ThisSym->next;
+ }
+ ThisSym->next=NULL;
+ ThisSym->name=(char *)new(strlen(FLine)+1);
+ strcpy(ThisSym->name, FLine);
+ }
+ break;
+
+ default:
+ return This; /*State machine should never reach this point, but just in case...*/
+ break;
+ }
+ }
+
+ return This; /*State machine should never reach this point, but just in case...*/
+}
+
+
+/* buildlibraryindex - build an in-memory cache of the symbols contained in
+ * the libraries
+ */
+int buildlibraryindex(void)
+{
+ FILE *libfp, *fp;
+ struct lbname *lbnh;
+ char relfil[NINPUT+2], str[PATH_MAX], *path;
+ char buf[NINPUT+2], c;
+ char symname[NINPUT+2];
+ pmlibraryfile This=NULL;
+ pmlibrarysymbol ThisSym;
+
+ /*
+ * 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, "?Aslink-Error-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)
+ {
+ strcpy(str, path);
+#ifdef OTHERSYSTEM
+ if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\'))
+ {
+ strcat(str,"/");
+ }
+#endif
+ }
+ else
+ {
+ strcpy(str, "");
+ }
+
+ if(strcmp(relfil, "<SDCCLIB>")==0)
+ {
+ /*Get the built in index of this library*/
+ This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
+ break; /*get the index for next library*/
+ }
+
+ /*From here down, build the index for the original library 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)
+ {
+ /* Opened OK - create a new libraryfile object for it */
+ if(libr==NULL)
+ {
+ libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ }
+ else
+ {
+ This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ This=This->next;
+ }
+ This->next = NULL;
+ This->loaded=-1;
+ This->offset=-1; /*We have a stand alone .rel file*/
+ This->libspc = lbnh->libspc;
+
+ This->relfil=(char *)new(strlen(relfil)+1);
+ strcpy(This->relfil, relfil);
+
+ This->filename=(char *)new(strlen(str)+1);
+ strcpy(This->filename, str);
+
+ /*Start a new linked list of symbols for this module:*/
+ This->symbols=ThisSym=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';
+ buf[strlen(buf) - 1] = '\0';
+
+ /*
+ * 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 it's an actual symbol, record it */
+ if (c == 'D')
+ {
+ if(ThisSym==NULL)
+ {
+ ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ }
+ else
+ {
+ ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ ThisSym=ThisSym->next;
+ }
+ This->loaded=0;
+ ThisSym->next=NULL;
+ ThisSym->name=(char *)new(strlen(symname)+1);
+ strcpy(ThisSym->name, symname);
+ }
+ } /* Closes while - read object file */
+ fclose(fp);
+ } /* Closes if object file opened OK */
+ else
+ {
+ fprintf(stderr, "?Aslink-Warning-Cannot open library module %s\n", str);
+ }
+ } /* Ends while - processing all in libr */
+ fclose(libfp);
+ } /* Ends good open of libr file */
+ return 0;
+}
+
+/*Release all memory allocated for the in-memory library index*/
+void freelibraryindex (void)
+{
+ pmlibraryfile ThisLibr, ThisLibr2Free;
+ pmlibrarysymbol ThisSym, ThisSym2Free;
+
+ ThisLibr = libr;
+
+ while (ThisLibr)
+ {
+ ThisSym = ThisLibr->symbols;
+
+ while (ThisSym)
+ {
+ free(ThisSym->name);
+ ThisSym2Free=ThisSym;
+ ThisSym=ThisSym->next;
+ free(ThisSym2Free);
+ }
+ free(ThisLibr->filename);
+ free(ThisLibr->relfil);
+ ThisLibr2Free=ThisLibr;
+ ThisLibr=ThisLibr->next;
+ free(ThisLibr2Free);
+ }
+
+ libr=NULL;
+}
+
+#else /* INDEXLIB */
+
+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, "?Aslink-Error-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 (strlen(str) && (str[strlen(str)-1] != '/') && (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);
+ 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);
+}
+
+#endif /*INDEXLIB*/
+
+void loadfile_SdccLib(char * libspc, char * module, long offset)
+{
+ FILE *fp;
+
+ if ((fp = fopen(libspc,"r")) != NULL)
+ {
+ fseek(fp, offset, SEEK_SET);
+ LoadRel(libspc, 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);
+ }
+ }
+#ifdef INDEXLIB
+ freelibraryindex();
+#endif
+}
+
+/*)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);
+ }
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
+
+/*)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()*/
+ ""
+ };
+
+ char * rel2[]={
+ "XH",
+ "H C 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()*/
+ "A BIT_BANK size 0 flags 4", /*Bit register bank is overlayable*/
+ "A DSEG size 0 flags 0",
+ "A OSEG size 0 flags 4",
+ "A ISEG size 0 flags 0",
+ "A SSEG size 0 flags 4",
+ ""
+ };
+ int j;
+ struct sym * sp;
+
+ if(packflag)
+ {
+ for (j=0; rel2[j][0]!=0; j++)
+ {
+ ip=rel2[j];
+ link_main();
+ }
+ }
+ else
+ {
+ 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; }
+ else if (!strcmp(ap->a_id, "SSEG"))
+ {
+ if(stacksize) ap->a_axp->a_size=stacksize;
+ }
+ }
+
+ sp = lkpsym("l_IRAM", 1);
+ sp->s_addr = ((iram_size>0) && (iram_size<=0x100)) ? iram_size : 0x0100;
+ sp->s_axp = NULL;
+ sp->s_type |= S_DEF;
+}
+
+/*)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 functions as_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 as_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(int argc, 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 (as_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 (as_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.
+ */
+ if(!packflag)
+ lnkarea();
+ else
+ lnkarea2();
+ /*
+ * 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(!packflag)
+ {
+ if(summary(areap)) lkexit(1);
+ }
+ else
+ {
+ if(summary2(areap)) lkexit(1);
+ }
+ }
+
+ if ((iram_size) && (!packflag))
+ 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(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);
+ remove("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 char 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 == ';')
+ return(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*/
+ ++sflag;
+ break;
+
+ case 'Y':
+ unget(getnb());
+ packflag=1;
+ break;
+
+ case 'A':
+ unget(getnb());
+ if (ip && *ip)
+ {
+ stacksize=expr(0);
+ if(stacksize>256) stacksize=256;
+ else if(stacksize<0) stacksize=0;
+ }
+ return(0);
+
+ 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':
+ 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);
+ }
+ }
+ if ( c == ';')
+ return(0);
+ } 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 the
+ * 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 the
+ * 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(char *fn, char *ft, int wf)
+{
+ 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*/
+ if (fb[i] != '.')
+ {
+ 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 = expr(0); /* evaluate size expression */
+ else
+ iram_size = 128; /* Default is 128 (0x80) bytes */
+ if ((iram_size<=0) || (iram_size>256))
+ 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",
+ " -y Generate memory usage summary file[mem]",
+ " -Y Pack internal ram",
+ " -A [stack-size] Allocate space for stack",
+ "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);
+ }
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+ 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, 8, 8, "REG_BANK_0", 0x0001},
+ {0x8, 8, 8, "REG_BANK_1", 0x0002},
+ {0x10, 8, 8, "REG_BANK_2", 0x0004},
+ {0x18, 8, 8, "REG_BANK_3", 0x0008},
+ {0x20, 0, 16, "BSEG_BYTES", 0x0010},
+ {0, 0, 128, "UNUSED", 0x0000},
+ {0x7f, 0, 128, "DATA", 0x0020},
+ {0, 0, 128, "TOTAL:", 0x0000}
+ };
+
+ _Mem IRam= {0xff, 0, 128, "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(stacksize==0) stacksize=MIN_STACK;
+
+ 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;
+ }
+
+ 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, "BIT_BANK"))
+ {
+ Ram[4].Size+=xp->a_size;
+ }
+
+ else if(xp->a_flag & A_CODE)
+ {
+ if(xp->a_size>0)
+ {
+ 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(xp->a_flag & A_XDATA)
+ {
+ if(xp->a_size>0)
+ {
+ 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;
+ }
+
+ /*If is not a register bank, bit, stack, or idata, then it should be data*/
+ else if((xp->a_flag & (A_CODE|A_BIT|A_XDATA))==0)
+ {
+ if(xp->a_size)
+ {
+ Ram[6].Size+=xp->a_size;
+ if(xp->a_addr<Ram[6].Start) Ram[6].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*/
+
+ for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
+ dram[k]|=IRam.flag; /*Mark as used*/
+
+ /*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);
+ }
+ }
+
+ 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);
+ }
+
+ /*Report the position of the beginning 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);
+
+ /*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 ((int)k<stacksize)
+ {
+ sprintf(buff, "Only %d byte%s available for stack.\n",
+ k, (k==1)?"":"s");
+ REPORT_WARNING(buff, 1);
+ }
+ }
+
+ fprintf(of, "\nOther memory:\n");
+ fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+ fprintf(of, format, line, line, line, line, line);
+
+ /*Report IRam totals:*/
+ if(IRam.Size==0)
+ {
+ start[0]=0;/*Empty string*/
+ end[0]=0;/*Empty string*/
+ }
+ else
+ {
+ sprintf(start, "0x%02lx", IRam.Start);
+ 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:*/
+ if(XRam.Size==0)
+ {
+ start[0]=0;/*Empty string*/
+ end[0]=0;/*Empty string*/
+ }
+ else
+ {
+ sprintf(start, "0x%04lx", XRam.Start);
+ 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:*/
+ if(Rom.Size==0)
+ {
+ start[0]=0;/*Empty string*/
+ end[0]=0;/*Empty string*/
+ }
+ else
+ {
+ sprintf(start, "0x%04lx", Rom.Start);
+ 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((IRam.Start+IRam.Size)>(IRam.Max+0x80))
+ {
+ sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ 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;
+}
+
+extern char idatamap[]; //0:not used, 1:used
+
+
+int summary2(struct area * areap)
+{
+ #define EQ(A,B) !as_strcmpi((A),(B))
+
+ char buff[128];
+ int toreturn = 0;
+ unsigned int j;
+ unsigned long int Stack_Start=0, Stack_Size;
+
+ struct area * xp;
+ struct area * xstack_xp = NULL;
+ 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 End;
+ unsigned long Size;
+ unsigned long Max;
+ char Name[NCPS];
+ unsigned long flag;
+ } _Mem;
+
+ _Mem Stack={0xff, 0, 0, 1, "STACK", 0x0000};
+ _Mem Paged={0xff, 0, 0, 256, "PAGED EXT. RAM", A_PAG};
+ _Mem XRam= {0xffff, 0, 0, 65536, "EXTERNAL RAM", 0x0100};
+ _Mem Rom= {0xffff, 0, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
+
+ if(rflag) /*For the DS390*/
+ {
+ XRam.Max=0x1000000; /*24 bits*/
+ XRam.Start=0xffffff;
+ Rom.Max=0x1000000;
+ Rom.Start=0xffffff;
+ }
+
+ /* Open Memory Summary File*/
+ of = afile(linkp->f_idp, "mem", 1);
+ if (of == NULL)
+ {
+ lkexit(1);
+ }
+
+ xp=areap;
+ while (xp)
+ {
+ if(xp->a_flag & A_CODE)
+ {
+ if(xp->a_size)
+ {
+ Rom.Size += xp->a_size;
+ if(xp->a_addr < Rom.Start)
+ Rom.Start = xp->a_addr;
+ if(xp->a_addr + xp->a_size > Rom.End)
+ Rom.End = xp->a_addr + xp->a_size;
+ }
+ }
+
+ else if (EQ(xp->a_id, "SSEG"))
+ {
+ Stack.Size += xp->a_size;
+ if(xp->a_addr < Stack.Start)
+ Stack.Start = xp->a_addr;
+ if(xp->a_addr + xp->a_size > Stack.End)
+ Stack.End = xp->a_addr + xp->a_size;
+ }
+
+ else if (EQ(xp->a_id, "PSEG"))
+ {
+ Paged.Size += xp->a_size;
+ if(xp->a_addr < Paged.Start)
+ Paged.Start = xp->a_addr;
+ if(xp->a_addr + xp->a_size > Paged.End)
+ Paged.End = xp->a_addr + xp->a_size;
+ }
+
+ else if (EQ(xp->a_id, "XSTK"))
+ {
+ xstack_xp = xp;
+ Paged.Size += xp->a_size;
+ if(xp->a_addr < Paged.Start)
+ Paged.Start = xp->a_addr;
+ if(xp->a_addr + xp->a_size > Paged.End)
+ Paged.End = xp->a_addr + xp->a_size;
+ }
+
+ else if(xp->a_flag & A_XDATA)
+ {
+ if(xp->a_size)
+ {
+ XRam.Size += xp->a_size;
+ if(xp->a_addr < XRam.Start)
+ XRam.Start = xp->a_addr;
+ if(xp->a_addr + xp->a_size > XRam.End)
+ XRam.End = xp->a_addr + xp->a_size;
+ }
+ }
+
+ xp = xp->a_ap;
+ }
+
+ /*Report the Ram totals*/
+ fprintf(of, "Internal RAM layout:\n");
+ fprintf(of, " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
+ for(j=0; j<256; j++)
+ {
+ if(j%16==0) fprintf(of, "\n0x%02x:|", j);
+ fprintf(of, "%c|", idatamap[j]);
+ }
+ fprintf(of, "\n0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute\n");
+
+ for(j=0; j<256; j++)
+ {
+ if(idatamap[j]=='S')
+ {
+ Stack_Start=j;
+ break;
+ }
+ }
+
+ for(j=Stack_Start, Stack_Size=0; j<((iram_size)?iram_size:256); j++)
+ {
+ if((idatamap[j]=='S')||(idatamap[j]==' ')) Stack_Size++;
+ else break;
+ }
+
+ xp=areap;
+ while (xp)
+ {
+ if(xp->a_unaloc>0)
+ {
+ fprintf(of, "\nERROR: Couldn't get %d byte%s allocated"
+ " in internal RAM for area %s.",
+ xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id);
+ toreturn=1;
+ }
+ xp=xp->a_ap;
+ }
+
+ /*Report the position of the begining of the stack*/
+ if(Stack_Start!=256)
+ fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx) with %ld bytes available.",
+ rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1, Stack_Size);
+ else
+ fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
+
+ /*Report about xstack*/
+ if (xstack_xp)
+ {
+ Stack_Start = xstack_xp->a_addr;
+ Stack_Size = xstack_xp->a_size;
+ fprintf(of, "\nXstack starts at: 0x%04lx with %ld bytes available.",
+ Stack_Start, Stack_Size);
+ }
+
+ fprintf(of, "\n\nOther memory:\n");
+ fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+ fprintf(of, format, line, line, line, line, line);
+
+ /*Report Paged XRam totals:*/
+ if(Paged.Size==0)
+ {
+ start[0]=0;/*Empty string*/
+ end[0]=0;/*Empty string*/
+ }
+ else
+ {
+ sprintf(start, "0x%04lx", Paged.Start);
+ sprintf(end, "0x%04lx", Paged.End-1);
+ }
+ sprintf(size, "%5lu", Paged.Size);
+ sprintf(max, "%5lu", xram_size<0 ? Paged.Max : xram_size<256 ? xram_size : 256);
+ fprintf(of, format, Paged.Name, start, end, size, max);
+
+ /*Report XRam totals:*/
+ if(XRam.Size==0)
+ {
+ start[0]=0;/*Empty string*/
+ end[0]=0;/*Empty string*/
+ }
+ else
+ {
+ sprintf(start, "0x%04lx", XRam.Start);
+ sprintf(end, "0x%04lx", XRam.End-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:*/
+ if(Rom.Size==0)
+ {
+ start[0]=0;/*Empty string*/
+ end[0]=0;/*Empty string*/
+ }
+ else
+ {
+ sprintf(start, "0x%04lx", Rom.Start);
+ sprintf(end, "0x%04lx", Rom.End-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( ((XRam.End) > XRam.Max) ||
+ (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
+ {
+ sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ if( ((Rom.End) > 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;
+}
--- /dev/null
+/* 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 );
+}
--- /dev/null
+/* 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(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(VOID)
+{
+ 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(VOID)
+{
+ 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_BIT)
+ {
+ relv = adb_24_bit(reli, rtp);
+ }
+ else 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_BIT) {
+ relv = adb_bit(reli, rtp);
+ } else 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;
+ if ((mode & R_BIT) && (relv & ~0x87FF))
+ error = 5;
+
+ /*
+ * 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 (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;
+ }
+ 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",
+ "Bit-addressable 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(VOID)
+{
+ 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(VOID)
+{
+ 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(VOID)
+{
+ 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(register Addr_T v, register int i)
+{
+ return(rtval[i] += v);
+}
+
+/*)Function Addr_T adb_bit(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_bit() converts the single
+ * byte address value contained in rtval[i] to bit-
+ * addressable space and adds the value of v to it.
+ * The new value of rtval[i] is returned.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ *
+ */
+
+Addr_T adb_bit(register Addr_T v, register int i)
+{
+ register Addr_T j;
+
+ j = adb_lo(v, i) & 0xFF;
+ if ((j >= 0x20) && (j <= 0x2F)) {
+ j = (j - 0x20) * 8;
+ } else if ((j < 0x80) || ((j & 0x07) != 0)) {
+ return(0x100);//error
+ }
+
+ if (hilo) {
+ j = rtval[i+1] = j + (rtval[i] & 0x07);
+ } else {
+ j = rtval[i] = j + (rtval[i+1] & 0x07);
+ }
+ return(j);
+}
+
+/*)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(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(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_bit(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_24_bit() converts the single
+ * byte address value contained in rtval[i] to bit-
+ * addressable space and adds the value of v to it.
+ * The new value of rtval[i] is returned.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ *
+ */
+
+Addr_T adb_24_bit(register Addr_T v, register int i)
+{
+ register Addr_T j;
+
+ j = adb_24_lo(v, i) & 0xFF;
+ if ((j >= 0x20) && (j <= 0x2F)) {
+ j = (j - 0x20) * 8;
+ } else if ((j < 0x80) || ((j & 0x07) != 0)) {
+ return(0x100);//error
+ }
+
+ if (hilo) {
+ j = rtval[i+2] = j + (rtval[i+1] & 0x07);
+ } else {
+ j = rtval[i] = j + (rtval[i+1] & 0x07);
+ }
+ 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(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(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(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(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(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(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(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(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);
+}
--- /dev/null
+/* 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");
+ }
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+DS80C390 flat mode support
+
+2/4/2000 Kevin Vigor (e-mail: kevin at vigor.nu)
+
+I have hacked the 8051 assembler to support the 24 bit flat address mode of
+the DS80C390 processor. This mode allows the chip to directly address up to
+4 Meg of RAM. Details can be found at Dallas' web site: www.dalsemi.com.
+
+1: Assembler changes.
+
+24 bit mode is entered via a new assembler directive, .flat24. This directive
+takes a mandatory argument, which is either the string "on" or the string
+"off". ".flat24 on" enables 24-bit mode, and ".flat24 off" puts the assembler
+into standard 8051 mode.
+
+Note that any .included files within a ".flat24 on" segment of the code will
+be compiled in 24-bit mode.
+
+In 24-bit mode, 8 instructions have altered behavior. Of these, 5 modify
+the instruction encoding, while 3 differ only in behavior. These
+instructions are discussed in the DS80C390 User's Guide, but a summary is
+included here:
+
+ACALL and AJMP now take a 19 bit offset instead of the 8051's 11 bit offset.
+An extra address byte is added to the encoded instruction.
+
+LCALL and LJMP now take a 24 bit target address instead of the 8051's 16 bit
+address. An extra address byte is added to the encoded instruction.
+
+MOV DPTR, #immed now takes a 24 bit immediate value instead of the 8051's 16
+bit address. An extra data byte is added to the encoded instruction.
+
+INC DPTR now increments the entire 24 bit DPTR. The encoding is not changed.
+
+RET and RETI restore the full 24 bit PC from the stack. The encoding is not
+changed.
+
+2: Linker changes.
+
+The linker supports (through a variety of evil hacks) 19 bit ACALL/AJMP
+relocations and 24 bit LCALL/LJMP/DPTR relocations. These changes should be
+invisible to the user.
+
+The linker can now also generated extended linear address records in the
+Intel hex output format. This is necessary for any areas located above the
+64K mark. This is enabled by the "-r" linker flag, and is disabled by
+default (but the linker will throw a warning if an extended address is
+encountered without the -r flag being enabled).
+
+Note that for various reasons, areas may still not be larger than 64K.
+However, they may be located anywhere in the 4 Meg address space via the
+assembler .org directive (for ABS areas) or the linker "-b" option.
+
+3: Examples
+
+Note that this example uses ABS areas to make the layout obvious. This code
+won't do anything useful at all, but demonstrates the instruction encoding
+in .flat24 mode vs 8051 mode.
+
+; test1.asm
+.area CODE (ABS)
+.org 0
+
+; SFRs not known to the assembler yet...
+$TA = 0x00C7
+$ACON = 0x009D
+
+; Set the chip to 24 bit flat mode via the DS "timed access" procedure.
+mov $TA, #0xAA
+mov $TA, #0x55
+mov $ACON, #0x06 ; 10 bit stack & 24 bit flat addressing.
+
+.flat24 on ; Enable 24-bit mode. The AM1 bit had better be
+ ; on...
+
+mov dptr, #myData ; Valid on the '390: myData is in the FARDATA
+ ; area at 0x300001.
+ ; Generates: 90 30 00 01
+acall _junkNear ; Within 11 bit range, but still must generate
+ ; 19 bit address for '390 flat mode.
+ ; Generates: 11 04 00
+ajmp _junkFar ; Within 16 bit range.
+ ; Generates 01 08 00
+acall _junkReallyFar ; Within 19 bit range.
+ ; Generates 91 00 00
+lcall _junkReallyReallyFar ; Within 24 bit range.
+ ; Generates 12 08 00 00
+
+; Set the chip to 8051 mode via the DS "timed access" procedure.
+mov $TA, #0x0AA
+mov $TA, #0x055
+mov $ACON, #0x00 ; 8 bit stack & 16 bit flat addressing.
+
+.flat24 off ; Now we're an 8051 again. The AM1 bit had better be
+ ; off...
+
+;mov dptr, #myData ; Can't do that: myData is too far away.
+acall _junkNear ; Within 11 bit range.
+ ; Generates 91 00
+ljmp _junkFar ; Within 16 bit range; can't AJMP, but can LJMP
+ ; Generates 02 08 00
+ret
+
+.area CODE2 (ABS)
+.org 0x400
+; This is within the 11 bit ACALL/AJMP range of the 8051.
+_junkNear:
+ret
+
+.area CODE3 (ABS)
+.org 0x800
+; This is within the 390's 19 bit ACALL/AJMP range, and inside the stock
+; 8051's 16 bit LCALL range.
+_junkFar:
+ret
+
+.area CODE4 (ABS)
+; This is within the 390's 19 bit ACALL/AJMP range and outside the
+; 8051's LCALL range.
+; Note that to link an image with an area beyond 64K (like this one),
+; the '-r' flag must be provided to the linker, and Intel Hex output format
+; must be used.
+.org 0x40000
+_junkReallyFar:
+ret
+
+.area CODE5 (ABS)
+; This is outside anybody's ACALL/AJMP range.
+.org 0x80000
+_junkReallyReallyFar:
+ret
+
+.area FARDATA (ABS)
+.org 0x300000
+; This is way, way up there.
+.byte 0x01
+myData:
+.byte 0x02
+
+; test1.asm ends.
+
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* strcmpi.h */
+
+int as_strcmpi (const char *s1, const char *s2);
+++ /dev/null
-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)
-# Makefile for Borlad C++
+# Makefile for Borland C++
PRJDIR = ../..
asexpr.obj asdata.obj aslist.obj asout.obj asstore.obj \
i51ext.obj i51pst.obj i51mch.obj i51adr.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)
+all: $(ASX8051)
$(ASX8051): $(ASOBJECTS)
$(CC) $(CFLAGS) -e$@ $(ASOBJECTS)
-
-$(ASLINK): $(LKOBJECTS)
- $(CC) $(CFLAGS) -e$@ $(LKOBJECTS)
i51ext.o i51pst.o i51mch.o i51adr.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 = $(top_builddir)bin/asx8051$(EXEEXT)
-ASLINK = $(top_builddir)bin/aslink$(EXEEXT)
transform = @program_transform_name@
# Compiling entire program or any subproject
# ------------------------------------------
-all: checkconf $(ASX8051) $(ASLINK)
+all: checkconf $(ASX8051)
$(ASX8051): $(ASOBJECTS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ASOBJECTS)
-
-$(ASLINK): $(LKOBJECTS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LKOBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ASOBJECTS)
-# Compiling and installing everything and runing test
-# ---------------------------------------------------
+# Compiling and installing everything and running test
+# ----------------------------------------------------
install: all installdirs
$(INSTALL) $(ASX8051) `echo $(DESTDIR)$(bindir)/asx8051$(EXEEXT)|sed '$(transform)'`
$(STRIP) `echo $(DESTDIR)$(bindir)/asx8051$(EXEEXT)|sed '$(transform)'`
- $(INSTALL) $(ASLINK) `echo $(DESTDIR)$(bindir)/aslink$(EXEEXT)|sed '$(transform)'`
- $(STRIP) `echo $(DESTDIR)$(bindir)/aslink$(EXEEXT)|sed '$(transform)'`
# Deleting all the installed files
# --------------------------------
uninstall:
- rm -f $(DESTDIR)$(bindir)/asx8051$(EXEEXT) $(DESTDIR)$(bindir)/aslink$(EXEEXT)
+ rm -f $(DESTDIR)$(bindir)/asx8051$(EXEEXT)
# Performing self-test
# ---------------------
dep: Makefile.dep
-Makefile.dep: $(ASSOURCES) $(LKSOURCES) $(srcdir)/*.h $(top_builddir)*.h $(top_srcdir)/*.h
+Makefile.dep: $(ASSOURCES) $(srcdir)/*.h $(top_builddir)*.h $(top_srcdir)/*.h
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(filter %.c,$^) >Makefile.dep
ifeq "$(findstring $(MAKECMDGOALS),uninstall check installcheck installdirs \
+++ /dev/null
-/* 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_BIT 0x400 /* Linker will convert from byte-addressable
- * space to bit-addressable space.
- */
-
-#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 */
- Addr_T a_unaloc; /* Total number of unalocated bytes, for error reporting */
- 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 as_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 packflag; /* Pack data memory flag
- */
-extern int stacksize; /* Pack data memory 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 as_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 lnkarea2();
-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(register Addr_T v, register int i);
-extern Addr_T adb_bit(register Addr_T v, register int i);
-extern Addr_T adb_hi(Addr_T v, int i);
-extern Addr_T adb_lo(Addr_T v, int i);
-extern Addr_T adb_24_bit(register Addr_T v, register int i);
-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(register Addr_T v, register int i);
-extern Addr_T adw_24(Addr_T v, int i);
-extern Addr_T adw_hi(Addr_T v, int i);
-extern Addr_T adw_lo(Addr_T v, int i);
-extern Addr_T evword(VOID);
-extern VOID rele(VOID);
-extern VOID reloc(char c);
-extern VOID relt(VOID);
-extern VOID relr(VOID);
-extern VOID relp(VOID);
-extern VOID relerr(char *str);
-extern char * errmsg[];
-extern VOID errdmp(FILE *fptr, char *str);
-extern VOID relerp(char *str);
-extern VOID erpdmp(FILE *fptr, char *str);
-extern VOID prntval(FILE *fptr, Addr_T v);
-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);
-extern int summary2(struct area * xp);
-
-/* JCF: lkaomf51.c */
-extern void SaveLinkedFilePath(char * filepath);
-extern void CreateAOMF51(void);
+++ /dev/null
-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
-
-
-
-
clean:
rm -f *core *[%~] *.[oa]
rm -f .[a-z]*~
- rm -f $(top_builddir)bin/asx8051$(EXEEXT) $(top_builddir)bin/aslink$(EXEEXT) asx8051$(EXEEXT) aslink$(EXEEXT)
+ rm -f $(top_builddir)bin/asx8051$(EXEEXT) asx8051$(EXEEXT)
# Deleting all files created by configuring or building the program
+++ /dev/null
-/*-------------------------------------------------------------------------
- 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;
-#if 0
-typedef struct
-{
- char * name;
- int usage;
-}
-_UsageType;
-
-_UsageType UsageType[]=
-{
- {"CSEG", 0},
- {"GSINIT", 0},
- {"GSINIT0", 0},
- {"GSINIT1", 0},
- {"GSINIT2", 0},
- {"GSINIT3", 0},
- {"GSINIT4", 0},
- {"GSINIT5", 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?*/
-};
-#endif
-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*/
- symbol[numsym].Static=-1; // o_gloom
- 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 (unsigned char hex_digit)
-{
- if (isdigit (hex_digit))
- return hex_digit-'0';
- else
- return toupper (hex_digit)-'A'+10;
-}
-
-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();
- }
-}
+++ /dev/null
-/* 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 the 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++; */
-/* } */
- }
- /*
- * Evaluate area address
- */
- skip(-1);
- axp->a_addr = eval();
- /*
- * 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(char *id)
-{
- register struct area *tap;
- register struct areax *taxp;
-
- ap = areap;
- axp = (struct areax *) new (sizeof(struct areax));
- axp->a_addr = -1; /* default: no address yet */
- 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 are 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() lksym.c
- * char * strncpy() c_library
- * int symeq() lksym.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 + 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 relocation 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(register struct area *tap)
-{
- register Addr_T size, addr;
- register struct areax *taxp;
-
- size = 0;
- addr = tap->a_addr;
-#if 0
- if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
- fprintf(stderr,
- "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
- lkerr++;
- }
-#endif
- 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++;
- }
- if ((tap->a_flag&A_PAG) && (tap->a_size) &&
- ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
- {
- fprintf(stderr,
- "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
- lkerr++;
- }
-}
-
-Addr_T lnksect2 (struct area *tap, int locIndex);
-char idatamap[256];
-unsigned long codemap[524288];
-unsigned long xdatamap[131072];
-
-/*Modified version of the functions for packing variables in internal data memory*/
-VOID lnkarea2 (void)
-{
- Addr_T rloc[4]={0, 0, 0, 0};
- Addr_T gs_size = 0;
- int locIndex;
- char temp[NCPS];
- struct sym *sp;
- int j;
- struct area *dseg_ap = NULL;
- struct area *abs_ap = NULL;
- struct area *gs0_ap = NULL;
- struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
-
- for(j=0; j<256; j++) idatamap[j]=' ';
- memset(codemap, 0, sizeof(codemap));
- memset(xdatamap, 0, sizeof(xdatamap));
-
- /* first sort all absolute areas to the front */
- ap = areap;
- /* no need to check first area, it's in front anyway */
- while (ap && ap->a_ap)
- {
- if (ap->a_ap->a_flag & A_ABS)
- {/* next area is absolute, move it to front,
- reversed sequence is no problem for absolutes */
- abs_ap = ap->a_ap;
- ap->a_ap = abs_ap->a_ap;
- abs_ap->a_ap = areap;
- areap = abs_ap;
- }
- else
- {
- ap = ap->a_ap;
- }
- }
-
- /* next accumulate all GSINITx/GSFINAL area sizes
- into GSINIT so they stay together */
- ap = areap;
- while (ap)
- {
- if (!strncmp(ap->a_id, "GS", 2))
- {/* GSxxxxx area */
- if (ap->a_size == 0)
- {
- axp = ap->a_axp;
- while (axp)
- {
- ap->a_size += axp->a_size;
- axp = axp->a_axp;
- }
- }
- gs_size += ap->a_size;
- if (!strcmp(ap->a_id, "GSINIT0"))
- {/* GSINIT0 area */
- gs0_ap = ap;
- }
- }
- ap = ap->a_ap;
- }
- if (gs0_ap)
- gs0_ap->a_size = gs_size;
-
- ap = areap;
- while (ap)
- {
- /* Determine memory space */
- if (ap->a_flag & A_CODE) locIndex = 1;
- else if (ap->a_flag & A_XDATA) locIndex = 2;
- else if (ap->a_flag & A_BIT) locIndex = 3;
- else locIndex = 0;
-
- if (ap->a_flag & A_ABS) /* Absolute sections */
- {
- lnksect2(ap, locIndex);
- }
- else /* Relocatable sections */
- {
- if (ap->a_type == 0)
- {
- ap->a_addr = rloc[locIndex];
- ap->a_type = 1;
- }
-
- rloc[locIndex] = lnksect2(ap, locIndex);
- }
-
- /*
- * 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_type |= S_DEF;
- if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
-
- *temp = 'l';
- sp = lkpsym(temp, 1);
- sp->s_addr = ap->a_size;
- sp->s_axp = NULL;
- sp->s_type |= S_DEF;
- if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
- }
-
- /*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 + ap->a_size + 7)/8); /*Bits to bytes*/
- }
- else if (!strcmp(ap->a_id, "DSEG"))
- {
- dseg_ap=ap; /*Need it later to set its correct size*/
- }
- ap = ap->a_ap;
- }
-
- /*Compute the size of DSEG*/
- if(dseg_ap!=NULL)
- {
- dseg_ap->a_addr=0;
- dseg_ap->a_size=0;
- for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
- }
- if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
- if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
-}
-
-static
-Addr_T find_empty_space(Addr_T start, Addr_T size, unsigned long *map)
-{
- int i, j, k;
- unsigned long mask, b;
-
- while (1)
- {
- Addr_T a = start;
- i = start >> 5;
- j = (start + size) >> 5;
- mask = -(1 << (start & 0x1F));
-
- while (i < j)
- {
- if (map[i] & mask)
- {
- k = 32;
- for (b=0x80000000; b!=0; b>>=1, k--)
- {
- if (map[i] & b)
- break;
- }
- start = a + k;
- break;
- }
- i++;
- mask = 0xFFFFFFFF;
- a += 32;
- }
- if (start > a)
- continue;
-
- mask &= (1 << ((start + size) & 0x1F)) - 1;
- if (map[i] & mask)
- {
- k = 32;
- for (b=0x80000000; b!=0; b>>=1, k--)
- {
- if (map[i] & b)
- break;
- }
- start = (a & ~0x1F) + k;
- }
- if (start <= a)
- break;
- }
- return start;
-}
-
-static
-Addr_T allocate_space(Addr_T start, Addr_T size, char* id, unsigned long *map)
-{
- int i, j;
- unsigned long mask;
- Addr_T a = start;
- i = start >> 5;
- j = (start + size) >> 5;
- mask = -(1 << (start & 0x1F));
-
- while (i < j)
- {
- if (map[i] & mask)
- {
- fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
- }
- map[i++] |= mask;
- mask = 0xFFFFFFFF;
- a += 32;
- }
- mask &= (1 << ((start + size) & 0x1F)) - 1;
- if (map[i] & mask)
- {
- fprintf(stderr, "memory overlap near 0x%X for %s\n", a, id);
- }
- map[i] |= mask;
- return start;
-}
-
-Addr_T lnksect2 (struct area *tap, int locIndex)
-{
- register Addr_T size, addr;
- register struct areax *taxp;
- int j, k, ramlimit;
- char fchar=' ', dchar='a';
- char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
- " in internal RAM for area %s.\n";
-
- tap->a_unaloc=0;
-
- /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
- if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
- {
- if((iram_size<=0)||(iram_size>0x100))
- ramlimit=0x100;
- else
- ramlimit=iram_size;
- }
- else
- {
- if((iram_size<=0)||(iram_size>0x80))
- ramlimit=0x80;
- else
- ramlimit=iram_size;
- }
-
- size = 0;
- addr = tap->a_addr;
-#if 0
- if ((tap->a_flag&A_PAG) && (addr & 0xFF))
- {
- fprintf(stderr,
- "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
- lkerr++;
- }
-#endif
- taxp = tap->a_axp;
-
- /*Use a letter to identify each area in the internal RAM layout map*/
- if (locIndex==0)
- {
- /**/ if(!strcmp(tap->a_id, "DSEG"))
- fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
- else if(!strcmp(tap->a_id, "ISEG"))
- fchar='I';
- else if(!strcmp(tap->a_id, "SSEG"))
- fchar='S';
- else if(!strcmp(tap->a_id, "OSEG"))
- fchar='Q';
- else if(!strcmp(tap->a_id, "REG_BANK_0"))
- fchar='0';
- else if(!strcmp(tap->a_id, "REG_BANK_1"))
- fchar='1';
- else if(!strcmp(tap->a_id, "REG_BANK_2"))
- fchar='2';
- else if(!strcmp(tap->a_id, "REG_BANK_3"))
- fchar='3';
- else if(!strcmp(tap->a_id, "BSEG_BYTES"))
- fchar='B';
- else if(!strcmp(tap->a_id, "BIT_BANK"))
- fchar='T';
- else
- fchar=' ';/*???*/
- }
- else if (locIndex == 1)
- {
- /**/ if(!strcmp(tap->a_id, "GSINIT"))
- fchar='G';
- }
- else if (locIndex == 2)
- {
- /**/ if(!strcmp(tap->a_id, "XSTK"))
- fchar='K';
- }
-
- if (tap->a_flag&A_OVR) /* Overlayed sections */
- {
- while (taxp)
- {
- if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
- {
- addr=(fchar-'0')*8;
- taxp->a_addr=addr;
- size=taxp->a_size;
- for(j=addr; (j<(int)(addr+taxp->a_size)) && (j<ramlimit); j++)
- idatamap[j]=fchar;
- }
- else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
- {
- /*Find the size of the space currently used for this areax overlay*/
- for(j=0, size=0; j<ramlimit; j++)
- if(idatamap[j]==fchar) size++;
-
- if( (fchar=='S') && (stacksize==0) )
- {
- /*Search for the largest space available and use it for stack*/
- for(j=0, k=0, taxp->a_size=0; j<ramlimit; j++)
- {
- if(idatamap[j]==' ')
- {
- if((++k)>(int)taxp->a_size) taxp->a_size=k;
- }
- else
- {
- k=0;
- }
- }
- stacksize=taxp->a_size;
- }
-
- /*If more space required, release the previously allocated areax in
- internal RAM and search for a bigger one*/
- if((int)taxp->a_size>size)
- {
- size=(int)taxp->a_size;
-
- for(j=0; j<ramlimit; j++)
- if(idatamap[j]==fchar) idatamap[j]=' ';
-
- /*Search for a space large enough in data memory for this overlay areax*/
- for(j=0, k=0; j<ramlimit; j++)
- {
- if(idatamap[j]==' ')
- k++;
- else
- k=0;
- if(k==(int)taxp->a_size) break;
- }
-
- if(k==(int)taxp->a_size)
- {
- taxp->a_addr = j-k+1;
- if(addr<(unsigned int)ramlimit)
- {
- for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
- if(j>=0) addr=j+1;
- }
- }
-
- /*Mark the memory used for overlay*/
- if(k==(int)taxp->a_size)
- {
- for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
- idatamap[j]=fchar;
-
- /*Set the new size of the data memory area*/
- size=ramlimit-addr;
- }
- else /*Couldn't find a chunk big enough: report the problem.*/
- {
- tap->a_unaloc=taxp->a_size;
- fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
- lkerr++;
- }
- }
-
- for(j=0; j<ramlimit; j++)
- {
- if (idatamap[j]==fchar)
- {
- addr=j;
- tap->a_addr=addr;
- taxp->a_addr=addr;
- break;
- }
- }
- }
- else if (fchar=='T') /*Bit addressable bytes in internal RAM*/
- {
- /*Find the size of the space currently used for this areax overlay*/
- for(j=0x20, size=0; j<0x30; j++)
- if(idatamap[j]==fchar) size++;
-
- /*If more space required, release the previously allocated areax in
- internal RAM and search for a bigger one*/
- if((int)taxp->a_size>size)
- {
- size=(int)taxp->a_size;
-
- for(j=0x20; j<0x30; j++)
- if(idatamap[j]==fchar) idatamap[j]=' ';
-
- /*Search for a space large enough in data memory for this overlay areax*/
- for(j=0x20, k=0; j<0x30; j++)
- {
- if(idatamap[j]==' ')
- k++;
- else
- k=0;
- if(k==(int)taxp->a_size) break;
- }
-
- if(k==(int)taxp->a_size)
- {
- taxp->a_addr = j-k+1;
- if(addr<(unsigned int)0x30)
- {
- for(j=0x2F; (j>=0x20)&&(idatamap[j]==' '); j--);
- if(j>=0x20) addr=j+1;
- }
- }
-
- /*Mark the memory used for overlay*/
- if(k==(int)taxp->a_size)
- {
- for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<0x30); j++)
- idatamap[j]=fchar;
-
- /*Set the new size of the data memory area*/
- size=ramlimit-addr;
- }
- else /*Couldn't find a chunk big enough: report the problem.*/
- {
- tap->a_unaloc=taxp->a_size;
- fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
- lkerr++;
- }
- }
-
- for(j=0x20; j<0x30; j++)
- {
- if (idatamap[j]==fchar)
- {
- addr=j;
- tap->a_addr=addr;
- taxp->a_addr=addr;
- break;
- }
- }
- }
- else /*Overlay areas not in internal ram*/
- {
- taxp->a_addr = addr;
- if (taxp->a_size > size) size = taxp->a_size;
- }
- taxp = taxp->a_axp;
- }
- }
- else if (tap->a_flag & A_ABS) /* Absolute sections */
- {
- while (taxp)
- {
- if (locIndex == 0)
- {
- for (j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
- idatamap[j] = 'A';
- }
- if (locIndex == 1)
- {
- allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, codemap);
- }
- if (locIndex == 2)
- {
- allocate_space(taxp->a_addr, taxp->a_size, tap->a_id, xdatamap);
- }
- taxp->a_addr = 0; /* reset to zero so relative addresses become absolute */
- size += taxp->a_size;
- taxp = taxp->a_axp;
- }
- }
- else /* Concatenated sections */
- {
- if ((locIndex == 1) && tap->a_size)
- {
- addr = find_empty_space(addr, tap->a_size, codemap);
- }
- if ((locIndex == 2) && tap->a_size)
- {
- addr = find_empty_space(addr, tap->a_size, xdatamap);
- }
- while (taxp)
- {
- if( (fchar=='D') || (fchar=='I') )
- {
- if(taxp->a_size)
- {
- /*Search for a space large enough in internal RAM for this areax*/
- for(j=0, k=0; j<ramlimit; j++)
- {
- if(idatamap[j]==' ')
- k++;
- else
- k=0;
- if(k==(int)taxp->a_size) break;
- }
-
- if(k==(int)taxp->a_size)
- {
- taxp->a_addr = j-k+1;
- if(addr<(unsigned int)ramlimit)
- {
- for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
- if(j>=0) addr=j+1;
- size=ramlimit-addr;
- }
-
- for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
- idatamap[j]=(fchar=='D')?dchar:fchar;
- if((taxp->a_size>0)&&(fchar=='D'))dchar++;
- if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
- }
- else /*We are in trouble, there is not enough memory for an areax chunk*/
- {
- taxp->a_addr = addr;
- addr += taxp->a_size;
- size += taxp->a_size;
- tap->a_unaloc+=taxp->a_size;
- fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
- lkerr++;
- }
- }
- taxp = taxp->a_axp;
- }
- else if(fchar=='B')
- {
- if(taxp->a_size!=0)
- {
- for(j=addr; j<((int)(addr+taxp->a_size)); j++)
- idatamap[j]=fchar;
- }
-
- taxp->a_addr = addr;
- addr += taxp->a_size;
- size += taxp->a_size;
- taxp = taxp->a_axp;
- }
- else /*For concatenated BIT, CODE, and XRAM areax's*/
- {
- if((fchar=='K') && (taxp->a_size == 1))
- {
- taxp->a_size = 256-(addr & 0xFF);
- }
- //find next unused address now
- if ((locIndex == 1) && taxp->a_size)
- {
- addr = find_empty_space(addr, taxp->a_size, codemap);
- allocate_space(addr, taxp->a_size, tap->a_id, codemap);
- }
- if ((locIndex == 2) && taxp->a_size)
- {
- addr = find_empty_space(addr, taxp->a_size, xdatamap);
- allocate_space(addr, taxp->a_size, tap->a_id, xdatamap);
- }
- 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++;
- }
- if ((tap->a_flag&A_PAG) && (tap->a_size) &&
- ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
- {
- fprintf(stderr,
- "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
- lkerr++;
- }
- return addr;
-}
+++ /dev/null
-/* 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 packflag=0; /* JCF: Pack internal memory flag
- */
-int stacksize=0; /* JCF: Stack size
- */
-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 as_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, BINOP, 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
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-/* 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;
-}
-
-/*)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++;
- }
-}
+++ /dev/null
-/* 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) && (rflag) ) {
- 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 (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");
- }
- }
- }
- }
- 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;
-}
+++ /dev/null
-/* 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 as_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();
- if (c == ';')
- while (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 as_getline()
- *
- * The function as_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
- * as_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
-as_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;
-}
+++ /dev/null
-/* 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*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.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()
- *
- */
-
-#ifdef INDEXLIB
-typedef struct slibrarysymbol mlibrarysymbol;
-typedef struct slibrarysymbol *pmlibrarysymbol;
-
-struct slibrarysymbol {
- char * name; /*Warning: allocate memory before using*/
- pmlibrarysymbol next;
-};
-
-typedef struct slibraryfile mlibraryfile;
-typedef struct slibraryfile *pmlibraryfile;
-
-struct slibraryfile {
- int loaded;
- char * libspc;
- char * relfil; /*Warning: allocate memory before using*/
- char * filename; /*Warning: allocate memory before using*/
- long offset; //if > 0, the embedded file offset in the library file libspc
- pmlibrarysymbol symbols;
- pmlibraryfile next;
-};
-
-/* First entry in the library object symbol cache */
-pmlibraryfile libr=NULL;
-
-int buildlibraryindex();
-void freelibraryindex (void);
-#endif /* INDEXLIB */
-
-/*)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)
- {
- fprintf(stderr, "?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 (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\'))
- {
- strcat(str,"/");
- }
-#endif
- }
- else
- {
- str = (char *) new (strlen(libfil) + 5);
- }
-
-#ifdef OTHERSYSTEM
- if ((libfil[0] == '/') || (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) + 1);
- 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(char * libfname, 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
- {
- fprintf(stderr, "?Aslink-Error-Bad offset in library file %s(%s)\n",
- libfname, 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(PathLib, 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.
- */
-
-#ifdef INDEXLIB
-
-int fndsym( char *name )
-{
- struct lbfile *lbfh, *lbf;
- pmlibraryfile ThisLibr;
- pmlibrarysymbol ThisSym = NULL;
-
- pmlibraryfile FirstFound;
- int numfound=0;
-
- /* Build the index if this is the first call to fndsym */
- if (libr==NULL) buildlibraryindex();
-
- /* Iterate through all library object files */
- ThisLibr = libr;
- FirstFound = libr; /*So gcc stops whining*/
- while (ThisLibr)
- {
- /* Iterate through all symbols in an object file */
- ThisSym = ThisLibr->symbols;
-
- while (ThisSym)
- {
- if (!strcmp(ThisSym->name, name))
- {
- if ((!ThisLibr->loaded) && (numfound==0))
- {
- /* Object file is not loaded - add it to the list */
- 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 = ThisLibr->libspc;
- lbfh->filspc = ThisLibr->filename;
- lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
- strcpy(lbfh->relfil, ThisLibr->relfil);
- lbfh->offset = ThisLibr->offset;
- if(lbfh->offset>0)
- { /*For an embedded object file in a library*/
- void loadfile_SdccLib(char * libspc, char * module, long offset);
- loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
- }
- else
- { /*For a stand alone object file*/
- /* if cdb information required & adb file present */
- if (dflag && dfp)
- {
- FILE *xfp = afile(lbfh->filspc, "adb",0);
- if (xfp)
- {
- SaveLinkedFilePath(lbfh->filspc);
- copyfile(dfp, xfp);
- fclose(xfp);
- }
- }
- loadfile(lbfh->filspc);
- }
- ThisLibr->loaded=1;
- }
-
- if(numfound==0)
- {
- numfound++;
- FirstFound=ThisLibr;
- }
- else
- {
- char absPath1[PATH_MAX];
- char absPath2[PATH_MAX];
-#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
- int j;
-
- _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
- _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
- for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
- for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
-#else
- realpath(FirstFound->libspc, absPath1);
- realpath(ThisLibr->libspc, absPath2);
-#endif
- if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
- {
- if(numfound==1)
- {
- fprintf(stderr, "?Aslink-Warning-Definition of public symbol '%s'"
- " found more than once:\n", name);
- fprintf(stderr, " Library: '%s', Module: '%s'\n",
- FirstFound->libspc, FirstFound->relfil);
- }
- fprintf(stderr, " Library: '%s', Module: '%s'\n",
- ThisLibr->libspc, ThisLibr->relfil);
- numfound++;
- }
- }
- }
- ThisSym=ThisSym->next; /* Next sym in library */
- }
- ThisLibr=ThisLibr->next; /* Next library in list */
- }
- return numfound;
-}
-
-pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
-{
- char ModName[NCPS]="";
- char FLine[MAXLINE+1];
- char buff[PATH_MAX];
- int state=0;
- long IndexOffset=0, FileOffset;
- pmlibrarysymbol ThisSym = NULL;
-
- 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;
-
- /*Create a new libraryfile object for this module*/
- if(libr==NULL)
- {
- libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
- }
- else
- {
- This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
- This=This->next;
- }
- This->next = NULL;
- This->loaded=-1;
- This->offset=FileOffset+IndexOffset;
- This->libspc=PathLib;
-
- This->relfil=(char *)new(strlen(ModName)+1);
- strcpy(This->relfil, ModName);
-
- sprintf(buff, "%s%s%crel", DirLib, ModName, FSEPX);
- This->filename=(char *)new(strlen(buff)+1);
- strcpy(This->filename, buff);
-
- This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
- }
- else if(EQ(FLine, "</INDEX>"))
- {
- return This; /*Finish, get out of here*/
- }
- break;
- case 2:
- if(EQ(FLine, "</MODULE>"))
- {
- This->loaded=0;
- /*Create the index for the next module*/
- state=1;
- }
- else
- {
- /*Add the symbols*/
- if(ThisSym==NULL) /*First symbol of the current module*/
- {
- ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- }
- else
- {
- ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- ThisSym=ThisSym->next;
- }
- ThisSym->next=NULL;
- ThisSym->name=(char *)new(strlen(FLine)+1);
- strcpy(ThisSym->name, FLine);
- }
- break;
-
- default:
- return This; /*State machine should never reach this point, but just in case...*/
- break;
- }
- }
-
- return This; /*State machine should never reach this point, but just in case...*/
-}
-
-
-/* buildlibraryindex - build an in-memory cache of the symbols contained in
- * the libraries
- */
-int buildlibraryindex(void)
-{
- FILE *libfp, *fp;
- struct lbname *lbnh;
- char relfil[NINPUT+2], str[PATH_MAX], *path;
- char buf[NINPUT+2], c;
- char symname[NINPUT+2];
- pmlibraryfile This=NULL;
- pmlibrarysymbol ThisSym;
-
- /*
- * 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, "?Aslink-Error-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)
- {
- strcpy(str, path);
-#ifdef OTHERSYSTEM
- if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\'))
- {
- strcat(str,"/");
- }
-#endif
- }
- else
- {
- strcpy(str, "");
- }
-
- if(strcmp(relfil, "<SDCCLIB>")==0)
- {
- /*Get the built in index of this library*/
- This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
- break; /*get the index for next library*/
- }
-
- /*From here down, build the index for the original library 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)
- {
- /* Opened OK - create a new libraryfile object for it */
- if(libr==NULL)
- {
- libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
- }
- else
- {
- This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
- This=This->next;
- }
- This->next = NULL;
- This->loaded=-1;
- This->offset=-1; /*We have a stand alone .rel file*/
- This->libspc = lbnh->libspc;
-
- This->relfil=(char *)new(strlen(relfil)+1);
- strcpy(This->relfil, relfil);
-
- This->filename=(char *)new(strlen(str)+1);
- strcpy(This->filename, str);
-
- /*Start a new linked list of symbols for this module:*/
- This->symbols=ThisSym=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';
- buf[strlen(buf) - 1] = '\0';
-
- /*
- * 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 it's an actual symbol, record it */
- if (c == 'D')
- {
- if(ThisSym==NULL)
- {
- ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- }
- else
- {
- ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- ThisSym=ThisSym->next;
- }
- This->loaded=0;
- ThisSym->next=NULL;
- ThisSym->name=(char *)new(strlen(symname)+1);
- strcpy(ThisSym->name, symname);
- }
- } /* Closes while - read object file */
- fclose(fp);
- } /* Closes if object file opened OK */
- else
- {
- fprintf(stderr, "?Aslink-Warning-Cannot open library module %s\n", str);
- }
- } /* Ends while - processing all in libr */
- fclose(libfp);
- } /* Ends good open of libr file */
- return 0;
-}
-
-/*Release all memory allocated for the in-memory library index*/
-void freelibraryindex (void)
-{
- pmlibraryfile ThisLibr, ThisLibr2Free;
- pmlibrarysymbol ThisSym, ThisSym2Free;
-
- ThisLibr = libr;
-
- while (ThisLibr)
- {
- ThisSym = ThisLibr->symbols;
-
- while (ThisSym)
- {
- free(ThisSym->name);
- ThisSym2Free=ThisSym;
- ThisSym=ThisSym->next;
- free(ThisSym2Free);
- }
- free(ThisLibr->filename);
- free(ThisLibr->relfil);
- ThisLibr2Free=ThisLibr;
- ThisLibr=ThisLibr->next;
- free(ThisLibr2Free);
- }
-
- libr=NULL;
-}
-
-#else /* INDEXLIB */
-
-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, "?Aslink-Error-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 (strlen(str) && (str[strlen(str)-1] != '/') && (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);
- 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);
-}
-
-#endif /*INDEXLIB*/
-
-void loadfile_SdccLib(char * libspc, char * module, long offset)
-{
- FILE *fp;
-
- if ((fp = fopen(libspc,"r")) != NULL)
- {
- fseek(fp, offset, SEEK_SET);
- LoadRel(libspc, 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);
- }
- }
-#ifdef INDEXLIB
- freelibraryindex();
-#endif
-}
-
-/*)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);
- }
-}
+++ /dev/null
-/* 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);
-}
+++ /dev/null
-/* 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
-
-/*)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()*/
- ""
- };
-
- char * rel2[]={
- "XH",
- "H C 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()*/
- "A BIT_BANK size 0 flags 4", /*Bit register bank is overlayable*/
- "A DSEG size 0 flags 0",
- "A OSEG size 0 flags 4",
- "A ISEG size 0 flags 0",
- "A SSEG size 0 flags 4",
- ""
- };
- int j;
- struct sym * sp;
-
- if(packflag)
- {
- for (j=0; rel2[j][0]!=0; j++)
- {
- ip=rel2[j];
- link_main();
- }
- }
- else
- {
- 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; }
- else if (!strcmp(ap->a_id, "SSEG"))
- {
- if(stacksize) ap->a_axp->a_size=stacksize;
- }
- }
-
- sp = lkpsym("l_IRAM", 1);
- sp->s_addr = ((iram_size>0) && (iram_size<=0x100)) ? iram_size : 0x0100;
- sp->s_axp = NULL;
- sp->s_type |= S_DEF;
-}
-
-/*)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 functions as_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 as_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(int argc, 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 (as_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 (as_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.
- */
- if(!packflag)
- lnkarea();
- else
- lnkarea2();
- /*
- * 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(!packflag)
- {
- if(summary(areap)) lkexit(1);
- }
- else
- {
- if(summary2(areap)) lkexit(1);
- }
- }
-
- if ((iram_size) && (!packflag))
- 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(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);
- remove("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 char 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 == ';')
- return(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*/
- ++sflag;
- break;
-
- case 'Y':
- unget(getnb());
- packflag=1;
- break;
-
- case 'A':
- unget(getnb());
- if (ip && *ip)
- {
- stacksize=expr(0);
- if(stacksize>256) stacksize=256;
- else if(stacksize<0) stacksize=0;
- }
- return(0);
-
- 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':
- 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);
- }
- }
- if ( c == ';')
- return(0);
- } 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 the
- * 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 the
- * 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(char *fn, char *ft, int wf)
-{
- 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*/
- if (fb[i] != '.')
- {
- 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 = expr(0); /* evaluate size expression */
- else
- iram_size = 128; /* Default is 128 (0x80) bytes */
- if ((iram_size<=0) || (iram_size>256))
- 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",
- " -y Generate memory usage summary file[mem]",
- " -Y Pack internal ram",
- " -A [stack-size] Allocate space for stack",
- "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);
- }
-}
+++ /dev/null
-/*-------------------------------------------------------------------------
- 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, 8, 8, "REG_BANK_0", 0x0001},
- {0x8, 8, 8, "REG_BANK_1", 0x0002},
- {0x10, 8, 8, "REG_BANK_2", 0x0004},
- {0x18, 8, 8, "REG_BANK_3", 0x0008},
- {0x20, 0, 16, "BSEG_BYTES", 0x0010},
- {0, 0, 128, "UNUSED", 0x0000},
- {0x7f, 0, 128, "DATA", 0x0020},
- {0, 0, 128, "TOTAL:", 0x0000}
- };
-
- _Mem IRam= {0xff, 0, 128, "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(stacksize==0) stacksize=MIN_STACK;
-
- 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;
- }
-
- 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, "BIT_BANK"))
- {
- Ram[4].Size+=xp->a_size;
- }
-
- else if(xp->a_flag & A_CODE)
- {
- if(xp->a_size>0)
- {
- 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(xp->a_flag & A_XDATA)
- {
- if(xp->a_size>0)
- {
- 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;
- }
-
- /*If is not a register bank, bit, stack, or idata, then it should be data*/
- else if((xp->a_flag & (A_CODE|A_BIT|A_XDATA))==0)
- {
- if(xp->a_size)
- {
- Ram[6].Size+=xp->a_size;
- if(xp->a_addr<Ram[6].Start) Ram[6].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*/
-
- for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
- dram[k]|=IRam.flag; /*Mark as used*/
-
- /*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);
- }
- }
-
- 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);
- }
-
- /*Report the position of the beginning 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);
-
- /*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 ((int)k<stacksize)
- {
- sprintf(buff, "Only %d byte%s available for stack.\n",
- k, (k==1)?"":"s");
- REPORT_WARNING(buff, 1);
- }
- }
-
- fprintf(of, "\nOther memory:\n");
- fprintf(of, format, "Name", "Start", "End", "Size", "Max");
- fprintf(of, format, line, line, line, line, line);
-
- /*Report IRam totals:*/
- if(IRam.Size==0)
- {
- start[0]=0;/*Empty string*/
- end[0]=0;/*Empty string*/
- }
- else
- {
- sprintf(start, "0x%02lx", IRam.Start);
- 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:*/
- if(XRam.Size==0)
- {
- start[0]=0;/*Empty string*/
- end[0]=0;/*Empty string*/
- }
- else
- {
- sprintf(start, "0x%04lx", XRam.Start);
- 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:*/
- if(Rom.Size==0)
- {
- start[0]=0;/*Empty string*/
- end[0]=0;/*Empty string*/
- }
- else
- {
- sprintf(start, "0x%04lx", Rom.Start);
- 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((IRam.Start+IRam.Size)>(IRam.Max+0x80))
- {
- sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
- REPORT_ERROR(buff, 1);
- }
- 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;
-}
-
-extern char idatamap[]; //0:not used, 1:used
-
-
-int summary2(struct area * areap)
-{
- #define EQ(A,B) !as_strcmpi((A),(B))
-
- char buff[128];
- int toreturn = 0;
- unsigned int j;
- unsigned long int Stack_Start=0, Stack_Size;
-
- struct area * xp;
- struct area * xstack_xp = NULL;
- 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 End;
- unsigned long Size;
- unsigned long Max;
- char Name[NCPS];
- unsigned long flag;
- } _Mem;
-
- _Mem Stack={0xff, 0, 0, 1, "STACK", 0x0000};
- _Mem Paged={0xff, 0, 0, 256, "PAGED EXT. RAM", A_PAG};
- _Mem XRam= {0xffff, 0, 0, 65536, "EXTERNAL RAM", 0x0100};
- _Mem Rom= {0xffff, 0, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
-
- if(rflag) /*For the DS390*/
- {
- XRam.Max=0x1000000; /*24 bits*/
- XRam.Start=0xffffff;
- Rom.Max=0x1000000;
- Rom.Start=0xffffff;
- }
-
- /* Open Memory Summary File*/
- of = afile(linkp->f_idp, "mem", 1);
- if (of == NULL)
- {
- lkexit(1);
- }
-
- xp=areap;
- while (xp)
- {
- if(xp->a_flag & A_CODE)
- {
- if(xp->a_size)
- {
- Rom.Size += xp->a_size;
- if(xp->a_addr < Rom.Start)
- Rom.Start = xp->a_addr;
- if(xp->a_addr + xp->a_size > Rom.End)
- Rom.End = xp->a_addr + xp->a_size;
- }
- }
-
- else if (EQ(xp->a_id, "SSEG"))
- {
- Stack.Size += xp->a_size;
- if(xp->a_addr < Stack.Start)
- Stack.Start = xp->a_addr;
- if(xp->a_addr + xp->a_size > Stack.End)
- Stack.End = xp->a_addr + xp->a_size;
- }
-
- else if (EQ(xp->a_id, "PSEG"))
- {
- Paged.Size += xp->a_size;
- if(xp->a_addr < Paged.Start)
- Paged.Start = xp->a_addr;
- if(xp->a_addr + xp->a_size > Paged.End)
- Paged.End = xp->a_addr + xp->a_size;
- }
-
- else if (EQ(xp->a_id, "XSTK"))
- {
- xstack_xp = xp;
- Paged.Size += xp->a_size;
- if(xp->a_addr < Paged.Start)
- Paged.Start = xp->a_addr;
- if(xp->a_addr + xp->a_size > Paged.End)
- Paged.End = xp->a_addr + xp->a_size;
- }
-
- else if(xp->a_flag & A_XDATA)
- {
- if(xp->a_size)
- {
- XRam.Size += xp->a_size;
- if(xp->a_addr < XRam.Start)
- XRam.Start = xp->a_addr;
- if(xp->a_addr + xp->a_size > XRam.End)
- XRam.End = xp->a_addr + xp->a_size;
- }
- }
-
- xp = xp->a_ap;
- }
-
- /*Report the Ram totals*/
- fprintf(of, "Internal RAM layout:\n");
- fprintf(of, " 0 1 2 3 4 5 6 7 8 9 A B C D E F");
- for(j=0; j<256; j++)
- {
- if(j%16==0) fprintf(of, "\n0x%02x:|", j);
- fprintf(of, "%c|", idatamap[j]);
- }
- fprintf(of, "\n0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute\n");
-
- for(j=0; j<256; j++)
- {
- if(idatamap[j]=='S')
- {
- Stack_Start=j;
- break;
- }
- }
-
- for(j=Stack_Start, Stack_Size=0; j<((iram_size)?iram_size:256); j++)
- {
- if((idatamap[j]=='S')||(idatamap[j]==' ')) Stack_Size++;
- else break;
- }
-
- xp=areap;
- while (xp)
- {
- if(xp->a_unaloc>0)
- {
- fprintf(of, "\nERROR: Couldn't get %d byte%s allocated"
- " in internal RAM for area %s.",
- xp->a_unaloc, xp->a_unaloc>1?"s":"", xp->a_id);
- toreturn=1;
- }
- xp=xp->a_ap;
- }
-
- /*Report the position of the begining of the stack*/
- if(Stack_Start!=256)
- fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx) with %ld bytes available.",
- rflag ? "16 bit mode initial s" : "S", Stack_Start, Stack_Start-1, Stack_Size);
- else
- fprintf(of, "\nI don't have a clue where the stack ended up! Sorry...");
-
- /*Report about xstack*/
- if (xstack_xp)
- {
- Stack_Start = xstack_xp->a_addr;
- Stack_Size = xstack_xp->a_size;
- fprintf(of, "\nXstack starts at: 0x%04lx with %ld bytes available.",
- Stack_Start, Stack_Size);
- }
-
- fprintf(of, "\n\nOther memory:\n");
- fprintf(of, format, "Name", "Start", "End", "Size", "Max");
- fprintf(of, format, line, line, line, line, line);
-
- /*Report Paged XRam totals:*/
- if(Paged.Size==0)
- {
- start[0]=0;/*Empty string*/
- end[0]=0;/*Empty string*/
- }
- else
- {
- sprintf(start, "0x%04lx", Paged.Start);
- sprintf(end, "0x%04lx", Paged.End-1);
- }
- sprintf(size, "%5lu", Paged.Size);
- sprintf(max, "%5lu", xram_size<0 ? Paged.Max : xram_size<256 ? xram_size : 256);
- fprintf(of, format, Paged.Name, start, end, size, max);
-
- /*Report XRam totals:*/
- if(XRam.Size==0)
- {
- start[0]=0;/*Empty string*/
- end[0]=0;/*Empty string*/
- }
- else
- {
- sprintf(start, "0x%04lx", XRam.Start);
- sprintf(end, "0x%04lx", XRam.End-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:*/
- if(Rom.Size==0)
- {
- start[0]=0;/*Empty string*/
- end[0]=0;/*Empty string*/
- }
- else
- {
- sprintf(start, "0x%04lx", Rom.Start);
- sprintf(end, "0x%04lx", Rom.End-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( ((XRam.End) > XRam.Max) ||
- (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
- {
- sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
- REPORT_ERROR(buff, 1);
- }
- if( ((Rom.End) > 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;
-}
+++ /dev/null
-/* 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 );
-}
+++ /dev/null
-/* 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(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(VOID)
-{
- 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(VOID)
-{
- 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_BIT)
- {
- relv = adb_24_bit(reli, rtp);
- }
- else 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_BIT) {
- relv = adb_bit(reli, rtp);
- } else 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;
- if ((mode & R_BIT) && (relv & ~0x87FF))
- error = 5;
-
- /*
- * 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 (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;
- }
- 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",
- "Bit-addressable 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(VOID)
-{
- 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(VOID)
-{
- 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(VOID)
-{
- 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(register Addr_T v, register int i)
-{
- return(rtval[i] += v);
-}
-
-/*)Function Addr_T adb_bit(v, i)
- *
- * int v value to add to byte
- * int i rtval[] index
- *
- * The function adb_bit() converts the single
- * byte address value contained in rtval[i] to bit-
- * addressable space and adds the value of v to it.
- * The new value of rtval[i] is returned.
- *
- * local variable:
- * Addr_T j temporary evaluation variable
- *
- * global variables:
- * none
- *
- * called functions:
- * none
- *
- * side effects:
- * The value of rtval[] is changed.
- *
- */
-
-Addr_T adb_bit(register Addr_T v, register int i)
-{
- register Addr_T j;
-
- j = adb_lo(v, i) & 0xFF;
- if ((j >= 0x20) && (j <= 0x2F)) {
- j = (j - 0x20) * 8;
- } else if ((j < 0x80) || ((j & 0x07) != 0)) {
- return(0x100);//error
- }
-
- if (hilo) {
- j = rtval[i+1] = j + (rtval[i] & 0x07);
- } else {
- j = rtval[i] = j + (rtval[i+1] & 0x07);
- }
- return(j);
-}
-
-/*)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(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(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_bit(v, i)
- *
- * int v value to add to byte
- * int i rtval[] index
- *
- * The function adb_24_bit() converts the single
- * byte address value contained in rtval[i] to bit-
- * addressable space and adds the value of v to it.
- * The new value of rtval[i] is returned.
- *
- * local variable:
- * Addr_T j temporary evaluation variable
- *
- * global variables:
- * none
- *
- * called functions:
- * none
- *
- * side effects:
- * The value of rtval[] is changed.
- *
- */
-
-Addr_T adb_24_bit(register Addr_T v, register int i)
-{
- register Addr_T j;
-
- j = adb_24_lo(v, i) & 0xFF;
- if ((j >= 0x20) && (j <= 0x2F)) {
- j = (j - 0x20) * 8;
- } else if ((j < 0x80) || ((j & 0x07) != 0)) {
- return(0x100);//error
- }
-
- if (hilo) {
- j = rtval[i+2] = j + (rtval[i+1] & 0x07);
- } else {
- j = rtval[i] = j + (rtval[i+1] & 0x07);
- }
- 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(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(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(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(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(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(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(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(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);
-}
+++ /dev/null
-/* 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");
- }
-}
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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);
-}
fi
if test $OPT_DISABLE_MCS51 = 0; then
- ac_config_files="$ac_config_files src/mcs51/Makefile as/mcs51/Makefile debugger/mcs51/Makefile"
+ ac_config_files="$ac_config_files src/mcs51/Makefile as/mcs51/Makefile as/link/mcs51/Makefile debugger/mcs51/Makefile"
test $OPT_DISABLE_DEVICE_LIB = 0 && ac_config_files="$ac_config_files device/lib/mcs51/Makefile device/lib/small/Makefile device/lib/medium/Makefile device/lib/large/Makefile"
###############################################################################
-Project: "aslink"=.\as\aslink.dsp - Package Owner=<4>
+Project: "aslink"=.\as\link\mcs51\aslink.dsp - Package Owner=<4>
Package=<5>
{{{