mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-02-20 00:32:21 +01:00
copied only the required files to build link-gbz80 and included it on the makefile removing all the sdcc build
This commit is contained in:
54
Makefile
54
Makefile
@@ -26,14 +26,16 @@ TARGETSTRIP = $(TOOLSPREFIX)strip
|
||||
TARGETCXXFLAGS =
|
||||
|
||||
# Directory containing the source to sdcc
|
||||
SDCCDIR = $(TOPDIR)/sdcc
|
||||
#SDCCDIR = $(ZGB_PATH)/../env/SDCC
|
||||
#SDCCDIR = $(TOPDIR)/sdcc
|
||||
SDCCDIR = $(ZGB_PATH)/../env/SDCC
|
||||
# Directory containing the source to gbdk-lib
|
||||
GBDKLIBDIR = $(TOPDIR)/gbdk-lib
|
||||
# Directory containing the source to gbdk-support
|
||||
GBDKSUPPORTDIR = $(TOPDIR)/gbdk-support
|
||||
# Directory containing the source to maccer
|
||||
MACCERDIR = $(TOPDIR)/maccer
|
||||
# Directory containing the source to linker
|
||||
LINKERDIR = $(TOPDIR)/link
|
||||
|
||||
# Base setup
|
||||
# Extension to add to executables
|
||||
@@ -53,7 +55,7 @@ NOISELOG = $(TOPDIR)/noise.log
|
||||
|
||||
all: native-build
|
||||
|
||||
clean: maccer-clean gbdk-support-clean gbdk-lib-clean
|
||||
clean: maccer-clean linker-clean gbdk-support-clean gbdk-lib-clean
|
||||
|
||||
distclean: clean build-dir-clean
|
||||
|
||||
@@ -95,9 +97,9 @@ src: clean
|
||||
tar czf gbdk-$(VER).tar.gz gbdk
|
||||
|
||||
# Base rules
|
||||
gbdk-build: maccer-build gbdk-support-build gbdk-lib-build
|
||||
gbdk-build: maccer-build linker-build gbdk-support-build gbdk-lib-build
|
||||
|
||||
gbdk-install: gbdk-support-install gbdk-lib-install
|
||||
gbdk-install: build-bin-dir linker-install gbdk-support-install gbdk-lib-install
|
||||
|
||||
# Directories
|
||||
build-bin-dir:
|
||||
@@ -121,36 +123,7 @@ setup-from-cvs:
|
||||
cvs -d :pserver:anonymous@cvs.gbdk.sourceforge.net:/cvsroot/gbdk -q co $(CVSFLAGS) gbdk-support
|
||||
|
||||
# Rules for sdcc
|
||||
SDCCCONFIGUREFLAGS = \
|
||||
--disable-mcs51-port \
|
||||
--disable-avr-port \
|
||||
--disable-ds390-port \
|
||||
--disable-pic-port \
|
||||
--disable-i186-port \
|
||||
--disable-tlcs900h-port \
|
||||
--disable-ucsim \
|
||||
--disable-device-lib-build \
|
||||
--disable-packihx
|
||||
|
||||
SDCCCONFIGUREFLAGS += \
|
||||
--prefix=$(TARGETDIR) \
|
||||
--program-suffix=$(EXEEXTENSION)
|
||||
|
||||
sdcc-build: $(SDCCDIR)/sdccconf.h
|
||||
$(MAKE) -C $(SDCCDIR) SDCC_SUB_VERSION=$(PKG)-$(VER)
|
||||
|
||||
$(SDCCDIR)/sdccconf.h:
|
||||
cd $(SDCCDIR); CC=$(TARGETCC) CXX=$(TARGETCXX) STRIP=$(TARGETSTRIP) RANLIB=$(TARGETRANLIB) CXXFLAGS=$(TARGETCXXFLAGS) ./configure $(SDCCCONFIGUREFLAGS) --host=$(HOSTOS)
|
||||
|
||||
sdcc-install: sdcc-build build-bin-dir
|
||||
rm -fr tmp
|
||||
$(MAKE) -C $(SDCCDIR) install prefix=$(TOPDIR)/tmp
|
||||
cp tmp/bin/sdcc* tmp/bin/sdcpp* tmp/bin/link-* tmp/bin/as-* $(BUILDDIR)/bin
|
||||
|
||||
# PENDING: Hack below
|
||||
sdcc-clean:
|
||||
-$(MAKE) -C $(SDCCDIR) distclean
|
||||
touch $(SDCCDIR)/doc/holder.pdf
|
||||
|
||||
# Rules for gbdk-support
|
||||
gbdk-support-build:
|
||||
@@ -184,10 +157,21 @@ gbdk-lib-examples-makefile:
|
||||
|
||||
# Rules for maccer
|
||||
maccer-build:
|
||||
$(MAKE) -C $(MACCERDIR)
|
||||
$(MAKE) -C $(MACCERDIR) BUILDDIR=$(BUILDDIR)
|
||||
|
||||
maccer-clean:
|
||||
$(MAKE) -C $(MACCERDIR) clean
|
||||
|
||||
#rules for linker
|
||||
linker-build:
|
||||
$(MAKE) -C $(LINKERDIR)
|
||||
|
||||
linker-install:
|
||||
$(MAKE) -C $(LINKERDIR) install BUILDDIR=$(BUILDDIR)
|
||||
|
||||
linker-clean:
|
||||
$(MAKE) -C $(LINKERDIR) clean
|
||||
|
||||
|
||||
# Final binary
|
||||
binary: binary-tidyup
|
||||
|
||||
16
link/Makefile
Normal file
16
link/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
PRJDIR = ./
|
||||
|
||||
LINK_DIR = $(shell pwd)
|
||||
|
||||
include Makefile.common
|
||||
|
||||
PORTS = gbz80
|
||||
|
||||
all:
|
||||
$(MAKE) -C z80 _link-gbz80 E=$(E) BUILDDIR=../bin/
|
||||
|
||||
install: all
|
||||
$(INSTALL) $(PRJDIR)/bin/link-gbz80 `echo $(BUILDDIR)/bin/link-gbz80|sed '$(transform)'`
|
||||
$(STRIP) `echo $(BUILDDIR)/bin/link-gbz80.exe|sed '$(transform)'`
|
||||
|
||||
include clean.mk
|
||||
65
link/Makefile.common
Normal file
65
link/Makefile.common
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated automatically from Makefile.common.in by configure.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
# HACK
|
||||
PORT = mcs51
|
||||
|
||||
# Version
|
||||
VERSION = 2.3.1
|
||||
VERSIONHI = 2
|
||||
VERSIONLO = 3
|
||||
VERSIONP = 1
|
||||
|
||||
# Programs
|
||||
SHELL = /bin/sh
|
||||
CC = gcc
|
||||
CPP = gcc -E
|
||||
RANLIB = ranlib
|
||||
INSTALL = install -c
|
||||
YACC = bison -y
|
||||
LEX = flex
|
||||
AWK = gawk
|
||||
STRIP = strip
|
||||
prefix = /opt/gbdk
|
||||
exec_prefix = ${prefix}
|
||||
bindir = ${exec_prefix}/bin
|
||||
libdir = ${exec_prefix}/lib
|
||||
datadir = ${prefix}/share
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/man
|
||||
man1dir = $(mandir)/man1
|
||||
man2dir = $(mandir)/man2
|
||||
infodir = ${prefix}/info
|
||||
srcdir = .
|
||||
docdir = ${prefix}/share/doc/sdcc
|
||||
|
||||
# Modules to enable/disable
|
||||
OPT_ENABLE_UCSIM = no
|
||||
OPT_ENABLE_DEVICE_LIB_BUILD = no
|
||||
OPT_ENABLE_PACKIHX = no
|
||||
|
||||
SLIB = $(PRJDIR)/support/Util
|
||||
|
||||
transform = s,$$,,;
|
||||
|
||||
# Flags
|
||||
|
||||
DEFS = $(subs -DHAVE_CONFIG_H,,-DHAVE_CONFIG_H)
|
||||
CPPFLAGS = $(INCLUDEFLAGS) -I. -I$(PRJDIR) -I$(SLIB)
|
||||
CFLAGS = -ggdb -O2 -pipe -Wall
|
||||
M_OR_MM = -MM
|
||||
|
||||
EXTRALIBS =
|
||||
|
||||
# Shared settings between all the sub Makefiles
|
||||
# Done here so that we don't have to start a Make from the top levelport
|
||||
# directory.
|
||||
|
||||
# Library compilation options
|
||||
SCC = $(PRJDIR)/src/sdcc
|
||||
SAS = $(PRJDIR)/as/$(PORT)/as
|
||||
CLEANSPEC = *.lst *.asm *.sym *~ *.cdb *.dep *.rul
|
||||
|
||||
OBJ = $(SOURCES:.c=.o)
|
||||
8
link/README
Normal file
8
link/README
Normal file
@@ -0,0 +1,8 @@
|
||||
sdcc/link
|
||||
---------
|
||||
|
||||
In gbdk the linker and assembler were split into seperate packages.
|
||||
|
||||
For now I'm keeping that split, and leaving the mcs51 version as is.
|
||||
|
||||
-- Michael
|
||||
20
link/as/Makefile
Normal file
20
link/as/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
PRJDIR = ..
|
||||
include $(PRJDIR)/Makefile.common
|
||||
|
||||
PORTS = z80 gbz80
|
||||
DOCS = README abstra.doc appendk.txt asmlnk.doc asxhtm.html format.txt
|
||||
|
||||
all:
|
||||
$(MAKE) -C z80 _as-z80 _as-gbz80 E=$(E) BUILDDIR=../../bin/
|
||||
|
||||
install: all install-doc
|
||||
$(INSTALL) $(PRJDIR)/bin/as-z80 `echo $(bindir)/as-z80|sed '$(transform)'`
|
||||
$(STRIP) `echo $(bindir)/as-z80|sed '$(transform)'`
|
||||
$(INSTALL) $(PRJDIR)/bin/as-gbz80 `echo $(bindir)/as-gbz80|sed '$(transform)'`
|
||||
$(STRIP) `echo $(bindir)/as-gbz80|sed '$(transform)'`
|
||||
|
||||
install-doc:
|
||||
$(INSTALL) -d $(docdir)/aslink
|
||||
cp -f `find doc -maxdepth 1 -not -type d` $(docdir)/aslink
|
||||
|
||||
include clean.mk
|
||||
5
link/as/README
Normal file
5
link/as/README
Normal file
@@ -0,0 +1,5 @@
|
||||
sdcc/as
|
||||
-------
|
||||
|
||||
Both the z80 and mcs51 assemblers are derrived from the same tree. One
|
||||
day they may be re-combined.
|
||||
131
link/as/as_z80.dsp
Normal file
131
link/as/as_z80.dsp
Normal file
@@ -0,0 +1,131 @@
|
||||
# Microsoft Developer Studio Project File - Name="as_z80" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=as_z80 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "as_z80.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "as_z80.mak" CFG="as_z80 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "as_z80 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "as_z80___Win32_Debug"
|
||||
# PROP BASE Intermediate_Dir "as_z80___Win32_Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "z80"
|
||||
# PROP Intermediate_Dir "z80"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G3 /ML /W3 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /J /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\as-z80.exe" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
# Begin Target
|
||||
|
||||
# Name "as_z80 - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\asdata.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\asexpr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\aslex.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\aslist.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\asmain.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\asout.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\assubr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\assym.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\z80adr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\z80ext.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\z80mch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\z80pst.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\asm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\string.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\z80\z80.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
143
link/as/aslink.dsp
Normal file
143
link/as/aslink.dsp
Normal file
@@ -0,0 +1,143 @@
|
||||
# Microsoft Developer Studio Project File - Name="aslink" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=aslink - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "aslink.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "aslink.mak" CFG="aslink - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "aslink - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "aslink___Win32_Debug"
|
||||
# PROP BASE Intermediate_Dir "aslink___Win32_Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "mcs51"
|
||||
# PROP Intermediate_Dir "mcs51"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G3 /ML /W3 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /J /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\bin\aslink.exe" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /incremental:no /nodefaultlib
|
||||
# Begin Target
|
||||
|
||||
# Name "aslink - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkarea.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkdata.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkeval.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkhead.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkihx.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lklex.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lklibr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lklist.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkmain.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lknoice.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkrloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lks19.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lkstore.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\lksym.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\aslink.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\asm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\i8051.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\string.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
131
link/as/asx8051.dsp
Normal file
131
link/as/asx8051.dsp
Normal file
@@ -0,0 +1,131 @@
|
||||
# Microsoft Developer Studio Project File - Name="asx8051" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=asx8051 - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "asx8051.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "asx8051.mak" CFG="asx8051 - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "asx8051 - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "mcs51"
|
||||
# PROP Intermediate_Dir "mcs51"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G3 /ML /W3 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "INDEXLIB" /D "MLH_MAP" /D "SDK" /FR /J /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"\sdcc\bin\asx8051.exe" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
# Begin Target
|
||||
|
||||
# Name "asx8051 - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\asdata.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\asexpr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\aslex.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\aslist.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\asmain.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\asnoice.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\asout.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\asstore.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\assubr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\assym.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\i51adr.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\i51ext.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\i51mch.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=mcs51\i51pst.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\asm.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mcs51\i8051.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
6
link/as/clean.mk
Normal file
6
link/as/clean.mk
Normal file
@@ -0,0 +1,6 @@
|
||||
clean:
|
||||
$(MAKE) -C z80 -f clean.mk clean
|
||||
|
||||
distclean:
|
||||
$(MAKE) -C z80 -f clean.mk distclean
|
||||
|
||||
53
link/as/z80/Makefile
Normal file
53
link/as/z80/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
PRJDIR = ../..
|
||||
|
||||
include $(PRJDIR)/Makefile.common
|
||||
|
||||
OBJDIR = obj/$(EXT)
|
||||
|
||||
SDC = .
|
||||
|
||||
SLIBSRC = NewAlloc.c
|
||||
|
||||
SRC = asdata.c asexpr.c aslex.c aslist.c asmain.c asout.c \
|
||||
assubr.c assym.c z80adr.c z80ext.c z80mch.c z80pst.c
|
||||
|
||||
OBJS = $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
SLIBOBJS = $(SLIBSRC:%.c=$(OBJDIR)/%.o)
|
||||
|
||||
BINS = $(BUILDDIR)as$(EXT)
|
||||
|
||||
CFLAGS += $(CPPFLAGS) $(OPTS) -I. -DINDEXLIB -DMLH_MAP -DUNIX -DSDK
|
||||
CFLAGS += -funsigned-char
|
||||
CFLAGS += -I$(SLIB)
|
||||
|
||||
LDFLAGS += -lm $(EXTRALIBS)
|
||||
|
||||
all: $(OBJDIR) dep $(BINS)
|
||||
|
||||
dep: Makefile.dep
|
||||
|
||||
Makefile.dep: $(SRC) *.h
|
||||
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(SRC) > Makefile.dep
|
||||
|
||||
include Makefile.dep
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(BINS): $(OBJS) $(SLIBOBJS)
|
||||
$(CC) -o $(BINS) $(OBJS) $(SLIBOBJS) $(LDFLAGS)
|
||||
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: $(SLIB)/%.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
_as-z80:
|
||||
$(MAKE) EXT=-z80$(E)
|
||||
|
||||
_as-gbz80:
|
||||
$(MAKE) EXT=-gbz80$(E) OPTS=-DGAMEBOY
|
||||
|
||||
include clean.mk
|
||||
97
link/as/z80/Makefile.in
Normal file
97
link/as/z80/Makefile.in
Normal file
@@ -0,0 +1,97 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
VERSION = @VERSION@
|
||||
VERSIONHI = @VERSIONHI@
|
||||
VERSIONLO = @VERSIONLO@
|
||||
VERSIONP = @VERSIONP@
|
||||
|
||||
SHELL = /bin/sh
|
||||
CC = @CC@
|
||||
CPP = @CPP@
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
PRJDIR = ../..
|
||||
|
||||
srcdir = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
datadir = @datadir@
|
||||
includedir = @include@
|
||||
mandir = @mandir@
|
||||
man1dir = $(mandir)/man1
|
||||
man2dir = $(mandir)/man2
|
||||
infodir = @infodir@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ -I. -I$(PRJDIR)
|
||||
CFLAGS = @CFLAGS@ -Wall -DINDEXLIB -DMLH_MAP -DUNIX -DSDK -funsigned-char -ggdb
|
||||
M_OR_MM = @M_OR_MM@
|
||||
LDFLAGS = @LDFLAGS@ -lm
|
||||
|
||||
ASOBJECTS = asdata.o asexpr.o aslex.o aslist.o asmain.o asout.o \
|
||||
assubr.o assym.o z80adr.o z80ext.o z80mch.o z80pst.o
|
||||
ASSOURCES = $(patsubst %.o,%.c,$(ASOBJECTS))
|
||||
|
||||
ASXZ80 = $(PRJDIR)/bin/as-z80
|
||||
|
||||
# Compiling entire program or any subproject
|
||||
# ------------------------------------------
|
||||
all: checkconf $(ASXZ80)
|
||||
|
||||
$(ASXZ80): $(ASOBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $(ASOBJECTS) $(LDFLAGS)
|
||||
|
||||
# Compiling and installing everything and runing test
|
||||
# ---------------------------------------------------
|
||||
install: all installdirs
|
||||
$(INSTALL) $(ASXZ80) $(bindir)/as-z80
|
||||
|
||||
# Deleting all the installed files
|
||||
# --------------------------------
|
||||
uninstall:
|
||||
rm -f $(bindir)/as-z80
|
||||
|
||||
|
||||
# Performing self-test
|
||||
# --------------------
|
||||
check:
|
||||
|
||||
|
||||
# Performing installation test
|
||||
# ----------------------------
|
||||
installcheck:
|
||||
|
||||
|
||||
# Creating installation directories
|
||||
# ---------------------------------
|
||||
installdirs:
|
||||
$(INSTALL) -d $(bindir)
|
||||
|
||||
|
||||
# Creating dependencies
|
||||
# ---------------------
|
||||
dep: Makefile.dep
|
||||
|
||||
Makefile.dep: $(ASSOURCES) *.h $(PRJDIR)/*.h
|
||||
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(ASSOURCES) >Makefile.dep
|
||||
|
||||
include Makefile.dep
|
||||
include clean.mk
|
||||
|
||||
# My rules
|
||||
# --------
|
||||
.c.o:
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
|
||||
# Remaking configuration
|
||||
# ----------------------
|
||||
checkconf:
|
||||
@if [ -f $(PRJDIR)/devel ]; then\
|
||||
$(MAKE) -f conf.mk srcdir="$(srcdir)" PRJDIR="$(PRJDIR)" freshconf;\
|
||||
fi
|
||||
|
||||
# End of Makefile
|
||||
10
link/as/z80/alloc.h
Normal file
10
link/as/z80/alloc.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* alloc.h */
|
||||
/* DECUS C */
|
||||
|
||||
#ifndef SDK
|
||||
//extern char *alloc();
|
||||
//extern char *malloc();
|
||||
//extern char *calloc();
|
||||
//extern char *realloc();
|
||||
#endif
|
||||
|
||||
279
link/as/z80/asdata.c
Normal file
279
link/as/z80/asdata.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/* asdata.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm.h"
|
||||
|
||||
/*)Module asdata.c
|
||||
*
|
||||
* The module asdata.c contains the global constants,
|
||||
* structures, and variables used in the assembler.
|
||||
*/
|
||||
|
||||
int aserr; /* ASxxxx error counter
|
||||
*/
|
||||
jmp_buf jump_env; /* compiler dependent structure
|
||||
* used by setjmp() and longjmp()
|
||||
*/
|
||||
int inpfil; /* count of assembler
|
||||
* input files specified
|
||||
*/
|
||||
int incfil; /* current file handle index
|
||||
* for include files
|
||||
*/
|
||||
int cfile; /* current file handle index
|
||||
* of input assembly files
|
||||
*/
|
||||
int flevel; /* IF-ELSE-ENDIF flag will be non
|
||||
* zero for false conditional case
|
||||
*/
|
||||
int tlevel; /* current conditional level
|
||||
*/
|
||||
int ifcnd[MAXIF+1]; /* array of IF statement condition
|
||||
* values (0 = FALSE) indexed by tlevel
|
||||
*/
|
||||
int iflvl[MAXIF+1]; /* array of IF-ELSE-ENDIF flevel
|
||||
* values indexed by tlevel
|
||||
*/
|
||||
|
||||
char afn[FILSPC]; /* afile temporary file name
|
||||
*/
|
||||
char srcfn[MAXFIL][FILSPC]; /* array of source file names
|
||||
*/
|
||||
int srcline[MAXFIL]; /* source line number
|
||||
*/
|
||||
char incfn[MAXINC][FILSPC]; /* array of include file names
|
||||
*/
|
||||
int incline[MAXINC]; /* include line number
|
||||
*/
|
||||
|
||||
int radix; /* current number conversion radix:
|
||||
* 2 (binary), 8 (octal), 10 (decimal),
|
||||
* 16 (hexadecimal)
|
||||
*/
|
||||
int line; /* current assembler source
|
||||
* line number
|
||||
*/
|
||||
int page; /* current page number
|
||||
*/
|
||||
int lop; /* current line number on page
|
||||
*/
|
||||
int pass; /* assembler pass number
|
||||
*/
|
||||
int lflag; /* -l, generate listing flag
|
||||
*/
|
||||
int gflag; /* -g, make undefined symbols global flag
|
||||
*/
|
||||
int aflag; /* -a, make all symbols global flag
|
||||
*/
|
||||
int oflag; /* -o, generate relocatable output flag
|
||||
*/
|
||||
int sflag; /* -s, generate symbol table flag
|
||||
*/
|
||||
int pflag; /* -p, enable listing pagination
|
||||
*/
|
||||
int xflag; /* -x, listing radix flag
|
||||
*/
|
||||
int fflag; /* -f(f), relocations flagged flag
|
||||
*/
|
||||
Addr_T laddr; /* address of current assembler line
|
||||
* or value of .if argument
|
||||
*/
|
||||
Addr_T fuzz; /* tracks pass to pass changes in the
|
||||
* address of symbols caused by
|
||||
* variable length instruction formats
|
||||
*/
|
||||
int lmode; /* listing mode
|
||||
*/
|
||||
char *ep; /* pointer into error list
|
||||
* array eb[NERR]
|
||||
*/
|
||||
char eb[NERR]; /* array of generated error codes
|
||||
*/
|
||||
char *ip; /* pointer into the assembler-source
|
||||
* text line in ib[]
|
||||
*/
|
||||
char ib[NINPUT]; /* assembler-source text line
|
||||
*/
|
||||
char *cp; /* pointer to assembler output
|
||||
* array cb[]
|
||||
*/
|
||||
char cb[NCODE]; /* array of assembler output values
|
||||
*/
|
||||
int *cpt; /* pointer to assembler relocation type
|
||||
* output array cbt[]
|
||||
*/
|
||||
int cbt[NCODE]; /* array of assembler relocation types
|
||||
* describing the data in cb[]
|
||||
*/
|
||||
char tb[NTITL]; /* Title string buffer
|
||||
*/
|
||||
char stb[NSBTL]; /* Subtitle string buffer
|
||||
*/
|
||||
|
||||
char symtbl[] = { "Symbol Table" };
|
||||
char aretbl[] = { "Area Table" };
|
||||
|
||||
char module[NCPS]; /* module name string
|
||||
*/
|
||||
|
||||
/*
|
||||
* The mne structure is a linked list of the assembler
|
||||
* mnemonics and directives. The list of mnemonics and
|
||||
* directives contained in the device dependent file
|
||||
* xxxpst.c are hashed and linked into NHASH lists in
|
||||
* module assym.c by syminit(). The structure contains
|
||||
* the mnemonic/directive name, a subtype which directs
|
||||
* the evaluation of this mnemonic/directive, a flag which
|
||||
* is used to detect the end of the mnemonic/directive
|
||||
* list in xxxpst.c, and a value which is normally
|
||||
* associated with the assembler mnemonic base instruction
|
||||
* value.
|
||||
*
|
||||
* struct mne
|
||||
* {
|
||||
* struct mne *m_mp; Hash link
|
||||
* char m_id[NCPS]; Mnemonic
|
||||
* char m_type; Mnemonic subtype
|
||||
* char m_flag; Mnemonic flags
|
||||
* Addr_T m_valu; Value
|
||||
* };
|
||||
*/
|
||||
struct mne *mnehash[NHASH];
|
||||
|
||||
/*
|
||||
* The sym structure is a linked list of symbols defined
|
||||
* in the assembler source files. The first symbol is "."
|
||||
* defined here. The entry 'struct tsym *s_tsym'
|
||||
* links any temporary symbols following this symbol and
|
||||
* preceeding the next normal symbol. The structure also
|
||||
* contains the symbol's name, type (USER or NEW), flag
|
||||
* (global, assigned, and multiply defined), a pointer
|
||||
* to the area structure defining where the symbol is
|
||||
* located, a reference number assigned by outgsd() in
|
||||
* asout.c, and the symbols address relative to the base
|
||||
* address of the area where the symbol is located.
|
||||
*
|
||||
* struct sym
|
||||
* {
|
||||
* struct sym *s_sp; Hash link
|
||||
* struct tsym *s_tsym; Temporary symbol link
|
||||
* char s_id[NCPS]; Symbol
|
||||
* char s_type; Symbol subtype
|
||||
* char s_flag; Symbol flags
|
||||
* struct area *s_area; Area line, 0 if absolute
|
||||
* int s_ref; Ref. number
|
||||
* Addr_T s_addr; Address
|
||||
* };
|
||||
*/
|
||||
struct sym sym[] = {
|
||||
{ NULL, NULL, ".", S_USER, S_END, NULL, 0, }
|
||||
};
|
||||
|
||||
struct sym *symp; /* pointer to a symbol structure
|
||||
*/
|
||||
struct sym *symhash[NHASH]; /* array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*/
|
||||
|
||||
/*
|
||||
* The area structure contains the parameter values for a
|
||||
* specific program or data section. The area structure
|
||||
* is a linked list of areas. The initial default area
|
||||
* is "_CODE" defined here, the next area structure
|
||||
* will be linked to this structure through the structure
|
||||
* element 'struct area *a_ep'. The structure contains the
|
||||
* area name, area reference number ("_CODE" is 0) determined
|
||||
* by the order of .area directives, area size determined
|
||||
* from the total code and/or data in an area, area fuzz is
|
||||
* an variable used to track pass to pass changes in the
|
||||
* area size caused by variable length instruction formats,
|
||||
* and area flags which specify the area's relocation type.
|
||||
*
|
||||
* struct area
|
||||
* {
|
||||
* struct area *a_ap; Area link
|
||||
* char a_id[NCPS]; Area Name
|
||||
* int a_ref; Reference number
|
||||
* Addr_T a_size; Area size
|
||||
* Addr_T a_fuzz; Area fuzz
|
||||
* int a_flag; Area flags
|
||||
* };
|
||||
*/
|
||||
struct area area[] = {
|
||||
{ NULL, "_CODE", 0, 0, 0, A_CON|A_REL }
|
||||
};
|
||||
|
||||
struct area *areap; /* pointer to an area structure
|
||||
*/
|
||||
|
||||
FILE *lfp; /* list output file handle
|
||||
*/
|
||||
FILE *ofp; /* relocation output file handle
|
||||
*/
|
||||
FILE *tfp; /* symbol table output file handle
|
||||
*/
|
||||
FILE *sfp[MAXFIL]; /* array of assembler-source file handles
|
||||
*/
|
||||
FILE *ifp[MAXINC]; /* array of include-file file handles
|
||||
*/
|
||||
|
||||
/*
|
||||
* array of character types, one per
|
||||
* ASCII character
|
||||
*/
|
||||
char ctype[128] = {
|
||||
/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
|
||||
/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL,
|
||||
/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
|
||||
/*CAN*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
|
||||
/*SPC*/ SPACE, ETC, ETC, ETC, LETTER, BINOP, BINOP, ETC,
|
||||
/*(*/ ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, BINOP,
|
||||
/*0*/ DGT2, DGT2, DGT8, DGT8, DGT8, DGT8, DGT8, DGT8,
|
||||
/*8*/ DGT10, DGT10, ETC, ETC, BINOP, ETC, BINOP, ETC,
|
||||
/*@*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
|
||||
/*H*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*P*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*X*/ LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER,
|
||||
/*`*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
|
||||
/*h*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*p*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*x*/ LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC
|
||||
};
|
||||
|
||||
/*
|
||||
* an array of characters which
|
||||
* perform the case translation function
|
||||
*/
|
||||
#if CASE_SENSITIVE
|
||||
#else
|
||||
char ccase[128] = {
|
||||
/*NUL*/ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
|
||||
/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
|
||||
/*DLE*/ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
|
||||
/*CAN*/ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
|
||||
/*SPC*/ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
|
||||
/*(*/ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
|
||||
/*0*/ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
|
||||
/*8*/ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
|
||||
/*@*/ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
/*H*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
/*P*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
/*X*/ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
|
||||
/*`*/ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
/*h*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
/*p*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
/*x*/ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177'
|
||||
};
|
||||
#endif
|
||||
667
link/as/z80/asexpr.c
Normal file
667
link/as/z80/asexpr.c
Normal file
@@ -0,0 +1,667 @@
|
||||
/* asexpr.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm.h"
|
||||
|
||||
/*)Module asexpr.c
|
||||
*
|
||||
* The module asexpr.c contains the routines to evaluate
|
||||
* arithmetic/numerical expressions. The functions in
|
||||
* asexpr.c perform a recursive evaluation of the arithmetic
|
||||
* expression read from the assembler-source text line.
|
||||
* The expression may include binary/unary operators, brackets,
|
||||
* symbols, labels, and constants in hexadecimal, decimal, octal
|
||||
* and binary. Arithmetic operations are prioritized and
|
||||
* evaluated by normal arithmetic conventions.
|
||||
*
|
||||
* asexpr.c contains the following functions:
|
||||
* VOID abscheck()
|
||||
* Addr_T absexpr()
|
||||
* VOID clrexpr()
|
||||
* int digit()
|
||||
* VOID expr()
|
||||
* int oprio()
|
||||
* VOID term()
|
||||
*
|
||||
* asexpr.c contains no local/static variables
|
||||
*/
|
||||
|
||||
/*)Function VOID expr(esp, n)
|
||||
*
|
||||
* expr * esp pointer to an expr structure
|
||||
* int n a firewall priority; all top
|
||||
* level calls (from the user)
|
||||
* should be made with n set to 0.
|
||||
*
|
||||
* The function expr() evaluates an expression and
|
||||
* stores its value and relocation information into
|
||||
* the expr structure supplied by the user.
|
||||
*
|
||||
* local variables:
|
||||
* int c current assembler-source
|
||||
* text character
|
||||
* int p current operator priority
|
||||
* area * ap pointer to an area structure
|
||||
* exp re internal expr structure
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] array of character types, one per
|
||||
* ASCII character
|
||||
*
|
||||
* functions called:
|
||||
* VOID abscheck() asexpr.c
|
||||
* VOID clrexpr() asexpr.c
|
||||
* VOID expr() asexpr.c
|
||||
* int getnb() aslex.c
|
||||
* int oprio() asexpr.c
|
||||
* VOID qerr() assubr.c
|
||||
* VOID rerr() assubr.c
|
||||
* VOID term() asexpr.c
|
||||
* VOID unget() aslex.c
|
||||
*
|
||||
*
|
||||
* side effects:
|
||||
* An expression is evaluated modifying the user supplied
|
||||
* expr structure, a sym structure maybe created for an
|
||||
* undefined symbol, and the parse of the expression may
|
||||
* terminate if a 'q' error occurs.
|
||||
*/
|
||||
|
||||
VOID
|
||||
expr(esp, n)
|
||||
register struct expr *esp;
|
||||
int n;
|
||||
{
|
||||
register int c, p;
|
||||
struct area *ap;
|
||||
struct expr re;
|
||||
|
||||
term(esp);
|
||||
while (ctype[c = getnb()] & BINOP) {
|
||||
/*
|
||||
* Handle binary operators + - * / & | % ^ << >>
|
||||
*/
|
||||
if ((p = oprio(c)) <= n)
|
||||
break;
|
||||
if ((c == '>' || c == '<') && c != get())
|
||||
qerr();
|
||||
clrexpr(&re);
|
||||
expr(&re, p);
|
||||
esp->e_rlcf |= re.e_rlcf;
|
||||
if (c == '+') {
|
||||
/*
|
||||
* esp + re, at least one must be absolute
|
||||
*/
|
||||
if (esp->e_base.e_ap == NULL) {
|
||||
/*
|
||||
* esp is absolute (constant),
|
||||
* use area from re
|
||||
*/
|
||||
esp->e_base.e_ap = re.e_base.e_ap;
|
||||
} else
|
||||
if (re.e_base.e_ap) {
|
||||
/*
|
||||
* re should be absolute (constant)
|
||||
*/
|
||||
rerr();
|
||||
}
|
||||
if (esp->e_flag && re.e_flag)
|
||||
rerr();
|
||||
if (re.e_flag)
|
||||
esp->e_flag = 1;
|
||||
esp->e_addr += re.e_addr;
|
||||
} else
|
||||
if (c == '-') {
|
||||
/*
|
||||
* esp - re
|
||||
*/
|
||||
if ((ap = re.e_base.e_ap) != NULL) {
|
||||
if (esp->e_base.e_ap == ap) {
|
||||
esp->e_base.e_ap = NULL;
|
||||
} else {
|
||||
rerr();
|
||||
}
|
||||
}
|
||||
if (re.e_flag)
|
||||
rerr();
|
||||
esp->e_addr -= re.e_addr;
|
||||
} else {
|
||||
/*
|
||||
* Both operands (esp and re) must be constants
|
||||
*/
|
||||
abscheck(esp);
|
||||
abscheck(&re);
|
||||
switch (c) {
|
||||
|
||||
case '*':
|
||||
esp->e_addr *= re.e_addr;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
esp->e_addr /= re.e_addr;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
esp->e_addr &= re.e_addr;
|
||||
break;
|
||||
|
||||
case '|':
|
||||
esp->e_addr |= re.e_addr;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
esp->e_addr %= re.e_addr;
|
||||
break;
|
||||
|
||||
case '^':
|
||||
esp->e_addr ^= re.e_addr;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
esp->e_addr <<= re.e_addr;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
esp->e_addr >>= re.e_addr;
|
||||
break;
|
||||
|
||||
default:
|
||||
qerr();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
unget(c);
|
||||
}
|
||||
|
||||
/*)Function Addr_T absexpr()
|
||||
*
|
||||
* The function absexpr() evaluates an expression, verifies it
|
||||
* is absolute (i.e. not position dependent or relocatable), and
|
||||
* returns its value.
|
||||
*
|
||||
* local variables:
|
||||
* expr e expr structure
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* VOID abscheck() asexpr.c
|
||||
* VOID clrexpr() asexpr.c
|
||||
* VOID expr() asexpr.c
|
||||
*
|
||||
* side effects:
|
||||
* If the expression is not absolute then
|
||||
* a 'r' error is reported.
|
||||
*/
|
||||
|
||||
Addr_T
|
||||
absexpr()
|
||||
{
|
||||
struct expr e;
|
||||
|
||||
clrexpr(&e);
|
||||
expr(&e, 0);
|
||||
abscheck(&e);
|
||||
return (e.e_addr);
|
||||
}
|
||||
|
||||
/*)Function VOID term(esp)
|
||||
*
|
||||
* expr * esp pointer to an expr structure
|
||||
*
|
||||
* The function term() evaluates a single constant
|
||||
* or symbol value prefaced by any unary operator
|
||||
* ( +, -, ~, ', ", >, or < ). This routine is also
|
||||
* responsible for setting the relocation type to symbol
|
||||
* based (e.flag != 0) on global references.
|
||||
*
|
||||
* local variables:
|
||||
* int c current character
|
||||
* char id[] symbol name
|
||||
* char * jp pointer to assembler-source text
|
||||
* int n constant evaluation running sum
|
||||
* int r current evaluation radix
|
||||
* sym * sp pointer to a sym structure
|
||||
* tsym * tp pointer to a tsym structure
|
||||
* int v current digit evaluation
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] array of character types, one per
|
||||
* ASCII character
|
||||
* sym * symp pointer to a symbol structure
|
||||
*
|
||||
* functions called:
|
||||
* VOID abscheck() asexpr.c
|
||||
* int digit() asexpr.c
|
||||
* VOID err() assubr.c
|
||||
* VOID expr() asexpr.c
|
||||
* int is_abs() asexpr.c
|
||||
* int get() aslex.c
|
||||
* VOID getid() aslex.c
|
||||
* int getmap() aslex.c
|
||||
* int getnb() aslex.c
|
||||
* sym * lookup() assym.c
|
||||
* VOID qerr() assubr.c
|
||||
* VOID unget() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* An arithmetic term is evaluated, a symbol structure
|
||||
* may be created, term evaluation may be terminated
|
||||
* by a 'q' error.
|
||||
*/
|
||||
|
||||
VOID
|
||||
term(esp)
|
||||
register struct expr *esp;
|
||||
{
|
||||
register int c, n;
|
||||
register char *jp;
|
||||
char id[NCPS];
|
||||
struct sym *sp;
|
||||
struct tsym *tp;
|
||||
int r = 0, v;
|
||||
|
||||
c = getnb();
|
||||
/*
|
||||
* Discard the unary '+' at this point and
|
||||
* also any reference to numerical arguments
|
||||
* associated with the '#' prefix.
|
||||
*/
|
||||
while (c == '+' || c == '#') { c = getnb(); }
|
||||
/*
|
||||
* Evaluate all binary operators
|
||||
* by recursively calling expr().
|
||||
*/
|
||||
if (c == LFTERM) {
|
||||
expr(esp, 0);
|
||||
if (getnb() != RTTERM)
|
||||
qerr();
|
||||
return;
|
||||
}
|
||||
if (c == '-') {
|
||||
expr(esp, 100);
|
||||
abscheck(esp);
|
||||
esp->e_addr = 0 - esp->e_addr;
|
||||
return;
|
||||
}
|
||||
if (c == '~') {
|
||||
expr(esp, 100);
|
||||
abscheck(esp);
|
||||
esp->e_addr = ~esp->e_addr;
|
||||
return;
|
||||
}
|
||||
if (c == '\'') {
|
||||
esp->e_mode = S_USER;
|
||||
esp->e_addr = getmap(-1)&0377;
|
||||
return;
|
||||
}
|
||||
if (c == '\"') {
|
||||
esp->e_mode = S_USER;
|
||||
if (hilo) {
|
||||
esp->e_addr = (getmap(-1)&0377)<<8;
|
||||
esp->e_addr |= (getmap(-1)&0377);
|
||||
} else {
|
||||
esp->e_addr = (getmap(-1)&0377);
|
||||
esp->e_addr |= (getmap(-1)&0377)<<8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (c == '>' || c == '<') {
|
||||
expr(esp, 100);
|
||||
if (is_abs (esp)) {
|
||||
/*
|
||||
* evaluate msb/lsb directly
|
||||
*/
|
||||
if (c == '>')
|
||||
esp->e_addr >>= 8;
|
||||
esp->e_addr &= 0377;
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* let linker perform msb/lsb, lsb is default
|
||||
*/
|
||||
esp->e_rlcf |= R_BYT2;
|
||||
if (c == '>')
|
||||
esp->e_rlcf |= R_MSB;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Evaluate digit sequences as local symbols
|
||||
* if followed by a '$' or as constants.
|
||||
*/
|
||||
if (ctype[c] & DIGIT) {
|
||||
esp->e_mode = S_USER;
|
||||
jp = ip;
|
||||
while (ctype[(unsigned char)(*jp)] & RAD10) {
|
||||
jp++;
|
||||
}
|
||||
if (*jp == '$') {
|
||||
n = 0;
|
||||
while ((v = digit(c, 10)) >= 0) {
|
||||
n = 10*n + v;
|
||||
c = get();
|
||||
}
|
||||
tp = symp->s_tsym;
|
||||
while (tp) {
|
||||
if (n == tp->t_num) {
|
||||
esp->e_base.e_ap = tp->t_area;
|
||||
esp->e_addr = tp->t_addr;
|
||||
return;
|
||||
}
|
||||
tp = tp->t_lnk;
|
||||
}
|
||||
err('u');
|
||||
return;
|
||||
}
|
||||
r = radix;
|
||||
if (c == '0') {
|
||||
c = get();
|
||||
switch (c) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
r = 2;
|
||||
c = get();
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
case 'q':
|
||||
case 'Q':
|
||||
r = 8;
|
||||
c = get();
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
r = 10;
|
||||
c = get();
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
case 'x':
|
||||
case 'X':
|
||||
r = 16;
|
||||
c = get();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
n = 0;
|
||||
while ((v = digit(c, r)) >= 0) {
|
||||
n = r*n + v;
|
||||
c = get();
|
||||
}
|
||||
unget(c);
|
||||
esp->e_addr = n;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Evaluate '$' sequences as a temporary radix
|
||||
* if followed by a '%', '&', '#', or '$'.
|
||||
*/
|
||||
if (c == '$') {
|
||||
c = get();
|
||||
if (c == '%' || c == '&' || c == '#' || c == '$') {
|
||||
switch (c) {
|
||||
case '%':
|
||||
r = 2;
|
||||
break;
|
||||
case '&':
|
||||
r = 8;
|
||||
break;
|
||||
case '#':
|
||||
r = 10;
|
||||
break;
|
||||
case '$':
|
||||
r = 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
c = get();
|
||||
n = 0;
|
||||
while ((v = digit(c, r)) >= 0) {
|
||||
n = r*n + v;
|
||||
c = get();
|
||||
}
|
||||
unget(c);
|
||||
esp->e_mode = S_USER;
|
||||
esp->e_addr = n;
|
||||
return;
|
||||
}
|
||||
unget(c);
|
||||
c = '$';
|
||||
}
|
||||
/*
|
||||
* Evaluate symbols and labels
|
||||
*/
|
||||
if (ctype[c] & LETTER) {
|
||||
esp->e_mode = S_USER;
|
||||
getid(id, c);
|
||||
sp = lookup(id);
|
||||
if (sp->s_type == S_NEW) {
|
||||
if (sp->s_flag&S_GBL) {
|
||||
esp->e_flag = 1;
|
||||
esp->e_base.e_sp = sp;
|
||||
return;
|
||||
}
|
||||
err('u');
|
||||
} else {
|
||||
esp->e_mode = sp->s_type;
|
||||
esp->e_addr = sp->s_addr;
|
||||
esp->e_base.e_ap = sp->s_area;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Else not a term.
|
||||
*/
|
||||
qerr();
|
||||
}
|
||||
|
||||
/*)Function int digit(c, r)
|
||||
*
|
||||
* int c digit character
|
||||
* int r current radix
|
||||
*
|
||||
* The function digit() returns the value of c
|
||||
* in the current radix r. If the c value is not
|
||||
* a number of the current radix then a -1 is returned.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] array of character types, one per
|
||||
* ASCII character
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*/
|
||||
|
||||
int
|
||||
digit(c, r)
|
||||
register int c, r;
|
||||
{
|
||||
if (r == 16) {
|
||||
if (ctype[c] & RAD16) {
|
||||
if (c >= 'A' && c <= 'F')
|
||||
return (c - 'A' + 10);
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return (c - 'a' + 10);
|
||||
return (c - '0');
|
||||
}
|
||||
} else
|
||||
if (r == 10) {
|
||||
if (ctype[c] & RAD10)
|
||||
return (c - '0');
|
||||
} else
|
||||
if (r == 8) {
|
||||
if (ctype[c] & RAD8)
|
||||
return (c - '0');
|
||||
} else
|
||||
if (r == 2) {
|
||||
if (ctype[c] & RAD2)
|
||||
return (c - '0');
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*)Function VOID abscheck(esp)
|
||||
*
|
||||
* expr * esp pointer to an expr structure
|
||||
*
|
||||
* The function abscheck() tests the evaluation of an
|
||||
* expression to verify it is absolute. If the evaluation
|
||||
* is relocatable then an 'r' error is noted and the expression
|
||||
* made absolute.
|
||||
*
|
||||
* Note: The area type (i.e. ABS) is not checked because
|
||||
* the linker can be told to explicitly relocate an
|
||||
* absolute area.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* VOID rerr() assubr.c
|
||||
*
|
||||
* side effects:
|
||||
* The expression may be changed to absolute and the
|
||||
* 'r' error invoked.
|
||||
*/
|
||||
|
||||
VOID
|
||||
abscheck(esp)
|
||||
register struct expr *esp;
|
||||
{
|
||||
if (esp->e_flag || esp->e_base.e_ap) {
|
||||
esp->e_flag = 0;
|
||||
esp->e_base.e_ap = NULL;
|
||||
rerr();
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function int is_abs(esp)
|
||||
*
|
||||
* expr * esp pointer to an expr structure
|
||||
*
|
||||
* The function is_abs() tests the evaluation of an
|
||||
* expression to verify it is absolute. If the evaluation
|
||||
* is absolute then 1 is returned, else 0 is returned.
|
||||
*
|
||||
* Note: The area type (i.e. ABS) is not checked because
|
||||
* the linker can be told to explicitly relocate an
|
||||
* absolute area.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*/
|
||||
|
||||
int
|
||||
is_abs (esp)
|
||||
register struct expr *esp;
|
||||
{
|
||||
if (esp->e_flag || esp->e_base.e_ap) {
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*)Function int oprio(c)
|
||||
*
|
||||
* int c operator character
|
||||
*
|
||||
* The function oprio() returns a relative priority
|
||||
* for all valid unary and binary operators.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*/
|
||||
|
||||
int
|
||||
oprio(c)
|
||||
register int c;
|
||||
{
|
||||
if (c == '*' || c == '/' || c == '%')
|
||||
return (10);
|
||||
if (c == '+' || c == '-')
|
||||
return (7);
|
||||
if (c == '<' || c == '>')
|
||||
return (5);
|
||||
if (c == '^')
|
||||
return (4);
|
||||
if (c == '&')
|
||||
return (3);
|
||||
if (c == '|')
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*)Function VOID clrexpr(esp)
|
||||
*
|
||||
* expr * esp pointer to expression structure
|
||||
*
|
||||
* The function clrexpr() clears the expression structure.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* expression structure cleared.
|
||||
*/
|
||||
|
||||
VOID
|
||||
clrexpr(esp)
|
||||
register struct expr *esp;
|
||||
{
|
||||
esp->e_mode = 0;
|
||||
esp->e_flag = 0;
|
||||
esp->e_addr = 0;
|
||||
esp->e_base.e_ap = NULL;
|
||||
esp->e_rlcf = 0;
|
||||
}
|
||||
502
link/as/z80/aslex.c
Normal file
502
link/as/z80/aslex.c
Normal file
@@ -0,0 +1,502 @@
|
||||
/* aslex.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber, M. Hope
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm.h"
|
||||
|
||||
/*)Module aslex.c
|
||||
*
|
||||
* The module aslex.c includes the general lexical
|
||||
* analysis routines for the assembler.
|
||||
*
|
||||
* aslex.c contains the following functions:
|
||||
* char endline()
|
||||
* char get()
|
||||
* VOID getid(id,c)
|
||||
* int getLine_()
|
||||
* int getmap()
|
||||
* char getnb()
|
||||
* VOID getst()
|
||||
* int more()
|
||||
* VOID unget(c)
|
||||
*
|
||||
* aslex.c contains no local/static variables
|
||||
*/
|
||||
|
||||
/*)Function VOID getid(id,c)
|
||||
*
|
||||
* char * id a pointer to a string of
|
||||
* maximum length NCPS
|
||||
* int c mode flag
|
||||
* >=0 this is first character to
|
||||
* copy to the string buffer
|
||||
* <0 skip white space, first
|
||||
* character must be a LETTER
|
||||
*
|
||||
* The function getid() scans the current assembler-source text line
|
||||
* from the current position copying the next LETTER | DIGIT string
|
||||
* into the external string buffer (id). The string ends when a non
|
||||
* LETTER or DIGIT character is found. The maximum number of
|
||||
* characters copied is NCPS. If the input string is larger than
|
||||
* NCPS characters then the string is truncated, if the input string
|
||||
* is shorter than NCPS characters then the string is NULL filled.
|
||||
* If the mode argument (c) is >=0 then (c) is the first character
|
||||
* copied to the string buffer, if (c) is <0 then intervening white
|
||||
* space (SPACES and TABS) are skipped and the first character found
|
||||
* must be a LETTER else a 'q' error terminates the parse of this
|
||||
* assembler-source text line.
|
||||
*
|
||||
* local variables:
|
||||
* char * p pointer to external string buffer
|
||||
* int c current character value
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] a character array which defines the
|
||||
* type of character being processed.
|
||||
* This index is the character
|
||||
* being processed.
|
||||
*
|
||||
* called functions:
|
||||
* char get() aslex.c
|
||||
* char getnb() aslex.c
|
||||
* VOID unget() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of getnb(), get(), and unget() updates the
|
||||
* global pointer ip, the position in the current
|
||||
* assembler-source text line.
|
||||
*/
|
||||
|
||||
VOID
|
||||
getid(id, c)
|
||||
register int c;
|
||||
char *id;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (c < 0) {
|
||||
c = getnb();
|
||||
if ((ctype[c] & LETTER) == 0)
|
||||
qerr();
|
||||
}
|
||||
p = id;
|
||||
do {
|
||||
if (p < &id[NCPS])
|
||||
*p++ = c;
|
||||
} while (ctype[c=get()] & (LETTER|DIGIT));
|
||||
unget(c);
|
||||
while (p < &id[NCPS])
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/*)Function VOID getst(id,c)
|
||||
*
|
||||
* char * id a pointer to a string of
|
||||
* maximum length NCPS
|
||||
* int c mode flag
|
||||
* >=0 this is first character to
|
||||
* copy to the string buffer
|
||||
* <0 skip white space, first
|
||||
* character must be a LETTER
|
||||
*
|
||||
* The function getnbid() scans the current assembler-source text line
|
||||
* from the current position copying the next character string into
|
||||
* the external string buffer (id). The string ends when a SPACE or
|
||||
* ILL character is found. The maximum number of
|
||||
* characters copied is NCPS. If the input string is larger than
|
||||
* NCPS characters then the string is truncated, if the input string
|
||||
* is shorter than NCPS characters then the string is NULL filled.
|
||||
* If the mode argument (c) is >=0 then (c) is the first character
|
||||
* copied to the string buffer, if (c) is <0 then intervening white
|
||||
* space (SPACES and TABS) are skipped and the first character found
|
||||
* must be a LETTER else a 'q' error terminates the parse of this
|
||||
* assembler-source text line.
|
||||
*
|
||||
* local variables:
|
||||
* char * p pointer to external string buffer
|
||||
* int c current character value
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] a character array which defines the
|
||||
* type of character being processed.
|
||||
* This index is the character
|
||||
* being processed.
|
||||
*
|
||||
* called functions:
|
||||
* char get() aslex.c
|
||||
* char getnb() aslex.c
|
||||
* VOID unget() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of getnb(), get(), and unget() updates the
|
||||
* global pointer ip, the position in the current
|
||||
* assembler-source text line.
|
||||
*/
|
||||
|
||||
VOID
|
||||
getst(id, c)
|
||||
register int c;
|
||||
char *id;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (c < 0) {
|
||||
c = getnb();
|
||||
if ((ctype[c] & LETTER) == 0)
|
||||
qerr();
|
||||
}
|
||||
p = id;
|
||||
do {
|
||||
if (p < &id[NCPS])
|
||||
*p++ = c;
|
||||
} while (ctype[c=get()] & ~(SPACE|ILL));
|
||||
unget(c);
|
||||
while (p < &id[NCPS])
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/*)Function char getnb()
|
||||
*
|
||||
* The function getnb() scans the current assembler-source
|
||||
* text line returning the first character not a SPACE or TAB.
|
||||
*
|
||||
* local variables:
|
||||
* int c current character from
|
||||
* assembler-source text line
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* called functions:
|
||||
* char get() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of get() updates the global pointer ip, the position
|
||||
* in the current assembler-source text line
|
||||
*/
|
||||
|
||||
char
|
||||
getnb()
|
||||
{
|
||||
register int c;
|
||||
|
||||
while ((c=get()) == ' ' || c == '\t')
|
||||
;
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*)Function char get()
|
||||
*
|
||||
* The function get() returns the next character in the
|
||||
* assembler-source text line, at the end of the line a
|
||||
* NULL character is returned.
|
||||
*
|
||||
* local variables:
|
||||
* int c current character from
|
||||
* assembler-source text line
|
||||
*
|
||||
* global variables:
|
||||
* char * ip pointer into the current
|
||||
* assembler-source text line
|
||||
*
|
||||
* called functions:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* updates ip to the next character position in the
|
||||
* assembler-source text line. If ip is at the end of the
|
||||
* line, ip is not updated.
|
||||
*/
|
||||
|
||||
char
|
||||
get()
|
||||
{
|
||||
register int c;
|
||||
|
||||
if ((c = *ip) != 0)
|
||||
++ip;
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*)Function VOID unget(c)
|
||||
*
|
||||
* int c value of last character read from
|
||||
* assembler-source text line
|
||||
*
|
||||
* If (c) is not a NULL character then the global pointer ip
|
||||
* is updated to point to the preceeding character in the
|
||||
* assembler-source text line.
|
||||
*
|
||||
* NOTE: This function does not push the character (c)
|
||||
* back into the assembler-source text line, only
|
||||
* the pointer ip is changed.
|
||||
*
|
||||
* local variables:
|
||||
* int c last character read from
|
||||
* assembler-source text line
|
||||
*
|
||||
* global variables:
|
||||
* char * ip position into the current
|
||||
* assembler-source text line
|
||||
*
|
||||
* called functions:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* ip decremented by 1 character position
|
||||
*/
|
||||
|
||||
VOID
|
||||
unget(c)
|
||||
{
|
||||
if (c)
|
||||
if (ip != ib)
|
||||
--ip;
|
||||
}
|
||||
|
||||
/*)Function int getmap(d)
|
||||
*
|
||||
* int d value to compare with the
|
||||
* assembler-source text line character
|
||||
*
|
||||
* The function getmap() converts the 'C' style characters \b, \f,
|
||||
* \n, \r, and \t to their equivalent ascii values and also
|
||||
* converts 'C' style octal constants '\123' to their equivalent
|
||||
* numeric values. If the first character is equivalent to (d) then
|
||||
* a (-1) is returned, if the end of the line is detected then
|
||||
* a 'q' error terminates the parse for this line, or if the first
|
||||
* character is not a \ then the character value is returned.
|
||||
*
|
||||
* local variables:
|
||||
* int c value of character from the
|
||||
* assembler-source text line
|
||||
* int n looping counter
|
||||
* int v current value of numeric conversion
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* called functions:
|
||||
* char get() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of get() updates the global pointer ip the position
|
||||
* in the current assembler-source text line
|
||||
*/
|
||||
|
||||
int
|
||||
getmap(d)
|
||||
{
|
||||
register int c, n, v;
|
||||
|
||||
if ((c=get()) == '\0')
|
||||
qerr();
|
||||
if (c == d)
|
||||
return (-1);
|
||||
if (c == '\\') {
|
||||
c = get();
|
||||
switch (c) {
|
||||
|
||||
case 'b':
|
||||
c = '\b';
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
c = '\f';
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
c = '\r';
|
||||
break;
|
||||
|
||||
case 't':
|
||||
c = '\t';
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
n = 0;
|
||||
v = 0;
|
||||
while (++n<=3 && c>='0' && c<='7') {
|
||||
v = (v<<3) + c - '0';
|
||||
c = get();
|
||||
}
|
||||
unget(c);
|
||||
c = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*)Function int getLine_()
|
||||
*
|
||||
* The function getLine_() reads a line of assembler-source text
|
||||
* from an assembly source text file or an include file.
|
||||
* Lines of text are processed from assembler-source files until
|
||||
* all files have been read. If an include file is opened then
|
||||
* lines of text are read from the include file (or nested
|
||||
* include file) until the end of the include file is found.
|
||||
* The input text line is copied into the global string ib[]
|
||||
* and converted to a NULL terminated string. The function
|
||||
* getLine_() returns a (1) after succesfully reading a line
|
||||
* or a (0) if all files have been read.
|
||||
*
|
||||
* local variables:
|
||||
* int i string length
|
||||
*
|
||||
* global variables:
|
||||
* char ib[] string buffer containing
|
||||
* assembler-source text line
|
||||
* char ifp[] array of file handles for
|
||||
* include files
|
||||
* int incfil index for ifp[] specifies
|
||||
* active include file
|
||||
* int incline[] array of include file
|
||||
* line numbers
|
||||
* char sfp[] array of file handles for
|
||||
* assembler source files
|
||||
* int cfile index for sfp[] specifies
|
||||
* active source file
|
||||
* int srcline[] array of source file
|
||||
* line numbers
|
||||
* int inpfil maximum input file index
|
||||
*
|
||||
* called functions:
|
||||
* int fclose() c-library
|
||||
* char * fgets() c-library
|
||||
* int strlen() c-library
|
||||
*
|
||||
* side effects:
|
||||
* include file will be closed at detection of end of file.
|
||||
* the next sequential source file may be selected.
|
||||
* the global file indexes incfil or cfile may be changed.
|
||||
* The respective source line or include line counter
|
||||
* will be updated.
|
||||
*/
|
||||
|
||||
int
|
||||
getLine_()
|
||||
{
|
||||
register int i;
|
||||
|
||||
loop: if (incfil >= 0) {
|
||||
if (fgets(ib, sizeof ib, ifp[incfil]) == NULL) {
|
||||
#ifdef SDK
|
||||
fclose(ifp[incfil]);
|
||||
ifp[incfil--] = NULL;
|
||||
#else /* SDK */
|
||||
fclose(ifp[incfil--]);
|
||||
#endif /* SDK */
|
||||
lop = NLPP;
|
||||
goto loop;
|
||||
} else {
|
||||
++incline[incfil];
|
||||
}
|
||||
} else {
|
||||
if (fgets(ib, sizeof ib, sfp[cfile]) == NULL) {
|
||||
if (++cfile <= inpfil) {
|
||||
srcline[cfile] = 0;
|
||||
goto loop;
|
||||
}
|
||||
return (0);
|
||||
} else {
|
||||
++srcline[cfile];
|
||||
}
|
||||
}
|
||||
i = strlen(ib) - 1;
|
||||
if (ib[i] == '\n')
|
||||
ib[i] = 0;
|
||||
if (i >= 1 && ib[i-1] == '\r')
|
||||
ib[i-1] = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*)Function int more()
|
||||
*
|
||||
* The function more() scans the assembler-source text line
|
||||
* skipping white space (SPACES and TABS) and returns a (0)
|
||||
* if the end of the line or a comment delimeter (;) is found,
|
||||
* or a (1) if their are additional characters in the line.
|
||||
*
|
||||
* local variables:
|
||||
* int c next character from the
|
||||
* assembler-source text line
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* called functions:
|
||||
* char getnb() aslex.c
|
||||
* VOID unget() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of getnb() and unget() updates the global pointer ip
|
||||
* the position in the current assembler-source text line
|
||||
*/
|
||||
|
||||
int
|
||||
more()
|
||||
{
|
||||
register int c;
|
||||
|
||||
c = getnb();
|
||||
unget(c);
|
||||
return( (c == '\0' || c == ';') ? 0 : 1 );
|
||||
}
|
||||
|
||||
/*)Function char endline()
|
||||
*
|
||||
* The function endline() scans the assembler-source text line
|
||||
* skipping white space (SPACES and TABS) and returns the next
|
||||
* character or a (0) if the end of the line is found or a
|
||||
* comment delimiter (;) is found.
|
||||
*
|
||||
* local variables:
|
||||
* int c next character from the
|
||||
* assembler-source text line
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* called functions:
|
||||
* char getnb() aslex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of getnb() updates the global pointer ip the
|
||||
* position in the current assembler-source text line
|
||||
*/
|
||||
|
||||
char
|
||||
endline()
|
||||
{
|
||||
register int c;
|
||||
|
||||
c = getnb();
|
||||
return( (c == '\0' || c == ';') ? 0 : c );
|
||||
}
|
||||
810
link/as/z80/aslist.c
Normal file
810
link/as/z80/aslist.c
Normal file
@@ -0,0 +1,810 @@
|
||||
/* aslist.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/malloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "asm.h"
|
||||
|
||||
/*)Module aslist.c
|
||||
*
|
||||
* The module aslist.c contains all the functions used
|
||||
* to generate the assembler list and symbol output files.
|
||||
*
|
||||
* aslist.c contains the following functions:
|
||||
* VOID list()
|
||||
* VOID list1()
|
||||
* VOID list2()
|
||||
* VOID slew()
|
||||
* VOID lstsym()
|
||||
*
|
||||
* The module aslist.c contains no local/static variables
|
||||
*/
|
||||
|
||||
/*)Function VOID list()
|
||||
*
|
||||
* The function list() generates the listing output
|
||||
* which includes the input source, line numbers,
|
||||
* and generated code. Numerical output may be selected
|
||||
* as hexadecimal, decimal, or octal.
|
||||
*
|
||||
* local variables:
|
||||
* int * wp pointer to the assembled data bytes
|
||||
* int * wpt pointer to the data byte mode
|
||||
* int nb computed number of assembled bytes
|
||||
*
|
||||
* global variables:
|
||||
* int cb[] array of assembler output values
|
||||
* int cbt[] array of assembler relocation types
|
||||
* describing the data in cb[]
|
||||
* int * cp pointer to assembler output array cb[]
|
||||
* int * cpt pointer to assembler relocation type
|
||||
* output array cbt[]
|
||||
* char eb[] array of generated error codes
|
||||
* char * ep pointer into error list
|
||||
* array eb[]
|
||||
* char ib[] assembler-source text line
|
||||
* FILE * lfp list output file handle
|
||||
* int line current assembler source line number
|
||||
* int lmode listing mode
|
||||
* int xflag -x, listing radix flag
|
||||
*
|
||||
* functions called:
|
||||
* int fprintf() c_library
|
||||
* VOID list1() aslist.c
|
||||
* int putc() c_library
|
||||
* VOID slew() asslist.c
|
||||
*
|
||||
* side effects:
|
||||
* Listing or symbol output updated.
|
||||
*/
|
||||
|
||||
#ifndef MLH_LST
|
||||
VOID
|
||||
list()
|
||||
{
|
||||
register char *wp;
|
||||
register int *wpt;
|
||||
register int nb;
|
||||
|
||||
if (lfp == NULL || lmode == NLIST)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Get Correct Line Number
|
||||
*/
|
||||
if (incfil >= 0) {
|
||||
line = incline[incfil];
|
||||
if (line == 0) {
|
||||
if (incfil > 0) {
|
||||
line = incline[incfil-1];
|
||||
} else {
|
||||
line = srcline[cfile];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
line = srcline[cfile];
|
||||
}
|
||||
|
||||
/*
|
||||
* Move to next line.
|
||||
*/
|
||||
slew(lfp, pflag);
|
||||
|
||||
/*
|
||||
* Output a maximum of NERR error codes with listing.
|
||||
*/
|
||||
while (ep < &eb[NERR])
|
||||
*ep++ = ' ';
|
||||
fprintf(lfp, "%.2s", eb);
|
||||
|
||||
/*
|
||||
* Source listing only option.
|
||||
*/
|
||||
if (lmode == SLIST) {
|
||||
fprintf(lfp, "%24s%5u %s\n", "", line, ib);
|
||||
return;
|
||||
}
|
||||
#ifndef SDK
|
||||
if (lmode == ALIST) {
|
||||
outchk(HUGE,HUGE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HEX output Option.
|
||||
*/
|
||||
if (xflag == 0) { /* HEX */
|
||||
/*
|
||||
* Equate only
|
||||
*/
|
||||
if (lmode == ELIST) {
|
||||
fprintf(lfp, "%18s%04X", "", laddr);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Address (with allocation)
|
||||
*/
|
||||
fprintf(lfp, " %04X", laddr);
|
||||
if (lmode == ALIST || lmode == BLIST) {
|
||||
fprintf(lfp, "%19s%5u %s\n", "", line, ib);
|
||||
#ifndef SDK
|
||||
outdot();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
wp = cb;
|
||||
wpt = cbt;
|
||||
nb = (int) (cp - cb);
|
||||
|
||||
/*
|
||||
* First line of output for this source line with data.
|
||||
*/
|
||||
list1(wp, wpt, nb, 1);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
|
||||
/*
|
||||
* Subsequent lines of output if more data.
|
||||
*/
|
||||
while ((nb -= 6) > 0) {
|
||||
wp += 6;
|
||||
wpt += 6;
|
||||
slew(lfp, 0);
|
||||
fprintf(lfp, "%7s", "");
|
||||
list1(wp, wpt, nb, 0);
|
||||
putc('\n', lfp);
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* OCTAL output Option.
|
||||
*/
|
||||
if (xflag == 1) { /* OCTAL */
|
||||
/*
|
||||
* Equate only
|
||||
*/
|
||||
if (lmode == ELIST) {
|
||||
fprintf(lfp, "%16s%06o", "", laddr);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Address (with allocation)
|
||||
*/
|
||||
fprintf(lfp, " %06o", laddr);
|
||||
if (lmode == ALIST || lmode == BLIST) {
|
||||
fprintf(lfp, "%17s%5u %s\n", "", line, ib);
|
||||
#ifndef SDK
|
||||
outdot();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
wp = cb;
|
||||
wpt = cbt;
|
||||
nb = (int) (cp - cb);
|
||||
|
||||
/*
|
||||
* First line of output for this source line with data.
|
||||
*/
|
||||
list1(wp, wpt, nb, 1);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
|
||||
/*
|
||||
* Subsequent lines of output if more data.
|
||||
*/
|
||||
while ((nb -= 4) > 0) {
|
||||
wp += 4;
|
||||
wpt += 4;
|
||||
slew(lfp, 0);
|
||||
fprintf(lfp, "%9s", "");
|
||||
list1(wp, wpt, nb, 0);
|
||||
putc('\n', lfp);
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* DECIMAL output Option.
|
||||
*/
|
||||
if (xflag == 2) { /* DECIMAL */
|
||||
/*
|
||||
* Equate only
|
||||
*/
|
||||
if (lmode == ELIST) {
|
||||
fprintf(lfp, "%16s%05u", "", laddr);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Address (with allocation)
|
||||
*/
|
||||
fprintf(lfp, " %05u", laddr);
|
||||
if (lmode == ALIST || lmode == BLIST) {
|
||||
fprintf(lfp, "%17s%5u %s\n", "", line, ib);
|
||||
#ifndef SDK
|
||||
outdot();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
wp = cb;
|
||||
wpt = cbt;
|
||||
nb = (int) (cp - cb);
|
||||
|
||||
/*
|
||||
* First line of output for this source line with data.
|
||||
*/
|
||||
list1(wp, wpt, nb, 1);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
|
||||
/*
|
||||
* Subsequent lines of output if more data.
|
||||
*/
|
||||
while ((nb -= 4) > 0) {
|
||||
wp += 4;
|
||||
wpt += 4;
|
||||
slew(lfp, 0);
|
||||
fprintf(lfp, "%9s", "");
|
||||
list1(wp, wpt, nb, 0);
|
||||
putc('\n', lfp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
VOID
|
||||
list()
|
||||
{
|
||||
register char *wp;
|
||||
register int *wpt;
|
||||
register nb;
|
||||
|
||||
if (lfp == NULL || lmode == NLIST)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Get Correct Line Number
|
||||
*/
|
||||
if (incfil >= 0) {
|
||||
line = incline[incfil];
|
||||
if (line == 0) {
|
||||
if (incfil > 0) {
|
||||
line = incline[incfil-1];
|
||||
} else {
|
||||
line = srcline[cfile];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
line = srcline[cfile];
|
||||
}
|
||||
|
||||
/*
|
||||
* HEX output Option.
|
||||
*/
|
||||
/* Output filename relative_address line_number */
|
||||
|
||||
if (incfil >= 0) {
|
||||
fprintf(lfp, "%s ", incfn[incfil]);
|
||||
}
|
||||
else {
|
||||
fprintf(lfp, "%s ", srcfn[cfile]);
|
||||
}
|
||||
fprintf(lfp, "%u %04X\n", line, laddr);
|
||||
#if 0
|
||||
wp = cb;
|
||||
wpt = cbt;
|
||||
nb = (int) (cp - cb);
|
||||
|
||||
/*
|
||||
* First line of output for this source line with data.
|
||||
*/
|
||||
list1(wp, wpt, nb, 1);
|
||||
fprintf(lfp, " %5u %s\n", line, ib);
|
||||
|
||||
/*
|
||||
* Subsequent lines of output if more data.
|
||||
*/
|
||||
while ((nb -= 6) > 0) {
|
||||
wp += 6;
|
||||
wpt += 6;
|
||||
slew(lfp, 0);
|
||||
fprintf(lfp, "%7s", "");
|
||||
list1(wp, wpt, nb, 0);
|
||||
putc('\n', lfp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* MLH_LST */
|
||||
|
||||
/*)Function VOID list1(wp, wpt, nw, f)
|
||||
*
|
||||
* int f fill blank fields (1)
|
||||
* int nb number of data bytes
|
||||
* int * wp pointer to data bytes
|
||||
* int * wpt pointer to data byte mode
|
||||
*
|
||||
* local variables:
|
||||
* int i loop counter
|
||||
*
|
||||
* global variables:
|
||||
* int xflag -x, listing radix flag
|
||||
*
|
||||
* functions called:
|
||||
* VOID list2() asslist.c
|
||||
* int fprintf() c_library
|
||||
*
|
||||
* side effects:
|
||||
* Data formatted and output to listing.
|
||||
*/
|
||||
|
||||
VOID
|
||||
list1(wp, wpt, nb, f)
|
||||
register char *wp;
|
||||
register int *wpt, nb, f;
|
||||
{
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* HEX output Option.
|
||||
*/
|
||||
if (xflag == 0) { /* HEX */
|
||||
/*
|
||||
* Bound number of words to HEX maximum per line.
|
||||
*/
|
||||
if (nb > 6)
|
||||
nb = 6;
|
||||
|
||||
/*
|
||||
* Output bytes.
|
||||
*/
|
||||
for (i=0; i<nb; ++i) {
|
||||
list2(*wpt++);
|
||||
fprintf(lfp, "%02X", (*wp++)&0377);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output blanks if required.
|
||||
*/
|
||||
if (f) {
|
||||
while (i < 6) {
|
||||
fprintf(lfp, " ");
|
||||
++i;
|
||||
}
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* OCTAL output Option.
|
||||
*/
|
||||
if (xflag == 1) { /* OCTAL */
|
||||
/*
|
||||
* Bound number of words to OCTAL maximum per line.
|
||||
*/
|
||||
if (nb > 4)
|
||||
nb = 4;
|
||||
|
||||
/*
|
||||
* Output bytes.
|
||||
*/
|
||||
for (i=0; i<nb; ++i) {
|
||||
list2(*wpt++);
|
||||
fprintf(lfp, "%03o", (*wp++)&0377);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output blanks if required.
|
||||
*/
|
||||
if (f) {
|
||||
while (i < 4) {
|
||||
fprintf(lfp, " ");
|
||||
++i;
|
||||
}
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* DECIMAL output Option.
|
||||
*/
|
||||
if (xflag == 2) { /* DECIMAL */
|
||||
/*
|
||||
* Bound number of words to DECIMAL maximum per line.
|
||||
*/
|
||||
if (nb > 4)
|
||||
nb = 4;
|
||||
|
||||
/*
|
||||
* Output bytes.
|
||||
*/
|
||||
for (i=0; i<nb; ++i) {
|
||||
list2(*wpt++);
|
||||
fprintf(lfp, "%03u", (*wp++)&0377);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output blanks if required.
|
||||
*/
|
||||
if (f) {
|
||||
while (i < 4) {
|
||||
fprintf(lfp, " ");
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function VOID list2(wpt)
|
||||
*
|
||||
* int * wpt pointer to relocation mode
|
||||
*
|
||||
* The function list2() outputs the selected
|
||||
* relocation flag as specified by fflag.
|
||||
*
|
||||
* local variables:
|
||||
* int c relocation flag character
|
||||
* int t relocation mode
|
||||
*
|
||||
* global variables:
|
||||
* int fflag -f(f), relocations flagged flag
|
||||
*
|
||||
* functions called:
|
||||
* int putc() c_library
|
||||
*
|
||||
* side effects:
|
||||
* Relocation flag output to listing file.
|
||||
*/
|
||||
|
||||
VOID
|
||||
list2(t)
|
||||
register int t;
|
||||
{
|
||||
register int c;
|
||||
|
||||
c = ' ';
|
||||
|
||||
/*
|
||||
* Designate a relocatable word by `.
|
||||
*/
|
||||
if (fflag == 1) {
|
||||
if (t & R_RELOC) {
|
||||
c = '`';
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* Designate a relocatable word by its mode:
|
||||
* page0 or paged *
|
||||
* unsigned u (v)
|
||||
* operand offset p (q)
|
||||
* relocatable symbol r (s)
|
||||
*/
|
||||
if (fflag >= 2) {
|
||||
if (t & R_RELOC) {
|
||||
if (t & (R_PAG0|R_PAG)) {
|
||||
c = '*';
|
||||
} else if (t & R_USGN) {
|
||||
c = 'u';
|
||||
} else if (t & R_PCR) {
|
||||
c = 'p';
|
||||
} else {
|
||||
c = 'r';
|
||||
}
|
||||
if (t & R_HIGH) c += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output the selected mode.
|
||||
*/
|
||||
putc(c, lfp);
|
||||
}
|
||||
|
||||
/*)Function VOID slew(fp, flag)
|
||||
*
|
||||
* FILE * fp file handle for listing
|
||||
* int flag enable pagination
|
||||
*
|
||||
* The function slew() increments the page line count.
|
||||
* If the page overflows and pagination is enabled:
|
||||
* 1) put out a page skip,
|
||||
* 2) a title,
|
||||
* 3) a subtitle,
|
||||
* 4) and reset the line count.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* char cpu[] cpu type string
|
||||
* int lop current line number on page
|
||||
* int page current page number
|
||||
* char stb[] Subtitle string buffer
|
||||
* char tb[] Title string buffer
|
||||
*
|
||||
* functions called:
|
||||
* int fprintf() c_library
|
||||
*
|
||||
* side effects:
|
||||
* Increments page line counter, on overflow
|
||||
* a new page header is output to the listing file.
|
||||
*/
|
||||
|
||||
VOID
|
||||
slew(fp,flag)
|
||||
FILE *fp;
|
||||
int flag;
|
||||
{
|
||||
if ((lop++ >= NLPP) && flag) {
|
||||
fprintf(fp, "\fASxxxx Assembler %s (%s), page %u.\n",
|
||||
VERSION, cpu, ++page);
|
||||
fprintf(fp, "%s\n", tb);
|
||||
fprintf(fp, "%s\n\n", stb);
|
||||
lop = 5;
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function VOID lstsym(fp)
|
||||
*
|
||||
* FILE * fp file handle for output
|
||||
*
|
||||
* The function lstsym() outputs alphabetically
|
||||
* sorted symbol and area tables.
|
||||
*
|
||||
* local variables:
|
||||
* int c temporary
|
||||
* int i loop counter
|
||||
* int j temporary
|
||||
* int k temporary
|
||||
* char * ptr pointer to an id string
|
||||
* int nmsym number of symbols
|
||||
* int narea number of areas
|
||||
* sym * sp pointer to symbol structure
|
||||
* sym ** p pointer to an array of
|
||||
* pointers to symbol structures
|
||||
* area * ap pointer to an area structure
|
||||
*
|
||||
* global variables:
|
||||
* area * areap pointer to an area structure
|
||||
* char aretbl[] string "Area Table"
|
||||
* sym dot defined as sym[0]
|
||||
* char stb[] Subtitle string buffer
|
||||
* sym * symhash[] array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
* char symtbl[] string "Symbol Table"
|
||||
* FILE * tfp symbol table output file handle
|
||||
* int xflag -x, listing radix flag
|
||||
*
|
||||
* functions called:
|
||||
* int fprintf() c_library
|
||||
* int putc() c_library
|
||||
* VOID slew() aslist.c
|
||||
* int strcmp() c_library
|
||||
* char * strcpy() c_library
|
||||
*
|
||||
* side effects:
|
||||
* Symbol and area tables output.
|
||||
*/
|
||||
|
||||
VOID
|
||||
lstsym(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
register int c, i, j, k;
|
||||
register char *ptr;
|
||||
int nmsym, narea;
|
||||
struct sym *sp;
|
||||
struct sym **p;
|
||||
struct area *ap;
|
||||
|
||||
/*
|
||||
* Symbol Table Header
|
||||
*/
|
||||
strcpy(stb, &symtbl[0]);
|
||||
lop = NLPP;
|
||||
if (fp == tfp)
|
||||
page = 0;
|
||||
slew(fp, 1);
|
||||
|
||||
/*
|
||||
* Find number of symbols
|
||||
*/
|
||||
nmsym = 0;
|
||||
for (i=0; i<NHASH; i++) {
|
||||
sp = symhash[i];
|
||||
while (sp) {
|
||||
if (sp != &dot)
|
||||
++nmsym;
|
||||
sp = sp->s_sp;
|
||||
}
|
||||
}
|
||||
if (nmsym == 0)
|
||||
goto atable;
|
||||
|
||||
/*
|
||||
* Allocate space for an array of pointers to symbols
|
||||
* and load array.
|
||||
*/
|
||||
if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
|
||||
== NULL) {
|
||||
fprintf(fp, "Insufficient space to build Symbol Table.\n");
|
||||
return;
|
||||
}
|
||||
nmsym = 0;
|
||||
for (i=0; i<NHASH; i++) {
|
||||
sp = symhash[i];
|
||||
while (sp) {
|
||||
if (sp != &dot)
|
||||
p[nmsym++] = sp;
|
||||
sp = sp->s_sp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Bubble Sort on Symbol Table Array
|
||||
*/
|
||||
j = 1;
|
||||
c = nmsym - 1;
|
||||
while (j) {
|
||||
j = 0;
|
||||
for (i=0; i<c; ++i) {
|
||||
if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
|
||||
j = 1;
|
||||
sp = p[i+1];
|
||||
p[i+1] = p[i];
|
||||
p[i] = sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Symbol Table Output
|
||||
*/
|
||||
for (i=0; i<nmsym;) {
|
||||
sp = p[i];
|
||||
if (sp->s_area) {
|
||||
j = sp->s_area->a_ref;
|
||||
if (xflag == 0) {
|
||||
fprintf(fp, " %2X ", j);
|
||||
} else
|
||||
if (xflag == 1) {
|
||||
fprintf(fp, "%3o ", j);
|
||||
} else
|
||||
if (xflag == 2) {
|
||||
fprintf(fp, "%3u ", j);
|
||||
}
|
||||
} else {
|
||||
fprintf(fp, " ");
|
||||
}
|
||||
ptr = &sp->s_id[0];
|
||||
while (ptr < &sp->s_id[NCPS]) {
|
||||
if ((c = *ptr++) != 0) {
|
||||
putc(c, fp);
|
||||
} else {
|
||||
putc(' ', fp);
|
||||
}
|
||||
}
|
||||
if (sp->s_flag & S_ASG) {
|
||||
putc('=', fp);
|
||||
} else {
|
||||
putc(' ', fp);
|
||||
}
|
||||
if (sp->s_type == S_NEW) {
|
||||
if (xflag == 0) {
|
||||
fprintf(fp, " **** ");
|
||||
} else
|
||||
if (xflag == 1) {
|
||||
fprintf(fp, "****** ");
|
||||
} else
|
||||
if (xflag == 2) {
|
||||
fprintf(fp, " ***** ");
|
||||
}
|
||||
} else {
|
||||
j = sp->s_addr;
|
||||
if (xflag == 0) {
|
||||
fprintf(fp, " %04X ", j);
|
||||
} else
|
||||
if (xflag == 1) {
|
||||
fprintf(fp, "%06o ", j);
|
||||
} else
|
||||
if (xflag == 2) {
|
||||
fprintf(fp, " %05u ", j);
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
if (sp->s_flag & S_GBL) {
|
||||
putc('G', fp);
|
||||
++j;
|
||||
}
|
||||
if (sp->s_area != NULL) {
|
||||
putc('R', fp);
|
||||
++j;
|
||||
}
|
||||
if (sp->s_type == S_NEW) {
|
||||
putc('X', fp);
|
||||
++j;
|
||||
}
|
||||
#if NCPS-8
|
||||
putc('\n', fp);
|
||||
slew(fp, 0);
|
||||
++i;
|
||||
#else
|
||||
if (++i % 3 == 0) {
|
||||
putc('\n', fp);
|
||||
slew(fp, pflag);
|
||||
} else
|
||||
if (i < nmsym) {
|
||||
while (j++ < 4)
|
||||
putc(' ', fp);
|
||||
fprintf(fp, "| ");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
putc('\n', fp);
|
||||
|
||||
/*
|
||||
* Area Table Header
|
||||
*/
|
||||
|
||||
atable:
|
||||
strcpy(stb, &aretbl[0]);
|
||||
lop = NLPP;
|
||||
slew(fp, 1);
|
||||
|
||||
/*
|
||||
* Area Table Output
|
||||
*/
|
||||
narea = 0;
|
||||
ap = areap;
|
||||
while (ap) {
|
||||
++narea;
|
||||
ap = ap->a_ap;
|
||||
}
|
||||
for (i=0; i<narea; ++i) {
|
||||
ap = areap;
|
||||
for (j=i+1; j<narea; ++j)
|
||||
ap = ap->a_ap;
|
||||
j = ap->a_ref;
|
||||
if (xflag == 0) {
|
||||
fprintf(fp, " %2X ", j);
|
||||
} else
|
||||
if (xflag == 1) {
|
||||
fprintf(fp, " %3o ", j);
|
||||
} else
|
||||
if (xflag == 2) {
|
||||
fprintf(fp, " %3u ", j);
|
||||
}
|
||||
ptr = &ap->a_id[0];
|
||||
while (ptr < &ap->a_id[NCPS]) {
|
||||
if ((c = *ptr++) != 0) {
|
||||
putc(c, fp);
|
||||
} else {
|
||||
putc(' ', fp);
|
||||
}
|
||||
}
|
||||
j = ap->a_size;
|
||||
k = ap->a_flag;
|
||||
if (xflag==0) {
|
||||
fprintf(fp, " size %4X flags %X\n", j, k);
|
||||
} else
|
||||
if (xflag==1) {
|
||||
fprintf(fp, " size %6o flags %o\n", j, k);
|
||||
} else
|
||||
if (xflag==2) {
|
||||
fprintf(fp, " size %5u flags %u\n", j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
598
link/as/z80/asm.h
Normal file
598
link/as/z80/asm.h
Normal file
@@ -0,0 +1,598 @@
|
||||
/* asm.h */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1996
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#define VERSION "V01.75"
|
||||
|
||||
/*
|
||||
* Case Sensitivity Flag
|
||||
*/
|
||||
#define CASE_SENSITIVE 0
|
||||
|
||||
/*)Module asm.h
|
||||
*
|
||||
* The module asm.h contains the definitions for constants,
|
||||
* structures, global variables, and ASxxxx functions
|
||||
* contained in the ASxxxx.c files. The two functions
|
||||
* and three global variables from the machine dependent
|
||||
* files are also defined.
|
||||
*/
|
||||
|
||||
/*
|
||||
* compiler/operating system specific definitions
|
||||
*/
|
||||
|
||||
/* DECUS C void definition */
|
||||
/* File/extension seperator */
|
||||
|
||||
#ifdef decus
|
||||
#define VOID char
|
||||
#define FSEPX '.'
|
||||
#endif
|
||||
|
||||
/* PDOS C void definition */
|
||||
/* File/extension seperator */
|
||||
|
||||
#ifdef PDOS
|
||||
#define VOID char
|
||||
#define FSEPX ':'
|
||||
#endif
|
||||
|
||||
/* Default void definition */
|
||||
/* File/extension seperator */
|
||||
|
||||
#ifndef VOID
|
||||
#define VOID void
|
||||
#define FSEPX '.'
|
||||
#define OTHERSYSTEM
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assembler definitions.
|
||||
*/
|
||||
#define LFTERM '(' /* Left expression delimeter */
|
||||
#define RTTERM ')' /* Right expression delimeter */
|
||||
|
||||
#ifdef SDK
|
||||
#define NCPS 32 /* characters per symbol */
|
||||
#else /* SDK */
|
||||
#define NCPS 8 /* Chars. per symbol */
|
||||
#endif /* SDK */
|
||||
/* #define NCPS 32 */ /* Chars. per symbol */
|
||||
#define HUGE 1000 /* A huge number */
|
||||
#define NERR 3 /* Errors per line */
|
||||
#define NINPUT 128 /* Input buffer size */
|
||||
#define NCODE 128 /* Listing code buffer size */
|
||||
#define NTITL 64 /* Title buffer size */
|
||||
#define NSBTL 64 /* SubTitle buffer size */
|
||||
#define NHASH 64 /* Buckets in hash table */
|
||||
#define HMASK 077 /* Hash mask */
|
||||
#define NLPP 60 /* Lines per page */
|
||||
#define MAXFIL 6 /* Maximum command line input files */
|
||||
#define MAXINC 6 /* Maximum nesting of include files */
|
||||
#define MAXIF 10 /* Maximum nesting of if/else/endif */
|
||||
#define FILSPC 256 /* Chars. in filespec */
|
||||
|
||||
#define NLIST 0 /* No listing */
|
||||
#define SLIST 1 /* Source only */
|
||||
#define ALIST 2 /* Address only */
|
||||
#define BLIST 3 /* Address only with allocation */
|
||||
#define CLIST 4 /* Code */
|
||||
#define ELIST 5 /* Equate only */
|
||||
|
||||
#define dot sym[0] /* Dot, current loc */
|
||||
#define dca area[0] /* Dca, default code area */
|
||||
|
||||
|
||||
typedef unsigned int Addr_T;
|
||||
|
||||
/*
|
||||
* The area structure contains the parameter values for a
|
||||
* specific program or data section. The area structure
|
||||
* is a linked list of areas. The initial default area
|
||||
* is "_CODE" defined in asdata.c, the next area structure
|
||||
* will be linked to this structure through the structure
|
||||
* element 'struct area *a_ap'. The structure contains the
|
||||
* area name, area reference number ("_CODE" is 0) determined
|
||||
* by the order of .area directives, area size determined
|
||||
* from the total code and/or data in an area, area fuzz is
|
||||
* a variable used to track pass to pass changes in the
|
||||
* area size caused by variable length instruction formats,
|
||||
* and area flags which specify the area's relocation type.
|
||||
*/
|
||||
struct area
|
||||
{
|
||||
struct area *a_ap; /* Area link */
|
||||
char a_id[NCPS]; /* Area Name */
|
||||
int a_ref; /* Ref. number */
|
||||
Addr_T a_size; /* Area size */
|
||||
Addr_T a_fuzz; /* Area fuzz */
|
||||
int a_flag; /* Area flags */
|
||||
};
|
||||
|
||||
/*
|
||||
* The "A_" area constants define values used in
|
||||
* generating the assembler area output data.
|
||||
*
|
||||
* Area flags
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
* | | | | PAG | ABS | OVR | | |
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
*/
|
||||
|
||||
#define A_CON 000 /* Concatenating */
|
||||
#define A_OVR 004 /* Overlaying */
|
||||
#define A_REL 000 /* Relocatable */
|
||||
#define A_ABS 010 /* absolute */
|
||||
#define A_NOPAG 000 /* Non-Paged */
|
||||
#define A_PAG 020 /* Paged */
|
||||
|
||||
/*
|
||||
* The "R_" relocation constants define values used in
|
||||
* generating the assembler relocation output data for
|
||||
* areas, symbols, and code.
|
||||
*
|
||||
* Relocation flags
|
||||
*
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
* | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
|
||||
* +-----+-----+-----+-----+-----+-----+-----+-----+
|
||||
*/
|
||||
|
||||
#define R_WORD 0000 /* 16 bit */
|
||||
#define R_BYTE 0001 /* 8 bit */
|
||||
|
||||
#define R_AREA 0000 /* Base type */
|
||||
#define R_SYM 0002
|
||||
|
||||
#define R_NORM 0000 /* PC adjust */
|
||||
#define R_PCR 0004
|
||||
|
||||
#define R_BYT1 0000 /* Byte count for R_BYTE = 1 */
|
||||
#define R_BYT2 0010 /* Byte count for R_BYTE = 2 */
|
||||
|
||||
#define R_SGND 0000 /* Signed Byte */
|
||||
#define R_USGN 0020 /* Unsigned Byte */
|
||||
|
||||
#define R_NOPAG 0000 /* Page Mode */
|
||||
#define R_PAG0 0040 /* Page '0' */
|
||||
#define R_PAG 0100 /* Page 'nnn' */
|
||||
|
||||
#define R_LSB 0000 /* low byte */
|
||||
#define R_MSB 0200 /* high byte */
|
||||
|
||||
/*
|
||||
* Listing Control Flags
|
||||
*/
|
||||
|
||||
#define R_HIGH 0040000 /* High Byte */
|
||||
#define R_RELOC 0100000 /* Relocation */
|
||||
|
||||
#define R_DEF 00 /* Global def. */
|
||||
#define R_REF 01 /* Global ref. */
|
||||
#define R_REL 00 /* Relocatable */
|
||||
#define R_ABS 02 /* Absolute */
|
||||
#define R_GBL 00 /* Global */
|
||||
#define R_LCL 04 /* Local */
|
||||
|
||||
/*
|
||||
* The mne structure is a linked list of the assembler
|
||||
* mnemonics and directives. The list of mnemonics and
|
||||
* directives contained in the device dependent file
|
||||
* xxxpst.c are hashed and linked into NHASH lists in
|
||||
* module assym.c by syminit(). The structure contains
|
||||
* the mnemonic/directive name, a subtype which directs
|
||||
* the evaluation of this mnemonic/directive, a flag which
|
||||
* is used to detect the end of the mnemonic/directive
|
||||
* list in xxxpst.c, and a value which is normally
|
||||
* associated with the assembler mnemonic base instruction
|
||||
* value.
|
||||
*/
|
||||
struct mne
|
||||
{
|
||||
struct mne *m_mp; /* Hash link */
|
||||
char m_id[NCPS]; /* Mnemonic */
|
||||
char m_type; /* Mnemonic subtype */
|
||||
char m_flag; /* Mnemonic flags */
|
||||
Addr_T m_valu; /* Value */
|
||||
};
|
||||
|
||||
/*
|
||||
* The sym structure is a linked list of symbols defined
|
||||
* in the assembler source files. The first symbol is "."
|
||||
* defined in asdata.c. The entry 'struct tsym *s_tsym'
|
||||
* links any temporary symbols following this symbol and
|
||||
* preceeding the next normal symbol. The structure also
|
||||
* contains the symbol's name, type (USER or NEW), flag
|
||||
* (global, assigned, and multiply defined), a pointer
|
||||
* to the area structure defining where the symbol is
|
||||
* located, a reference number assigned by outgsd() in
|
||||
* asout.c, and the symbols address relative to the base
|
||||
* address of the area where the symbol is located.
|
||||
*/
|
||||
struct sym
|
||||
{
|
||||
struct sym *s_sp; /* Hash link */
|
||||
struct tsym *s_tsym; /* Temporary symbol link */
|
||||
char s_id[NCPS]; /* Symbol */
|
||||
char s_type; /* Symbol subtype */
|
||||
char s_flag; /* Symbol flags */
|
||||
struct area *s_area; /* Area line, 0 if absolute */
|
||||
int s_ref; /* Ref. number */
|
||||
Addr_T s_addr; /* Address */
|
||||
};
|
||||
|
||||
#define S_GBL 01 /* Global */
|
||||
#define S_ASG 02 /* Assigned */
|
||||
#define S_MDF 04 /* Mult. def */
|
||||
#define S_END 010 /* End mark for pst. */
|
||||
|
||||
#define S_NEW 0 /* New name */
|
||||
#define S_USER 1 /* User name */
|
||||
/* unused slot */
|
||||
/* unused slot */
|
||||
/* unused slot */
|
||||
|
||||
#define S_BYTE 5 /* .byte */
|
||||
#define S_WORD 6 /* .word */
|
||||
#define S_ASCII 7 /* .ascii */
|
||||
#define S_ASCIZ 8 /* .asciz */
|
||||
#define S_BLK 9 /* .blkb or .blkw */
|
||||
#define S_INCL 10 /* .include */
|
||||
#define S_DAREA 11 /* .area */
|
||||
#define S_ATYP 12 /* .area type */
|
||||
#define S_AREA 13 /* .area name */
|
||||
#define S_GLOBL 14 /* .globl */
|
||||
#define S_PAGE 15 /* .page */
|
||||
#define S_TITLE 16 /* .title */
|
||||
#define S_SBTL 17 /* .sbttl */
|
||||
#define S_IF 18 /* .if */
|
||||
#define S_ELSE 19 /* .else */
|
||||
#define S_ENDIF 20 /* .endif */
|
||||
#define S_EVEN 21 /* .even */
|
||||
#define S_ODD 22 /* .odd */
|
||||
#define S_RADIX 23 /* .radix */
|
||||
#define S_ORG 24 /* .org */
|
||||
#define S_MODUL 25 /* .module */
|
||||
#define S_ASCIS 26 /* .ascis */
|
||||
#ifdef SDK
|
||||
# define S_FLOAT 27 /* .df */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The tsym structure is a linked list of temporary
|
||||
* symbols defined in the assembler source files following
|
||||
* a normal symbol. The structure contains the temporary
|
||||
* symbols number, a flag (multiply defined), a pointer to the
|
||||
* area structure defining where the temporary structure
|
||||
* is located, and the temporary symbol's address relative
|
||||
* to the base address of the area where the symbol
|
||||
* is located.
|
||||
*/
|
||||
struct tsym
|
||||
{
|
||||
struct tsym *t_lnk; /* Link to next */
|
||||
int t_num; /* 0-lots$ */
|
||||
char t_flg; /* flags */
|
||||
struct area *t_area; /* Area */
|
||||
Addr_T t_addr; /* Address */
|
||||
};
|
||||
|
||||
/*
|
||||
* External Definitions for all Global Variables
|
||||
*/
|
||||
|
||||
extern int aserr; /* ASxxxx error counter
|
||||
*/
|
||||
extern jmp_buf jump_env; /* compiler dependent structure
|
||||
* used by setjmp() and longjmp()
|
||||
*/
|
||||
extern int inpfil; /* count of assembler
|
||||
* input files specified
|
||||
*/
|
||||
extern int incfil; /* current file handle index
|
||||
* for include files
|
||||
*/
|
||||
extern int cfile; /* current file handle index
|
||||
* of input assembly files
|
||||
*/
|
||||
extern int flevel; /* IF-ELSE-ENDIF flag will be non
|
||||
* zero for false conditional case
|
||||
*/
|
||||
extern int tlevel; /* current conditional level
|
||||
*/
|
||||
extern int ifcnd[MAXIF+1]; /* array of IF statement condition
|
||||
* values (0 = FALSE) indexed by tlevel
|
||||
*/
|
||||
extern int iflvl[MAXIF+1]; /* array of IF-ELSE-ENDIF flevel
|
||||
* values indexed by tlevel
|
||||
*/
|
||||
extern char
|
||||
afn[FILSPC]; /* afile() temporary filespec
|
||||
*/
|
||||
extern char
|
||||
srcfn[MAXFIL][FILSPC]; /* array of source file names
|
||||
*/
|
||||
extern int
|
||||
srcline[MAXFIL]; /* current source file line
|
||||
*/
|
||||
extern char
|
||||
incfn[MAXINC][FILSPC]; /* array of include file names
|
||||
*/
|
||||
extern int
|
||||
incline[MAXINC]; /* current include file line
|
||||
*/
|
||||
extern int radix; /* current number conversion radix:
|
||||
* 2 (binary), 8 (octal), 10 (decimal),
|
||||
* 16 (hexadecimal)
|
||||
*/
|
||||
extern int line; /* current assembler source
|
||||
* line number
|
||||
*/
|
||||
extern int page; /* current page number
|
||||
*/
|
||||
extern int lop; /* current line number on page
|
||||
*/
|
||||
extern int pass; /* assembler pass number
|
||||
*/
|
||||
extern int lflag; /* -l, generate listing flag
|
||||
*/
|
||||
extern int gflag; /* -g, make undefined symbols global flag
|
||||
*/
|
||||
extern int aflag; /* -a, make all symbols global flag
|
||||
*/
|
||||
extern int oflag; /* -o, generate relocatable output flag
|
||||
*/
|
||||
extern int sflag; /* -s, generate symbol table flag
|
||||
*/
|
||||
extern int pflag; /* -p, enable listing pagination
|
||||
*/
|
||||
extern int xflag; /* -x, listing radix flag
|
||||
*/
|
||||
extern int fflag; /* -f(f), relocations flagged flag
|
||||
*/
|
||||
extern Addr_T laddr; /* address of current assembler line
|
||||
* or value of .if argument
|
||||
*/
|
||||
extern Addr_T fuzz; /* tracks pass to pass changes in the
|
||||
* address of symbols caused by
|
||||
* variable length instruction formats
|
||||
*/
|
||||
extern int lmode; /* listing mode
|
||||
*/
|
||||
extern struct area area[]; /* array of 1 area
|
||||
*/
|
||||
extern struct area *areap; /* pointer to an area structure
|
||||
*/
|
||||
extern struct sym sym[]; /* array of 1 symbol
|
||||
*/
|
||||
extern struct sym *symp; /* pointer to a symbol structure
|
||||
*/
|
||||
extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*/
|
||||
extern struct mne *mnehash[NHASH]; /* array of pointers to NHASH
|
||||
* linked mnemonic/directive lists
|
||||
*/
|
||||
extern char *ep; /* pointer into error list
|
||||
* array eb[NERR]
|
||||
*/
|
||||
extern char eb[NERR]; /* array of generated error codes
|
||||
*/
|
||||
extern char *ip; /* pointer into the assembler-source
|
||||
* text line in ib[]
|
||||
*/
|
||||
extern char ib[NINPUT]; /* assembler-source text line
|
||||
*/
|
||||
extern char *cp; /* pointer to assembler output
|
||||
* array cb[]
|
||||
*/
|
||||
extern char cb[NCODE]; /* array of assembler output values
|
||||
*/
|
||||
extern int *cpt; /* pointer to assembler relocation type
|
||||
* output array cbt[]
|
||||
*/
|
||||
extern int cbt[NCODE]; /* array of assembler relocation types
|
||||
* describing the data in cb[]
|
||||
*/
|
||||
extern char tb[NTITL]; /* Title string buffer
|
||||
*/
|
||||
extern char stb[NSBTL]; /* Subtitle string buffer
|
||||
*/
|
||||
extern char symtbl[]; /* string "Symbol Table"
|
||||
*/
|
||||
extern char aretbl[]; /* string "Area Table"
|
||||
*/
|
||||
extern char module[NCPS]; /* module name string
|
||||
*/
|
||||
extern FILE *lfp; /* list output file handle
|
||||
*/
|
||||
extern FILE *ofp; /* relocation output file handle
|
||||
*/
|
||||
extern FILE *tfp; /* symbol table output file handle
|
||||
*/
|
||||
extern FILE *sfp[MAXFIL]; /* array of assembler-source file handles
|
||||
*/
|
||||
extern FILE *ifp[MAXINC]; /* array of include-file file handles
|
||||
*/
|
||||
extern char ctype[128]; /* array of character types, one per
|
||||
* ASCII character
|
||||
*/
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
#else
|
||||
extern char ccase[128]; /* an array of characters which
|
||||
* perform the case translation function
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definitions for Character Types
|
||||
*/
|
||||
#define SPACE 0000
|
||||
#define ETC 0000
|
||||
#define LETTER 0001
|
||||
#define DIGIT 0002
|
||||
#define BINOP 0004
|
||||
#define RAD2 0010
|
||||
#define RAD8 0020
|
||||
#define RAD10 0040
|
||||
#define RAD16 0100
|
||||
#define ILL 0200
|
||||
|
||||
#define DGT2 DIGIT|RAD16|RAD10|RAD8|RAD2
|
||||
#define DGT8 DIGIT|RAD16|RAD10|RAD8
|
||||
#define DGT10 DIGIT|RAD16|RAD10
|
||||
#define LTR16 LETTER|RAD16
|
||||
|
||||
/*
|
||||
* The exp structure is used to return the evaluation
|
||||
* of an expression. The structure supports three valid
|
||||
* cases:
|
||||
* (1) The expression evaluates to a constant,
|
||||
* mode = S_USER, flag = 0, addr contains the
|
||||
* constant, and base = NULL.
|
||||
* (2) The expression evaluates to a defined symbol
|
||||
* plus or minus a constant, mode = S_USER,
|
||||
* flag = 0, addr contains the constant, and
|
||||
* base = pointer to area symbol.
|
||||
* (3) The expression evaluates to a external
|
||||
* global symbol plus or minus a constant,
|
||||
* mode = S_NEW, flag = 1, addr contains the
|
||||
* constant, and base = pointer to symbol.
|
||||
*/
|
||||
struct expr
|
||||
{
|
||||
char e_mode; /* Address mode */
|
||||
char e_flag; /* Symbol flag */
|
||||
Addr_T e_addr; /* Address */
|
||||
union {
|
||||
struct area *e_ap;
|
||||
struct sym *e_sp;
|
||||
} e_base; /* Rel. base */
|
||||
char e_rlcf; /* Rel. flags */
|
||||
};
|
||||
|
||||
/* C Library functions */
|
||||
/* for reference only
|
||||
extern VOID exit();
|
||||
extern int fclose();
|
||||
extern char * fgets();
|
||||
extern FILE * fopen();
|
||||
extern int fprintf();
|
||||
extern VOID longjmp();
|
||||
extern VOID * malloc();
|
||||
extern int printf();
|
||||
extern char putc();
|
||||
extern int rewind();
|
||||
extern int setjmp();
|
||||
extern int strcmp();
|
||||
extern char * strcpy();
|
||||
extern int strlen();
|
||||
extern char * strncpy();
|
||||
*/
|
||||
|
||||
/* Machine independent functions */
|
||||
|
||||
/* asmain.c */
|
||||
extern FILE * afile();
|
||||
extern VOID asexit();
|
||||
extern VOID asmbl();
|
||||
extern int main();
|
||||
extern VOID newdot();
|
||||
extern VOID phase();
|
||||
extern VOID usage();
|
||||
|
||||
/* aslex.c */
|
||||
extern char endline();
|
||||
extern char get();
|
||||
extern VOID getid();
|
||||
extern int getLine_();
|
||||
extern int getmap();
|
||||
extern char getnb();
|
||||
extern VOID getst();
|
||||
extern int more();
|
||||
extern VOID unget();
|
||||
|
||||
/* assym.c */
|
||||
extern struct area * alookup();
|
||||
extern struct mne * mlookup();
|
||||
extern int hash();
|
||||
extern struct sym * lookup();
|
||||
extern VOID * new();
|
||||
extern int symeq();
|
||||
extern VOID syminit();
|
||||
extern VOID symglob();
|
||||
extern VOID allglob();
|
||||
|
||||
/* assubr.c */
|
||||
extern VOID aerr();
|
||||
extern VOID diag();
|
||||
extern VOID err();
|
||||
extern char * geterr();
|
||||
extern VOID qerr();
|
||||
extern VOID rerr();
|
||||
|
||||
/* asexpr.c */
|
||||
extern VOID abscheck();
|
||||
extern Addr_T absexpr();
|
||||
extern VOID clrexpr();
|
||||
extern int digit();
|
||||
extern int is_abs();
|
||||
extern VOID expr();
|
||||
extern int oprio();
|
||||
extern VOID term();
|
||||
|
||||
/* aslist.c */
|
||||
extern VOID list();
|
||||
extern VOID list1();
|
||||
extern VOID list2();
|
||||
extern VOID lstsym();
|
||||
extern VOID slew();
|
||||
|
||||
/* asout.c */
|
||||
extern int hibyte();
|
||||
extern int lobyte();
|
||||
extern VOID out();
|
||||
extern VOID outab();
|
||||
extern VOID outarea();
|
||||
extern VOID outaw();
|
||||
extern VOID outall();
|
||||
extern VOID outdot();
|
||||
extern VOID outbuf();
|
||||
extern VOID outchk();
|
||||
extern VOID outgsd();
|
||||
extern VOID outrb();
|
||||
extern VOID outrw();
|
||||
extern VOID outsym();
|
||||
extern VOID out_lb();
|
||||
extern VOID out_lw();
|
||||
extern VOID out_rw();
|
||||
extern VOID out_tw();
|
||||
|
||||
|
||||
/* Machine dependent variables */
|
||||
|
||||
extern char * cpu;
|
||||
extern char * dsft;
|
||||
extern int hilo;
|
||||
extern struct mne mne[];
|
||||
|
||||
/* Machine dependent functions */
|
||||
|
||||
extern VOID minit();
|
||||
|
||||
1197
link/as/z80/asmain.c
Normal file
1197
link/as/z80/asmain.c
Normal file
File diff suppressed because it is too large
Load Diff
1084
link/as/z80/asout.c
Normal file
1084
link/as/z80/asout.c
Normal file
File diff suppressed because it is too large
Load Diff
254
link/as/z80/assubr.c
Normal file
254
link/as/z80/assubr.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/* assubr.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber, M. Hope
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include "asm.h"
|
||||
|
||||
/*)Module assubr.c
|
||||
*
|
||||
* The module assubr.c contains the error
|
||||
* processing routines.
|
||||
*
|
||||
* assubr.c contains the following functions:
|
||||
* VOID aerr()
|
||||
* VOID diag()
|
||||
* VOID err()
|
||||
* VOID qerr()
|
||||
* VOID rerr()
|
||||
*
|
||||
* assubr.c contains the local array of *error[]
|
||||
*/
|
||||
|
||||
/*)Function VOID err(c)
|
||||
*
|
||||
* int c error type character
|
||||
*
|
||||
* The function err() logs the error code character
|
||||
* suppressing duplicate errors. If the error code
|
||||
* is 'q' then the parse of the current assembler-source
|
||||
* text line is terminated.
|
||||
*
|
||||
* local variables:
|
||||
* char * p pointer to the error array
|
||||
*
|
||||
* global variables:
|
||||
* char eb[] array of generated error codes
|
||||
*
|
||||
* functions called:
|
||||
* VOID longjmp() c_library
|
||||
*
|
||||
* side effects:
|
||||
* The error code may be inserted into the
|
||||
* error code array eb[] or the parse terminated.
|
||||
*/
|
||||
|
||||
VOID
|
||||
err(c)
|
||||
register int c;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
#ifndef SDK
|
||||
aserr++;
|
||||
#endif /* SDK */
|
||||
p = eb;
|
||||
while (p < ep)
|
||||
if (*p++ == c)
|
||||
return;
|
||||
if (p < &eb[NERR]) {
|
||||
*p++ = c;
|
||||
ep = p;
|
||||
}
|
||||
if (c == 'q')
|
||||
longjmp(jump_env, -1);
|
||||
}
|
||||
|
||||
/*)Function VOID diag()
|
||||
*
|
||||
* The function diag() prints any error codes and
|
||||
* the source line number to the stderr output device.
|
||||
*
|
||||
* local variables:
|
||||
* char * p pointer to error code array eb[]
|
||||
*
|
||||
* global variables:
|
||||
* int cfile current source file index
|
||||
* char eb[] array of generated error codes
|
||||
* char * ep pointer into error list
|
||||
* int incfile current include file index
|
||||
* char incfn[] array of include file names
|
||||
* int incline[] array of include line numbers
|
||||
* char srcfn[] array of source file names
|
||||
* int srcline[] array of source line numbers
|
||||
* FILE * stderr c_library
|
||||
*
|
||||
* functions called:
|
||||
* int fprintf() c_library
|
||||
* char * geterr() assubr.c
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*/
|
||||
|
||||
VOID
|
||||
diag()
|
||||
{
|
||||
register char *p,*errstr;
|
||||
|
||||
if (eb != ep) {
|
||||
p = eb;
|
||||
#ifndef SDK
|
||||
fprintf(stderr, "?ASxxxx-Error-<");
|
||||
while (p < ep) {
|
||||
fprintf(stderr, "%c", *p++);
|
||||
}
|
||||
fprintf(stderr, "> in line ");
|
||||
if (incfil >= 0) {
|
||||
fprintf(stderr, "%d", incline[incfil]);
|
||||
fprintf(stderr, " of %s\n", incfn[incfil]);
|
||||
} else {
|
||||
fprintf(stderr, "%d", srcline[cfile]);
|
||||
fprintf(stderr, " of %s\n", srcfn[cfile]);
|
||||
}
|
||||
p = eb;
|
||||
#endif /* SDK */
|
||||
while (p < ep) {
|
||||
if ((errstr = geterr(*p++)) != NULL) {
|
||||
#ifdef SDK
|
||||
/* Modified to conform to gcc error standard, M. Hope, 7 Feb 98. */
|
||||
if (incfil >= 0) {
|
||||
fprintf(stderr, "%s:", incfn[incfil]);
|
||||
fprintf(stderr, "%d: Error:", incline[incfil]);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s:", srcfn[cfile]);
|
||||
fprintf(stderr, "%d: Error:", srcline[cfile]);
|
||||
}
|
||||
fprintf(stderr, " %s\n", errstr);
|
||||
#else
|
||||
fprintf(stderr, " %s\n", errstr);
|
||||
#endif /* SDK */
|
||||
}
|
||||
}
|
||||
#ifdef SDK
|
||||
aserr++;
|
||||
#endif /* SDK */
|
||||
}
|
||||
}
|
||||
|
||||
/*)Functions: VOID aerr()
|
||||
* VOID qerr()
|
||||
* VOID rerr()
|
||||
*
|
||||
* The functions aerr(), qerr(), and rerr() report their
|
||||
* respective error type. These are included only for
|
||||
* convenience.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* VOID err() assubr.c
|
||||
*
|
||||
* side effects:
|
||||
* The appropriate error code is inserted into the
|
||||
* error array and the parse may be terminated.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note an 'r' error.
|
||||
*/
|
||||
VOID
|
||||
rerr()
|
||||
{
|
||||
err('r');
|
||||
}
|
||||
|
||||
/*
|
||||
* Note an 'a' error.
|
||||
*/
|
||||
VOID
|
||||
aerr()
|
||||
{
|
||||
err('a');
|
||||
}
|
||||
|
||||
/*
|
||||
* Note a 'q' error.
|
||||
*/
|
||||
VOID
|
||||
qerr()
|
||||
{
|
||||
err('q');
|
||||
}
|
||||
|
||||
/*
|
||||
* ASxxxx assembler errors
|
||||
*/
|
||||
char *errors[] = {
|
||||
"<.> use \". = . + <arg>\" not \". = <arg>\"",
|
||||
"<a> machine specific addressing or addressing mode error",
|
||||
"<b> direct page boundary error",
|
||||
"<d> direct page addressing error",
|
||||
"<i> .include file error or an .if/.endif mismatch",
|
||||
"<m> multiple definitions error",
|
||||
"<o> .org in REL area or directive / mnemonic error",
|
||||
"<p> phase error: label location changing between passes 2 and 3",
|
||||
"<q> missing or improper operators, terminators, or delimiters",
|
||||
"<r> relocation error",
|
||||
"<u> undefined symbol encountered during assembly",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*)Function: char *getarr(c)
|
||||
*
|
||||
* int c the error code character
|
||||
*
|
||||
* The function geterr() scans the list of errors returning the
|
||||
* error string corresponding to the input error character.
|
||||
*
|
||||
* local variables:
|
||||
* int i error index counter
|
||||
*
|
||||
* global variables:
|
||||
* char *errors[] array of pointers to the
|
||||
* error strings
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* A pointer to the appropriate
|
||||
* error code string is returned.
|
||||
*/
|
||||
char *
|
||||
geterr(c)
|
||||
int c;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; errors[i]!=NULL; i++) {
|
||||
if (c == errors[i][1]) {
|
||||
return(errors[i]);
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
446
link/as/z80/assym.c
Normal file
446
link/as/z80/assym.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/* assym.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/malloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include "asm.h"
|
||||
|
||||
/*)Module assym.c
|
||||
*
|
||||
* The module assym.c contains the functions that operate
|
||||
* on the mnemonic/directive and symbol structures.
|
||||
*
|
||||
* assym.c contains the following functions:
|
||||
* VOID allglob()
|
||||
* area * alookup()
|
||||
* int hash()
|
||||
* sym * lookup()
|
||||
* mne * mlookup()
|
||||
* VOID * new()
|
||||
* int symeq()
|
||||
* VOID syminit()
|
||||
* VOID symglob()
|
||||
*
|
||||
* assym.c contains no local/static variables.
|
||||
*/
|
||||
|
||||
/*)Function VOID syminit()
|
||||
*
|
||||
* The function syminit() is called early in the game
|
||||
* to set up the hashtables. First all buckets in a
|
||||
* table are cleared. Then a pass is made through
|
||||
* the respective symbol lists, linking them into
|
||||
* their hash buckets. Finally the base area pointer
|
||||
* is set to 'dca'.
|
||||
*
|
||||
* local variables:
|
||||
* int h computed hash value
|
||||
* mne * mp pointer to a mne structure
|
||||
* mne ** mpp pointer to an array of
|
||||
* mne structure pointers
|
||||
* sym * sp pointer to a sym structure
|
||||
* sym ** spp pointer to an array of
|
||||
* sym structure pointers
|
||||
*
|
||||
* global variables:
|
||||
* area area[] single elememt area array
|
||||
* area dca defined as area[0]
|
||||
* mne * mnehash[] array of pointers to NHASH
|
||||
* linked mnemonic/directive lists
|
||||
* sym * symhash[] array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* (1) The symbol hash tables are initialized,
|
||||
* the only defined symbol is '.'.
|
||||
* (2) The mnemonic/directive hash tables are
|
||||
* initialized with the assembler directives
|
||||
* and mnemonics found in the machine dependent
|
||||
* file ___pst.c.
|
||||
* (3) The area pointer is initialized to dca (area[0]).
|
||||
*/
|
||||
|
||||
VOID
|
||||
syminit()
|
||||
{
|
||||
register struct mne *mp;
|
||||
struct mne **mpp;
|
||||
register struct sym *sp;
|
||||
struct sym **spp;
|
||||
register int h;
|
||||
|
||||
mpp = &mnehash[0];
|
||||
while (mpp < &mnehash[NHASH])
|
||||
*mpp++ = NULL;
|
||||
mp = &mne[0];
|
||||
for (;;) {
|
||||
h = hash(mp->m_id);
|
||||
mp->m_mp = mnehash[h];
|
||||
mnehash[h] = mp;
|
||||
if (mp->m_flag&S_END)
|
||||
break;
|
||||
++mp;
|
||||
}
|
||||
|
||||
spp = &symhash[0];
|
||||
while (spp < &symhash[NHASH])
|
||||
*spp++ = NULL;
|
||||
sp = &sym[0];
|
||||
for (;;) {
|
||||
h = hash(sp->s_id);
|
||||
sp->s_sp = symhash[h];
|
||||
symhash[h] = sp;
|
||||
if (sp->s_flag&S_END)
|
||||
break;
|
||||
++sp;
|
||||
}
|
||||
|
||||
areap = &dca;
|
||||
}
|
||||
|
||||
/*)Function area * alookup(id)
|
||||
*
|
||||
* char * id area name string
|
||||
*
|
||||
* The function alookup() searches the area list for a
|
||||
* match with id. If the area is defined then a pointer
|
||||
* to this area is returned else a NULL is returned.
|
||||
*
|
||||
* local variables:
|
||||
* area * ap pointer to area structure
|
||||
*
|
||||
* global variables:
|
||||
* area * areap pointer to an area structure
|
||||
*
|
||||
* functions called:
|
||||
* int symeq() assym.c
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*/
|
||||
|
||||
struct area *
|
||||
alookup(id)
|
||||
char *id;
|
||||
{
|
||||
register struct area *ap;
|
||||
|
||||
ap = areap;
|
||||
while (ap) {
|
||||
if (symeq(id, ap->a_id)) {
|
||||
return (ap);
|
||||
}
|
||||
ap = ap->a_ap;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*)Function mne * mlookup(id)
|
||||
*
|
||||
* char * id mnemonic/directive name string
|
||||
*
|
||||
* The function mlookup() searches the mnemonic/directive
|
||||
* hash tables for a match returning a pointer to the
|
||||
* mne structure else it returns a NULL.
|
||||
*
|
||||
* local variables:
|
||||
* mne * mp pointer to mne structure
|
||||
* int h calculated hash value
|
||||
*
|
||||
* global variables:
|
||||
* mne * mnehash[] array of pointers to NHASH
|
||||
* linked mnemonic/directive lists
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*/
|
||||
|
||||
struct mne *
|
||||
mlookup(id)
|
||||
char *id;
|
||||
{
|
||||
register struct mne *mp;
|
||||
register int h;
|
||||
|
||||
h = hash(id);
|
||||
mp = mnehash[h];
|
||||
while (mp) {
|
||||
if (symeq(id, mp->m_id))
|
||||
return (mp);
|
||||
mp = mp->m_mp;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*)Function sym * lookup(id)
|
||||
*
|
||||
* char * id symbol name string
|
||||
*
|
||||
* The function lookup() searches the symbol hash tables for
|
||||
* a symbol name match returning a pointer to the sym structure.
|
||||
* If the symbol is not found then a sym structure is created,
|
||||
* initialized, and linked to the appropriate hash table.
|
||||
* A pointer to this new sym structure is returned.
|
||||
*
|
||||
* local variables:
|
||||
* int h computed hash value
|
||||
* sym * sp pointer to a sym structure
|
||||
*
|
||||
* global varaibles:
|
||||
* sym * symhash[] array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*
|
||||
* functions called:
|
||||
* int hash() assym.c
|
||||
* VOID * new() assym.c
|
||||
* int symeq() assym.c
|
||||
*
|
||||
* side effects:
|
||||
* If the function new() fails to allocate space
|
||||
* for the new sym structure the assembly terminates.
|
||||
*/
|
||||
|
||||
struct sym *
|
||||
lookup(id)
|
||||
char *id;
|
||||
{
|
||||
register struct sym *sp;
|
||||
register int h;
|
||||
|
||||
h = hash(id);
|
||||
sp = symhash[h];
|
||||
while (sp) {
|
||||
if (symeq(id, sp->s_id))
|
||||
return (sp);
|
||||
sp = sp->s_sp;
|
||||
}
|
||||
sp = (struct sym *) new (sizeof(struct sym));
|
||||
sp->s_sp = symhash[h];
|
||||
symhash[h] = sp;
|
||||
sp->s_tsym = NULL;
|
||||
strncpy(sp->s_id, id, NCPS);
|
||||
sp->s_type = S_NEW;
|
||||
sp->s_flag = 0;
|
||||
sp->s_area = NULL;
|
||||
sp->s_ref = 0;
|
||||
sp->s_addr = 0;
|
||||
return (sp);
|
||||
}
|
||||
|
||||
/*)Function VOID symglob()
|
||||
*
|
||||
* The function symglob() will mark all symbols of
|
||||
* type S_NEW as global. Called at the beginning of pass 1
|
||||
* if the assembly option -g was specified.
|
||||
*
|
||||
* local variables:
|
||||
* sym * sp pointer to a sym structure
|
||||
* int i loop index
|
||||
*
|
||||
* global variables:
|
||||
* sym * symhash[] array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* Symbol types changed.
|
||||
*/
|
||||
|
||||
VOID
|
||||
symglob()
|
||||
{
|
||||
register struct sym *sp;
|
||||
register int i;
|
||||
|
||||
for (i=0; i<NHASH; ++i) {
|
||||
sp = symhash[i];
|
||||
while (sp != NULL) {
|
||||
if (sp->s_type == S_NEW)
|
||||
sp->s_flag |= S_GBL;
|
||||
sp = sp->s_sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function VOID allglob()
|
||||
*
|
||||
* The function allglob() will mark all symbols of
|
||||
* type S_USER as global. Called at the beginning of pass 1
|
||||
* if the assembly option -a was specified.
|
||||
*
|
||||
* local variables:
|
||||
* sym * sp pointer to a sym structure
|
||||
* int i loop index
|
||||
*
|
||||
* global variables:
|
||||
* sym * symhash[] array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* Symbol types changed.
|
||||
*/
|
||||
|
||||
VOID
|
||||
allglob()
|
||||
{
|
||||
register struct sym *sp;
|
||||
register int i;
|
||||
|
||||
for (i=0; i<NHASH; ++i) {
|
||||
sp = symhash[i];
|
||||
while (sp != NULL) {
|
||||
if (sp != &dot && sp->s_type == S_USER)
|
||||
sp->s_flag |= S_GBL;
|
||||
sp = sp->s_sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function int symeq(p1, p2)
|
||||
*
|
||||
* char * p1 name string
|
||||
* char * p2 name string
|
||||
*
|
||||
* The function symeq() compares the two name strings for a match.
|
||||
* The return value is 1 for a match and 0 for no match.
|
||||
*
|
||||
* local variables:
|
||||
* int h loop counter
|
||||
*
|
||||
* global variables:
|
||||
* char ccase[] an array of characters which
|
||||
* perform the case translation function
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* none
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
symeq(p1, p2)
|
||||
register char *p1, *p2;
|
||||
{
|
||||
register int n;
|
||||
|
||||
n = NCPS;
|
||||
do {
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
if (*p1++ != *p2++)
|
||||
return (0);
|
||||
#else
|
||||
if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
} while (--n);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*)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, n;
|
||||
|
||||
h = 0;
|
||||
n = NCPS;
|
||||
do {
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
h += *p++;
|
||||
#else
|
||||
h += ccase[(unsigned char)(*p++)];
|
||||
#endif
|
||||
|
||||
} while (--n);
|
||||
return (h&HMASK);
|
||||
}
|
||||
|
||||
/*)Function VOID * new(n)
|
||||
*
|
||||
* unsigned int n allocation size in bytes
|
||||
*
|
||||
* The function new() allocates n bytes of space and returns
|
||||
* a pointer to this memory. If no space is available the
|
||||
* assembly is terminated.
|
||||
*
|
||||
* local variables:
|
||||
* VOID * p a general pointer
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* functions called:
|
||||
* VOID asexit() asmain.c
|
||||
* int fprintf() c_library
|
||||
* VOID * malloc() c_library
|
||||
*
|
||||
* side effects:
|
||||
* Memory is allocated, if allocation fails
|
||||
* the assembly is terminated.
|
||||
*/
|
||||
|
||||
VOID *
|
||||
new(n)
|
||||
unsigned int n;
|
||||
{
|
||||
register VOID *p;
|
||||
|
||||
if ((p = (VOID *) malloc(n)) == NULL) {
|
||||
fprintf(stderr, "Out of space!\n");
|
||||
asexit(1);
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
23
link/as/z80/clean.mk
Normal file
23
link/as/z80/clean.mk
Normal file
@@ -0,0 +1,23 @@
|
||||
# Deleting all files created by building the program
|
||||
# --------------------------------------------------
|
||||
clean:
|
||||
rm -rf obj
|
||||
rm -f *core *[%~] *.[oa]
|
||||
rm -f .[a-z]*~
|
||||
rm -f $(PRJDIR)/as-z80 as-z80
|
||||
|
||||
# Deleting all files created by configuring or building the program
|
||||
# -----------------------------------------------------------------
|
||||
distclean: clean
|
||||
rm -f *.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
|
||||
23
link/as/z80/conf.mk
Normal file
23
link/as/z80/conf.mk
Normal file
@@ -0,0 +1,23 @@
|
||||
# Deleting all files created by building the program
|
||||
# --------------------------------------------------
|
||||
clean:
|
||||
rm -f *core *[%~] *.[oa]
|
||||
rm -f .[a-z]*~
|
||||
rm -f $(PRJDIR)/as-z80 as-z80
|
||||
|
||||
|
||||
# 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
|
||||
10
link/as/z80/incld1.asm
Normal file
10
link/as/z80/incld1.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
xxx ;1
|
||||
.include "incld2.asm" ;2
|
||||
;3
|
||||
;4
|
||||
;5
|
||||
xxx ;6
|
||||
;7
|
||||
;8
|
||||
;9
|
||||
;10
|
||||
10
link/as/z80/incld2.asm
Normal file
10
link/as/z80/incld2.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
;1
|
||||
xxx ;2
|
||||
.include "incld3.asm" ;3
|
||||
;4
|
||||
;5
|
||||
;6
|
||||
xxx ;7
|
||||
;8
|
||||
;9
|
||||
;10
|
||||
10
link/as/z80/incld3.asm
Normal file
10
link/as/z80/incld3.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
;1
|
||||
;2
|
||||
xxx ;3
|
||||
.include "incld4.asm" ;4
|
||||
;5
|
||||
;6
|
||||
;7
|
||||
xxx ;8
|
||||
;9
|
||||
;10
|
||||
10
link/as/z80/incld4.asm
Normal file
10
link/as/z80/incld4.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
;1
|
||||
;2
|
||||
;3
|
||||
xxx ;4
|
||||
.include "incld5.asm" ;5
|
||||
;6
|
||||
;7
|
||||
;8
|
||||
xxx ;9
|
||||
;10
|
||||
10
link/as/z80/incld5.asm
Normal file
10
link/as/z80/incld5.asm
Normal file
@@ -0,0 +1,10 @@
|
||||
;1
|
||||
;2
|
||||
;3
|
||||
;4
|
||||
xxx ;5
|
||||
.include "incldx.asm" ;6
|
||||
;7
|
||||
;8
|
||||
;9
|
||||
xxx ;10
|
||||
42
link/as/z80/itsta.asm
Normal file
42
link/as/z80/itsta.asm
Normal file
@@ -0,0 +1,42 @@
|
||||
.include "incld1.asm" ;1
|
||||
;2
|
||||
;3
|
||||
;4
|
||||
;5
|
||||
;6
|
||||
;7
|
||||
;8
|
||||
;9
|
||||
;10
|
||||
xxx ;11
|
||||
;
|
||||
; This is a simple test of the error reporting
|
||||
; for source and include files.
|
||||
;
|
||||
; assemble inctst:
|
||||
; asxxxx itsta itstb
|
||||
;
|
||||
; ?ASxxxx-E-<o> in line 1 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 2 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 3 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 4 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 5 of incld5.asm
|
||||
; ?ASxxxx-E-<i> in line 6 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 10 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 9 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 8 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 7 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 6 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 11 of itsta.asm
|
||||
; ?ASxxxx-E-<o> in line 1 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 2 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 3 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 4 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 5 of incld5.asm
|
||||
; ?ASxxxx-E-<i> in line 6 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 10 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 9 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 8 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 7 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 6 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 11 of itstb.asm
|
||||
42
link/as/z80/itstb.asm
Normal file
42
link/as/z80/itstb.asm
Normal file
@@ -0,0 +1,42 @@
|
||||
.include "incld1.asm" ;1
|
||||
;2
|
||||
;3
|
||||
;4
|
||||
;5
|
||||
;6
|
||||
;7
|
||||
;8
|
||||
;9
|
||||
;10
|
||||
xxx ;11
|
||||
;
|
||||
; This is a simple test of the error reporting
|
||||
; for source and include files.
|
||||
;
|
||||
; assemble inctst:
|
||||
; asxxxx itsta itstb
|
||||
;
|
||||
; ?ASxxxx-E-<o> in line 1 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 2 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 3 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 4 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 5 of incld5.asm
|
||||
; ?ASxxxx-E-<i> in line 6 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 10 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 9 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 8 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 7 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 6 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 11 of itsta.asm
|
||||
; ?ASxxxx-E-<o> in line 1 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 2 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 3 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 4 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 5 of incld5.asm
|
||||
; ?ASxxxx-E-<i> in line 6 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 10 of incld5.asm
|
||||
; ?ASxxxx-E-<o> in line 9 of incld4.asm
|
||||
; ?ASxxxx-E-<o> in line 8 of incld3.asm
|
||||
; ?ASxxxx-E-<o> in line 7 of incld2.asm
|
||||
; ?ASxxxx-E-<o> in line 6 of incld1.asm
|
||||
; ?ASxxxx-E-<o> in line 11 of itstb.asm
|
||||
15
link/as/z80/string.h
Normal file
15
link/as/z80/string.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* STRING.H */
|
||||
/* DECUC C */
|
||||
|
||||
extern char * strcat();
|
||||
extern char * strchr();
|
||||
extern int strcmp();
|
||||
extern char * strcpy();
|
||||
extern int streq();
|
||||
extern int strlen();
|
||||
extern char * strncat();
|
||||
extern int strncmp();
|
||||
extern char * strncpy();
|
||||
extern int strneq();
|
||||
extern char * strrchr();
|
||||
|
||||
68
link/as/z80/tconst.asm
Normal file
68
link/as/z80/tconst.asm
Normal file
@@ -0,0 +1,68 @@
|
||||
.title Assembler Link Test Constants
|
||||
|
||||
.module tconst
|
||||
|
||||
.area TEST (ABS,OVR)
|
||||
|
||||
bra1 == 0 ; branching constants
|
||||
bra2 == 0x80
|
||||
bra3 == 0x182
|
||||
bra4 == 0x204
|
||||
|
||||
.blkb 0x7E ;bra1:
|
||||
.blkb 0x02
|
||||
.blkb 0x7F ;bra2:
|
||||
.blkb 0x02
|
||||
.blkb 0x02
|
||||
.blkb 0x7F
|
||||
.blkb 0x00 ;bra3:
|
||||
.blkb 0x02
|
||||
.blkb 0x80
|
||||
.blkb 0x00 ;bra4:
|
||||
|
||||
.globl bra5,bra6,bra7,bra8
|
||||
|
||||
; branching labels
|
||||
bra5: .blkb 0x7E ;bra5:
|
||||
.blkb 0x02
|
||||
bra6: .blkb 0x7F ;bra6:
|
||||
.blkb 0x02
|
||||
.blkb 0x02
|
||||
.blkb 0x7F
|
||||
bra7: .blkb 0x00 ;bra7:
|
||||
.blkb 0x02
|
||||
.blkb 0x80
|
||||
bra8: .blkb 0x00 ;bra8:
|
||||
|
||||
|
||||
; 12-Bit numbers are considered valid if:
|
||||
; 1) the most significant 4 bits of the 16-bit number are zero
|
||||
; 2) the most significant 4 bits of the 16-bit number are all ones
|
||||
|
||||
n0FFF == 0x0FFF ;largest positive
|
||||
n1000 == 0x1000 ;+1
|
||||
|
||||
nF000 == 0xF000 ;largest negative
|
||||
nEFFF == 0xEFFF ;-1
|
||||
|
||||
|
||||
.area DIRECT (ABS,OVR)
|
||||
.setdp
|
||||
|
||||
boundary == 0x101
|
||||
|
||||
minus1 == -1 ; paging / indexing constants
|
||||
zero == 0
|
||||
two55 == 0d255
|
||||
two56 == 0d256
|
||||
five11 == 0d511
|
||||
five12 == 0d512
|
||||
|
||||
|
||||
.globl lzero,ltwo55,ltwo56,lminus1
|
||||
|
||||
lzero: .blkb 0x00FF ; paging labels
|
||||
ltwo55: .blkb 0x0001
|
||||
ltwo56: .blkb 0xFEFF
|
||||
lminus1:.blkb 0d0000
|
||||
|
||||
1013
link/as/z80/tz80.asm
Normal file
1013
link/as/z80/tz80.asm
Normal file
File diff suppressed because it is too large
Load Diff
47
link/as/z80/tz80l.asm
Normal file
47
link/as/z80/tz80l.asm
Normal file
@@ -0,0 +1,47 @@
|
||||
.sbttl Assembler Link Tests
|
||||
|
||||
.module tz80l
|
||||
|
||||
; This file and TCONST.ASM should be assembled and linked.
|
||||
;
|
||||
; ASZ80 -XGOL TZ80L
|
||||
; ASZ80 -XGOL TCONST
|
||||
;
|
||||
; ASLINK -C
|
||||
; -XMS
|
||||
; TZ80L
|
||||
; TCONST
|
||||
; -E
|
||||
;
|
||||
; The following tests verify the correct processing of
|
||||
; external references for the branches.
|
||||
;
|
||||
; *L signifies an error will be reported at link time.
|
||||
|
||||
; branch test must be first
|
||||
|
||||
.area TEST (ABS,OVR)
|
||||
|
||||
.blkb 0x7E ;bra1:
|
||||
jr C,bra1 ; 38 00 [38 80]
|
||||
.blkb 0x7F ;bra2:
|
||||
jr C,bra2 ;*L 38 00 [38 7F]
|
||||
jr C,bra3 ; 38 00 [38 7F]
|
||||
.blkb 0x7F
|
||||
.blkb 0x00 ;bra3:
|
||||
jr C,bra4 ;*L 38 00 [38 [80]
|
||||
.blkb 0x80
|
||||
.blkb 0x00 ;bra4:
|
||||
|
||||
.blkb 0x7E ;bra5:
|
||||
jr C,bra5 ; 38 00 [38 80]
|
||||
.blkb 0x7F ;bra6:
|
||||
jr C,bra6 ;*L 38 00 [38 7F]
|
||||
jr C,bra7 ; 38 00 [38 7F]
|
||||
.blkb 0x7F
|
||||
.blkb 0x00 ;bra7:
|
||||
jr C,bra8 ;*L 38 00 [38 [80]
|
||||
.blkb 0x80
|
||||
.blkb 0x00 ;bra8:
|
||||
|
||||
|
||||
191
link/as/z80/z80.h
Normal file
191
link/as/z80/z80.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/* z80.h */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
/*)BUILD
|
||||
$(PROGRAM) = ASZ80
|
||||
$(INCLUDE) = {
|
||||
ASM.H
|
||||
Z80.H
|
||||
}
|
||||
$(FILES) = {
|
||||
Z80EXT.C
|
||||
Z80MCH.C
|
||||
Z80ADR.C
|
||||
Z80PST.C
|
||||
ASMAIN.C
|
||||
ASLEX.C
|
||||
ASSYM.C
|
||||
ASSUBR.C
|
||||
ASEXPR.C
|
||||
ASDATA.C
|
||||
ASLIST.C
|
||||
ASOUT.C
|
||||
}
|
||||
$(STACK) = 2000
|
||||
*/
|
||||
|
||||
/*
|
||||
* Indirect Addressing delimeters
|
||||
*/
|
||||
#define LFIND '('
|
||||
#define RTIND ')'
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
#define B 0
|
||||
#define C 1
|
||||
#define D 2
|
||||
#define E 3
|
||||
#define H 4
|
||||
#define L 5
|
||||
#define A 7
|
||||
|
||||
#define I 0107
|
||||
#define R 0117
|
||||
|
||||
#define BC 0
|
||||
#define DE 1
|
||||
#define HL 2
|
||||
#define SP 3
|
||||
#define AF 4
|
||||
#ifndef GAMEBOY
|
||||
#define IX 5
|
||||
#define IY 6
|
||||
#else /* GAMEBOY */
|
||||
#define HLD 5
|
||||
#define HLI 6
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
/*
|
||||
* Conditional definitions
|
||||
*/
|
||||
#define NZ 0
|
||||
#define Z 1
|
||||
#define NC 2
|
||||
#define CS 3
|
||||
#ifndef GAMEBOY
|
||||
#define PO 4
|
||||
#define PE 5
|
||||
#define P 6
|
||||
#define M 7
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
/*
|
||||
* Symbol types
|
||||
*/
|
||||
#define S_IMMED 30
|
||||
#define S_R8 31
|
||||
#define S_R8X 32
|
||||
#define S_R16 33
|
||||
#define S_R16X 34
|
||||
#define S_CND 35
|
||||
#define S_FLAG 36
|
||||
|
||||
/*
|
||||
* Indexing modes
|
||||
*/
|
||||
#define S_INDB 40
|
||||
#define S_IDC 41
|
||||
#define S_INDR 50
|
||||
#define S_IDBC 50
|
||||
#define S_IDDE 51
|
||||
#define S_IDHL 52
|
||||
#define S_IDSP 53
|
||||
#ifndef GAMEBOY
|
||||
#define S_IDIX 55
|
||||
#define S_IDIY 56
|
||||
#else /* GAMEBOY */
|
||||
#define S_IDHLD 55
|
||||
#define S_IDHLI 56
|
||||
#endif /* GAMEBOY */
|
||||
#define S_INDM 57
|
||||
|
||||
/*
|
||||
* Instruction types
|
||||
*/
|
||||
#define S_LD 60
|
||||
#define S_CALL 61
|
||||
#define S_JP 62
|
||||
#define S_JR 63
|
||||
#define S_RET 64
|
||||
#define S_BIT 65
|
||||
#define S_INC 66
|
||||
#define S_DEC 67
|
||||
#define S_ADD 68
|
||||
#define S_ADC 69
|
||||
#define S_AND 70
|
||||
#ifndef GAMEBOY
|
||||
#define S_EX 71
|
||||
#endif /* GAMEBOY */
|
||||
#define S_PUSH 72
|
||||
#ifndef GAMEBOY
|
||||
#define S_IN 73
|
||||
#define S_OUT 74
|
||||
#endif /* GAMEBOY */
|
||||
#define S_RL 75
|
||||
#define S_RST 76
|
||||
#define S_IM 77
|
||||
#define S_INH1 78
|
||||
#ifndef GAMEBOY
|
||||
#define S_INH2 79
|
||||
#define S_DJNZ 80
|
||||
#endif /* GAMEBOY */
|
||||
#define S_SUB 81
|
||||
#define S_SBC 82
|
||||
#ifdef GAMEBOY
|
||||
#define S_STOP 83
|
||||
#define S_LDH 84
|
||||
#define S_LDA 85
|
||||
#define S_LDHL 86
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
/*
|
||||
* HD64180 Instructions
|
||||
*/
|
||||
#define X_HD64 90
|
||||
#define X_INH2 91
|
||||
#define X_IN 92
|
||||
#define X_OUT 93
|
||||
#define X_MLT 94
|
||||
#define X_TST 95
|
||||
#define X_TSTIO 96
|
||||
|
||||
struct adsym
|
||||
{
|
||||
char a_str[4]; /* addressing string */
|
||||
int a_val; /* addressing mode value */
|
||||
};
|
||||
|
||||
extern struct adsym R8[];
|
||||
extern struct adsym R8X[];
|
||||
extern struct adsym R16[];
|
||||
extern struct adsym R16X[];
|
||||
extern struct adsym CND[];
|
||||
|
||||
/* machine dependent functions */
|
||||
|
||||
/* z80adr.c */
|
||||
extern int addr();
|
||||
extern int admode();
|
||||
extern int any();
|
||||
extern int srch();
|
||||
|
||||
/* z80mch.c */
|
||||
extern int comma();
|
||||
extern int genop();
|
||||
extern int gixiy();
|
||||
extern VOID minit();
|
||||
extern VOID machine(struct mne *mp) ;
|
||||
256
link/as/z80/z80adr.c
Normal file
256
link/as/z80/z80adr.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* z80adr.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include "asm.h"
|
||||
#include "z80.h"
|
||||
|
||||
/*
|
||||
* Read an address specifier. Pack the
|
||||
* address information into the supplied
|
||||
* `expr' structure. Return the mode of
|
||||
* the address.
|
||||
*
|
||||
* This addr(esp) routine performs the following addressing decoding:
|
||||
*
|
||||
* address mode flag addr base
|
||||
* #n S_IMMED 0 n NULL
|
||||
* label s_type ---- s_addr s_area
|
||||
* [REG] S_IND+icode 0 0 NULL
|
||||
* [label] S_INDM ---- s_addr s_area
|
||||
* offset[REG] S_IND+icode ---- offset ----
|
||||
*/
|
||||
int
|
||||
addr(esp)
|
||||
register struct expr *esp;
|
||||
{
|
||||
register int c, mode = 0, indx;
|
||||
|
||||
if ((c = getnb()) == '#') {
|
||||
expr(esp, 0);
|
||||
esp->e_mode = S_IMMED;
|
||||
} else
|
||||
if (c == LFIND) {
|
||||
if ((indx = admode(R8)) != 0) {
|
||||
mode = S_INDB;
|
||||
} else
|
||||
if ((indx = admode(R16)) != 0) {
|
||||
mode = S_INDR;
|
||||
} else
|
||||
if ((indx = admode(R8X)) != 0) {
|
||||
mode = S_R8X;
|
||||
aerr();
|
||||
} else
|
||||
if ((indx = admode(R16X)) != 0) {
|
||||
mode = S_R16X;
|
||||
aerr();
|
||||
} else {
|
||||
expr(esp, 0);
|
||||
esp->e_mode = S_INDM;
|
||||
}
|
||||
if (indx) {
|
||||
esp->e_mode = (mode + indx)&0xFF;
|
||||
esp->e_base.e_ap = NULL;
|
||||
}
|
||||
if ((c = getnb()) != RTIND)
|
||||
qerr();
|
||||
} else {
|
||||
unget(c);
|
||||
if ((indx = admode(R8)) != 0) {
|
||||
mode = S_R8;
|
||||
} else
|
||||
if ((indx = admode(R16)) != 0) {
|
||||
mode = S_R16;
|
||||
} else
|
||||
if ((indx = admode(R8X)) != 0) {
|
||||
mode = S_R8X;
|
||||
} else
|
||||
if ((indx = admode(R16X)) != 0) {
|
||||
mode = S_R16X;
|
||||
} else {
|
||||
expr(esp, 0);
|
||||
esp->e_mode = S_USER;
|
||||
}
|
||||
if (indx) {
|
||||
esp->e_addr = indx&0xFF;
|
||||
esp->e_mode = mode;
|
||||
esp->e_base.e_ap = NULL;
|
||||
}
|
||||
if ((c = getnb()) == LFIND) {
|
||||
#ifndef GAMEBOY
|
||||
if ((indx=admode(R16))!=0
|
||||
&& ((indx&0xFF)==IX || (indx&0xFF)==IY)) {
|
||||
#else /* GAMEBOY */
|
||||
if ((indx=admode(R16))!=0) {
|
||||
#endif /* GAMEBOY */
|
||||
esp->e_mode = S_INDR + (indx&0xFF);
|
||||
} else {
|
||||
aerr();
|
||||
}
|
||||
if ((c = getnb()) != RTIND)
|
||||
qerr();
|
||||
} else {
|
||||
unget(c);
|
||||
}
|
||||
}
|
||||
return (esp->e_mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter admode() to search a specific addressing mode table
|
||||
* for a match. Return the addressing value on a match or
|
||||
* zero for no match.
|
||||
*/
|
||||
int
|
||||
admode(sp)
|
||||
register struct adsym *sp;
|
||||
{
|
||||
register char *ptr;
|
||||
register int i;
|
||||
register char *ips;
|
||||
|
||||
ips = ip;
|
||||
unget(getnb());
|
||||
|
||||
i = 0;
|
||||
while ( *(ptr = (char *) &sp[i]) ) {
|
||||
if (srch(ptr)) {
|
||||
return(sp[i].a_val);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ip = ips;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* srch --- does string match ?
|
||||
*/
|
||||
int
|
||||
srch(str)
|
||||
register char *str;
|
||||
{
|
||||
register char *ptr;
|
||||
ptr = ip;
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
while (*ptr && *str) {
|
||||
if (*ptr != *str)
|
||||
break;
|
||||
ptr++;
|
||||
str++;
|
||||
}
|
||||
if (*ptr == *str) {
|
||||
ip = ptr;
|
||||
return(1);
|
||||
}
|
||||
#else
|
||||
while (*ptr && *str) {
|
||||
if (ccase[(unsigned char)(*ptr)] != ccase[(unsigned char)(*str)])
|
||||
break;
|
||||
ptr++;
|
||||
str++;
|
||||
}
|
||||
if (ccase[(unsigned char)(*ptr)] == ccase[(unsigned char)(*str)]) {
|
||||
ip = ptr;
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!*str)
|
||||
if (any(*ptr," \t\n,);")) {
|
||||
ip = ptr;
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* any --- does str contain c?
|
||||
*/
|
||||
int
|
||||
any(c,str)
|
||||
char c, *str;
|
||||
{
|
||||
while (*str)
|
||||
if(*str++ == c)
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
|
||||
struct adsym R8[] = {
|
||||
{ "b", B|0400 },
|
||||
{ "c", C|0400 },
|
||||
{ "d", D|0400 },
|
||||
{ "e", E|0400 },
|
||||
{ "h", H|0400 },
|
||||
{ "l", L|0400 },
|
||||
{ "a", A|0400 },
|
||||
{ "", 000 }
|
||||
};
|
||||
|
||||
struct adsym R8X[] = {
|
||||
{ "i", I|0400 },
|
||||
{ "r", R|0400 },
|
||||
{ "", 000 }
|
||||
};
|
||||
|
||||
struct adsym R16[] = {
|
||||
{ "bc", BC|0400 },
|
||||
{ "de", DE|0400 },
|
||||
{ "hl", HL|0400 },
|
||||
{ "sp", SP|0400 },
|
||||
#ifndef GAMEBOY
|
||||
{ "ix", IX|0400 },
|
||||
{ "iy", IY|0400 },
|
||||
#else /* GAMEBOY */
|
||||
{ "hl-", HLD|0400 },
|
||||
{ "hl+", HLI|0400 },
|
||||
{ "hld", HLD|0400 },
|
||||
{ "hli", HLI|0400 },
|
||||
#endif /* GAMEBOY */
|
||||
{ "", 000 }
|
||||
};
|
||||
|
||||
struct adsym R16X[] = {
|
||||
{ "af", AF|0400 },
|
||||
#ifndef GAMEBOY
|
||||
{ "af'", AF|0400 },
|
||||
#endif /* GAMEBOY */
|
||||
{ "", 000 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Conditional definitions
|
||||
*/
|
||||
|
||||
struct adsym CND[] = {
|
||||
{ "NZ", NZ|0400 },
|
||||
{ "Z", Z |0400 },
|
||||
{ "NC", NC|0400 },
|
||||
{ "C", CS|0400 },
|
||||
#ifndef GAMEBOY
|
||||
{ "PO", PO|0400 },
|
||||
{ "PE", PE|0400 },
|
||||
{ "P", P |0400 },
|
||||
{ "M", M |0400 },
|
||||
#endif /* GAMEBOY */
|
||||
{ "", 000 }
|
||||
};
|
||||
27
link/as/z80/z80ext.c
Normal file
27
link/as/z80/z80ext.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* z80ext.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include "asm.h"
|
||||
#include "z80.h"
|
||||
|
||||
#ifndef GAMEBOY
|
||||
char *cpu = "Zilog Z80 / Hitachi HD64180";
|
||||
#else /* GAMEBOY */
|
||||
char *cpu = "GameBoy Z80-like CPU";
|
||||
#endif /* GAMEBOY */
|
||||
int hilo = 0;
|
||||
char *dsft = "ASM";
|
||||
773
link/as/z80/z80mch.c
Normal file
773
link/as/z80/z80mch.c
Normal file
@@ -0,0 +1,773 @@
|
||||
/* z80mch.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include "asm.h"
|
||||
#include "z80.h"
|
||||
|
||||
char imtab[3] = { 0x46, 0x56, 0x5E };
|
||||
#ifndef GAMEBOY
|
||||
int hd64;
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
/*
|
||||
* Process a machine op.
|
||||
*/
|
||||
VOID
|
||||
machine(mp)
|
||||
struct mne *mp;
|
||||
{
|
||||
register int op, t1, t2;
|
||||
struct expr e1, e2;
|
||||
int rf, v1, v2;
|
||||
|
||||
clrexpr(&e1);
|
||||
clrexpr(&e2);
|
||||
op = mp->m_valu;
|
||||
rf = mp->m_type;
|
||||
#ifndef GAMEBOY
|
||||
if (!hd64 && rf>X_HD64)
|
||||
rf = 0;
|
||||
#endif /* GAMEBOY */
|
||||
switch (rf) {
|
||||
|
||||
case S_INH1:
|
||||
outab(op);
|
||||
break;
|
||||
|
||||
#ifndef GAMEBOY
|
||||
case S_INH2:
|
||||
outab(0xED);
|
||||
outab(op);
|
||||
break;
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
case S_RET:
|
||||
if (more()) {
|
||||
if ((v1 = admode(CND)) != 0) {
|
||||
outab(op | v1<<3);
|
||||
} else {
|
||||
qerr();
|
||||
}
|
||||
} else {
|
||||
outab(0xC9);
|
||||
}
|
||||
break;
|
||||
|
||||
case S_PUSH:
|
||||
if (admode(R16X)) {
|
||||
outab(op+0x30);
|
||||
break;
|
||||
} else
|
||||
if ((v1 = admode(R16)) != 0 && (v1 &= 0xFF) != SP) {
|
||||
if (v1 != gixiy(v1)) {
|
||||
outab(op+0x20);
|
||||
break;
|
||||
}
|
||||
outab(op | v1<<4);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case S_RST:
|
||||
v1 = absexpr();
|
||||
if (v1 & ~0x38) {
|
||||
aerr();
|
||||
v1 = 0;
|
||||
}
|
||||
outab(op|v1);
|
||||
break;
|
||||
|
||||
case S_IM:
|
||||
expr(&e1, 0);
|
||||
abscheck(&e1);
|
||||
if (e1.e_addr > 2) {
|
||||
aerr();
|
||||
e1.e_addr = 0;
|
||||
}
|
||||
outab(op);
|
||||
outab(imtab[e1.e_addr]);
|
||||
break;
|
||||
|
||||
case S_BIT:
|
||||
expr(&e1, 0);
|
||||
t1 = 0;
|
||||
v1 = e1.e_addr;
|
||||
if (v1 > 7) {
|
||||
++t1;
|
||||
v1 &= 0x07;
|
||||
}
|
||||
op |= (v1<<3);
|
||||
comma();
|
||||
addr(&e2);
|
||||
abscheck(&e1);
|
||||
if (genop(0xCB, op, &e2, 0) || t1)
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case S_RL:
|
||||
t1 = 0;
|
||||
t2 = addr(&e2);
|
||||
if (more()) {
|
||||
if ((t2 != S_R8) || (e2.e_addr != A))
|
||||
++t1;
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
}
|
||||
if (genop(0xCB, op, &e2, 0) || t1)
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case S_AND:
|
||||
case S_SUB:
|
||||
t1 = 0;
|
||||
t2 = addr(&e2);
|
||||
if (more()) {
|
||||
if ((t2 != S_R8) || (e2.e_addr != A))
|
||||
++t1;
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
}
|
||||
if (genop(0, op, &e2, 1) || t1)
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case S_ADD:
|
||||
case S_ADC:
|
||||
case S_SBC:
|
||||
t1 = addr(&e1);
|
||||
t2 = 0;
|
||||
if (more()) {
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
}
|
||||
if (t2 == 0) {
|
||||
if (genop(0, op, &e1, 1))
|
||||
aerr();
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_R8) && (e1.e_addr == A)) {
|
||||
if (genop(0, op, &e2, 1))
|
||||
aerr();
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_R16) && (t2 == S_R16)) {
|
||||
#ifndef GAMEBOY
|
||||
if (rf == S_ADD)
|
||||
op = 0x09;
|
||||
if (rf == S_ADC)
|
||||
op = 0x4A;
|
||||
if (rf == S_SBC)
|
||||
op = 0x42;
|
||||
v1 = e1.e_addr;
|
||||
v2 = e2.e_addr;
|
||||
if ((v1 == HL) && (v2 <= SP)) {
|
||||
if (rf != S_ADD)
|
||||
outab(0xED);
|
||||
outab(op | (v2<<4));
|
||||
break;
|
||||
}
|
||||
if (rf != S_ADD) {
|
||||
aerr();
|
||||
break;
|
||||
}
|
||||
if ((v1 == IX) && (v2 != HL) && (v2 != IY)) {
|
||||
if (v2 == IX)
|
||||
v2 = HL;
|
||||
outab(0xDD);
|
||||
outab(op | (v2<<4));
|
||||
break;
|
||||
}
|
||||
if ((v1 == IY) && (v2 != HL) && (v2 != IX)) {
|
||||
if (v2 == IY)
|
||||
v2 = HL;
|
||||
outab(0xFD);
|
||||
outab(op | (v2<<4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else /* GAMEBOY */
|
||||
v1 = e1.e_addr;
|
||||
v2 = e2.e_addr;
|
||||
if ((v1 == HL) && (v2 <= SP) && (rf == S_ADD)) {
|
||||
outab(0x09 | (v2<<4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 0xE8 : ADD SP,#n
|
||||
*/
|
||||
if ((rf == S_ADD) && (t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
|
||||
outab(0xE8);
|
||||
outrb(&e2,0);
|
||||
break;
|
||||
}
|
||||
#endif /* GAMEBOY */
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case S_LD:
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
if (t1 == S_R8) {
|
||||
v1 = op | e1.e_addr<<3;
|
||||
if (genop(0, v1, &e2, 0) == 0)
|
||||
break;
|
||||
if (t2 == S_IMMED) {
|
||||
outab(e1.e_addr<<3 | 0x06);
|
||||
outrb(&e2,0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
v1 = e1.e_addr;
|
||||
v2 = e2.e_addr;
|
||||
if ((t1 == S_R16) && (t2 == S_IMMED)) {
|
||||
v1 = gixiy(v1);
|
||||
outab(0x01|v1<<4);
|
||||
outrw(&e2, 0);
|
||||
break;
|
||||
}
|
||||
#ifndef GAMEBOY
|
||||
if ((t1 == S_R16) && (t2 == S_INDM)) {
|
||||
if (gixiy(v1) == HL) {
|
||||
outab(0x2A);
|
||||
} else {
|
||||
outab(0xED);
|
||||
outab(0x4B | v1<<4);
|
||||
}
|
||||
outrw(&e2, 0);
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_INDM) && (t2 == S_R16)) {
|
||||
if (gixiy(v2) == HL) {
|
||||
outab(0x22);
|
||||
} else {
|
||||
outab(0xED);
|
||||
outab(0x43 | v2<<4);
|
||||
}
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_R8) && (v1 == A) && (t2 == S_INDM)) {
|
||||
outab(0x3A);
|
||||
outrw(&e2, 0);
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
|
||||
outab(0x32);
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
}
|
||||
#endif /* GAMEBOY */
|
||||
if ((t2 == S_R8) && (gixiy(t1) == S_IDHL)) {
|
||||
outab(0x70|v2);
|
||||
if (t1 != S_IDHL)
|
||||
outrb(&e1, 0);
|
||||
break;
|
||||
}
|
||||
if ((t2 == S_IMMED) && (gixiy(t1) == S_IDHL)) {
|
||||
outab(0x36);
|
||||
if (t1 != S_IDHL)
|
||||
outrb(&e1, 0);
|
||||
outrb(&e2, 0);
|
||||
break;
|
||||
}
|
||||
#ifndef GAMEBOY
|
||||
if ((t1 == S_R8X) && (t2 == S_R8) && (v2 == A)) {
|
||||
outab(0xED);
|
||||
outab(v1);
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_R8) && (v1 == A) && (t2 == S_R8X)) {
|
||||
outab(0xED);
|
||||
outab(v2|0x10);
|
||||
break;
|
||||
}
|
||||
#endif /* GAMEBOY */
|
||||
if ((t1 == S_R16) && (v1 == SP)) {
|
||||
if ((t2 == S_R16) && (gixiy(v2) == HL)) {
|
||||
outab(0xF9);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((t1 == S_R8) && (v1 == A)) {
|
||||
if ((t2 == S_IDBC) || (t2 == S_IDDE)) {
|
||||
outab(0x0A | (t2-S_INDR)<<4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((t2 == S_R8) && (v2 == A)) {
|
||||
if ((t1 == S_IDBC) || (t1 == S_IDDE)) {
|
||||
outab(0x02 | (t1-S_INDR)<<4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef GAMEBOY
|
||||
/*
|
||||
* 0x08 : LD (nn),SP
|
||||
*/
|
||||
if ((t1 == S_INDM) && (t2 == S_R16) && (v2 == SP)) {
|
||||
outab(0x08);
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* 0xEA : LD (nn),A
|
||||
* 0xFA : LD A,(nn)
|
||||
*/
|
||||
if ((t1 == S_INDM) && (t2 == S_R8) && (v2 == A)) {
|
||||
outab(0xEA);
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
}
|
||||
if ((t2 == S_INDM) && (t1 == S_R8) && (v1 == A)) {
|
||||
outab(0xFA);
|
||||
outrw(&e2, 0);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* 0x32 : LD (HL-),A
|
||||
* 0x3A : LD A,(HL-)
|
||||
*/
|
||||
if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLD)) {
|
||||
outab(0x3A);
|
||||
break;
|
||||
}
|
||||
if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLD)) {
|
||||
outab(0x32);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* 0x22 : LD (HL+),A
|
||||
* 0x2A : LD A,(HL+)
|
||||
*/
|
||||
if ((t1 == S_R8) && (v1 == A) && (t2 == S_IDHLI)) {
|
||||
outab(0x2A);
|
||||
break;
|
||||
}
|
||||
if ((t2 == S_R8) && (v2 == A) && (t1 == S_IDHLI)) {
|
||||
outab(0x22);
|
||||
break;
|
||||
}
|
||||
#endif /* GAMEBOY */
|
||||
aerr();
|
||||
break;
|
||||
|
||||
|
||||
#ifdef GAMEBOY
|
||||
case S_STOP: /* 0x10 */
|
||||
/*
|
||||
* 0x10 : STOP
|
||||
*/
|
||||
outab(op);
|
||||
outab(0x00);
|
||||
break;
|
||||
|
||||
|
||||
case S_LDH: /* 0xE0 */
|
||||
/*
|
||||
* 0xE0 : LDH (n),A = LD ($FF00+n),A
|
||||
* 0xE2 : LDH (C),A = LD ($FF00+C),A
|
||||
* 0xF0 : LDH A,(n) = LD A,($FF00+n)
|
||||
* 0xF2 : LDH A,(C) = LD A,($FF00+C)
|
||||
*/
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
if ((t1 == S_INDM) && (t2 == S_R8) && (e2.e_addr == A)) {
|
||||
outab(0xE0);
|
||||
outrb(&e1, 0);
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_IDC) && (t2 == S_R8) && (e2.e_addr == A)) {
|
||||
outab(0xE2);
|
||||
break;
|
||||
}
|
||||
if ((t2 == S_INDM) && (t1 == S_R8) && (e1.e_addr == A)) {
|
||||
outab(0xF0);
|
||||
outrb(&e2, 0);
|
||||
break;
|
||||
}
|
||||
if ((t2 == S_IDC) && (t1 == S_R8) && (e1.e_addr == A)) {
|
||||
outab(0xF2);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
|
||||
case S_LDA: /* 0xE8 */
|
||||
/*
|
||||
* 0xE8 : LDA SP,#n(SP)
|
||||
* 0xF8 : LDA HL,#n(SP)
|
||||
*/
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_INDR+SP)) {
|
||||
outab(0xE8);
|
||||
outrb(&e2,0);
|
||||
break;
|
||||
}
|
||||
if ((t1 == S_R16) && (e1.e_addr == HL) && (t2 == S_INDR+SP)) {
|
||||
outab(0xF8);
|
||||
outrb(&e2,0);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
|
||||
case S_LDHL: /* 0xF8 */
|
||||
/*
|
||||
* 0xF8 : LDHL SP,#n
|
||||
*/
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
if ((t1 == S_R16) && (e1.e_addr == SP) && (t2 == S_IMMED)) {
|
||||
outab(0xF8);
|
||||
outrb(&e2,0);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
|
||||
#ifndef GAMEBOY
|
||||
case S_EX:
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
if (t2 == S_R16) {
|
||||
v1 = e1.e_addr;
|
||||
v2 = e2.e_addr;
|
||||
if ((t1 == S_IDSP) && (v1 == 0)) {
|
||||
if (gixiy(v2) == HL) {
|
||||
outab(op);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t1 == S_R16) {
|
||||
if ((v1 == DE) && (v2 == HL)) {
|
||||
outab(0xEB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((t1 == S_R16X) && (t2 == S_R16X)) {
|
||||
outab(0x08);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case S_IN:
|
||||
case S_OUT:
|
||||
if (rf == S_IN) {
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
} else {
|
||||
t2 = addr(&e2);
|
||||
comma();
|
||||
t1 = addr(&e1);
|
||||
}
|
||||
v1 = e1.e_addr;
|
||||
v2 = e2.e_addr;
|
||||
if (t1 == S_R8) {
|
||||
if ((v1 == A) && (t2 == S_INDM)) {
|
||||
outab(op);
|
||||
outab(v2);
|
||||
break;
|
||||
}
|
||||
if (t2 == S_IDC) {
|
||||
outab(0xED);
|
||||
outab(((rf == S_IN) ? 0x40 : 0x41) + (v1<<3));
|
||||
break;
|
||||
}
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
case S_DEC:
|
||||
case S_INC:
|
||||
t1 = addr(&e1);
|
||||
v1 = e1.e_addr;
|
||||
if (t1 == S_R8) {
|
||||
outab(op|(v1<<3));
|
||||
break;
|
||||
}
|
||||
if (t1 == S_IDHL) {
|
||||
outab(op|0x30);
|
||||
break;
|
||||
}
|
||||
if (t1 != gixiy(t1)) {
|
||||
outab(op|0x30);
|
||||
outrb(&e1,0);
|
||||
break;
|
||||
}
|
||||
if (t1 == S_R16) {
|
||||
v1 = gixiy(v1);
|
||||
if (rf == S_INC) {
|
||||
outab(0x03|(v1<<4));
|
||||
break;
|
||||
}
|
||||
if (rf == S_DEC) {
|
||||
outab(0x0B|(v1<<4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
#ifndef GAMEBOY
|
||||
case S_DJNZ:
|
||||
case S_JR:
|
||||
if ((v1 = admode(CND)) != 0 && rf != S_DJNZ) {
|
||||
#else /* GAMEBOY */
|
||||
case S_JR:
|
||||
if ((v1 = admode(CND)) != 0) {
|
||||
#endif /* GAMEBOY */
|
||||
if ((v1 &= 0xFF) <= 0x18) {
|
||||
op += (v1+1)<<3;
|
||||
} else {
|
||||
aerr();
|
||||
}
|
||||
comma();
|
||||
}
|
||||
expr(&e2, 0);
|
||||
outab(op);
|
||||
if (e2.e_base.e_ap == NULL || e2.e_base.e_ap == dot.s_area) {
|
||||
v2 = e2.e_addr - dot.s_addr - 1;
|
||||
if (pass == 2 && ((v2 < -128) || (v2 > 127)))
|
||||
aerr();
|
||||
outab(v2);
|
||||
} else {
|
||||
outrb(&e2, R_PCR);
|
||||
}
|
||||
if (e2.e_mode != S_USER)
|
||||
rerr();
|
||||
break;
|
||||
|
||||
case S_CALL:
|
||||
if ((v1 = admode(CND)) != 0) {
|
||||
op |= (v1&0xFF)<<3;
|
||||
comma();
|
||||
} else {
|
||||
op = 0xCD;
|
||||
}
|
||||
expr(&e1, 0);
|
||||
outab(op);
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
|
||||
case S_JP:
|
||||
if ((v1 = admode(CND)) != 0) {
|
||||
op |= (v1&0xFF)<<3;
|
||||
comma();
|
||||
expr(&e1, 0);
|
||||
outab(op);
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
}
|
||||
t1 = addr(&e1);
|
||||
if (t1 == S_USER) {
|
||||
outab(0xC3);
|
||||
outrw(&e1, 0);
|
||||
break;
|
||||
}
|
||||
if ((e1.e_addr == 0) && (gixiy(t1) == S_IDHL)) {
|
||||
outab(0xE9);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
#ifndef GAMEBOY
|
||||
case X_HD64:
|
||||
++hd64;
|
||||
break;
|
||||
|
||||
case X_INH2:
|
||||
outab(0xED);
|
||||
outab(op);
|
||||
break;
|
||||
|
||||
case X_IN:
|
||||
case X_OUT:
|
||||
if (rf == X_IN) {
|
||||
t1 = addr(&e1);
|
||||
comma();
|
||||
t2 = addr(&e2);
|
||||
} else {
|
||||
t2 = addr(&e2);
|
||||
comma();
|
||||
t1 = addr(&e1);
|
||||
}
|
||||
if ((t1 == S_R8) && (t2 == S_INDM)) {
|
||||
outab(0xED);
|
||||
outab(op | e1.e_addr<<3);
|
||||
outrb(&e2, 0);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case X_MLT:
|
||||
t1 = addr(&e1);
|
||||
if ((t1 == S_R16) && ((v1 = e1.e_addr) <= SP)) {
|
||||
outab(0xED);
|
||||
outab(op | v1<<4);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case X_TST:
|
||||
t1 = addr(&e1);
|
||||
if (t1 == S_R8) {
|
||||
outab(0xED);
|
||||
outab(op | e1.e_addr<<3);
|
||||
break;
|
||||
}
|
||||
if (t1 == S_IDHL) {
|
||||
outab(0xED);
|
||||
outab(0x34);
|
||||
break;
|
||||
}
|
||||
if (t1 == S_IMMED) {
|
||||
outab(0xED);
|
||||
outab(0x64);
|
||||
outrb(&e1, 0);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
|
||||
case X_TSTIO:
|
||||
t1 = addr(&e1);
|
||||
if (t1 == S_IMMED) {
|
||||
outab(0xED);
|
||||
outab(op);
|
||||
outrb(&e1, 0);
|
||||
break;
|
||||
}
|
||||
aerr();
|
||||
break;
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
default:
|
||||
err('o');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* general addressing evaluation
|
||||
* return(0) if general addressing mode output, else
|
||||
* return(esp->e_mode)
|
||||
*/
|
||||
int
|
||||
genop(pop, op, esp, f)
|
||||
register int pop, op;
|
||||
register struct expr *esp;
|
||||
int f;
|
||||
{
|
||||
register int t1;
|
||||
if ((t1 = esp->e_mode) == S_R8) {
|
||||
if (pop)
|
||||
outab(pop);
|
||||
outab(op|esp->e_addr);
|
||||
return(0);
|
||||
}
|
||||
if (t1 == S_IDHL) {
|
||||
if (pop)
|
||||
outab(pop);
|
||||
outab(op|0x06);
|
||||
return(0);
|
||||
}
|
||||
if (gixiy(t1) == S_IDHL) {
|
||||
if (pop) {
|
||||
outab(pop);
|
||||
outrb(esp,0);
|
||||
outab(op|0x06);
|
||||
} else {
|
||||
outab(op|0x06);
|
||||
outrb(esp,0);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
if ((t1 == S_IMMED) && (f)) {
|
||||
if (pop)
|
||||
outab(pop);
|
||||
outab(op|0x46);
|
||||
outrb(esp,0);
|
||||
return(0);
|
||||
}
|
||||
return(t1);
|
||||
}
|
||||
|
||||
/*
|
||||
* IX and IY prebyte check
|
||||
*/
|
||||
int
|
||||
gixiy(v)
|
||||
int v;
|
||||
{
|
||||
#ifndef GAMEBOY
|
||||
if (v == IX) {
|
||||
v = HL;
|
||||
outab(0xDD);
|
||||
} else if (v == IY) {
|
||||
v = HL;
|
||||
outab(0xFD);
|
||||
} else if (v == S_IDIX) {
|
||||
v = S_IDHL;
|
||||
outab(0xDD);
|
||||
} else if (v == S_IDIY) {
|
||||
v = S_IDHL;
|
||||
outab(0xFD);
|
||||
}
|
||||
#endif /* GAMEBOY */
|
||||
return(v);
|
||||
}
|
||||
|
||||
/*
|
||||
* The next character must be a
|
||||
* comma.
|
||||
*/
|
||||
int
|
||||
comma()
|
||||
{
|
||||
if (getnb() != ',')
|
||||
qerr();
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Machine dependent initialization
|
||||
*/
|
||||
VOID
|
||||
minit()
|
||||
{
|
||||
#ifndef GAMEBOY
|
||||
hd64 = 0;
|
||||
#endif /* GAMEBOY */
|
||||
}
|
||||
179
link/as/z80/z80pst.c
Normal file
179
link/as/z80/z80pst.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/* z80pst.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include "asm.h"
|
||||
#include "z80.h"
|
||||
|
||||
struct mne mne[] = {
|
||||
|
||||
/* machine */
|
||||
|
||||
/* system */
|
||||
|
||||
{ NULL, "CON", S_ATYP, 0, A_CON },
|
||||
{ NULL, "OVR", S_ATYP, 0, A_OVR },
|
||||
{ NULL, "REL", S_ATYP, 0, A_REL },
|
||||
{ NULL, "ABS", S_ATYP, 0, A_ABS|A_OVR },
|
||||
{ NULL, "NOPAG", S_ATYP, 0, A_NOPAG },
|
||||
{ NULL, "PAG", S_ATYP, 0, A_PAG },
|
||||
|
||||
{ NULL, ".byte", S_BYTE, 0, 0 },
|
||||
{ NULL, ".db", S_BYTE, 0, 0 },
|
||||
{ NULL, ".word", S_WORD, 0, 0 },
|
||||
{ NULL, ".dw", S_WORD, 0, 0 },
|
||||
{ NULL, ".df", S_FLOAT, 0, 0 },
|
||||
{ NULL, ".ascii", S_ASCII, 0, 0 },
|
||||
{ NULL, ".asciz", S_ASCIZ, 0, 0 },
|
||||
{ NULL, ".blkb", S_BLK, 0, 1 },
|
||||
{ NULL, ".ds", S_BLK, 0, 1 },
|
||||
{ NULL, ".blkw", S_BLK, 0, 2 },
|
||||
{ NULL, ".page", S_PAGE, 0, 0 },
|
||||
{ NULL, ".title", S_TITLE, 0, 0 },
|
||||
{ NULL, ".sbttl", S_SBTL, 0, 0 },
|
||||
{ NULL, ".globl", S_GLOBL, 0, 0 },
|
||||
{ NULL, ".area", S_DAREA, 0, 0 },
|
||||
{ NULL, ".even", S_EVEN, 0, 0 },
|
||||
{ NULL, ".odd", S_ODD, 0, 0 },
|
||||
{ NULL, ".if", S_IF, 0, 0 },
|
||||
{ NULL, ".else", S_ELSE, 0, 0 },
|
||||
{ NULL, ".endif", S_ENDIF, 0, 0 },
|
||||
{ NULL, ".include", S_INCL, 0, 0 },
|
||||
{ NULL, ".radix", S_RADIX, 0, 0 },
|
||||
{ NULL, ".org", S_ORG, 0, 0 },
|
||||
{ NULL, ".module", S_MODUL, 0, 0 },
|
||||
{ NULL, ".ascis", S_ASCIS, 0, 0 },
|
||||
|
||||
/* z80 / hd64180 */
|
||||
|
||||
{ NULL, "ld", S_LD, 0, 0x40 },
|
||||
|
||||
{ NULL, "call", S_CALL, 0, 0xC4 },
|
||||
{ NULL, "jp", S_JP, 0, 0xC2 },
|
||||
{ NULL, "jr", S_JR, 0, 0x18 },
|
||||
#ifndef GAMEBOY
|
||||
{ NULL, "djnz", S_DJNZ, 0, 0x10 },
|
||||
#endif /* GAMEBOY */
|
||||
{ NULL, "ret", S_RET, 0, 0xC0 },
|
||||
|
||||
{ NULL, "bit", S_BIT, 0, 0x40 },
|
||||
{ NULL, "res", S_BIT, 0, 0x80 },
|
||||
{ NULL, "set", S_BIT, 0, 0xC0 },
|
||||
|
||||
{ NULL, "inc", S_INC, 0, 0x04 },
|
||||
{ NULL, "dec", S_DEC, 0, 0x05 },
|
||||
|
||||
{ NULL, "add", S_ADD, 0, 0x80 },
|
||||
{ NULL, "adc", S_ADC, 0, 0x88 },
|
||||
{ NULL, "sub", S_SUB, 0, 0x90 },
|
||||
{ NULL, "sbc", S_SBC, 0, 0x98 },
|
||||
|
||||
{ NULL, "and", S_AND, 0, 0xA0 },
|
||||
{ NULL, "cp", S_AND, 0, 0xB8 },
|
||||
{ NULL, "or", S_AND, 0, 0xB0 },
|
||||
{ NULL, "xor", S_AND, 0, 0xA8 },
|
||||
|
||||
#ifndef GAMEBOY
|
||||
{ NULL, "ex", S_EX, 0, 0xE3 },
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
{ NULL, "push", S_PUSH, 0, 0xC5 },
|
||||
{ NULL, "pop", S_PUSH, 0, 0xC1 },
|
||||
|
||||
#ifndef GAMEBOY
|
||||
{ NULL, "in", S_IN, 0, 0xDB },
|
||||
{ NULL, "out", S_OUT, 0, 0xD3 },
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
{ NULL, "rl", S_RL, 0, 0x10 },
|
||||
{ NULL, "rlc", S_RL, 0, 0x00 },
|
||||
{ NULL, "rr", S_RL, 0, 0x18 },
|
||||
{ NULL, "rrc", S_RL, 0, 0x08 },
|
||||
{ NULL, "sla", S_RL, 0, 0x20 },
|
||||
{ NULL, "sra", S_RL, 0, 0x28 },
|
||||
{ NULL, "srl", S_RL, 0, 0x38 },
|
||||
|
||||
{ NULL, "rst", S_RST, 0, 0xC7 },
|
||||
|
||||
#ifndef GAMEBOY
|
||||
{ NULL, "im", S_IM, 0, 0xED },
|
||||
#endif /* GAMEBOY */
|
||||
|
||||
{ NULL, "ccf", S_INH1, 0, 0x3F },
|
||||
{ NULL, "cpl", S_INH1, 0, 0x2F },
|
||||
{ NULL, "daa", S_INH1, 0, 0x27 },
|
||||
{ NULL, "di", S_INH1, 0, 0xF3 },
|
||||
{ NULL, "ei", S_INH1, 0, 0xFB },
|
||||
#ifndef GAMEBOY
|
||||
{ NULL, "exx", S_INH1, 0, 0xD9 },
|
||||
#endif /* GAMEBOY */
|
||||
{ NULL, "nop", S_INH1, 0, 0x00 },
|
||||
{ NULL, "halt", S_INH1, 0, 0x76 },
|
||||
{ NULL, "rla", S_INH1, 0, 0x17 },
|
||||
{ NULL, "rlca", S_INH1, 0, 0x07 },
|
||||
{ NULL, "rra", S_INH1, 0, 0x1F },
|
||||
{ NULL, "rrca", S_INH1, 0, 0x0F },
|
||||
{ NULL, "scf", S_INH1, 0, 0x37 },
|
||||
|
||||
#ifndef GAMEBOY
|
||||
{ NULL, "cpd", S_INH2, 0, 0xA9 },
|
||||
{ NULL, "cpdr", S_INH2, 0, 0xB9 },
|
||||
{ NULL, "cpi", S_INH2, 0, 0xA1 },
|
||||
{ NULL, "cpir", S_INH2, 0, 0xB1 },
|
||||
{ NULL, "ind", S_INH2, 0, 0xAA },
|
||||
{ NULL, "indr", S_INH2, 0, 0xBA },
|
||||
{ NULL, "ini", S_INH2, 0, 0xA2 },
|
||||
{ NULL, "inir", S_INH2, 0, 0xB2 },
|
||||
{ NULL, "ldd", S_INH2, 0, 0xA8 },
|
||||
{ NULL, "lddr", S_INH2, 0, 0xB8 },
|
||||
{ NULL, "ldi", S_INH2, 0, 0xA0 },
|
||||
{ NULL, "ldir", S_INH2, 0, 0xB0 },
|
||||
{ NULL, "neg", S_INH2, 0, 0x44 },
|
||||
{ NULL, "otdr", S_INH2, 0, 0xBB },
|
||||
{ NULL, "otir", S_INH2, 0, 0xB3 },
|
||||
{ NULL, "outd", S_INH2, 0, 0xAB },
|
||||
{ NULL, "outi", S_INH2, 0, 0xA3 },
|
||||
{ NULL, "reti", S_INH2, 0, 0x4D },
|
||||
{ NULL, "retn", S_INH2, 0, 0x45 },
|
||||
{ NULL, "rld", S_INH2, 0, 0x6F },
|
||||
{ NULL, "rrd", S_INH2, 0, 0x67 },
|
||||
|
||||
/* 64180 */
|
||||
|
||||
{ NULL, ".hd64", X_HD64, 0, 0 },
|
||||
|
||||
{ NULL, "otdm", X_INH2, 0, 0x8B },
|
||||
{ NULL, "otdmr", X_INH2, 0, 0x9B },
|
||||
{ NULL, "otim", X_INH2, 0, 0x83 },
|
||||
{ NULL, "otimr", X_INH2, 0, 0x93 },
|
||||
{ NULL, "slp", X_INH2, 0, 0x76 },
|
||||
|
||||
{ NULL, "in0", X_IN, 0, 0x00 },
|
||||
{ NULL, "out0", X_OUT, 0, 0x01 },
|
||||
|
||||
{ NULL, "mlt", X_MLT, 0, 0x4C },
|
||||
|
||||
{ NULL, "tst", X_TST, 0, 0x04 },
|
||||
{ NULL, "tstio", X_TSTIO, S_END, 0x7 }
|
||||
#else /* GAMEBOY */
|
||||
{ NULL, "stop", S_STOP, 0, 0x10 },
|
||||
{ NULL, "swap", S_RL, 0, 0x30 },
|
||||
{ NULL, "reti", S_INH1, 0, 0xD9 },
|
||||
{ NULL, "ldh", S_LDH, 0, 0xE0 },
|
||||
{ NULL, "lda", S_LDA, 0, 0xE8 },
|
||||
{ NULL, "ldhl", S_LDHL, S_END, 0xF }
|
||||
#endif /* GAMEBOY */
|
||||
};
|
||||
4
link/clean.mk
Normal file
4
link/clean.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
clean:
|
||||
$(MAKE) -C z80 -f clean.mk clean
|
||||
|
||||
distclean: clean
|
||||
46
link/sdccconf.h
Normal file
46
link/sdccconf.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* sdccconf.h. Generated automatically by configure. */
|
||||
/*
|
||||
*/
|
||||
|
||||
#ifndef SDCCCONF_HEADER
|
||||
#define SDCCCONF_HEADER
|
||||
|
||||
|
||||
#define SDCC_VERSION_HI 2
|
||||
#define SDCC_VERSION_LO 3
|
||||
#define SDCC_VERSION_P 1
|
||||
#define SDCC_VERSION_STR "2.3.1"
|
||||
|
||||
#define PREFIX "/opt/gbdk"
|
||||
#define DATADIR "/opt/gbdk/share/sdcc"
|
||||
#define SRCDIR "/home/Zalo/Desktop/gb/gbdk-2020/sdcc"
|
||||
|
||||
#define STANDARD_INCLUDE_DIR "/opt/gbdk/share/sdcc/include"
|
||||
#define SDCC_INCLUDE_DIR "/opt/gbdk/share/sdcc/include"
|
||||
#define SDCC_LIB_DIR "/opt/gbdk/share/sdcc/lib"
|
||||
#define STD_LIB "libsdcc"
|
||||
#define STD_INT_LIB "libint"
|
||||
#define STD_LONG_LIB "liblong"
|
||||
#define STD_FP_LIB "libfloat"
|
||||
#define STD_DS390_LIB "libds390"
|
||||
/* #undef HAVE_SYS_SOCKET_H */
|
||||
/* #undef HAVE_SYS_ISA_DEFS_H */
|
||||
/* #undef HAVE_ENDIAN_H */
|
||||
/* #undef HAVE_MACHINE_ENDIAN_H */
|
||||
|
||||
#define HAVE_STRERROR 1
|
||||
|
||||
#define OPT_DISABLE_MCS51 1
|
||||
#define OPT_DISABLE_GBZ80 0
|
||||
#define OPT_DISABLE_Z80 0
|
||||
#define OPT_DISABLE_AVR 1
|
||||
#define OPT_DISABLE_DS390 1
|
||||
#define OPT_DISABLE_PIC 1
|
||||
#define OPT_DISABLE_I186 1
|
||||
#define OPT_DISABLE_TLCS900H 1
|
||||
|
||||
#define OPT_ENABLE_LIBGC 0
|
||||
|
||||
#endif
|
||||
|
||||
/* End of config.h */
|
||||
90
link/support/Util/BuildCmd.c
Normal file
90
link/support/Util/BuildCmd.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
BuildCmd - SDCC Support function
|
||||
|
||||
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding!
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
/*! Build a command line with parameter substitution
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
void
|
||||
buildCmdLine (char *into, const char **cmds,
|
||||
const char *p1, const char *p2,
|
||||
const char *p3, const char **list)
|
||||
{
|
||||
const char *p, *from;
|
||||
|
||||
*into = '\0';
|
||||
|
||||
while (*cmds)
|
||||
{
|
||||
from = *cmds;
|
||||
cmds++;
|
||||
|
||||
/* See if it has a '$' anywhere - if not, just copy */
|
||||
if ((p = strchr (from, '$')))
|
||||
{
|
||||
strncat (into, from, p - from);
|
||||
/* seperate it */
|
||||
strcat (into, " ");
|
||||
from = p + 2;
|
||||
p++;
|
||||
switch (*p)
|
||||
{
|
||||
case '1':
|
||||
if (p1)
|
||||
strcat (into, p1);
|
||||
break;
|
||||
case '2':
|
||||
if (p2)
|
||||
strcat (into, p2);
|
||||
break;
|
||||
case '3':
|
||||
if (p3)
|
||||
strcat (into, p3);
|
||||
break;
|
||||
case 'l':
|
||||
{
|
||||
const char **tmp = list;
|
||||
if (tmp)
|
||||
{
|
||||
while (*tmp)
|
||||
{
|
||||
strcat (into, *tmp);
|
||||
strcat (into, " ");
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
strcat (into, from); // this includes the ".asm" from "$1.asm"
|
||||
|
||||
strcat (into, " ");
|
||||
}
|
||||
}
|
||||
|
||||
34
link/support/Util/BuildCmd.h
Normal file
34
link/support/Util/BuildCmd.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
BuildCmd - SDCC Support function
|
||||
|
||||
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding!
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#if !defined(__BUILDCMD_H)
|
||||
|
||||
#define __BUILDCMD_H
|
||||
|
||||
void
|
||||
buildCmdLine (char *into, const char **cmds,
|
||||
const char *p1, const char *p2,
|
||||
const char *p3, const char **list) ;
|
||||
|
||||
#endif
|
||||
99
link/support/Util/MySystem.c
Normal file
99
link/support/Util/MySystem.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
MySystem - SDCC Support function
|
||||
|
||||
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding!
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#include "common.h"
|
||||
#include "newalloc.h"
|
||||
#if defined(_MSC_VER)
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(__BORLANDC__) && !defined(_MSC_VER)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
// No unistd.h in Borland C++
|
||||
extern int access (const char *, int);
|
||||
#define X_OK 1
|
||||
#endif
|
||||
|
||||
/*!
|
||||
Call an external program with arguements
|
||||
*/
|
||||
|
||||
//char *ExePathList[]= {SRCDIR "/bin",PREFIX "/bin", NULL};
|
||||
char *ExePathList[] = {NULL, NULL}; /* First entry may be overwritten, so use two. */
|
||||
|
||||
int
|
||||
my_system (const char *cmd)
|
||||
{
|
||||
int argsStart, e, i = 0;
|
||||
char *cmdLine = NULL;
|
||||
|
||||
argsStart = strstr (cmd, " ") - cmd;
|
||||
|
||||
// try to find the command in predefined path's
|
||||
while (ExePathList[i])
|
||||
{
|
||||
cmdLine = (char *) Safe_alloc (strlen (ExePathList[i]) + strlen (cmd) + 10);
|
||||
strcpy (cmdLine, ExePathList[i]); // the path
|
||||
|
||||
strcat (cmdLine, DIR_SEPARATOR_STRING);
|
||||
strncat (cmdLine, cmd, argsStart); // the command
|
||||
|
||||
#if NATIVE_WIN32
|
||||
strcat (cmdLine, ".exe");
|
||||
#endif
|
||||
|
||||
if (access (cmdLine, X_OK) == 0)
|
||||
{
|
||||
// the arguments
|
||||
strcat (cmdLine, cmd + argsStart);
|
||||
break;
|
||||
}
|
||||
Safe_free (cmdLine);
|
||||
cmdLine = NULL;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (verboseExec)
|
||||
{
|
||||
printf ("+ %s\n", cmdLine ? cmdLine : cmd);
|
||||
}
|
||||
|
||||
if (cmdLine)
|
||||
{
|
||||
// command found in predefined path
|
||||
e = system (cmdLine);
|
||||
Safe_free (cmdLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
// trust on $PATH
|
||||
e = system (cmd);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
32
link/support/Util/MySystem.h
Normal file
32
link/support/Util/MySystem.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
MySystem - SDCC Support function
|
||||
|
||||
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding!
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
#if !defined(__MYSYSTEM_H)
|
||||
#define __MYSYSTEM_H
|
||||
|
||||
int my_system (const char *cmd) ;
|
||||
|
||||
extern char *ExePathList[] ; // List of paths to try to locate exeucatbles
|
||||
|
||||
#endif
|
||||
275
link/support/Util/NewAlloc.c
Normal file
275
link/support/Util/NewAlloc.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
===============================================================================
|
||||
NEWALLOC - SDCC Memory allocation functions
|
||||
|
||||
These functions are wrappers for the standard malloc, realloc and free
|
||||
functions.
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding!
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <sys/malloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <assert.h>
|
||||
#include "newalloc.h"
|
||||
#include "sdccconf.h"
|
||||
|
||||
#if OPT_ENABLE_LIBGC
|
||||
#include <gc/gc.h>
|
||||
|
||||
#define MALLOC GC_malloc
|
||||
#define REALLOC GC_realloc
|
||||
/* PENDING: This is a mild hack. If we try to GC_free something
|
||||
allocated with malloc() then the program will segfault. Might as
|
||||
well drop it and let the garbase collector take care of things.
|
||||
*/
|
||||
#define FREE(_a)
|
||||
|
||||
#else
|
||||
|
||||
#define MALLOC malloc
|
||||
#define REALLOC realloc
|
||||
#define FREE free
|
||||
|
||||
#endif
|
||||
|
||||
#define TRACEMALLOC 0
|
||||
|
||||
#if TRACEMALLOC
|
||||
enum
|
||||
{
|
||||
TRACESIZE = 4096
|
||||
};
|
||||
|
||||
static int _allocs[TRACESIZE];
|
||||
static int _above;
|
||||
|
||||
static void
|
||||
_dumpTrace(int code, void *parg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TRACESIZE; i++)
|
||||
{
|
||||
if (_allocs[i])
|
||||
{
|
||||
printf("%u %u\n", _allocs[i], i);
|
||||
}
|
||||
}
|
||||
printf("%u above\n", _above);
|
||||
}
|
||||
|
||||
static void
|
||||
_log(int size)
|
||||
{
|
||||
static int registered;
|
||||
|
||||
if (registered == 0)
|
||||
{
|
||||
on_exit(_dumpTrace, NULL);
|
||||
registered = 1;
|
||||
}
|
||||
if (size == 12)
|
||||
{
|
||||
_above++;
|
||||
}
|
||||
|
||||
if (size >= TRACESIZE)
|
||||
{
|
||||
_above++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_allocs[size]++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Clear_realloc - Reallocate a memory block and clear any memory added with
|
||||
out of memory error detection
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Clear_realloc(void *OldPtr,size_t OldSize,size_t NewSize)
|
||||
|
||||
{
|
||||
void *NewPtr ;
|
||||
|
||||
NewPtr = REALLOC(OldPtr,NewSize) ;
|
||||
|
||||
if (!NewPtr)
|
||||
{
|
||||
printf("ERROR - No more memory\n") ;
|
||||
/* werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (NewPtr)
|
||||
if (NewSize > OldSize)
|
||||
memset((char *) NewPtr + OldSize,0x00,NewSize - OldSize) ;
|
||||
|
||||
return NewPtr ;
|
||||
}
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Safe_realloc - Reallocate a memory block with out of memory error detection
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Safe_realloc(void *OldPtr,size_t NewSize)
|
||||
|
||||
{
|
||||
void *NewPtr ;
|
||||
|
||||
NewPtr = REALLOC(OldPtr,NewSize) ;
|
||||
|
||||
if (!NewPtr)
|
||||
{
|
||||
printf("ERROR - No more memory\n") ;
|
||||
/* werror(E_OUT_OF_MEM,__FILE__,NewSize);*/
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NewPtr ;
|
||||
}
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Safe_calloc - Allocate a block of memory from the application heap, clearing
|
||||
all data to zero and checking for out of memory errors.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Safe_calloc(size_t Elements,size_t Size)
|
||||
|
||||
{
|
||||
void *NewPtr ;
|
||||
|
||||
NewPtr = MALLOC(Elements*Size) ;
|
||||
#if TRACEMALLOC
|
||||
_log(Elements*Size);
|
||||
#endif
|
||||
|
||||
if (!NewPtr)
|
||||
{
|
||||
printf("ERROR - No more memory\n") ;
|
||||
/* werror(E_OUT_OF_MEM,__FILE__,Size);*/
|
||||
exit (1);
|
||||
}
|
||||
|
||||
memset(NewPtr, 0, Elements*Size);
|
||||
|
||||
return NewPtr ;
|
||||
}
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Safe_malloc - Allocate a block of memory from the application heap
|
||||
and checking for out of memory errors.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Safe_malloc(size_t Size)
|
||||
|
||||
{
|
||||
void *NewPtr ;
|
||||
|
||||
NewPtr = MALLOC(Size) ;
|
||||
|
||||
#if TRACEMALLOC
|
||||
_log(Size);
|
||||
#endif
|
||||
|
||||
if (!NewPtr)
|
||||
{
|
||||
printf("ERROR - No more memory\n") ;
|
||||
/* werror(E_OUT_OF_MEM,__FILE__,Size);*/
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return NewPtr ;
|
||||
}
|
||||
|
||||
void *Safe_alloc(size_t Size)
|
||||
{
|
||||
return Safe_calloc(1, Size);
|
||||
}
|
||||
|
||||
void Safe_free(void *p)
|
||||
{
|
||||
FREE(p);
|
||||
}
|
||||
|
||||
char *Safe_strdup(const char *sz)
|
||||
{
|
||||
char *pret;
|
||||
assert(sz);
|
||||
|
||||
pret = Safe_alloc(strlen(sz) +1);
|
||||
strcpy(pret, sz);
|
||||
|
||||
return pret;
|
||||
}
|
||||
|
||||
void *traceAlloc(allocTrace *ptrace, void *p)
|
||||
{
|
||||
assert(ptrace);
|
||||
assert(p);
|
||||
|
||||
/* Also handles where max == 0 */
|
||||
if (ptrace->num == ptrace->max)
|
||||
{
|
||||
/* Add an offset to handle max == 0 */
|
||||
ptrace->max = (ptrace->max+2)*2;
|
||||
ptrace->palloced = Safe_realloc(ptrace->palloced, ptrace->max * sizeof(*ptrace->palloced));
|
||||
}
|
||||
ptrace->palloced[ptrace->num++] = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void freeTrace(allocTrace *ptrace)
|
||||
{
|
||||
int i;
|
||||
assert(ptrace);
|
||||
|
||||
for (i = 0; i < ptrace->num; i++)
|
||||
{
|
||||
Safe_free(ptrace->palloced[i]);
|
||||
}
|
||||
ptrace->num = 0;
|
||||
|
||||
Safe_free(ptrace->palloced);
|
||||
ptrace->palloced = NULL;
|
||||
ptrace->max = 0;
|
||||
}
|
||||
|
||||
463
link/support/Util/SDCCerr.c
Normal file
463
link/support/Util/SDCCerr.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* SDCCerr - Standard error handler
|
||||
*
|
||||
* 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 of the License, 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 Library 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDCCerr.h"
|
||||
|
||||
|
||||
#define USE_STDOUT_FOR_ERRORS 0
|
||||
|
||||
#if USE_STDOUT_FOR_ERRORS
|
||||
#define DEFAULT_ERROR_OUT stdout
|
||||
#else
|
||||
#define DEFAULT_ERROR_OUT stderr
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
ERROR_LOG_LEVEL logLevel;
|
||||
FILE *out;
|
||||
} _SDCCERRG;
|
||||
|
||||
extern char *filename ;
|
||||
extern int lineno ;
|
||||
extern int fatalError ;
|
||||
|
||||
/* Currently the errIndex field must match the position of the
|
||||
* entry in the array. It is only included in order to make
|
||||
* human error lookup easier.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
int errIndex;
|
||||
ERROR_LOG_LEVEL errType;
|
||||
const char *errText;
|
||||
} ErrTab [] =
|
||||
{
|
||||
{ E_DUPLICATE, ERROR_LEVEL_ERROR,
|
||||
"Duplicate symbol '%s', symbol IGNORED" },
|
||||
{ E_SYNTAX_ERROR, ERROR_LEVEL_ERROR,
|
||||
"Syntax error, declaration ignored at '%s'" },
|
||||
{ E_CONST_EXPECTED, ERROR_LEVEL_ERROR,
|
||||
"Constant Expected Found Variable" },
|
||||
{ E_OUT_OF_MEM, ERROR_LEVEL_ERROR,
|
||||
"'malloc' failed file '%s' for size %ld" },
|
||||
{ E_FILE_OPEN_ERR, ERROR_LEVEL_ERROR,
|
||||
"'fopen' failed on file '%s'" },
|
||||
{ E_INVALID_OCLASS, ERROR_LEVEL_ERROR,
|
||||
"Internal Error Oclass invalid '%s'" },
|
||||
{ E_CANNOT_ALLOC, ERROR_LEVEL_ERROR,
|
||||
"Cannot allocate variable '%s'." },
|
||||
{ E_OLD_STYLE, ERROR_LEVEL_ERROR,
|
||||
"Old style C declaration. IGNORED '%s'" },
|
||||
{ E_STACK_OUT, ERROR_LEVEL_ERROR,
|
||||
"Out of stack Space. '%s' not allocated" },
|
||||
{ E_INTERNAL_ERROR, ERROR_LEVEL_ERROR,
|
||||
"FATAL Compiler Internal Error in file '%s' line number '%d' : %s \n"
|
||||
"Contact Author with source code" },
|
||||
{ E_LVALUE_REQUIRED, ERROR_LEVEL_ERROR,
|
||||
"'lvalue' required for '%s' operation ." },
|
||||
{ E_TMPFILE_FAILED, ERROR_LEVEL_ERROR,
|
||||
"Creation of temp file failed" },
|
||||
{ E_FUNCTION_EXPECTED, ERROR_LEVEL_ERROR,
|
||||
"called object is not a function" },
|
||||
{ E_USING_ERROR, ERROR_LEVEL_ERROR,
|
||||
"'using', 'interrupt' or 'reentrant' must follow a function definiton .'%s'" },
|
||||
{ E_SFR_INIT, ERROR_LEVEL_ERROR,
|
||||
"Absolute address & initial value both cannot be specified for\n"
|
||||
" a 'sfr','sbit' storage class, initial value ignored '%s'" },
|
||||
{ W_INIT_IGNORED, ERROR_LEVEL_WARNING,
|
||||
"Variable in the storage class cannot be initialized.'%s'" },
|
||||
{ E_AUTO_ASSUMED, ERROR_LEVEL_ERROR,
|
||||
"storage class not allowed for automatic variable '%s' in reentrant function unless static" },
|
||||
{ E_AUTO_ABSA, ERROR_LEVEL_ERROR,
|
||||
"absolute address not allowed for automatic var '%s' in reentrant function " },
|
||||
{ W_INIT_WRONG, ERROR_LEVEL_WARNING,
|
||||
"Initializer different levels of indirections" },
|
||||
{ E_FUNC_REDEF, ERROR_LEVEL_ERROR,
|
||||
"Function name '%s' redefined " },
|
||||
{ E_ID_UNDEF, ERROR_LEVEL_ERROR,
|
||||
"Undefined identifier '%s'" },
|
||||
{ W_STACK_OVERFLOW, ERROR_LEVEL_WARNING,
|
||||
"stack exceeds 256 bytes for function '%s'" },
|
||||
{ E_NEED_ARRAY_PTR, ERROR_LEVEL_ERROR,
|
||||
"Array or pointer required for '%s' operation " },
|
||||
{ E_IDX_NOT_INT, ERROR_LEVEL_ERROR,
|
||||
"Array index not an integer" },
|
||||
{ E_ARRAY_BOUND, ERROR_LEVEL_ERROR,
|
||||
"Array bound Exceeded, assuming zero" },
|
||||
{ E_STRUCT_UNION, ERROR_LEVEL_ERROR,
|
||||
"Structure/Union expected left of '.%s'" },
|
||||
{ E_NOT_MEMBER, ERROR_LEVEL_ERROR,
|
||||
"'%s' not a structure/union member" },
|
||||
{ E_PTR_REQD, ERROR_LEVEL_ERROR,
|
||||
"Pointer required" },
|
||||
{ E_UNARY_OP, ERROR_LEVEL_ERROR,
|
||||
"'unary %c': illegal operand" },
|
||||
{ E_CONV_ERR, ERROR_LEVEL_ERROR,
|
||||
"convertion error: integral promotion failed" },
|
||||
{ E_INT_REQD, ERROR_LEVEL_ERROR,
|
||||
"type must be INT for bit field definition" },
|
||||
{ E_BITFLD_SIZE, ERROR_LEVEL_ERROR,
|
||||
"bit field size greater than 16 . assuming 16" },
|
||||
{ W_TRUNCATION, ERROR_LEVEL_WARNING,
|
||||
"high order truncation might occur" },
|
||||
{ E_CODE_WRITE, ERROR_LEVEL_ERROR,
|
||||
"Attempt to assign value to a constant variable %s" },
|
||||
{ E_LVALUE_CONST, ERROR_LEVEL_ERROR,
|
||||
"Lvalue specifies constant object" },
|
||||
{ E_ILLEGAL_ADDR, ERROR_LEVEL_ERROR,
|
||||
"'&' illegal operand , %s" },
|
||||
{ E_CAST_ILLEGAL, ERROR_LEVEL_ERROR,
|
||||
"illegal cast (cast cannot be aggregate)" },
|
||||
{ E_MULT_INTEGRAL, ERROR_LEVEL_ERROR,
|
||||
"'*' bad operand" },
|
||||
{ E_ARG_ERROR, ERROR_LEVEL_ERROR,
|
||||
"Argument count error, argument ignored" },
|
||||
{ E_ARG_COUNT, ERROR_LEVEL_ERROR,
|
||||
"Function was expecting more arguments" },
|
||||
{ E_FUNC_EXPECTED, ERROR_LEVEL_ERROR,
|
||||
"Function name expected '%s'.ANSI style declaration REQUIRED" },
|
||||
{ E_PLUS_INVALID, ERROR_LEVEL_ERROR,
|
||||
"invalid operand '%s'" },
|
||||
{ E_PTR_PLUS_PTR, ERROR_LEVEL_ERROR,
|
||||
"pointer + pointer invalid" },
|
||||
{ E_SHIFT_OP_INVALID, ERROR_LEVEL_ERROR,
|
||||
"invalid operand for shift operator" },
|
||||
{ E_COMPARE_OP, ERROR_LEVEL_ERROR,
|
||||
"compare operand cannot be struct/union" },
|
||||
{ E_BITWISE_OP, ERROR_LEVEL_ERROR,
|
||||
"operand invalid for bitwise operation" },
|
||||
{ E_ANDOR_OP, ERROR_LEVEL_ERROR,
|
||||
"Invalid operand for '&&' or '||'" },
|
||||
{ E_TYPE_MISMATCH, ERROR_LEVEL_ERROR,
|
||||
"indirections to different types %s %s " },
|
||||
{ E_AGGR_ASSIGN, ERROR_LEVEL_ERROR,
|
||||
"cannot assign values to aggregates" },
|
||||
{ E_ARRAY_DIRECT, ERROR_LEVEL_ERROR,
|
||||
"bit Arrays can be accessed by literal index only" },
|
||||
{ E_BIT_ARRAY, ERROR_LEVEL_ERROR,
|
||||
"Array or Pointer to bit|sbit|sfr not allowed.'%s'" },
|
||||
{ E_DUPLICATE_TYPEDEF, ERROR_LEVEL_ERROR,
|
||||
"typedef/enum '%s' duplicate.Previous definiton Ignored" },
|
||||
{ E_ARG_TYPE, ERROR_LEVEL_ERROR,
|
||||
"Actual Argument type different from declaration %d" },
|
||||
{ E_RET_VALUE, ERROR_LEVEL_ERROR,
|
||||
"Function return value mismatch" },
|
||||
{ E_FUNC_AGGR, ERROR_LEVEL_ERROR,
|
||||
"Function cannot return aggregate. Func body ignored" },
|
||||
{ E_FUNC_DEF, ERROR_LEVEL_ERROR,
|
||||
"ANSI Style declaration needed" },
|
||||
{ E_DUPLICATE_LABEL, ERROR_LEVEL_ERROR,
|
||||
"Label name redefined '%s'" },
|
||||
{ E_LABEL_UNDEF, ERROR_LEVEL_ERROR,
|
||||
"Label undefined '%s'" },
|
||||
{ E_FUNC_VOID, ERROR_LEVEL_ERROR,
|
||||
"void function returning value" },
|
||||
{ E_VOID_FUNC, ERROR_LEVEL_ERROR,
|
||||
"function '%s' must return value" },
|
||||
{ W_RETURN_MISMATCH, ERROR_LEVEL_WARNING,
|
||||
"function return value mismatch" },
|
||||
{ E_CASE_CONTEXT, ERROR_LEVEL_ERROR,
|
||||
"'case/default' found without 'switch'.statement ignored" },
|
||||
{ E_CASE_CONSTANT, ERROR_LEVEL_ERROR,
|
||||
"'case' expression not constant. statement ignored" },
|
||||
{ E_BREAK_CONTEXT, ERROR_LEVEL_ERROR,
|
||||
"'break/continue' statement out of context" },
|
||||
{ E_SWITCH_AGGR, ERROR_LEVEL_ERROR,
|
||||
"nonintegral used in switch expression" },
|
||||
{ E_FUNC_BODY, ERROR_LEVEL_ERROR,
|
||||
"function '%s' already has body" },
|
||||
{ E_UNKNOWN_SIZE, ERROR_LEVEL_ERROR,
|
||||
"attempt to allocate variable of unknown size '%s'" },
|
||||
{ E_AUTO_AGGR_INIT, ERROR_LEVEL_ERROR,
|
||||
"aggregate 'auto' variable '%s' cannot be initialized" },
|
||||
{ E_INIT_COUNT, ERROR_LEVEL_ERROR,
|
||||
"too many initializers" },
|
||||
{ E_INIT_STRUCT, ERROR_LEVEL_ERROR,
|
||||
"struct/union/array '%s' :initialization needs curly braces" },
|
||||
{ E_INIT_NON_ADDR, ERROR_LEVEL_ERROR,
|
||||
"non-address initialization expression" },
|
||||
{ E_INT_DEFINED, ERROR_LEVEL_ERROR,
|
||||
"interrupt no '%d' already has a service routine '%s'" },
|
||||
{ E_INT_ARGS, ERROR_LEVEL_ERROR,
|
||||
"interrupt routine cannot have arguments, arguments ingored" },
|
||||
{ E_INCLUDE_MISSING, ERROR_LEVEL_ERROR,
|
||||
"critical compiler #include file missing. " },
|
||||
{ E_NO_MAIN, ERROR_LEVEL_ERROR,
|
||||
"function 'main' undefined" },
|
||||
{ E_EXTERN_INIT, ERROR_LEVEL_ERROR,
|
||||
"'extern' variable '%s' cannot be initialised " },
|
||||
{ E_PRE_PROC_FAILED, ERROR_LEVEL_ERROR,
|
||||
"Pre-Processor %s" },
|
||||
{ E_DUP_FAILED, ERROR_LEVEL_ERROR,
|
||||
"_dup call failed" },
|
||||
{ E_INCOMPAT_TYPES, ERROR_LEVEL_ERROR,
|
||||
"incompatible types" },
|
||||
{ W_LOOP_ELIMINATE, ERROR_LEVEL_WARNING,
|
||||
"'while' loop with 'zero' constant.loop eliminated" },
|
||||
{ W_NO_SIDE_EFFECTS, ERROR_LEVEL_WARNING,
|
||||
"%s expression has NO side effects.expr eliminated" },
|
||||
{ W_CONST_TOO_LARGE, ERROR_LEVEL_PEDANTIC,
|
||||
"constant value '%s', out of range." },
|
||||
{ W_BAD_COMPARE, ERROR_LEVEL_WARNING,
|
||||
"comparison will either, ALWAYs succeed or ALWAYs fail" },
|
||||
{ E_TERMINATING, ERROR_LEVEL_ERROR,
|
||||
"Compiler Terminating , contact author with source" },
|
||||
{ W_LOCAL_NOINIT, ERROR_LEVEL_WARNING,
|
||||
"'auto' variable '%s' may be used before initialization at %s(%d)" },
|
||||
{ W_NO_REFERENCE, ERROR_LEVEL_WARNING,
|
||||
"in function %s unreferenced %s : '%s'" },
|
||||
{ E_OP_UNKNOWN_SIZE, ERROR_LEVEL_ERROR,
|
||||
"unknown size for operand" },
|
||||
{ W_LONG_UNSUPPORTED, ERROR_LEVEL_WARNING,
|
||||
"'%s' 'long' not supported , declared as 'int' ." },
|
||||
{ E_LITERAL_GENERIC, ERROR_LEVEL_ERROR,
|
||||
//"illegal cast of LITERAL value to 'generic' pointer: assuming 'xdata' pointer" },
|
||||
"illegal cast of LITERAL value to 'generic' pointer" },
|
||||
{ E_SFR_ADDR_RANGE, ERROR_LEVEL_ERROR,
|
||||
"%s '%s' address out of range" },
|
||||
{ E_BITVAR_STORAGE, ERROR_LEVEL_ERROR,
|
||||
"storage class CANNOT be specified for bit variable '%s'" },
|
||||
{ E_EXTERN_MISMATCH, ERROR_LEVEL_ERROR,
|
||||
"extern definition for '%s' mismatches with declaration." },
|
||||
{ W_NONRENT_ARGS, ERROR_LEVEL_WARNING,
|
||||
"Functions called via pointers must be 'reentrant' to take arguments" },
|
||||
{ W_DOUBLE_UNSUPPORTED, ERROR_LEVEL_WARNING,
|
||||
"type 'double' not supported assuming 'float'" },
|
||||
{ W_IF_NEVER_TRUE, ERROR_LEVEL_WARNING,
|
||||
"if-statement condition always false.if-statement not generated" },
|
||||
{ W_FUNC_NO_RETURN, ERROR_LEVEL_WARNING,
|
||||
"no 'return' statement found for function '%s'" },
|
||||
{ W_PRE_PROC_WARNING, ERROR_LEVEL_WARNING,
|
||||
"Pre-Processor %s" },
|
||||
{ W_STRUCT_AS_ARG, ERROR_LEVEL_WARNING,
|
||||
"structure '%s' passed as function argument changed to pointer" },
|
||||
{ E_PREV_DEF_CONFLICT, ERROR_LEVEL_ERROR,
|
||||
"conflict with previous definition of '%s' for attribute '%s'" },
|
||||
{ E_CODE_NO_INIT, ERROR_LEVEL_ERROR,
|
||||
"variable '%s' declared in code space must have initialiser" },
|
||||
{ E_OPS_INTEGRAL, ERROR_LEVEL_ERROR,
|
||||
"operands not integral for assignment operation" },
|
||||
{ E_TOO_MANY_PARMS, ERROR_LEVEL_ERROR,
|
||||
"too many parameters " },
|
||||
{ E_TOO_FEW_PARMS, ERROR_LEVEL_ERROR,
|
||||
"too few parameters" },
|
||||
{ E_FUNC_NO_CODE, ERROR_LEVEL_ERROR,
|
||||
"code not generated for '%s' due to previous errors" },
|
||||
{ E_TYPE_MISMATCH_PARM, ERROR_LEVEL_ERROR,
|
||||
"type mismatch for parameter number %d" },
|
||||
{ E_INVALID_FLOAT_CONST, ERROR_LEVEL_ERROR,
|
||||
"invalid float constant '%s'" },
|
||||
{ E_INVALID_OP, ERROR_LEVEL_ERROR,
|
||||
"invalid operand for '%s' operation" },
|
||||
{ E_SWITCH_NON_INTEGER, ERROR_LEVEL_ERROR,
|
||||
"switch value not an integer" },
|
||||
{ E_CASE_NON_INTEGER, ERROR_LEVEL_ERROR,
|
||||
"case label not an integer" },
|
||||
{ W_FUNC_TOO_LARGE, ERROR_LEVEL_WARNING,
|
||||
"function '%s' too large for global optimization" },
|
||||
{ W_CONTROL_FLOW, ERROR_LEVEL_PEDANTIC,
|
||||
"conditional flow changed by optimizer '%s(%d)':so said EVELYN the modified DOG" },
|
||||
{ W_PTR_TYPE_INVALID, ERROR_LEVEL_WARNING,
|
||||
"invalid type specifier for pointer type specifier ignored" },
|
||||
{ W_IMPLICIT_FUNC, ERROR_LEVEL_WARNING,
|
||||
"function '%s' implicit declaration" },
|
||||
{ W_CONTINUE, ERROR_LEVEL_WARNING,
|
||||
"%s" },
|
||||
{ I_TOOMANY_SPILS, ERROR_LEVEL_INFO,
|
||||
"extended by %d bytes for compiler temp(s) :in function '%s': %s " },
|
||||
{ W_UNKNOWN_PRAGMA, ERROR_LEVEL_WARNING,
|
||||
"unknown or unsupported #pragma directive '%s'" },
|
||||
{ W_SHIFT_CHANGED, ERROR_LEVEL_PEDANTIC,
|
||||
"%s shifting more than size of object changed to zero" },
|
||||
{ W_UNKNOWN_OPTION, ERROR_LEVEL_WARNING,
|
||||
"unknown compiler option '%s' ignored" },
|
||||
{ W_UNSUPP_OPTION, ERROR_LEVEL_WARNING,
|
||||
"option '%s' no longer supported '%s' " },
|
||||
{ W_UNKNOWN_FEXT, ERROR_LEVEL_WARNING,
|
||||
"don't know what to do with file '%s'. file extension unsupported" },
|
||||
{ W_TOO_MANY_SRC, ERROR_LEVEL_WARNING,
|
||||
"cannot compile more than one source file . file '%s' ignored" },
|
||||
{ I_CYCLOMATIC, ERROR_LEVEL_INFO,
|
||||
"function '%s', # edges %d , # nodes %d , cyclomatic complexity %d" },
|
||||
{ E_DIVIDE_BY_ZERO, ERROR_LEVEL_ERROR,
|
||||
"dividing by ZERO" },
|
||||
{ E_FUNC_BIT, ERROR_LEVEL_ERROR,
|
||||
"function cannot return 'bit'" },
|
||||
{ E_CAST_ZERO, ERROR_LEVEL_ERROR,
|
||||
"casting from to type 'void' is illegal" },
|
||||
{ W_CONST_RANGE, ERROR_LEVEL_WARNING,
|
||||
"constant is out of range %s" },
|
||||
{ W_CODE_UNREACH, ERROR_LEVEL_PEDANTIC,
|
||||
"unreachable code %s(%d)" },
|
||||
{ E_NONPTR2_GENPTR, ERROR_LEVEL_ERROR,
|
||||
"non-pointer type cast to generic pointer" },
|
||||
{ W_POSSBUG, ERROR_LEVEL_WARNING,
|
||||
"possible code generation error at line %d,\n"
|
||||
" send source to sandeep.dutta@usa.net" },
|
||||
{ E_INCOMPAT_PTYPES, ERROR_LEVEL_WARNING,
|
||||
"pointer types incompatible " },
|
||||
{ W_UNKNOWN_MODEL, ERROR_LEVEL_WARNING,
|
||||
"unknown memory model at %s : %d" },
|
||||
{ E_UNKNOWN_TARGET, ERROR_LEVEL_ERROR,
|
||||
"cannot generate code for target '%s'" },
|
||||
{ W_INDIR_BANKED, ERROR_LEVEL_WARNING,
|
||||
"Indirect call to a banked function not implemented." },
|
||||
{ W_UNSUPPORTED_MODEL, ERROR_LEVEL_WARNING,
|
||||
"Model '%s' not supported for %s, ignored." },
|
||||
{ W_BANKED_WITH_NONBANKED, ERROR_LEVEL_WARNING,
|
||||
"Both banked and nonbanked attributes used. nonbanked wins." },
|
||||
{ W_BANKED_WITH_STATIC, ERROR_LEVEL_WARNING,
|
||||
"Both banked and static used. static wins." },
|
||||
{ W_INT_TO_GEN_PTR_CAST, ERROR_LEVEL_WARNING,
|
||||
"converting integer type to generic pointer: assuming XDATA" },
|
||||
{ W_ESC_SEQ_OOR_FOR_CHAR, ERROR_LEVEL_WARNING,
|
||||
"escape sequence out of range for char." },
|
||||
{ E_INVALID_HEX, ERROR_LEVEL_ERROR,
|
||||
"\\x used with no following hex digits." },
|
||||
{ W_FUNCPTR_IN_USING_ISR, ERROR_LEVEL_WARNING,
|
||||
"call via function pointer in ISR using non-zero register bank.\n"
|
||||
" Cannot determine which register bank to save." },
|
||||
{ E_NO_SUCH_BANK, ERROR_LEVEL_ERROR,
|
||||
"called function uses unknown register bank %d." },
|
||||
{ E_TWO_OR_MORE_DATA_TYPES, ERROR_LEVEL_ERROR,
|
||||
"two or more data types in declaration for '%s'" },
|
||||
{ E_LONG_OR_SHORT_INVALID, ERROR_LEVEL_ERROR,
|
||||
"long or short specified for %s '%s'" },
|
||||
{ E_SIGNED_OR_UNSIGNED_INVALID, ERROR_LEVEL_ERROR,
|
||||
"signed or unsigned specified for %s '%s'" },
|
||||
{ E_LONG_AND_SHORT_INVALID, ERROR_LEVEL_ERROR,
|
||||
"both long and short specified for %s '%s'" },
|
||||
{ E_SIGNED_AND_UNSIGNED_INVALID, ERROR_LEVEL_ERROR,
|
||||
"both signed and unsigned specified for %s '%s'" },
|
||||
{ E_TWO_OR_MORE_STORAGE_CLASSES, ERROR_LEVEL_ERROR,
|
||||
"two or more storage classes in declaration for '%s'" },
|
||||
{ W_EXESS_ARRAY_INITIALIZERS, ERROR_LEVEL_WARNING,
|
||||
"excess elements in array initializer after `%s' at line %d" },
|
||||
{ E_ARGUMENT_MISSING, ERROR_LEVEL_ERROR,
|
||||
"Option %s requires an argument." },
|
||||
{ W_STRAY_BACKSLASH, ERROR_LEVEL_WARNING,
|
||||
"stray '\\' at column %d" },
|
||||
{ W_NEWLINE_IN_STRING, ERROR_LEVEL_WARNING,
|
||||
"newline in string constant" },
|
||||
{ E_CANNOT_USE_GENERIC_POINTER, ERROR_LEVEL_ERROR,
|
||||
"cannot use generic pointer %s to initialize %s" },
|
||||
{ W_EXCESS_SHORT_OPTIONS, ERROR_LEVEL_WARNING,
|
||||
"Only one short option can be specified at a time. Rest of %s ignored." },
|
||||
{ E_VOID_VALUE_USED, ERROR_LEVEL_ERROR,
|
||||
"void value not ignored as it ought to be" },
|
||||
{ W_INTEGRAL2PTR_NOCAST, ERROR_LEVEL_WARNING,
|
||||
"converting integral to pointer without a cast" },
|
||||
{ W_PTR2INTEGRAL_NOCAST, ERROR_LEVEL_WARNING,
|
||||
"converting pointer to integral without a cast" },
|
||||
{ W_SYMBOL_NAME_TOO_LONG, ERROR_LEVEL_WARNING,
|
||||
"symbol name too long, truncated to %d chars" },
|
||||
{ W_CAST_STRUCT_PTR,ERROR_LEVEL_WARNING,
|
||||
"cast of struct %s * to struct %s * " }
|
||||
};
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
SetErrorOut - Set the error output file
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
FILE *SetErrorOut(FILE *NewErrorOut)
|
||||
|
||||
{
|
||||
_SDCCERRG.out = NewErrorOut ;
|
||||
|
||||
return NewErrorOut ;
|
||||
}
|
||||
|
||||
void
|
||||
setErrorLogLevel (ERROR_LOG_LEVEL level)
|
||||
{
|
||||
_SDCCERRG.logLevel = level;
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
vwerror - Output a standard eror message with variable number of arguements
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void vwerror (int errNum, va_list marker)
|
||||
{
|
||||
if (_SDCCERRG.out == NULL) {
|
||||
_SDCCERRG.out = DEFAULT_ERROR_OUT;
|
||||
}
|
||||
|
||||
if (ErrTab[errNum].errIndex != errNum)
|
||||
{
|
||||
fprintf(_SDCCERRG.out,
|
||||
"*** Internal error: error table entry for %d inconsistent.", errNum);
|
||||
}
|
||||
|
||||
|
||||
if (ErrTab[errNum].errType >= _SDCCERRG.logLevel) {
|
||||
if ( ErrTab[errNum].errType == ERROR_LEVEL_ERROR )
|
||||
fatalError++ ;
|
||||
|
||||
if ( filename && lineno ) {
|
||||
fprintf(_SDCCERRG.out, "%s(%d):",filename,lineno);
|
||||
} else if (lineno) {
|
||||
fprintf(_SDCCERRG.out, "at %d:", lineno);
|
||||
}
|
||||
|
||||
switch(ErrTab[errNum].errType)
|
||||
{
|
||||
case ERROR_LEVEL_ERROR:
|
||||
fprintf(_SDCCERRG.out, "error *** ");
|
||||
break;
|
||||
case ERROR_LEVEL_WARNING:
|
||||
case ERROR_LEVEL_PEDANTIC:
|
||||
fprintf(_SDCCERRG.out, "warning *** ");
|
||||
break;
|
||||
case ERROR_LEVEL_INFO:
|
||||
fprintf(_SDCCERRG.out, "info *** ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vfprintf(_SDCCERRG.out, ErrTab[errNum].errText,marker);
|
||||
fprintf(_SDCCERRG.out, "\n");
|
||||
}
|
||||
else {
|
||||
// Below the logging level, drop.
|
||||
}
|
||||
}
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
werror - Output a standard eror message with variable number of arguements
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void werror (int errNum, ... )
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker,errNum);
|
||||
vwerror(errNum, marker);
|
||||
va_end( marker );
|
||||
}
|
||||
|
||||
231
link/support/Util/SDCCerr.h
Normal file
231
link/support/Util/SDCCerr.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
===============================================================================
|
||||
SDCCERR - SDCC Standard error handler
|
||||
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#if !defined(__SDCCERR_H)
|
||||
|
||||
#define __SDCCERR_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* ERROR Message Definition */
|
||||
|
||||
#define E_DUPLICATE 0 /* Duplicate variable */
|
||||
#define E_SYNTAX_ERROR 1 /* Syntax Error */
|
||||
#define E_CONST_EXPECTED 2 /* constant expected */
|
||||
#define E_OUT_OF_MEM 3 /* malloc failed */
|
||||
#define E_FILE_OPEN_ERR 4 /* File open failed */
|
||||
#define E_INVALID_OCLASS 5 /* output class invalid */
|
||||
#define E_CANNOT_ALLOC 6 /* cannot allocate space*/
|
||||
#define E_OLD_STYLE 7 /* old style C ! allowed*/
|
||||
#define E_STACK_OUT 8 /* v r out of stack */
|
||||
#define E_INTERNAL_ERROR 9 /* unable to alloc tvar */
|
||||
#define E_LVALUE_REQUIRED 10 /* lvalue required */
|
||||
#define E_TMPFILE_FAILED 11 /* tmpfile creation failed */
|
||||
#define E_FUNCTION_EXPECTED 12 /* function expected */
|
||||
#define E_USING_ERROR 13 /* using in error */
|
||||
#define E_SFR_INIT 14 /* init error for sbit */
|
||||
#define W_INIT_IGNORED 15 /* initialiser ignored */
|
||||
#define E_AUTO_ASSUMED 16 /* sclass auto assumed */
|
||||
#define E_AUTO_ABSA 17 /* abs addr for auto var*/
|
||||
#define W_INIT_WRONG 18 /* initializer type != */
|
||||
#define E_FUNC_REDEF 19 /* func name redefined */
|
||||
#define E_ID_UNDEF 20 /* identifer undefined */
|
||||
#define W_STACK_OVERFLOW 21 /* stack overflow */
|
||||
#define E_NEED_ARRAY_PTR 22 /* array or pointer reqd*/
|
||||
#define E_IDX_NOT_INT 23 /* index not an integer */
|
||||
#define E_ARRAY_BOUND 24 /* array limit exceeded */
|
||||
#define E_STRUCT_UNION 25 /* struct,union expected*/
|
||||
#define E_NOT_MEMBER 26 /* !struct/union member */
|
||||
#define E_PTR_REQD 27 /* pointer required */
|
||||
#define E_UNARY_OP 28 /* unary operator bad op*/
|
||||
#define E_CONV_ERR 29 /* conversion error */
|
||||
#define E_INT_REQD 30 /* bit field must be int*/
|
||||
#define E_BITFLD_SIZE 31 /* bit field size > 16 */
|
||||
#define W_TRUNCATION 32 /* high order trucation */
|
||||
#define E_CODE_WRITE 33 /* trying 2 write to code */
|
||||
#define E_LVALUE_CONST 34 /* lvalue is a const */
|
||||
#define E_ILLEGAL_ADDR 35 /* address of bit */
|
||||
#define E_CAST_ILLEGAL 36 /* cast illegal */
|
||||
#define E_MULT_INTEGRAL 37 /* mult opernd must b integral */
|
||||
#define E_ARG_ERROR 38 /* argument count error*/
|
||||
#define E_ARG_COUNT 39 /* func expecting more */
|
||||
#define E_FUNC_EXPECTED 40 /* func name expected */
|
||||
#define E_PLUS_INVALID 41 /* plus invalid */
|
||||
#define E_PTR_PLUS_PTR 42 /* pointer + pointer */
|
||||
#define E_SHIFT_OP_INVALID 43 /* shft op op invalid */
|
||||
#define E_COMPARE_OP 44 /* compare operand */
|
||||
#define E_BITWISE_OP 45 /* bit op invalid op */
|
||||
#define E_ANDOR_OP 46 /* && || op invalid */
|
||||
#define E_TYPE_MISMATCH 47 /* type mismatch */
|
||||
#define E_AGGR_ASSIGN 48 /* aggr assign */
|
||||
#define E_ARRAY_DIRECT 49 /* array indexing in */
|
||||
#define E_BIT_ARRAY 50 /* bit array not allowed */
|
||||
#define E_DUPLICATE_TYPEDEF 51 /* typedef name duplicate */
|
||||
#define E_ARG_TYPE 52 /* arg type mismatch */
|
||||
#define E_RET_VALUE 53 /* return value mismatch */
|
||||
#define E_FUNC_AGGR 54 /* function returing aggr */
|
||||
#define E_FUNC_DEF 55 /* ANSI Style def neede */
|
||||
#define E_DUPLICATE_LABEL 56 /* duplicate label name */
|
||||
#define E_LABEL_UNDEF 57 /* undefined label used */
|
||||
#define E_FUNC_VOID 58 /* void func ret value */
|
||||
#define E_VOID_FUNC 59 /* func must return value */
|
||||
#define W_RETURN_MISMATCH 60 /* return value mismatch */
|
||||
#define E_CASE_CONTEXT 61 /* case stmnt without switch */
|
||||
#define E_CASE_CONSTANT 62 /* case expression ! const*/
|
||||
#define E_BREAK_CONTEXT 63 /* break statement invalid*/
|
||||
#define E_SWITCH_AGGR 64 /* non integral for switch*/
|
||||
#define E_FUNC_BODY 65 /* func has body already */
|
||||
#define E_UNKNOWN_SIZE 66 /* variable has unknown size */
|
||||
#define E_AUTO_AGGR_INIT 67 /* auto aggregates no init */
|
||||
#define E_INIT_COUNT 68 /* too many initializers */
|
||||
#define E_INIT_STRUCT 69 /* struct init wrong */
|
||||
#define E_INIT_NON_ADDR 70 /* non address xpr for init */
|
||||
#define E_INT_DEFINED 71 /* interrupt already over */
|
||||
#define E_INT_ARGS 72 /* interrupt rtn cannot have args */
|
||||
#define E_INCLUDE_MISSING 73 /* compiler include missing */
|
||||
#define E_NO_MAIN 74 /* main function undefined */
|
||||
#define E_EXTERN_INIT 75 /* extern variable initialised */
|
||||
#define E_PRE_PROC_FAILED 76 /* preprocessor failed */
|
||||
#define E_DUP_FAILED 77 /* file DUP failed */
|
||||
#define E_INCOMPAT_TYPES 78 /* incompatible types casting */
|
||||
#define W_LOOP_ELIMINATE 79 /* loop eliminated */
|
||||
#define W_NO_SIDE_EFFECTS 80 /* expression has no side effects */
|
||||
#define W_CONST_TOO_LARGE 81 /* constant out of range */
|
||||
#define W_BAD_COMPARE 82 /* bad comparison */
|
||||
#define E_TERMINATING 83 /* compiler terminating */
|
||||
#define W_LOCAL_NOINIT 84 /* local reference before assignment */
|
||||
#define W_NO_REFERENCE 85 /* no reference to local variable */
|
||||
#define E_OP_UNKNOWN_SIZE 86 /* unknown size for operand */
|
||||
#define W_LONG_UNSUPPORTED 87 /* 'long' not supported yet */
|
||||
#define E_LITERAL_GENERIC 88 /* literal being cast to generic pointer */
|
||||
#define E_SFR_ADDR_RANGE 89 /* sfr address out of range */
|
||||
#define E_BITVAR_STORAGE 90 /* storage given for 'bit' variable */
|
||||
#define E_EXTERN_MISMATCH 91 /* extern declaration mismatches */
|
||||
#define W_NONRENT_ARGS 92 /* fptr non reentrant has args */
|
||||
#define W_DOUBLE_UNSUPPORTED 93 /* 'double' not supported yet */
|
||||
#define W_IF_NEVER_TRUE 94 /* if always false */
|
||||
#define W_FUNC_NO_RETURN 95 /* no return statement found */
|
||||
#define W_PRE_PROC_WARNING 96 /* preprocessor generated warning */
|
||||
#define W_STRUCT_AS_ARG 97 /* structure passed as argument */
|
||||
#define E_PREV_DEF_CONFLICT 98 /* previous definition conflicts with current */
|
||||
#define E_CODE_NO_INIT 99 /* vars in code space must have initializer */
|
||||
#define E_OPS_INTEGRAL 100 /* operans must be integral for certian assignments */
|
||||
#define E_TOO_MANY_PARMS 101 /* too many parameters */
|
||||
#define E_TOO_FEW_PARMS 102 /* to few parameters */
|
||||
#define E_FUNC_NO_CODE 103 /* fatalError */
|
||||
#define E_TYPE_MISMATCH_PARM 104 /* type mismatch for parameter */
|
||||
#define E_INVALID_FLOAT_CONST 105 /* invalid floating point literal string */
|
||||
#define E_INVALID_OP 106 /* invalid operand for some operation */
|
||||
#define E_SWITCH_NON_INTEGER 107 /* switch value not integer */
|
||||
#define E_CASE_NON_INTEGER 108 /* case value not integer */
|
||||
#define W_FUNC_TOO_LARGE 109 /* function too large */
|
||||
#define W_CONTROL_FLOW 110 /* control flow changed due to optimization */
|
||||
#define W_PTR_TYPE_INVALID 111 /* invalid type specifier for pointer */
|
||||
#define W_IMPLICIT_FUNC 112 /* function declared implicitly */
|
||||
#define W_CONTINUE 113 /* more than one line */
|
||||
#define I_TOOMANY_SPILS 114 /* too many spils occured */
|
||||
#define W_UNKNOWN_PRAGMA 115 /* #pragma directive unsupported */
|
||||
#define W_SHIFT_CHANGED 116 /* shift changed to zero */
|
||||
#define W_UNKNOWN_OPTION 117 /* don't know the option */
|
||||
#define W_UNSUPP_OPTION 118 /* processor reset has been redifned */
|
||||
#define W_UNKNOWN_FEXT 119 /* unknown file extension */
|
||||
#define W_TOO_MANY_SRC 120 /* can only compile one .c file at a time */
|
||||
#define I_CYCLOMATIC 121 /* information message */
|
||||
#define E_DIVIDE_BY_ZERO 122 /* / 0 */
|
||||
#define E_FUNC_BIT 123 /* function cannot return bit */
|
||||
#define E_CAST_ZERO 124 /* casting to from size zero */
|
||||
#define W_CONST_RANGE 125 /* constant too large */
|
||||
#define W_CODE_UNREACH 126 /* unreachable code */
|
||||
#define E_NONPTR2_GENPTR 127 /* non pointer cast to generic pointer */
|
||||
#define W_POSSBUG 128 /* possible code generation error */
|
||||
#define E_INCOMPAT_PTYPES 129 /* incampatible pointer assignment */
|
||||
#define W_UNKNOWN_MODEL 130 /* Unknown memory model */
|
||||
#define E_UNKNOWN_TARGET 131 /* target not defined */
|
||||
#define W_INDIR_BANKED 132 /* Indirect call to a banked fun */
|
||||
#define W_UNSUPPORTED_MODEL 133 /* Unsupported model, ignored */
|
||||
#define W_BANKED_WITH_NONBANKED 134 /* banked and nonbanked attributes mixed */
|
||||
#define W_BANKED_WITH_STATIC 135 /* banked and static mixed */
|
||||
#define W_INT_TO_GEN_PTR_CAST 136 /* Converting integer type to generic pointer. */
|
||||
#define W_ESC_SEQ_OOR_FOR_CHAR 137 /* Escape sequence of of range for char */
|
||||
#define E_INVALID_HEX 138 /* \x used with no following hex digits */
|
||||
#define W_FUNCPTR_IN_USING_ISR 139 /* Call via function pointer in ISR with using attribute. */
|
||||
#define E_NO_SUCH_BANK 140 /* 'using' attribute specifies non-existant register bank. */
|
||||
#define E_TWO_OR_MORE_DATA_TYPES 141
|
||||
#define E_LONG_OR_SHORT_INVALID 142 /* long or short invalid for .. */
|
||||
#define E_SIGNED_OR_UNSIGNED_INVALID 143 /* signed or unsigned invalid for .. */
|
||||
#define E_LONG_AND_SHORT_INVALID 144 /* long and short invalid for .. */
|
||||
#define E_SIGNED_AND_UNSIGNED_INVALID 145 /* signed and unsigned invalid for .. */
|
||||
#define E_TWO_OR_MORE_STORAGE_CLASSES 146
|
||||
#define W_EXESS_ARRAY_INITIALIZERS 147 /* too much initializers for array */
|
||||
#define E_ARGUMENT_MISSING 148 /* Option requires an argument. */
|
||||
#define W_STRAY_BACKSLASH 149
|
||||
#define W_NEWLINE_IN_STRING 150
|
||||
#define E_CANNOT_USE_GENERIC_POINTER 151
|
||||
#define W_EXCESS_SHORT_OPTIONS 152
|
||||
#define E_VOID_VALUE_USED 153
|
||||
#define W_INTEGRAL2PTR_NOCAST 154
|
||||
#define W_PTR2INTEGRAL_NOCAST 155
|
||||
#define W_SYMBOL_NAME_TOO_LONG 156
|
||||
#define W_CAST_STRUCT_PTR 157 /* pointer to different structure types */
|
||||
|
||||
/** Describes the maximum error level that will be logged. Any level
|
||||
* includes all of the levels listed after it.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum _ERROR_LOG_LEVEL {
|
||||
/** Everything. Currently the same as PEDANTIC. */
|
||||
ERROR_LEVEL_ALL,
|
||||
/** All warnings, including those considered 'reasonable to use,
|
||||
on occasion, in clean programs' (man 3 gcc). */
|
||||
ERROR_LEVEL_PEDANTIC,
|
||||
/** 'informational' warnings */
|
||||
ERROR_LEVEL_INFO,
|
||||
/** Most warnings. */
|
||||
ERROR_LEVEL_WARNING,
|
||||
/** Errors only. */
|
||||
ERROR_LEVEL_ERROR
|
||||
};
|
||||
|
||||
typedef enum _ERROR_LOG_LEVEL ERROR_LOG_LEVEL;
|
||||
|
||||
/** Sets the maximum error level to log.
|
||||
See MAX_ERROR_LEVEL. The default is ERROR_LEVEL_ALL.
|
||||
*/
|
||||
void
|
||||
setErrorLogLevel (ERROR_LOG_LEVEL level);
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
SetErrorOut - Set the error output file
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
FILE * SetErrorOut(FILE *NewErrorOut) ;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
vwerror - Output a standard eror message with variable number of arguements
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void vwerror (int errNum, va_list marker) ;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
werror - Output a standard eror message with variable number of arguements
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void werror (int errNum, ... ) ;
|
||||
|
||||
#endif
|
||||
103
link/support/Util/newalloc.h
Normal file
103
link/support/Util/newalloc.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
===============================================================================
|
||||
NEWALLOC - SDCC Memory allocation functions
|
||||
|
||||
These functions are wrappers for the standard malloc, realloc and free
|
||||
functions.
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding!
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#if !defined(_NewAlloc_H)
|
||||
|
||||
#define _NewAlloc_H
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
typedef struct _allocTrace
|
||||
{
|
||||
int num;
|
||||
int max;
|
||||
void **palloced;
|
||||
} allocTrace;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Clear_realloc - Reallocate a memory block and clear any memory added with
|
||||
out of memory error detection
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Clear_realloc(void *OldPtr,size_t OldSize,size_t NewSize) ;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Safe_realloc - Reallocate a memory block with out of memory error detection
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Safe_realloc(void *OldPtr,size_t NewSize) ;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Safe_calloc - Allocate a block of memory from the application heap, clearing
|
||||
all data to zero and checking for out or memory errors.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Safe_calloc(size_t Elements,size_t Size) ;
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Safe_malloc - Allocate a block of memory from the application heap
|
||||
and checking for out or memory errors.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void *Safe_malloc(size_t Size) ;
|
||||
|
||||
/** Replacement for Safe_malloc that also zeros memory. To make it interchangable.
|
||||
*/
|
||||
void *Safe_alloc(size_t Size) ;
|
||||
|
||||
/** Function to make the replacements complete.
|
||||
*/
|
||||
void Safe_free(void *p);
|
||||
|
||||
/** Creates a copy of a string in a safe way.
|
||||
*/
|
||||
char *Safe_strdup(const char *sz);
|
||||
|
||||
/** Logs the allocated memory 'p' in the given trace for batch freeing
|
||||
later using freeTrace.
|
||||
*/
|
||||
void *traceAlloc(allocTrace *ptrace, void *p);
|
||||
|
||||
/** Frees all the memory logged in the trace and resets the trace.
|
||||
*/
|
||||
void freeTrace(allocTrace *ptrace);
|
||||
|
||||
#endif
|
||||
47
link/z80/Makefile
Normal file
47
link/z80/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
PRJDIR = ..
|
||||
|
||||
include $(PRJDIR)/Makefile.common
|
||||
|
||||
OBJDIR = obj/$(EXT)
|
||||
|
||||
SLIBSRC = NewAlloc.c
|
||||
|
||||
SRC = lkarea.c lkdata.c lkeval.c lkhead.c lkihx.c lklex.c \
|
||||
lklibr.c lklist.c lkmain.c lkrloc.c lks19.c lksym.c \
|
||||
lkgb.c lkgg.c
|
||||
|
||||
OBJS = $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
SLIBOBJS = $(SLIBSRC:%.c=$(OBJDIR)/%.o)
|
||||
|
||||
BINS = $(BUILDDIR)link$(EXT)
|
||||
|
||||
CFLAGS += $(CPPFLAGS) $(OPTS) -DINDEXLIB -DMLH_MAP -DUNIX -DSDK
|
||||
CFLAGS += -funsigned-char -DUNIX
|
||||
CFLAGS += -I$(PRJDIR)/as/$(PORT) -I$(SLIB)
|
||||
|
||||
LDFLAGS += -lm $(EXTRALIBS)
|
||||
|
||||
all: $(BINS)
|
||||
|
||||
$(BINS): $(OBJDIR) $(BUILDDIR) $(OBJS) $(SLIBOBJS)
|
||||
$(CC) -g -o $(BINS) $(OBJS) $(SLIBOBJS) $(LDFLAGS)
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(BUILDDIR):
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: $(SLIB)/%.c
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
_link-z80:
|
||||
$(MAKE) EXT=-z80$(E) PORT=z80
|
||||
|
||||
_link-gbz80:
|
||||
$(MAKE) EXT=-gbz80$(E) OPTS=-DGAMEBOY PORT=z80
|
||||
|
||||
include clean.mk
|
||||
104
link/z80/Makefile.in
Normal file
104
link/z80/Makefile.in
Normal file
@@ -0,0 +1,104 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
VERSION = @VERSION@
|
||||
VERSIONHI = @VERSIONHI@
|
||||
VERSIONLO = @VERSIONLO@
|
||||
VERSIONP = @VERSIONP@
|
||||
|
||||
SHELL = /bin/sh
|
||||
CC = @CC@
|
||||
CPP = @CPP@
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
PRJDIR = ../..
|
||||
|
||||
srcdir = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
datadir = @datadir@
|
||||
includedir = @includedir@
|
||||
mandir = @mandir@
|
||||
man1dir = $(mandir)/man1
|
||||
man2dir = $(mandir)/man2
|
||||
infodir = @infodir@
|
||||
|
||||
SLIB =$(PRJDIR)/support/Util
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ -I. -I$(PRJDIR) -I$(PRJDIR)/as/z80 -I$(SLIB)
|
||||
CFLAGS = @CFLAGS@ -Wall -DINDEXLIB -DMLH_MAP -DUNIX -DSDK -DSDK_VERSION_STRING="\"3.0.0\"" -DTARGET_STRING="\"gbz80\"" -funsigned-char
|
||||
M_OR_MM = @M_OR_MM@
|
||||
LDFLAGS = @LDFLAGS@ -lm
|
||||
|
||||
SLIBOBJS = NewAlloc.o
|
||||
|
||||
LKOBJECTS = lkarea.o lkdata.o lkeval.o lkhead.o lkihx.o lklex.o \
|
||||
lklibr.o lklist.o lkmain.o lkrloc.o lks19.o lksym.o \
|
||||
lkgb.o lkgg.o
|
||||
LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS))
|
||||
|
||||
LKZ80 = $(PRJDIR)/bin/link-z80
|
||||
|
||||
# Compiling entire program or any subproject
|
||||
# ------------------------------------------
|
||||
all: checkconf $(LKZ80)
|
||||
|
||||
$(LKZ80): $(SLIBOBJS) $(LKOBJECTS)
|
||||
$(CC) $(CFLAGS) -o $@ $(SLIBOBJS) $(LKOBJECTS) $(LDFLAGS)
|
||||
|
||||
# Compiling and installing everything and runing test
|
||||
# ---------------------------------------------------
|
||||
install: all installdirs
|
||||
$(INSTALL) $(LKZ80) $(bindir)/link-z80
|
||||
|
||||
# Deleting all the installed files
|
||||
# --------------------------------
|
||||
uninstall:
|
||||
rm -f $(bindir)/link-z80
|
||||
|
||||
|
||||
# Performing self-test
|
||||
# --------------------
|
||||
check:
|
||||
|
||||
|
||||
# Performing installation test
|
||||
# ----------------------------
|
||||
installcheck:
|
||||
|
||||
|
||||
# Creating installation directories
|
||||
# ---------------------------------
|
||||
installdirs:
|
||||
$(INSTALL) -d $(bindir)
|
||||
|
||||
|
||||
# Creating dependencies
|
||||
# ---------------------
|
||||
dep: Makefile.dep
|
||||
|
||||
Makefile.dep: $(LKSOURCES) *.h $(PRJDIR)/*.h
|
||||
$(CPP) $(CPPFLAGS) $(M_OR_MM) $(LKSOURCES) >Makefile.dep
|
||||
|
||||
include Makefile.dep
|
||||
include clean.mk
|
||||
|
||||
# My rules
|
||||
# --------
|
||||
.c.o:
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(SLIBOBJS):%.o:$(SLIB)/%.c
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||
|
||||
# Remaking configuration
|
||||
# ----------------------
|
||||
checkconf:
|
||||
@if [ -f $(PRJDIR)/devel ]; then\
|
||||
$(MAKE) -f conf.mk srcdir="$(srcdir)" PRJDIR="$(PRJDIR)" freshconf;\
|
||||
fi
|
||||
|
||||
# End of Makefile
|
||||
720
link/z80/aslink.h
Normal file
720
link/z80/aslink.h
Normal file
@@ -0,0 +1,720 @@
|
||||
/* aslink.h */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1996
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
#include <limits.h>
|
||||
|
||||
#define VERSION "V01.75"
|
||||
|
||||
/*
|
||||
* Case Sensitivity Flag
|
||||
*/
|
||||
#define CASE_SENSITIVE 0
|
||||
|
||||
/*)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
|
||||
|
||||
/*
|
||||
* This file defines the format of the
|
||||
* relocatable binary file.
|
||||
*/
|
||||
|
||||
#ifdef SDK
|
||||
#define NCPS 32 /* characters per symbol */
|
||||
#else /* SDK */
|
||||
#define NCPS 8 /* characters per symbol */
|
||||
#endif /* SDK */
|
||||
/* #define NCPS 32 */ /* characters per symbol */
|
||||
#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 */
|
||||
#define FILSPC PATH_MAX /* File spec length */
|
||||
|
||||
/*
|
||||
* 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 value */
|
||||
#define R_USGN 0x10 /* Unsigned value */
|
||||
|
||||
#define R_NOPAG 0x00 /* Page Mode */
|
||||
#define R_PAG0 0x20 /* Page '0' */
|
||||
#define R_PAG 0x40 /* Page 'nnn' */
|
||||
|
||||
/*
|
||||
* Valid for R_BYT2:
|
||||
*/
|
||||
#define R_LSB 0x00 /* output low byte */
|
||||
#define R_MSB 0x80 /* output high byte */
|
||||
|
||||
/*
|
||||
* Global symbol types.
|
||||
*/
|
||||
#define S_REF 1 /* referenced */
|
||||
#define S_DEF 2 /* defined */
|
||||
|
||||
/*
|
||||
* Area types
|
||||
*/
|
||||
#define A_CON 000 /* concatenate */
|
||||
#define A_OVR 004 /* overlay */
|
||||
#define A_REL 000 /* relocatable */
|
||||
#define A_ABS 010 /* absolute */
|
||||
#define A_NOPAG 000 /* non-paged */
|
||||
#define A_PAG 020 /* paged */
|
||||
|
||||
/*
|
||||
* File types
|
||||
*/
|
||||
#define F_INV 0 /* invalid */
|
||||
#define F_STD 1 /* stdin */
|
||||
#define F_LNK 2 /* File.lnk */
|
||||
#define F_REL 3 /* File.rel */
|
||||
#ifdef SDK
|
||||
#define F_CMD 4 /* Command line */
|
||||
#endif /* SDK */
|
||||
|
||||
#ifdef GAMEBOY
|
||||
/*
|
||||
* Multiple banks support
|
||||
*/
|
||||
extern int nb_rom_banks;
|
||||
extern int nb_ram_banks;
|
||||
extern int current_rom_bank;
|
||||
extern int mbc_type;
|
||||
extern char cart_name[];
|
||||
/*
|
||||
* ROM patching support
|
||||
*/
|
||||
typedef struct _patch {
|
||||
unsigned int addr;
|
||||
unsigned char value;
|
||||
struct _patch *next;
|
||||
} patch;
|
||||
extern patch* patches;
|
||||
#endif /* GAMEBOY */
|
||||
/*
|
||||
* General assembler address type
|
||||
*/
|
||||
typedef unsigned int Addr_T;
|
||||
|
||||
/*
|
||||
* The structures of head, area, areax, and sym are created
|
||||
* as the REL files are read during the first pass of the
|
||||
* linker. The struct head is created upon encountering a
|
||||
* H directive in the REL file. The structure contains a
|
||||
* link to a link file structure (struct lfile) which describes
|
||||
* the file containing the H directive, the number of data/code
|
||||
* areas contained in this header segment, the number of
|
||||
* symbols referenced/defined in this header segment, a pointer
|
||||
* to an array of pointers to areax structures (struct areax)
|
||||
* created as each A directive is read, and a pointer to an
|
||||
* array of pointers to symbol structures (struct sym) for
|
||||
* all referenced/defined symbols. As H directives are read
|
||||
* from the REL files a linked list of head structures is
|
||||
* created by placing a link to the new head structure
|
||||
* in the previous head structure.
|
||||
*/
|
||||
struct head
|
||||
{
|
||||
struct head *h_hp; /* Header link */
|
||||
struct lfile *h_lfile;/* Associated file */
|
||||
int h_narea; /* # of areas */
|
||||
struct areax **a_list; /* Area list */
|
||||
int h_nglob; /* # of global symbols */
|
||||
struct sym **s_list; /* Globle symbol list */
|
||||
char m_id[NCPS]; /* Module name */
|
||||
};
|
||||
|
||||
/*
|
||||
* A structure area is created for each 'unique' data/code
|
||||
* area definition found as the REL files are read. The
|
||||
* struct area contains the name of the area, a flag byte
|
||||
* which contains the area attributes (REL/CON/OVR/ABS),
|
||||
* an area subtype (not used in this assembler), and the
|
||||
* area base address and total size which will be filled
|
||||
* in at the end of the first pass through the REL files.
|
||||
* As A directives are read from the REL files a linked
|
||||
* list of unique area structures is created by placing a
|
||||
* link to the new area structure in the previous area structure.
|
||||
*/
|
||||
struct area
|
||||
{
|
||||
struct area *a_ap; /* Area link */
|
||||
struct areax *a_axp; /* Area extension link */
|
||||
Addr_T a_addr; /* Beginning address of area */
|
||||
Addr_T a_size; /* Total size of the area */
|
||||
char a_type; /* Area subtype */
|
||||
char a_flag; /* Flag byte */
|
||||
char a_id[NCPS]; /* Name */
|
||||
};
|
||||
|
||||
/*
|
||||
* An areax structure is created for every A directive found
|
||||
* while reading the REL files. The struct areax contains a
|
||||
* link to the 'unique' area structure referenced by the A
|
||||
* directive and to the head structure this area segment is
|
||||
* a part of. The size of this area segment as read from the
|
||||
* A directive is placed in the areax structure. The beginning
|
||||
* address of this segment will be filled in at the end of the
|
||||
* first pass through the REL files. As A directives are read
|
||||
* from the REL files a linked list of areax structures is
|
||||
* created for each unique area. The final areax linked
|
||||
* list has at its head the 'unique' area structure linked
|
||||
* to the linked areax structures (one areax structure for
|
||||
* each A directive for this area).
|
||||
*/
|
||||
struct areax
|
||||
{
|
||||
struct areax *a_axp; /* Area extension link */
|
||||
struct area *a_bap; /* Base area link */
|
||||
struct head *a_bhp; /* Base header link */
|
||||
Addr_T a_addr; /* Beginning address of section */
|
||||
Addr_T a_size; /* Size of the area in section */
|
||||
};
|
||||
|
||||
/*
|
||||
* A sym structure is created for every unique symbol
|
||||
* referenced/defined while reading the REL files. The
|
||||
* struct sym contains the symbol's name, a flag value
|
||||
* (not used in this linker), a symbol type denoting
|
||||
* referenced/defined, and an address which is loaded
|
||||
* with the relative address within the area in which
|
||||
* the symbol was defined. The sym structure also
|
||||
* contains a link to the area where the symbol was defined.
|
||||
* The sym structures are linked into linked lists using
|
||||
* the symbol link element.
|
||||
*/
|
||||
struct sym
|
||||
{
|
||||
struct sym *s_sp; /* Symbol link */
|
||||
struct areax *s_axp; /* Symbol area link */
|
||||
char s_type; /* Symbol subtype */
|
||||
char s_flag; /* Flag byte */
|
||||
Addr_T s_addr; /* Address */
|
||||
char s_id[NCPS]; /* Name */
|
||||
};
|
||||
|
||||
/*
|
||||
* 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;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 char ctype[]; /* array of character types, one per
|
||||
* ASCII character
|
||||
*/
|
||||
|
||||
/*
|
||||
* Character Type Definitions
|
||||
*/
|
||||
#define SPACE 0000
|
||||
#define ETC 0000
|
||||
#define LETTER 0001
|
||||
#define DIGIT 0002
|
||||
#define BINOP 0004
|
||||
#define RAD2 0010
|
||||
#define RAD8 0020
|
||||
#define RAD10 0040
|
||||
#define RAD16 0100
|
||||
#define ILL 0200
|
||||
|
||||
#define DGT2 DIGIT|RAD16|RAD10|RAD8|RAD2
|
||||
#define DGT8 DIGIT|RAD16|RAD10|RAD8
|
||||
#define DGT10 DIGIT|RAD16|RAD10
|
||||
#define LTR16 LETTER|RAD16
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
#else
|
||||
extern char ccase[]; /* an array of characters which
|
||||
* perform the case translation function
|
||||
*/
|
||||
#endif
|
||||
|
||||
extern struct lfile *filep; /* The pointers (lfile *) filep,
|
||||
* (lfile *) cfp, and (FILE *) sfp
|
||||
* are used in conjunction with
|
||||
* the routine getLine_() to read
|
||||
* asmlnk commands from
|
||||
* (1) the standard input or
|
||||
* (2) or a command file
|
||||
* and to read the REL files
|
||||
* sequentially as defined by the
|
||||
* asmlnk input commands.
|
||||
*
|
||||
* The pointer *filep points to the
|
||||
* beginning of a linked list of
|
||||
* lfile structures.
|
||||
*/
|
||||
extern struct lfile *cfp; /* The pointer *cfp points to the
|
||||
* current lfile structure
|
||||
*/
|
||||
extern struct lfile *startp;/* asmlnk startup file structure
|
||||
*/
|
||||
extern struct lfile *linkp; /* pointer to first lfile structure
|
||||
* containing an input REL file
|
||||
* specification
|
||||
*/
|
||||
extern struct lfile *lfp; /* pointer to current lfile structure
|
||||
* being processed by parse()
|
||||
*/
|
||||
extern struct head *headp; /* The pointer to the first
|
||||
* head structure of a linked list
|
||||
*/
|
||||
extern struct head *hp; /* Pointer to the current
|
||||
* head structure
|
||||
*/
|
||||
extern struct area *areap; /* The pointer to the first
|
||||
* area structure of a linked list
|
||||
*/
|
||||
extern struct area *ap; /* Pointer to the current
|
||||
* area structure
|
||||
*/
|
||||
extern struct areax *axp; /* Pointer to the current
|
||||
* areax structure
|
||||
*/
|
||||
extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
|
||||
* linked symbol lists
|
||||
*/
|
||||
extern struct base *basep; /* The pointer to the first
|
||||
* base structure
|
||||
*/
|
||||
extern struct base *bsp; /* Pointer to the current
|
||||
* base structure
|
||||
*/
|
||||
extern struct globl *globlp;/* The pointer to the first
|
||||
* globl structure
|
||||
*/
|
||||
extern struct globl *gsp; /* Pointer to the current
|
||||
* globl structure
|
||||
*/
|
||||
extern struct sdp sdp; /* Base Paged structure
|
||||
*/
|
||||
extern struct rerr rerr; /* Structure containing the
|
||||
* linker error information
|
||||
*/
|
||||
extern FILE *ofp; /* Linker Output file handle
|
||||
*/
|
||||
extern FILE *mfp; /* Map output file handle
|
||||
*/
|
||||
extern FILE *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 int oflag; /* Output file type flag
|
||||
*/
|
||||
extern int mflag; /* Map output flag
|
||||
*/
|
||||
#ifdef SDK
|
||||
extern int symflag; /* no$gmb .sym output flag
|
||||
*/
|
||||
#endif
|
||||
extern int xflag; /* Map file radix type flag
|
||||
*/
|
||||
extern int pflag; /* print linker command file flag
|
||||
*/
|
||||
extern int uflag; /* Listing relocation 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
|
||||
*/
|
||||
|
||||
/* 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 link();
|
||||
extern VOID lkexit();
|
||||
extern int main();
|
||||
extern VOID map();
|
||||
#ifdef SDK
|
||||
extern VOID sym();
|
||||
#endif
|
||||
extern int parse();
|
||||
extern VOID setbas();
|
||||
extern VOID setgbl();
|
||||
extern VOID usage();
|
||||
|
||||
/* lklex.c */
|
||||
extern char endline();
|
||||
extern char get();
|
||||
extern VOID getfid();
|
||||
extern VOID getid();
|
||||
extern int getLine_();
|
||||
extern int getmap();
|
||||
extern char getnb();
|
||||
extern int more();
|
||||
extern VOID skip();
|
||||
extern VOID unget();
|
||||
|
||||
/* lkarea.c */
|
||||
extern VOID lkparea();
|
||||
extern VOID lnkarea();
|
||||
extern VOID lnksect();
|
||||
extern VOID newarea();
|
||||
|
||||
/* lkhead.c */
|
||||
extern VOID module();
|
||||
extern VOID newhead();
|
||||
|
||||
/* lksym.c */
|
||||
extern int hash();
|
||||
extern struct sym * lkpsym();
|
||||
extern VOID * new();
|
||||
extern struct sym * newsym();
|
||||
extern VOID symdef();
|
||||
extern int symeq();
|
||||
extern VOID syminit();
|
||||
extern VOID symmod();
|
||||
extern Addr_T symval();
|
||||
|
||||
/* lkeval.c */
|
||||
extern int digit();
|
||||
extern Addr_T eval();
|
||||
extern Addr_T expr();
|
||||
extern int oprio();
|
||||
extern Addr_T term();
|
||||
|
||||
/* lklist.c */
|
||||
extern int dgt();
|
||||
extern VOID lkulist();
|
||||
extern VOID lkalist();
|
||||
extern VOID lkglist();
|
||||
extern VOID lstarea();
|
||||
extern VOID newpag();
|
||||
extern VOID slew();
|
||||
|
||||
/* lkrloc.c */
|
||||
extern Addr_T adb_b();
|
||||
extern Addr_T adb_hi();
|
||||
extern Addr_T adb_lo();
|
||||
extern Addr_T adw_w();
|
||||
extern Addr_T adw_hi();
|
||||
extern Addr_T adw_lo();
|
||||
extern Addr_T evword();
|
||||
extern VOID rele();
|
||||
extern VOID reloc();
|
||||
extern VOID relt();
|
||||
extern VOID relr();
|
||||
extern VOID relp();
|
||||
extern VOID relerr();
|
||||
extern char * errmsg[];
|
||||
extern VOID errdmp();
|
||||
extern VOID relerp();
|
||||
extern VOID erpdmp();
|
||||
extern VOID prntval();
|
||||
|
||||
/* lklibr.c */
|
||||
extern VOID 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();
|
||||
|
||||
/* lkgb.h */
|
||||
VOID gb(int in);
|
||||
VOID gg(int in);
|
||||
|
||||
22
link/z80/clean.mk
Normal file
22
link/z80/clean.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
# Deleting all files created by building the program
|
||||
# --------------------------------------------------
|
||||
clean:
|
||||
rm -f *core *[%~] *.[oa]
|
||||
rm -f .[a-z]*~
|
||||
rm -f $(PRJDIR)/link-z80 link-z80
|
||||
rm -f *.dep
|
||||
rm -rf obj
|
||||
|
||||
# Deleting all files created by configuring or building the program
|
||||
# -----------------------------------------------------------------
|
||||
distclean: clean
|
||||
|
||||
|
||||
# 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
|
||||
23
link/z80/conf.mk
Normal file
23
link/z80/conf.mk
Normal file
@@ -0,0 +1,23 @@
|
||||
# Deleting all files created by building the program
|
||||
# --------------------------------------------------
|
||||
clean:
|
||||
rm -f *core *[%~] *.[oa]
|
||||
rm -f .[a-z]*~
|
||||
rm -f $(PRJDIR)/link-z80 link-z80
|
||||
|
||||
|
||||
# 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
|
||||
430
link/z80/lkarea.c
Normal file
430
link/z80/lkarea.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/* lkarea.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 lkarea.c
|
||||
*
|
||||
* The module lkarea.c contains the functions which
|
||||
* create and link together all area definitions read
|
||||
* from the .rel file(s).
|
||||
*
|
||||
* lkarea.c contains the following functions:
|
||||
* VOID lnkarea()
|
||||
* VOID lnksect()
|
||||
* VOID lkparea()
|
||||
* VOID newarea()
|
||||
*
|
||||
* lkarea.c contains no global variables.
|
||||
*/
|
||||
|
||||
/*)Function VOID newarea()
|
||||
*
|
||||
* The function newarea() creates and/or modifies area
|
||||
* and areax structures for each A directive read from
|
||||
* the .rel file(s). The function lkparea() is called
|
||||
* to find tha area structure associated with this name.
|
||||
* If the area does not yet exist then a new area
|
||||
* structure is created and linked to any existing
|
||||
* linked area structures. The area flags are copied
|
||||
* into the area flag variable. For each occurence of
|
||||
* an A directive an areax structure is created and
|
||||
* linked to the areax structures associated with this
|
||||
* area. The size of this area section is placed into
|
||||
* the areax structure. The flag value for all subsequent
|
||||
* area definitions for the same area are compared and
|
||||
* flagged as an error if they are not identical.
|
||||
* The areax structure created for every occurence of
|
||||
* an A directive is loaded with a pointer to the base
|
||||
* area structure and a pointer to the associated
|
||||
* head structure. And finally, a pointer to this
|
||||
* areax structure is loaded into the list of areax
|
||||
* structures in the head structure. Refer to lkdata.c
|
||||
* for details of the structures and their linkage.
|
||||
*
|
||||
* local variables:
|
||||
* areax **halp pointer to an array of pointers
|
||||
* int i counter, loop variable, value
|
||||
* char id[] id string
|
||||
* int narea number of areas in this head structure
|
||||
* areax * taxp pointer to an areax structure
|
||||
* to areax structures
|
||||
*
|
||||
* global variables:
|
||||
* area *ap Pointer to the current
|
||||
* area structure
|
||||
* areax *axp Pointer to the current
|
||||
* areax structure
|
||||
* head *hp Pointer to the current
|
||||
* head structure
|
||||
* int lkerr error flag
|
||||
*
|
||||
* functions called:
|
||||
* Addr_T eval() lkeval.c
|
||||
* VOID exit() c_library
|
||||
* int fprintf() c_library
|
||||
* VOID getid() lklex.c
|
||||
* VOID lkparea() lkarea.c
|
||||
* VOID skip() lklex.c
|
||||
*
|
||||
* side effects:
|
||||
* The area and areax structures are created and
|
||||
* linked with the appropriate head structures.
|
||||
* Failure to allocate area or areax structure
|
||||
* space will terminate the linker. Other internal
|
||||
* errors most likely caused by corrupted .rel
|
||||
* files will also terminate the linker.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create an area entry.
|
||||
*
|
||||
* A xxxxxx size nnnn flags mm
|
||||
* | | |
|
||||
* | | `-- ap->a_flag
|
||||
* | `------------- axp->a_size
|
||||
* `------------------------- ap->a_id
|
||||
*
|
||||
*/
|
||||
VOID
|
||||
newarea()
|
||||
{
|
||||
register int i, narea;
|
||||
struct areax *taxp;
|
||||
struct areax **halp;
|
||||
char id[NCPS];
|
||||
|
||||
/*
|
||||
* Create Area entry
|
||||
*/
|
||||
getid(id, -1);
|
||||
lkparea(id);
|
||||
/*
|
||||
* Evaluate area size
|
||||
*/
|
||||
skip(-1);
|
||||
axp->a_size = eval();
|
||||
/*
|
||||
* Evaluate flags
|
||||
*/
|
||||
skip(-1);
|
||||
i = 0;
|
||||
taxp = ap->a_axp;
|
||||
while (taxp->a_axp) {
|
||||
++i;
|
||||
taxp = taxp->a_axp;
|
||||
}
|
||||
if (i == 0) {
|
||||
ap->a_flag = eval();
|
||||
} else {
|
||||
i = eval();
|
||||
if (i && (ap->a_flag != i)) {
|
||||
fprintf(stderr, "Conflicting flags in area %.8s\n", id);
|
||||
lkerr++;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Place pointer in header area list
|
||||
*/
|
||||
if (headp == NULL) {
|
||||
fprintf(stderr, "No header defined\n");
|
||||
lkexit(1);
|
||||
}
|
||||
narea = hp->h_narea;
|
||||
halp = hp->a_list;
|
||||
for (i=0; i < narea ;++i) {
|
||||
if (halp[i] == NULL) {
|
||||
halp[i] = taxp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Header area list overflow\n");
|
||||
lkexit(1);
|
||||
}
|
||||
|
||||
/*)Function VOID lkparea(id)
|
||||
*
|
||||
* char * id pointer to the area name string
|
||||
*
|
||||
* The function lkparea() searches the linked area structures
|
||||
* for a name match. If the name is not found then an area
|
||||
* structure is created. An areax structure is created and
|
||||
* appended to the areax structures linked to the area structure.
|
||||
* The associated base area and head structure pointers are
|
||||
* loaded into the areax structure.
|
||||
*
|
||||
* local variables:
|
||||
* area * tap pointer to an area structure
|
||||
* areax * taxp pointer to an areax structure
|
||||
*
|
||||
* global variables:
|
||||
* area *ap Pointer to the current
|
||||
* area structure
|
||||
* area *areap The pointer to the first
|
||||
* area structure of a linked list
|
||||
* areax *axp Pointer to the current
|
||||
* areax structure
|
||||
*
|
||||
* functions called:
|
||||
* VOID * new() lksym()
|
||||
* char * strcpy() c_library
|
||||
* int symeq() lksym.c
|
||||
*
|
||||
* side effects:
|
||||
* Area and/or areax structures are created.
|
||||
* Failure to allocate space for created structures
|
||||
* will terminate the linker.
|
||||
*/
|
||||
|
||||
VOID
|
||||
lkparea(id)
|
||||
char *id;
|
||||
{
|
||||
register struct area *tap;
|
||||
register struct areax *taxp;
|
||||
|
||||
ap = areap;
|
||||
axp = (struct areax *) new (sizeof(struct areax));
|
||||
while (ap) {
|
||||
if (symeq(id, ap->a_id)) {
|
||||
taxp = ap->a_axp;
|
||||
while (taxp->a_axp)
|
||||
taxp = taxp->a_axp;
|
||||
taxp->a_axp = axp;
|
||||
axp->a_bap = ap;
|
||||
axp->a_bhp = hp;
|
||||
return;
|
||||
}
|
||||
ap = ap->a_ap;
|
||||
}
|
||||
ap = (struct area *) new (sizeof(struct area));
|
||||
if (areap == NULL) {
|
||||
areap = ap;
|
||||
} else {
|
||||
tap = areap;
|
||||
while (tap->a_ap)
|
||||
tap = tap->a_ap;
|
||||
tap->a_ap = ap;
|
||||
}
|
||||
ap->a_axp = axp;
|
||||
axp->a_bap = ap;
|
||||
axp->a_bhp = hp;
|
||||
strncpy(ap->a_id, id, NCPS);
|
||||
}
|
||||
|
||||
/*)Function VOID lnkarea()
|
||||
*
|
||||
* The function lnkarea() resolves all area addresses.
|
||||
* The function evaluates each area structure (and all
|
||||
* the associated areax structures) in sequence. The
|
||||
* linking process supports four (4) possible area types:
|
||||
*
|
||||
* ABS/OVR - All sections (each individual areax
|
||||
* section) starts at the identical base
|
||||
* area address overlaying all other
|
||||
* areax sections for this area. The
|
||||
* size of the area is largest of the area
|
||||
* sections.
|
||||
*
|
||||
* ABS/CON - All sections (each individual areax
|
||||
* section) are concatenated with the
|
||||
* first section starting at the base
|
||||
* area address. The size of the area
|
||||
* is the sum of the section sizes.
|
||||
*
|
||||
* NOTE: Multiple absolute (ABS) areas are
|
||||
* never concatenated with each other,
|
||||
* thus absolute area A and absolute area
|
||||
* B will overlay each other if they begin
|
||||
* at the same location (the default is
|
||||
* always address 0 for absolute areas).
|
||||
*
|
||||
* REL/OVR - All sections (each individual areax
|
||||
* section) starts at the identical base
|
||||
* area address overlaying all other
|
||||
* areax sections for this area. The
|
||||
* size of the area is largest of the area
|
||||
* sections.
|
||||
*
|
||||
* REL/CON - All sections (each individual areax
|
||||
* section) are concatenated with the
|
||||
* first section starting at the base
|
||||
* area address. The size of the area
|
||||
* is the sum of the section sizes.
|
||||
*
|
||||
* NOTE: Relocatable (REL) areas ae always concatenated
|
||||
* with each other, thus relocatable area B
|
||||
* (defined after area A) will follow
|
||||
* relocatable area A independent of the
|
||||
* starting address of area A. Within a
|
||||
* specific area each areax section may be
|
||||
* overlayed or concatenated with other
|
||||
* areax sections.
|
||||
*
|
||||
*
|
||||
* If a base address for an area is specified then the
|
||||
* area will start at that address. Any relocatable
|
||||
* areas defined subsequently will be concatenated to the
|
||||
* previous relocatable area if it does not have a base
|
||||
* address specified.
|
||||
*
|
||||
* The names s_<areaname> and l_<areaname> are created to
|
||||
* define the starting address and length of each area.
|
||||
*
|
||||
* local variables:
|
||||
* Addr_T rloc ;current relocation address
|
||||
* char temp[] ;temporary string
|
||||
* struct symbol *sp ;symbol structure
|
||||
*
|
||||
* global variables:
|
||||
* area *ap Pointer to the current
|
||||
* area structure
|
||||
* area *areap The pointer to the first
|
||||
* area structure of a linked list
|
||||
*
|
||||
* functions called:
|
||||
* int fprintf() c_library
|
||||
* VOID lnksect() lkarea.c
|
||||
* symbol *lkpsym() lksysm.c
|
||||
* char * strncpy() c_library
|
||||
* int symeq() lksysm.c
|
||||
*
|
||||
* side effects:
|
||||
* All area and areax addresses and sizes are
|
||||
* determined and saved in their respective
|
||||
* structures.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Resolve all area addresses.
|
||||
*/
|
||||
VOID
|
||||
lnkarea()
|
||||
{
|
||||
register int rloc;
|
||||
char temp[NCPS];
|
||||
struct sym *sp;
|
||||
|
||||
rloc = 0;
|
||||
ap = areap;
|
||||
while (ap) {
|
||||
if (ap->a_flag&A_ABS) {
|
||||
/*
|
||||
* Absolute sections
|
||||
*/
|
||||
lnksect(ap);
|
||||
} else {
|
||||
/*
|
||||
* Relocatable sections
|
||||
*/
|
||||
if (ap->a_addr == 0)
|
||||
ap->a_addr = rloc;
|
||||
lnksect(ap);
|
||||
rloc = 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 = 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;
|
||||
}
|
||||
ap = ap->a_ap;
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function VOID lnksect()
|
||||
*
|
||||
* area * tap pointer to an area structure
|
||||
*
|
||||
* The function lnksect() is the function called by
|
||||
* lnkarea() to resolve the areax addresses. Refer
|
||||
* to the function lnkarea() for more detail. Pageing
|
||||
* boundary and length errors will be reported by this
|
||||
* function.
|
||||
*
|
||||
* local variables:
|
||||
* Addr_T size size of area
|
||||
* Addr_T addr address of area
|
||||
* areax * taxp pointer to an areax structure
|
||||
*
|
||||
* global variables:
|
||||
* int lkerr error flag
|
||||
*
|
||||
* functions called:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* All area and areax addresses and sizes area determined
|
||||
* and linked into the structures.
|
||||
*/
|
||||
|
||||
VOID
|
||||
lnksect(tap)
|
||||
register struct area *tap;
|
||||
{
|
||||
register Addr_T size, addr;
|
||||
register struct areax *taxp;
|
||||
|
||||
size = 0;
|
||||
addr = tap->a_addr;
|
||||
if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
|
||||
fprintf(stderr,
|
||||
"\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
|
||||
lkerr++;
|
||||
}
|
||||
taxp = tap->a_axp;
|
||||
if (tap->a_flag&A_OVR) {
|
||||
/*
|
||||
* Overlayed sections
|
||||
*/
|
||||
while (taxp) {
|
||||
taxp->a_addr = addr;
|
||||
if (taxp->a_size > size)
|
||||
size = taxp->a_size;
|
||||
taxp = taxp->a_axp;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Concatenated sections
|
||||
*/
|
||||
while (taxp) {
|
||||
taxp->a_addr = addr;
|
||||
addr += taxp->a_size;
|
||||
size += taxp->a_size;
|
||||
taxp = taxp->a_axp;
|
||||
}
|
||||
}
|
||||
tap->a_size = size;
|
||||
if ((tap->a_flag&A_PAG) && (size > 256)) {
|
||||
fprintf(stderr,
|
||||
"\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
|
||||
lkerr++;
|
||||
}
|
||||
}
|
||||
465
link/z80/lkdata.c
Normal file
465
link/z80/lkdata.c
Normal file
@@ -0,0 +1,465 @@
|
||||
/* lkdata.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <alloc.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
|
||||
*/
|
||||
int oflag; /* Output file type flag
|
||||
*/
|
||||
int mflag; /* Map output flag
|
||||
*/
|
||||
#ifdef SDK
|
||||
int symflag; /* no$gmb .sym output flag
|
||||
*/
|
||||
#endif
|
||||
int xflag; /* Map file radix type flag
|
||||
*/
|
||||
int pflag; /* print linker command file flag
|
||||
*/
|
||||
int uflag; /* Listing relocation 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* The structure lfile contains a pointer to a
|
||||
* file specification string, the file type, and
|
||||
* a link to the next lfile structure.
|
||||
*
|
||||
* struct lfile
|
||||
* {
|
||||
* struct lfile *f_flp; lfile link
|
||||
* int f_type; File type
|
||||
* char *f_idp; Pointer to file spec
|
||||
* };
|
||||
*/
|
||||
struct lfile *filep; /* The pointers (lfile *) filep,
|
||||
* (lfile *) cfp, and (FILE *) sfp
|
||||
* are used in conjunction with
|
||||
* the routine getLine_() to read
|
||||
* asmlnk commands from
|
||||
* (1) the standard input or
|
||||
* (2) or a command file
|
||||
* and to read the REL files
|
||||
* sequentially as defined by the
|
||||
* asmlnk input commands.
|
||||
*
|
||||
* The pointer *filep points to the
|
||||
* beginning of a linked list of
|
||||
* lfile structures.
|
||||
*/
|
||||
struct lfile *cfp; /* The pointer *cfp points to the
|
||||
* current lfile structure
|
||||
*/
|
||||
struct lfile *startp;/* asmlnk startup file structure
|
||||
*/
|
||||
struct lfile *linkp; /* pointer to first lfile structure
|
||||
* containing an input REL file
|
||||
* specification
|
||||
*/
|
||||
struct lfile *lfp; /* pointer to current lfile structure
|
||||
* being processed by parse()
|
||||
*/
|
||||
FILE *ofp; /* Output file handle
|
||||
* for word formats
|
||||
*/
|
||||
FILE *mfp; /* Map output file handle
|
||||
*/
|
||||
FILE *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
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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[NCPS]; Name
|
||||
* };
|
||||
*/
|
||||
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
|
||||
*/
|
||||
char ctype[128] = {
|
||||
/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
|
||||
/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL,
|
||||
/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
|
||||
/*CAN*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
|
||||
/*SPC*/ SPACE, ETC, ETC, ETC, LETTER, BINOP, BINOP, ETC,
|
||||
/*(*/ ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, BINOP,
|
||||
/*0*/ DGT2, DGT2, DGT8, DGT8, DGT8, DGT8, DGT8, DGT8,
|
||||
/*8*/ DGT10, DGT10, ETC, ETC, BINOP, ETC, BINOP, ETC,
|
||||
/*@*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
|
||||
/*H*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*P*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*X*/ LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER,
|
||||
/*`*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
|
||||
/*h*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*p*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
|
||||
/*x*/ LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC
|
||||
};
|
||||
|
||||
/*
|
||||
* an array of characters which
|
||||
* perform the case translation function
|
||||
*/
|
||||
#if CASE_SENSITIVE
|
||||
#else
|
||||
char ccase[128] = {
|
||||
/*NUL*/ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
|
||||
/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
|
||||
/*DLE*/ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
|
||||
/*CAN*/ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
|
||||
/*SPC*/ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
|
||||
/*(*/ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
|
||||
/*0*/ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
|
||||
/*8*/ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
|
||||
/*@*/ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
/*H*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
/*P*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
/*X*/ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
|
||||
/*`*/ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
|
||||
/*h*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
|
||||
/*p*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
|
||||
/*x*/ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177'
|
||||
};
|
||||
#endif
|
||||
398
link/z80/lkeval.c
Normal file
398
link/z80/lkeval.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/* 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 <alloc.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(-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));
|
||||
}
|
||||
}
|
||||
/* Shouldn't get here. */
|
||||
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);
|
||||
}
|
||||
190
link/z80/lkgb.c
Normal file
190
link/z80/lkgb.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/* lkgb.c */
|
||||
|
||||
/*
|
||||
* P. Felber
|
||||
*/
|
||||
|
||||
#ifdef GAMEBOY
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "aslink.h"
|
||||
|
||||
/* Value used to fill the unused portions of the image */
|
||||
/* FFh puts less stress on a EPROM/Flash */
|
||||
#define FILLVALUE 0xFF
|
||||
|
||||
#define CARTSIZE ((unsigned long)nb_rom_banks*16UL*1024UL)
|
||||
#define NBSEG 8UL
|
||||
#define SEGSIZE (CARTSIZE/NBSEG)
|
||||
|
||||
#define ROMSIZE 0x8000UL
|
||||
#define BANKSTART 0x4000UL
|
||||
#define BANKSIZE 0x4000UL
|
||||
|
||||
unsigned char *cart[NBSEG];
|
||||
|
||||
int nb_rom_banks;
|
||||
int nb_ram_banks;
|
||||
int current_rom_bank;
|
||||
int mbc_type;
|
||||
char cart_name[16] = "";
|
||||
|
||||
patch* patches = NULL;
|
||||
|
||||
VOID gb(int in)
|
||||
{
|
||||
static int first = 1;
|
||||
unsigned long pos, chk;
|
||||
int i;
|
||||
patch *p;
|
||||
|
||||
if(first) {
|
||||
for(i = 0; i < NBSEG; i++) {
|
||||
if((cart[i] = malloc(SEGSIZE)) == NULL) {
|
||||
fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
|
||||
exit(-1);
|
||||
}
|
||||
memset(cart[i], FILLVALUE, SEGSIZE);
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
if(in) {
|
||||
if(rtcnt > 2) {
|
||||
if(hilo == 0)
|
||||
pos = rtval[0] | (rtval[1]<<8);
|
||||
else
|
||||
pos = rtval[1] | (rtval[0]<<8);
|
||||
|
||||
/* Perform some validity checks */
|
||||
if(pos >= ROMSIZE) {
|
||||
fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
|
||||
exit(-1);
|
||||
}
|
||||
if(current_rom_bank >= nb_rom_banks) {
|
||||
fprintf(stderr, "ERROR: bank overflow (addr %x > %x)\n", current_rom_bank, nb_rom_banks);
|
||||
exit(-1);
|
||||
}
|
||||
if(current_rom_bank > 0 && pos < BANKSTART) {
|
||||
fprintf(stderr, "ERROR: address underflow (addr %lx < %lx)\n", pos, BANKSTART);
|
||||
exit(-1);
|
||||
}
|
||||
if(nb_rom_banks == 2 && current_rom_bank > 0) {
|
||||
fprintf(stderr, "ERROR: only 1 32kB segment with 2 bank\n");
|
||||
exit(-1);
|
||||
}
|
||||
if(current_rom_bank > 1)
|
||||
pos += (current_rom_bank-1)*BANKSIZE;
|
||||
for(i = 2; i < rtcnt; i++) {
|
||||
if(rtflg[i]) {
|
||||
if(pos < CARTSIZE) {
|
||||
if(cart[pos/SEGSIZE][pos%SEGSIZE] != FILLVALUE)
|
||||
fprintf(stderr, "WARNING: possibly wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
|
||||
cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
|
||||
exit(-1);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* EOF */
|
||||
if(cart_name[0] == 0 && linkp->f_idp != NULL) {
|
||||
for(i = strlen(linkp->f_idp);
|
||||
i > 0 && (isalnum(linkp->f_idp[i-1]) || linkp->f_idp[i-1] == '.');
|
||||
i--)
|
||||
;
|
||||
for(pos = 0; pos < 16 && linkp->f_idp[i] != '.'; pos++, i++)
|
||||
cart_name[pos] = toupper(linkp->f_idp[i]);
|
||||
if(pos < 16)
|
||||
cart_name[pos] = 0;
|
||||
}
|
||||
for(pos = 0x0134, i = 0;
|
||||
pos < 0x0144 && cart_name[i];
|
||||
pos++, i++)
|
||||
cart[pos/SEGSIZE][pos%SEGSIZE] = cart_name[i];
|
||||
for(; pos < 0x0144; pos++)
|
||||
cart[pos/SEGSIZE][pos%SEGSIZE] = 0;
|
||||
cart[0x147/SEGSIZE][0x147%SEGSIZE] = mbc_type;
|
||||
switch(nb_rom_banks) {
|
||||
case 2:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
|
||||
break;
|
||||
case 4:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 1;
|
||||
break;
|
||||
case 8:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 2;
|
||||
break;
|
||||
case 16:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 3;
|
||||
break;
|
||||
case 32:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 4;
|
||||
break;
|
||||
case 64:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 5;
|
||||
break;
|
||||
case 128:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 6;
|
||||
break;
|
||||
case 256:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 7;
|
||||
break;
|
||||
case 512:
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 8;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "WARNING: unsupported number of ROM banks (%d)\n", nb_rom_banks);
|
||||
cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
|
||||
break;
|
||||
}
|
||||
switch(nb_ram_banks) {
|
||||
case 0:
|
||||
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
|
||||
break;
|
||||
case 1:
|
||||
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 2;
|
||||
break;
|
||||
case 4:
|
||||
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 3;
|
||||
break;
|
||||
case 16:
|
||||
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 4;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "WARNING: unsupported number of RAM banks (%d)\n", nb_ram_banks);
|
||||
cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Patch before calculating the checksum */
|
||||
if(patches)
|
||||
for(p = patches; p; p = p->next)
|
||||
cart[p->addr/SEGSIZE][p->addr%SEGSIZE] = p->value;
|
||||
|
||||
/* Update complement checksum */
|
||||
chk = 0;
|
||||
for(pos = 0x0134; pos < 0x014D; pos++)
|
||||
chk += cart[pos/SEGSIZE][pos%SEGSIZE];
|
||||
cart[0x014D/SEGSIZE][0x014D%SEGSIZE] = 0xE7 - (chk&0xFF);
|
||||
/* Update checksum */
|
||||
chk = 0;
|
||||
cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = 0;
|
||||
cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = 0;
|
||||
for(i = 0; i < NBSEG; i++)
|
||||
for(pos = 0; pos < SEGSIZE; pos++)
|
||||
chk += cart[i][pos];
|
||||
cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = (chk>>8)&0xFF;
|
||||
cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = chk&0xFF;
|
||||
|
||||
for(i = 0; i < NBSEG; i++)
|
||||
fwrite(cart[i], 1, SEGSIZE, ofp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GAMEBOY */
|
||||
79
link/z80/lkgg.c
Normal file
79
link/z80/lkgg.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* lkgg.c */
|
||||
|
||||
/*
|
||||
* P. Felber
|
||||
*/
|
||||
|
||||
#ifdef GAMEGEAR
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "aslink.h"
|
||||
|
||||
#define CARTSIZE ((unsigned long)4*16UL*1024UL)
|
||||
#define NBSEG 8UL
|
||||
#define SEGSIZE (CARTSIZE/NBSEG)
|
||||
|
||||
unsigned char *cart[NBSEG];
|
||||
|
||||
#define ROMSIZE 0x10000UL
|
||||
#define BANKSIZE 0x4000UL
|
||||
|
||||
int current_rom_bank;
|
||||
|
||||
VOID gg(int in)
|
||||
{
|
||||
static int first = 1;
|
||||
unsigned long pos;
|
||||
int i;
|
||||
|
||||
if(first) {
|
||||
for(i = 0; i < NBSEG; i++) {
|
||||
if((cart[i] = malloc(SEGSIZE)) == NULL) {
|
||||
fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
|
||||
exit(-1);
|
||||
}
|
||||
memset(cart[i], 0, SEGSIZE);
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
if(in) {
|
||||
if(rtcnt > 2) {
|
||||
if(hilo == 0)
|
||||
pos = rtval[0] | (rtval[1]<<8);
|
||||
else
|
||||
pos = rtval[1] | (rtval[0]<<8);
|
||||
|
||||
/* Perform some validity checks */
|
||||
if(pos >= ROMSIZE) {
|
||||
fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
|
||||
exit(-1);
|
||||
}
|
||||
if(current_rom_bank > 1)
|
||||
pos += (current_rom_bank-1)*BANKSIZE;
|
||||
for(i = 2; i < rtcnt; i++) {
|
||||
if(rtflg[i]) {
|
||||
if(pos < CARTSIZE) {
|
||||
if(cart[pos/SEGSIZE][pos%SEGSIZE] != 0)
|
||||
fprintf(stderr, "WARNING: wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
|
||||
cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
|
||||
exit(-1);
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* EOF */
|
||||
/* Patch before calculating the checksum */
|
||||
for(i = 0; i < NBSEG; i++)
|
||||
fwrite(cart[i], 1, SEGSIZE, ofp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GAMEGEAR */
|
||||
154
link/z80/lkhead.c
Normal file
154
link/z80/lkhead.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/* 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 <alloc.h>
|
||||
#include "aslink.h"
|
||||
|
||||
/*Module lkhead.c
|
||||
*
|
||||
* The module lkhead.c contains the function newhead() which
|
||||
* creates a head structure and the function module() which
|
||||
* loads the module name into the current head structure.
|
||||
*
|
||||
* lkhead.c contains the following functions:
|
||||
* VOID newhead()
|
||||
* VOID module()
|
||||
*
|
||||
* lkhead.c contains no local variables.
|
||||
*/
|
||||
|
||||
/*)Function VOID newhead()
|
||||
*
|
||||
* The function newhead() creates a head structure. All head
|
||||
* structures are linked to form a linked list of head structures
|
||||
* with the current head structure at the tail of the list.
|
||||
*
|
||||
* local variables:
|
||||
* int i evaluation value
|
||||
* head * thp temporary pointer
|
||||
* to a header structure
|
||||
*
|
||||
* global variables:
|
||||
* area *ap Pointer to the current
|
||||
* area structure
|
||||
* lfile *cfp The pointer *cfp points to the
|
||||
* current lfile structure
|
||||
* head *headp The pointer to the first
|
||||
* head structure of a linked list
|
||||
* head *hp Pointer to the current
|
||||
* head structure
|
||||
*
|
||||
* functions called:
|
||||
* Addr_T expr() lkeval.c
|
||||
* VOID * new() lksym.c
|
||||
* VOID lkparea() lkarea.c
|
||||
*
|
||||
* side effects:
|
||||
* A new head structure is created and linked to any
|
||||
* existing linked head structure. The head structure
|
||||
* parameters of file handle, number of areas, and number
|
||||
* of global symbols are loaded into the structure.
|
||||
* The default area "_abs_" is created when the first
|
||||
* head structure is created and an areax structure is
|
||||
* created for every head structure called.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create a new header entry.
|
||||
*
|
||||
* H n areas n global symbols
|
||||
* | |
|
||||
* | `---- hp->h_nglob
|
||||
* `------------ hp->h_narea
|
||||
*
|
||||
*/
|
||||
VOID
|
||||
newhead()
|
||||
{
|
||||
register int i;
|
||||
struct head *thp;
|
||||
|
||||
hp = (struct head *) new (sizeof(struct head));
|
||||
if (headp == NULL) {
|
||||
headp = hp;
|
||||
} else {
|
||||
thp = headp;
|
||||
while (thp->h_hp)
|
||||
thp = thp->h_hp;
|
||||
thp->h_hp = hp;
|
||||
}
|
||||
/*
|
||||
* Set file pointer
|
||||
*/
|
||||
hp->h_lfile = cfp;
|
||||
/*
|
||||
* Evaluate and build Area pointer list
|
||||
*/
|
||||
i = hp->h_narea = eval();
|
||||
if (i)
|
||||
hp->a_list = (struct areax **) new (i*sizeof(struct areax *));
|
||||
/*
|
||||
* Evaluate and build Global symbol pointer list
|
||||
*/
|
||||
skip(-1);
|
||||
i = hp->h_nglob = eval();
|
||||
if (i)
|
||||
hp->s_list = (struct sym **) new (i*sizeof(struct sym *));
|
||||
/*
|
||||
* Setup Absolute DEF linkage.
|
||||
*/
|
||||
lkparea(_abs_);
|
||||
ap->a_flag = A_ABS|A_OVR;
|
||||
}
|
||||
|
||||
/*)Function VOID module()
|
||||
*
|
||||
* The function module() copies the module name into
|
||||
* the current head structure.
|
||||
*
|
||||
* local variables:
|
||||
* char id[] module id string
|
||||
*
|
||||
* global variables:
|
||||
* head *headp The pointer to the first
|
||||
* head structure of a linked list
|
||||
* head *hp Pointer to the current
|
||||
* head structure
|
||||
* int lkerr error flag
|
||||
* FILE * stderr c_library
|
||||
*
|
||||
* functions called:
|
||||
* int fprintf() c_library
|
||||
* VOID getid() lklex.c
|
||||
* char * strncpy() c_library
|
||||
*
|
||||
* side effects:
|
||||
* The module name is copied into the head structure.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module Name
|
||||
*/
|
||||
VOID
|
||||
module()
|
||||
{
|
||||
char id[NCPS];
|
||||
|
||||
if (headp) {
|
||||
getid(id, -1);
|
||||
strncpy(hp->m_id, id, NCPS);
|
||||
} else {
|
||||
fprintf(stderr, "No header defined\n");
|
||||
lkerr++;
|
||||
}
|
||||
}
|
||||
134
link/z80/lkihx.c
Normal file
134
link/z80/lkihx.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* 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 <alloc.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 function:
|
||||
* VOID ihx(i)
|
||||
*
|
||||
* lkihx.c contains no local variables.
|
||||
*/
|
||||
|
||||
/*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.
|
||||
*/
|
||||
|
||||
/*)Function ihx(i)
|
||||
*
|
||||
* int i 0 - process data
|
||||
* 1 - end of data
|
||||
*
|
||||
* The function ihx() outputs the relocated data
|
||||
* in the standard Intel Hex 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
|
||||
ihx(i)
|
||||
{
|
||||
register Addr_T chksum;
|
||||
|
||||
if (i) {
|
||||
if (hilo == 0) {
|
||||
chksum = rtval[0];
|
||||
rtval[0] = rtval[1];
|
||||
rtval[1] = chksum;
|
||||
}
|
||||
for (i = 0, chksum = -2; i < rtcnt; i++) {
|
||||
if (rtflg[i])
|
||||
chksum++;
|
||||
}
|
||||
fprintf(ofp, ":%02X", chksum);
|
||||
for (i = 0; i < rtcnt ; i++) {
|
||||
if (rtflg[i]) {
|
||||
fprintf(ofp, "%02X", rtval[i]);
|
||||
chksum += rtval[i];
|
||||
}
|
||||
if (i == 1) {
|
||||
fprintf(ofp, "00");
|
||||
}
|
||||
}
|
||||
fprintf(ofp, "%02X\n", (-chksum) & 0xff);
|
||||
} else {
|
||||
fprintf(ofp, ":00000001FF\n");
|
||||
}
|
||||
}
|
||||
569
link/z80/lklex.c
Normal file
569
link/z80/lklex.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/* lklex.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber, M. Hope
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <alloc.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()
|
||||
* int getLine_()
|
||||
* int getmap()
|
||||
* char getnb()
|
||||
* int more()
|
||||
* VOID skip()
|
||||
* VOID unget()
|
||||
*
|
||||
* lklex.c contains no local variables.
|
||||
*/
|
||||
|
||||
/*)Function VOID getid(id,c)
|
||||
*
|
||||
* char * id a pointer to a string of
|
||||
* maximum length NCPS
|
||||
* int c mode flag
|
||||
* >=0 this is first character to
|
||||
* copy to the string buffer
|
||||
* <0 skip white space
|
||||
*
|
||||
* The function getid() scans the current input text line
|
||||
* from the current position copying the next LETTER | DIGIT string
|
||||
* into the external string buffer (id). The string ends when a non
|
||||
* LETTER or DIGIT character is found. The maximum number of
|
||||
* characters copied is NCPS. If the input string is larger than
|
||||
* NCPS characters then the string is truncated, if the input string
|
||||
* is shorter than NCPS characters then the string is NULL filled.
|
||||
* If the mode argument (c) is >=0 then (c) is the first character
|
||||
* copied to the string buffer, if (c) is <0 then intervening white
|
||||
* space (SPACES and TABS) are skipped.
|
||||
*
|
||||
* local variables:
|
||||
* char * p pointer to external string buffer
|
||||
* int c current character value
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] a character array which defines the
|
||||
* type of character being processed.
|
||||
* This index is the character
|
||||
* being processed.
|
||||
*
|
||||
* called functions:
|
||||
* char get() lklex.c
|
||||
* char getnb() lklex.c
|
||||
* VOID unget() lklex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of getnb(), get(), and unget() updates the
|
||||
* global pointer ip the position in the current
|
||||
* input text line.
|
||||
*/
|
||||
|
||||
VOID
|
||||
getid(id, c)
|
||||
register int c;
|
||||
char *id;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (c < 0) {
|
||||
c = getnb();
|
||||
}
|
||||
p = id;
|
||||
do {
|
||||
if (p < &id[NCPS])
|
||||
*p++ = c;
|
||||
} while (ctype[c=get()] & (LETTER|DIGIT));
|
||||
unget(c);
|
||||
while (p < &id[NCPS])
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/*)Function VOID getfid(fid,c)
|
||||
*
|
||||
* char * str a pointer to a string of
|
||||
* maximum length FILSPC
|
||||
* 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 a
|
||||
* non SPACE type character is found. The maximum number of
|
||||
* characters copied is FILSPC. If the input string is larger than
|
||||
* FILSPC characters then the string is truncated, if the input string
|
||||
* is shorter than FILSPC characters then the string is NULL filled.
|
||||
*
|
||||
* 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[FILSPC-1])
|
||||
*p++ = c;
|
||||
c = get();
|
||||
#ifdef SDK
|
||||
} while (c);
|
||||
#else /* SDK */
|
||||
} while (c && (ctype[c] != SPACE));
|
||||
#endif /* SDK */
|
||||
while (p < &str[FILSPC])
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/*)Function char getnb()
|
||||
*
|
||||
* The function getnb() scans the current input text
|
||||
* line returning the first character not a SPACE or TAB.
|
||||
*
|
||||
* local variables:
|
||||
* int c current character from input
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* called functions:
|
||||
* char get() lklex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of get() updates the global pointer ip, the position
|
||||
* in the current input text line
|
||||
*/
|
||||
|
||||
char
|
||||
getnb()
|
||||
{
|
||||
register int c;
|
||||
|
||||
while ((c=get())==' ' || c=='\t')
|
||||
;
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*)Function VOID skip()
|
||||
*
|
||||
* The function skip() scans the input text skipping all
|
||||
* letters and digits.
|
||||
*
|
||||
* local variables:
|
||||
* none
|
||||
*
|
||||
* global variables:
|
||||
* char ctype[] array of character types, one per
|
||||
* ASCII character
|
||||
*
|
||||
* functions called:
|
||||
* char get() lklex.c
|
||||
* char getnb() lklex.c
|
||||
* VOID unget() lklex.c
|
||||
*
|
||||
* side effects:
|
||||
* Input letters and digits are skipped.
|
||||
*/
|
||||
|
||||
VOID
|
||||
skip(c)
|
||||
register int c;
|
||||
{
|
||||
if (c < 0)
|
||||
c = getnb();
|
||||
while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
|
||||
unget(c);
|
||||
}
|
||||
|
||||
/*)Function char get()
|
||||
*
|
||||
* The function get() returns the next character in the
|
||||
* input text line, at the end of the line a
|
||||
* NULL character is returned.
|
||||
*
|
||||
* local variables:
|
||||
* int c current character from
|
||||
* input text line
|
||||
*
|
||||
* global variables:
|
||||
* char * ip pointer into the current
|
||||
* input text line
|
||||
*
|
||||
* called functions:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* updates ip to the next character position in the
|
||||
* input text line. If ip is at the end of the
|
||||
* line, ip is not updated.
|
||||
*/
|
||||
|
||||
char
|
||||
get()
|
||||
{
|
||||
register int c;
|
||||
|
||||
if ((c = *ip) != 0)
|
||||
++ip;
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*)Function VOID unget(c)
|
||||
*
|
||||
* int c value of last character
|
||||
* read from input text line
|
||||
*
|
||||
* If (c) is not a NULL character then the global pointer ip
|
||||
* is updated to point to the preceeding character in the
|
||||
* input text line.
|
||||
*
|
||||
* NOTE: This function does not push the character (c)
|
||||
* back into the input text line, only
|
||||
* the pointer ip is changed.
|
||||
*
|
||||
* local variables:
|
||||
* int c last character read
|
||||
* from input text line
|
||||
*
|
||||
* global variables:
|
||||
* char * ip position into the current
|
||||
* input text line
|
||||
*
|
||||
* called functions:
|
||||
* none
|
||||
*
|
||||
* side effects:
|
||||
* ip decremented by 1 character position
|
||||
*/
|
||||
|
||||
VOID
|
||||
unget(c)
|
||||
{
|
||||
if (c != 0)
|
||||
--ip;
|
||||
}
|
||||
|
||||
/*)Function int getmap(d)
|
||||
*
|
||||
* int d value to compare with the
|
||||
* input text line character
|
||||
*
|
||||
* The function getmap() converts the 'C' style characters \b, \f,
|
||||
* \n, \r, and \t to their equivalent ascii values and also
|
||||
* converts 'C' style octal constants '\123' to their equivalent
|
||||
* numeric values. If the first character is equivalent to (d) then
|
||||
* a (-1) is returned, if the end of the line is detected then
|
||||
* a 'q' error terminates the parse for this line, or if the first
|
||||
* character is not a \ then the character value is returned.
|
||||
*
|
||||
* local variables:
|
||||
* int c value of character
|
||||
* from input text line
|
||||
* int n looping counter
|
||||
* int v current value of numeric conversion
|
||||
*
|
||||
* global variables:
|
||||
* none
|
||||
*
|
||||
* called functions:
|
||||
* char get() lklex.c
|
||||
* VOID unget() lklex.c
|
||||
*
|
||||
* side effects:
|
||||
* use of get() updates the global pointer ip the position
|
||||
* in the current input text line
|
||||
*/
|
||||
|
||||
int
|
||||
getmap(d)
|
||||
{
|
||||
register int c, n, v;
|
||||
|
||||
if ((c = get()) == '\0')
|
||||
return (-1);
|
||||
if (c == d)
|
||||
return (-1);
|
||||
if (c == '\\') {
|
||||
c = get();
|
||||
switch (c) {
|
||||
|
||||
case 'b':
|
||||
c = '\b';
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
c = '\f';
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
c = '\n';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
c = '\r';
|
||||
break;
|
||||
|
||||
case 't':
|
||||
c = '\t';
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
n = 0;
|
||||
v = 0;
|
||||
while (++n<=3 && c>='0' && c<='7') {
|
||||
v = (v<<3) + c - '0';
|
||||
c = get();
|
||||
}
|
||||
unget(c);
|
||||
c = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*)Function int getLine_()
|
||||
*
|
||||
* The function getLine_() reads a line of input text from a
|
||||
* .rel source text file, a .lnk command file or from stdin.
|
||||
* Lines of text are processed from a single .lnk file or
|
||||
* multiple .rel files until all files have been read.
|
||||
* The input text line is copied into the global string ib[]
|
||||
* and converted to a NULL terminated string. The function
|
||||
* getLine_() returns a (1) after succesfully reading a line
|
||||
* or a (0) if all files have been read.
|
||||
* This function also opens each input .lst file and output
|
||||
* .rst file as each .rel file is processed.
|
||||
*
|
||||
* local variables:
|
||||
* int i string length
|
||||
* int ftype file type
|
||||
* char * fid file name
|
||||
*
|
||||
* global variables:
|
||||
* lfile *cfp The pointer *cfp points to the
|
||||
* current lfile structure
|
||||
* lfile *filep The pointer *filep points to the
|
||||
* beginning of a linked list of
|
||||
* lfile structures.
|
||||
* int gline get a line from the LST file
|
||||
* to translate for the RST file
|
||||
* char ib[NINPUT] REL file text line
|
||||
* int pass linker pass number
|
||||
* int pflag print linker command file flag
|
||||
* FILE *rfp The file handle to the current
|
||||
* output RST file
|
||||
* FILE *sfp The file handle sfp points to the
|
||||
* currently open file
|
||||
* FILE * stdin c_library
|
||||
* FILE * stdout c_library
|
||||
* FILE *tfp The file handle to the current
|
||||
* LST file being scanned
|
||||
* int uflag update listing flag
|
||||
*
|
||||
* called functions:
|
||||
* FILE * afile() lkmain.c
|
||||
* int fclose() c_library
|
||||
* char * fgets() c_library
|
||||
* int fprintf() c_library
|
||||
* VOID lkulist() lklist.c
|
||||
* VOID lkexit() lkmain.c
|
||||
* int strlen() c_library
|
||||
*
|
||||
* side effects:
|
||||
* The input stream is scanned. The .rel files will be
|
||||
* opened and closed sequentially scanning each in turn.
|
||||
*/
|
||||
|
||||
int
|
||||
getLine_()
|
||||
{
|
||||
register int i, ftype;
|
||||
register char *fid;
|
||||
|
||||
loop: if (pflag && cfp && cfp->f_type == F_STD)
|
||||
fprintf(stdout, "ASlink >> ");
|
||||
|
||||
#ifdef SDK
|
||||
if(cfp == NULL && filep != NULL && filep->f_type == F_CMD) {
|
||||
char **argv = (char **)filep->f_idp;
|
||||
if(argv[0] != NULL && strlen(argv[0]) < sizeof ib) {
|
||||
strcpy(ib, argv[0]);
|
||||
filep->f_idp = (char *)&argv[1];
|
||||
} else {
|
||||
filep = NULL;
|
||||
return(0);
|
||||
}
|
||||
} else
|
||||
#endif /* SDK */
|
||||
if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
|
||||
if (sfp) {
|
||||
fclose(sfp);
|
||||
#ifdef SDK
|
||||
sfp = NULL;
|
||||
#endif /* SDK */
|
||||
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) {
|
||||
#ifdef SDK
|
||||
sfp = afile(fid, "lnk", 0);
|
||||
#else /* SDK */
|
||||
sfp = afile(fid, "LNK", 0);
|
||||
#endif /* SDK */
|
||||
} else
|
||||
if (ftype == F_REL) {
|
||||
#ifdef SDK
|
||||
sfp = afile(fid, "", 0);
|
||||
if (uflag && pass != 0) {
|
||||
if ((tfp = afile(fid, "lst", 0)) != NULL) {
|
||||
if ((rfp = afile(fid, "rst", 1)) == NULL) {
|
||||
#else /* SDK */
|
||||
sfp = afile(fid, "REL", 0);
|
||||
if (uflag && pass != 0) {
|
||||
if ((tfp = afile(fid, "LST", 0)) != NULL) {
|
||||
if ((rfp = afile(fid, "RST", 1)) == NULL) {
|
||||
#endif /* SDK */
|
||||
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);
|
||||
}
|
||||
}
|
||||
i = strlen(ib) - 1;
|
||||
if (ib[i] == '\n')
|
||||
ib[i] = 0;
|
||||
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 );
|
||||
}
|
||||
810
link/z80/lklibr.c
Normal file
810
link/z80/lklibr.c
Normal file
@@ -0,0 +1,810 @@
|
||||
/* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extensions: P. Felber
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.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[40];
|
||||
pmlibrarysymbol next;
|
||||
};
|
||||
|
||||
typedef struct slibraryfile mlibraryfile;
|
||||
typedef struct slibraryfile *pmlibraryfile;
|
||||
|
||||
struct slibraryfile {
|
||||
int loaded;
|
||||
char *libspc;
|
||||
char *str;
|
||||
char relfil[FILSPC];
|
||||
char filename[FILSPC];
|
||||
pmlibrarysymbol symbols;
|
||||
pmlibraryfile next;
|
||||
};
|
||||
|
||||
int buildlibraryindex();
|
||||
#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
|
||||
*
|
||||
* 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;
|
||||
|
||||
unget(getnb());
|
||||
|
||||
if (lbphead == NULL) {
|
||||
addfile(NULL,ip);
|
||||
return;
|
||||
}
|
||||
for (lbph=lbphead; lbph; lbph=lbph->next) {
|
||||
addfile(lbph->path,ip);
|
||||
}
|
||||
}
|
||||
|
||||
/*)Function VOID 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.
|
||||
*/
|
||||
|
||||
VOID
|
||||
addfile(path,libfil)
|
||||
char *path;
|
||||
char *libfil;
|
||||
{
|
||||
FILE *fp;
|
||||
char *str;
|
||||
struct lbname *lbnh, *lbn;
|
||||
|
||||
if ((path != NULL) && (strchr(libfil,':') == NULL)){
|
||||
str = (char *) new (strlen(path) + strlen(libfil) + 6);
|
||||
strcpy(str,path);
|
||||
#ifdef OTHERSYSTEM
|
||||
#ifdef SDK
|
||||
#ifdef UNIX
|
||||
if (str[strlen(str)-1] != '/') {
|
||||
strcat(str,"/");
|
||||
#else /* UNIX */
|
||||
if (str[strlen(str)-1] != '\\') {
|
||||
strcat(str,"\\");
|
||||
#endif /* UNIX */
|
||||
#else /* SDK */
|
||||
if (str[strlen(str)-1] != '\\') {
|
||||
strcat(str,"\\");
|
||||
#endif /* SDK */
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
str = (char *) new (strlen(libfil) + 5);
|
||||
}
|
||||
#ifdef OTHERSYSTEM
|
||||
#ifdef SDK
|
||||
#ifdef UNIX
|
||||
if (libfil[0] == '/') { libfil++; }
|
||||
#else /* UNIX */
|
||||
if (libfil[0] == '\\') { libfil++; }
|
||||
#endif /* UNIX */
|
||||
#else /* SDK */
|
||||
if (libfil[0] == '\\') { libfil++; }
|
||||
#endif /* SDK */
|
||||
#endif
|
||||
strcat(str,libfil);
|
||||
if(strchr(str,FSEPX) == NULL) {
|
||||
sprintf(&str[strlen(str)], "%clib", FSEPX);
|
||||
}
|
||||
if ((fp = fopen(str, "r")) != 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;
|
||||
}
|
||||
if ((path != NULL) && (strchr(libfil,':') == NULL)){
|
||||
lbnh->path = path;
|
||||
}
|
||||
lbnh->libfil = (char *) new (strlen(libfil) + 1);
|
||||
strcpy(lbnh->libfil,libfil);
|
||||
lbnh->libspc = str;
|
||||
} else {
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
/*)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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*)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
|
||||
|
||||
/* First entry in the library object symbol cache */
|
||||
mlibraryfile libr;
|
||||
|
||||
int fndsym( char *name )
|
||||
{
|
||||
struct lbfile *lbfh, *lbf;
|
||||
pmlibraryfile ThisLibr;
|
||||
pmlibrarysymbol ThisSym = NULL;
|
||||
|
||||
/* Build the index if this is the first call to fndsym */
|
||||
if (libr.next==NULL)
|
||||
buildlibraryindex();
|
||||
|
||||
/* Iterate through all library object files */
|
||||
ThisLibr = libr.next;
|
||||
while (ThisLibr) {
|
||||
|
||||
/* Iterate through all symbols in an object file */
|
||||
ThisSym = ThisLibr->symbols->next;
|
||||
|
||||
while (ThisSym) {
|
||||
if (!strcmp(ThisSym->name, name)) {
|
||||
if (!ThisLibr->loaded) {
|
||||
/* 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->str;
|
||||
lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
|
||||
strcpy(lbfh->relfil,ThisLibr->relfil);
|
||||
loadfile(lbfh->filspc);
|
||||
ThisLibr->loaded=1;
|
||||
}
|
||||
return (1); /* Found the symbol, return */
|
||||
}
|
||||
ThisSym=ThisSym->next; /* Next sym in library */
|
||||
}
|
||||
ThisLibr=ThisLibr->next; /* Next library in list */
|
||||
}
|
||||
return 0; /* Failure - symbol not found in any library */
|
||||
};
|
||||
|
||||
/* buildlibraryindex - build an in-memory cache of the symbols contained in
|
||||
* the libraries
|
||||
*/
|
||||
|
||||
int buildlibraryindex()
|
||||
{
|
||||
FILE *libfp, *fp;
|
||||
struct lbname *lbnh;
|
||||
char relfil[NINPUT+2], *str, *path;
|
||||
char buf[NINPUT+2], c;
|
||||
char symname[NINPUT+2];
|
||||
pmlibraryfile This;
|
||||
pmlibrarysymbol ThisSym;
|
||||
|
||||
This=&libr;
|
||||
|
||||
/* Iterate through all library files */
|
||||
/*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
|
||||
libfp = fopen( lbnh->libspc, "r" );
|
||||
if (libfp) {
|
||||
path=lbnh->path;
|
||||
|
||||
/*
|
||||
* Read in a line from the library file.
|
||||
* This is the relative file specification
|
||||
* for a .REL file in this library.
|
||||
*/
|
||||
|
||||
/*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
|
||||
relfil[NINPUT+1] = '\0';
|
||||
relfil[strlen(relfil) - 1] = '\0';
|
||||
if (path != NULL) {
|
||||
str = (char *)new(strlen(path)+strlen(relfil)+6);
|
||||
strcpy(str,path);
|
||||
#ifdef OTHERSYSTEM
|
||||
#ifdef SDK
|
||||
#ifdef UNIX
|
||||
if (str[strlen(str)-1] != '/') {
|
||||
strcat(str,"/");
|
||||
#else /* UNIX */
|
||||
if (str[strlen(str)-1] != '\\') {
|
||||
strcat(str,"\\");
|
||||
#endif /* UNIX */
|
||||
#else /* SDK */
|
||||
if (str[strlen(str)-1] != '\\') {
|
||||
strcat(str,"\\");
|
||||
#endif /* SDK */
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
str = (char *)new(strlen(relfil) + 5);
|
||||
}
|
||||
#ifdef SDK
|
||||
#ifdef UNIX
|
||||
if (relfil[0] == '/') {
|
||||
#else /* UNIX */
|
||||
if (relfil[0] == '\\') {
|
||||
#endif /* UNIX */
|
||||
#else /* SDK */
|
||||
if (relfil[0] == '\\') {
|
||||
#endif /* SDK */
|
||||
strcat(str,relfil+1);
|
||||
} else {
|
||||
strcat(str,relfil);
|
||||
}
|
||||
if(strchr(str,FSEPX) == NULL) {
|
||||
#ifdef SDK
|
||||
sprintf(&str[strlen(str)], "%co", FSEPX);
|
||||
#else /* SDK */
|
||||
sprintf(&str[strlen(str)], "%crel", FSEPX);
|
||||
#endif /* SDK */
|
||||
}
|
||||
/*3*/ if ((fp = fopen(str, "r")) != NULL) {
|
||||
|
||||
/* Opened OK - create a new libraryfile object for it */
|
||||
This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
|
||||
if (This->next == NULL) {
|
||||
printf("panic: cant allocate memory.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
This=This->next;
|
||||
This->next = NULL;
|
||||
This->loaded=-1;
|
||||
|
||||
strcpy( This->filename, str );
|
||||
|
||||
ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
|
||||
ThisSym->next = 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.
|
||||
*/
|
||||
|
||||
/*4*/ 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 */
|
||||
/*5*/ if (c == 'D') {
|
||||
ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
|
||||
ThisSym=ThisSym->next;
|
||||
if (ThisSym == NULL) {
|
||||
printf("panic: cant allocate memory.\n");
|
||||
exit(-2);
|
||||
}
|
||||
This->loaded=0;
|
||||
ThisSym->next=NULL;
|
||||
This->str = str;
|
||||
strcpy(This->relfil,relfil);
|
||||
strcpy(ThisSym->name, symname);
|
||||
This->libspc = lbnh->libspc;
|
||||
}
|
||||
} /* Closes while - read object file */
|
||||
fclose(fp);
|
||||
} /* Closes if object file opened OK */
|
||||
} /* Ends while - processing all in libr */
|
||||
fclose(libfp);
|
||||
} /* Ends good open of libr file */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#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;
|
||||
|
||||
/*
|
||||
* Search through every library in the linked list "lbnhead".
|
||||
*/
|
||||
|
||||
/*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
|
||||
if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
|
||||
fprintf(stderr, "Cannot open library file %s\n",
|
||||
lbnh->libspc);
|
||||
lkexit(1);
|
||||
}
|
||||
path = lbnh->path;
|
||||
|
||||
/*
|
||||
* Read in a line from the library file.
|
||||
* This is the relative file specification
|
||||
* for a .REL file in this library.
|
||||
*/
|
||||
|
||||
/*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
|
||||
relfil[NINPUT+1] = '\0';
|
||||
relfil[strlen(relfil) - 1] = '\0';
|
||||
if (path != NULL) {
|
||||
str = (char *) new (strlen(path)+strlen(relfil)+6);
|
||||
strcpy(str,path);
|
||||
#ifdef OTHERSYSTEM
|
||||
#ifdef SDK
|
||||
#ifdef UNIX
|
||||
if (str[strlen(str)-1] != '/') {
|
||||
strcat(str,"/");
|
||||
#else /* UNIX */
|
||||
if (str[strlen(str)-1] != '\\') {
|
||||
strcat(str,"\\");
|
||||
#endif /* UNIX */
|
||||
#else /* SDK */
|
||||
if (str[strlen(str)-1] != '\\') {
|
||||
strcat(str,"\\");
|
||||
#endif /* SDK */
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
str = (char *) new (strlen(relfil) + 5);
|
||||
}
|
||||
#ifdef SDK
|
||||
#ifdef UNIX
|
||||
if (relfil[0] == '/') {
|
||||
#else /* UNIX */
|
||||
if (relfil[0] == '\\') {
|
||||
#endif /* UNIX */
|
||||
#else /* SDK */
|
||||
if (relfil[0] == '\\') {
|
||||
#endif /* SDK */
|
||||
strcat(str,relfil+1);
|
||||
} else {
|
||||
strcat(str,relfil);
|
||||
}
|
||||
if(strchr(str,FSEPX) == NULL) {
|
||||
#ifdef SDK
|
||||
sprintf(&str[strlen(str)], "%co", FSEPX);
|
||||
#else /* SDK */
|
||||
sprintf(&str[strlen(str)], "%crel", FSEPX);
|
||||
#endif /* SDK */
|
||||
}
|
||||
/*3*/ 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.
|
||||
*/
|
||||
|
||||
/*4*/ 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 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.
|
||||
*/
|
||||
/*5*/ 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);
|
||||
strcpy(lbfh->relfil,relfil);
|
||||
fclose(fp);
|
||||
fclose(libfp);
|
||||
loadfile(str);
|
||||
return (1);
|
||||
|
||||
/*5*/ }
|
||||
|
||||
/*4*/ }
|
||||
fclose(fp);
|
||||
/*3*/ }
|
||||
|
||||
free(str);
|
||||
/*2*/ }
|
||||
fclose(libfp);
|
||||
/*1*/ }
|
||||
return(0);
|
||||
}
|
||||
#endif /* INDEXLIB */
|
||||
|
||||
/*)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) {
|
||||
loadfile(lbfh->filspc);
|
||||
}
|
||||
}
|
||||
|
||||
/*)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() 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];
|
||||
int i;
|
||||
|
||||
if ((fp = fopen(filspc,"r")) != NULL) {
|
||||
while (fgets(str, NINPUT, fp) != NULL) {
|
||||
str[NINPUT+1] = '\0';
|
||||
i = strlen(str) - 1;
|
||||
if (str[i] == '\n')
|
||||
str[i] = '\0';
|
||||
ip = str;
|
||||
link();
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
1270
link/z80/lklist.c
Normal file
1270
link/z80/lklist.c
Normal file
File diff suppressed because it is too large
Load Diff
1411
link/z80/lkmain.c
Normal file
1411
link/z80/lkmain.c
Normal file
File diff suppressed because it is too large
Load Diff
1171
link/z80/lkrloc.c
Normal file
1171
link/z80/lkrloc.c
Normal file
File diff suppressed because it is too large
Load Diff
123
link/z80/lks19.c
Normal file
123
link/z80/lks19.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/* 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 <alloc.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", (-chksum-1) & 0xff);
|
||||
} else {
|
||||
fprintf(ofp, "S9030000FC\n");
|
||||
}
|
||||
}
|
||||
496
link/z80/lksym.c
Normal file
496
link/z80/lksym.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/* lksym.c */
|
||||
|
||||
/*
|
||||
* (C) Copyright 1989-1995
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Alan R. Baldwin
|
||||
* 721 Berkeley St.
|
||||
* Kent, Ohio 44240
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#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()
|
||||
{
|
||||
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 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 int c, i, nglob;
|
||||
struct sym *tsp;
|
||||
struct sym **s;
|
||||
char id[NCPS];
|
||||
|
||||
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) {
|
||||
#ifdef SDK
|
||||
fprintf(stderr, "Multiple definition of %s\n", id);
|
||||
#else
|
||||
fprintf(stderr, "Multiple definition of %.8s\n", id);
|
||||
#endif
|
||||
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);
|
||||
|
||||
/* Never reached */
|
||||
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;
|
||||
strncpy(sp->s_id, id, NCPS);
|
||||
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;
|
||||
{
|
||||
register int n;
|
||||
|
||||
n = NCPS;
|
||||
do {
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
if (*p1++ != *p2++)
|
||||
return (0);
|
||||
#else
|
||||
if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
} while (--n);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*)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, n;
|
||||
|
||||
h = 0;
|
||||
n = NCPS;
|
||||
do {
|
||||
|
||||
#if CASE_SENSITIVE
|
||||
h += *p++;
|
||||
#else
|
||||
h += ccase[(unsigned char)(*p++)];
|
||||
#endif
|
||||
|
||||
} while (--n);
|
||||
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,*q;
|
||||
register unsigned int i;
|
||||
|
||||
if ((p = (char *) malloc(n)) == NULL) {
|
||||
fprintf(stderr, "Out of space!\n");
|
||||
lkexit(1);
|
||||
}
|
||||
for (i=0,q=p; i<n; i++) {
|
||||
*q++ = 0;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
Reference in New Issue
Block a user