--- /dev/null
+CC=gcc
+LEX=flex
+YACC=bison
+INCROOT=.
+CFLAGS=-ggdb -O2 -I $(INCROOT)
+TARGETS=$(SDCCDIR)/bin/as_hc08
+ALLOBJECTS= asmain.o aslex.o assym.o assubr.o asnoice.o \
+ asexpr.o asdata.o aslist.o asout.o asstore.o \
+ h08ext.o h08pst.o h08mch.o h08adr.o strcmpi.o
+
+all:: $(TARGETS)
+
+clean::
+ rm -f $(TARGETS) $(ALLOBJECTS)
+
+asmain.o : asmain.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o asmain.o asmain.c
+
+aslex.o : aslex.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o aslex.o aslex.c
+
+assym.o : assym.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o assym.o assym.c
+
+assubr.o : assubr.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o assubr.o assubr.c
+
+asexpr.o : asexpr.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o asexpr.o asexpr.c
+
+asdata.o : asdata.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o asdata.o asdata.c
+
+aslist.o : aslist.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o aslist.o aslist.c
+
+asout.o : asout.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o asout.o asout.c
+
+asnoice.o : asnoice.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o asnoice.o asnoice.c
+
+asstore.o : asstore.c asm.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o asstore.o asstore.c
+
+h08ext.o : h08ext.c asm.h m6808.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08ext.o h08ext.c
+
+h08pst.o : h08pst.c asm.h m6808.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08pst.o h08pst.c
+
+h08mch.o : h08mch.c asm.h m6808.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08mch.o h08mch.c
+
+h08adr.o : h08adr.c asm.h m6808.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o h08adr.o h08adr.c
+
+strcmpi.o : strcmpi.c strcmpi.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o strcmpi.o strcmpi.c
+
+$(TARGETS): $(ALLOBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALLOBJECTS)
--- /dev/null
+CC=gcc
+LEX=flex
+YACC=bison
+INCROOT=.
+CFLAGS=-ggdb -O2 -I $(INCROOT)
+TARGETS=$(SDCCDIR)/bin/aslink
+ALLOBJECTS= lkmain.o lkhead.o lkarea.o lkdata.o\
+ lkeval.o lklex.o lksym.o lkrloc.o\
+ lklibr.o lklist.o lkihx.o lks19.o\
+ lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o
+all:: $(TARGETS)
+
+clean::
+ rm -f $(TARGETS) $(ALLOBJECTS)
+
+lkmain.o : lkmain.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmain.o lkmain.c
+
+lkhead.o : lkhead.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkhead.o lkhead.c
+
+lkarea.o : lkarea.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkarea.o lkarea.c
+
+lkdata.o : lkdata.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkdata.o lkdata.c
+
+lkeval.o : lkeval.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkeval.o lkeval.c
+
+lklex.o : lklex.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklex.o lklex.c
+
+lksym.o : lksym.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lksym.o lksym.c
+
+lkrloc.o : lkrloc.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkrloc.o lkrloc.c
+
+lklibr.o : lklibr.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklibr.o lklibr.c
+
+lklist.o : lklist.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lklist.o lklist.c
+
+lkihx.o : lkihx.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkihx.o lkihx.c
+
+lks19.o : lks19.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lks19.o lks19.c
+
+lkstore.o : lkstore.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkstore.o lkstore.c
+
+lknoice.o : lknoice.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lknoice.o lknoice.c
+
+strcmpi.o : strcmpi.c strcmpi.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o strcmpi.o strcmpi.c
+
+lkmem.o : lkmem.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkmem.o lkmem.c
+
+lkaomf51.o : lkaomf51.c aslink.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -c -o lkaomf51.o lkaomf51.c
+
+$(TARGETS): $(ALLOBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ALLOBJECTS)
--- /dev/null
+# Makefile for Borlad C++
+
+PRJDIR = ../..
+
+!include $(PRJDIR)/Bcc.inc
+
+ASOBJECTS = asmain.obj aslex.obj assym.obj assubr.obj asnoice.obj \
+ asexpr.obj asdata.obj aslist.obj asout.obj asstore.obj \
+ h08ext.obj h08pst.obj h08mch.obj h08adr.obj strcmpi.obj
+
+LKOBJECTS = lkmain.obj lkhead.obj lkarea.obj lkdata.obj \
+ lkeval.obj lklex.obj lksym.obj lkrloc.obj \
+ lklibr.obj lklist.obj lkihx.obj lks19.obj \
+ lkstore.obj lknoice.obj lkmem.obj lkaomf51.obj strcmpi.obj
+
+ASX8051 = $(PRJDIR)/bin/asx8051.exe
+ASLINK = $(PRJDIR)/bin/aslink.exe
+
+all: $(ASX8051) $(ASLINK)
+
+$(ASX8051): $(ASOBJECTS)
+ $(CC) $(CFLAGS) -e$@ $(ASOBJECTS)
+
+$(ASLINK): $(LKOBJECTS)
+ $(CC) $(CFLAGS) -e$@ $(LKOBJECTS)
--- /dev/null
+#
+#
+#
+
+VERSION = @VERSION@
+VERSIONHI = @VERSIONHI@
+VERSIONLO = @VERSIONLO@
+VERSIONP = @VERSIONP@
+
+SHELL = /bin/sh
+CC = @CC@
+CPP = @CPP@
+INSTALL = @INSTALL@
+STRIP = @STRIP@
+
+PRJDIR = ../..
+
+srcdir = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+datadir = @datadir@
+includedir = @includedir@
+mandir = @mandir@
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+infodir = @info@
+
+EXEEXT = @EXEEXT@
+
+CPPFLAGS = @CPPFLAGS@ -I. -I$(PRJDIR)
+CFLAGS = @CFLAGS@ -Wall
+M_OR_MM = @M_OR_MM@
+LDFLAGS = @LDFLAGS@
+
+ASOBJECTS = asmain.o aslex.o assym.o assubr.o asnoice.o \
+ asexpr.o asdata.o aslist.o asout.o asstore.o \
+ h08ext.o h08pst.o h08mch.o h08adr.o strcmpi.o
+ASSOURCES = $(patsubst %.o,%.c,$(ASOBJECTS))
+
+LKOBJECTS = lkmain.o lkhead.o lkarea.o lkdata.o \
+ lkeval.o lklex.o lksym.o lkrloc.o \
+ lklibr.o lklist.o lkihx.o lks19.o \
+ lkstore.o lknoice.o lkmem.o lkaomf51.o strcmpi.o
+LKSOURCES = $(patsubst %.o,%.c,$(LKOBJECTS))
+
+ASX8051 = $(PRJDIR)/bin/as-hc08$(EXEEXT)
+ASLINK = $(PRJDIR)/bin/link-hc08$(EXEEXT)
+
+transform = @program_transform_name@
+
+# Compiling entire program or any subproject
+# ------------------------------------------
+all: checkconf $(ASX8051) $(ASLINK)
+
+$(ASX8051): $(ASOBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(ASOBJECTS)
+
+$(ASLINK): $(LKOBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LKOBJECTS)
+
+# Compiling and installing everything and runing test
+# ---------------------------------------------------
+install: all installdirs
+ $(INSTALL) $(ASX8051) `echo $(bindir)/asx8051$(EXEEXT)|sed '$(transform)'`
+ $(STRIP) `echo $(bindir)/as-hc08$(EXEEXT)|sed '$(transform)'`
+ $(INSTALL) $(ASLINK) `echo $(bindir)/aslink$(EXEEXT)|sed '$(transform)'`
+ $(STRIP) `echo $(bindir)/link-hc08$(EXEEXT)|sed '$(transform)'`
+
+# Deleting all the installed files
+# --------------------------------
+uninstall:
+ rm -f $(bindir)/as-hc08$(EXEEXT) $(bindir)/link-hc08$(EXEEXT)
+
+
+# Performing self-test
+# --------------------
+check:
+
+
+# Performing installation test
+# ----------------------------
+installcheck:
+
+
+# Creating installation directories
+# ---------------------------------
+installdirs:
+ $(INSTALL) -d $(bindir)
+
+
+# Creating dependencies
+# ---------------------
+dep: Makefile.dep
+
+Makefile.dep: $(ASSOURCES) $(LKSOURCES) *.h $(PRJDIR)/*.h
+ $(CPP) $(CPPFLAGS) $(M_OR_MM) $(ASSOURCES) $(LKSOURCES) >Makefile.dep
+
+include Makefile.dep
+include clean.mk
+
+# My rules
+# --------
+.c.o:
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+
+# Remaking configuration
+# ----------------------
+checkconf:
+ @if [ -f $(PRJDIR)/devel ]; then\
+ $(MAKE) -f conf.mk srcdir="$(srcdir)" PRJDIR="$(PRJDIR)" freshconf;\
+ fi
+
+# End of Makefile
--- /dev/null
+/* alloc.h */
+/* DECUS C */
+
+#include <stdlib.h>
--- /dev/null
+/* asdata.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - change s_id from [NCPS] to pointer (comment)
+ * 2-Nov-97 JLH:
+ * - add jflag for debug control
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module asdata.c
+ *
+ * The module asdata.c contains the global constants,
+ * structures, and variables used in the assembler.
+ */
+
+int aserr; /* ASxxxx error counter
+ */
+jmp_buf jump_env; /* compiler dependent structure
+ * used by setjmp() and longjmp()
+ */
+int inpfil; /* count of assembler
+ * input files specified
+ */
+int incfil; /* current file handle index
+ * for include files
+ */
+int cfile; /* current file handle index
+ * of input assembly files
+ */
+int flevel; /* IF-ELSE-ENDIF flag will be non
+ * zero for false conditional case
+ */
+int tlevel; /* current conditional level
+ */
+int ifcnd[MAXIF+1]; /* array of IF statement condition
+ * values (0 = FALSE) indexed by tlevel
+ */
+int iflvl[MAXIF+1]; /* array of IF-ELSE-ENDIF flevel
+ * values indexed by tlevel
+ */
+
+char afn[PATH_MAX]; /* afile temporary file name
+ */
+char srcfn[MAXFIL][PATH_MAX]; /* array of source file names
+ */
+int srcline[MAXFIL]; /* source line number
+ */
+char incfn[MAXINC][PATH_MAX]; /* array of include file names
+ */
+int incline[MAXINC]; /* include line number
+ */
+
+int radix; /* current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ */
+int line; /* current assembler source
+ * line number
+ */
+int page; /* current page number
+ */
+int lop; /* current line number on page
+ */
+int pass; /* assembler pass number
+ */
+int lflag; /* -l, generate listing flag
+ */
+int cflag; /* -lc, generate sdcdb debug info
+ */
+int gflag; /* -g, make undefined symbols global flag
+ */
+int aflag; /* -a, make all symbols global flag
+ */
+int jflag; /* -j, generate debug information flag
+ */
+int oflag; /* -o, generate relocatable output flag
+ */
+int sflag; /* -s, generate symbol table flag
+ */
+int pflag; /* -p, enable listing pagination
+ */
+int xflag; /* -x, listing radix flag
+ */
+int fflag; /* -f(f), relocations flagged flag
+ */
+Addr_T laddr; /* address of current assembler line
+ * or value of .if argument
+ */
+Addr_T fuzz; /* tracks pass to pass changes in the
+ * address of symbols caused by
+ * variable length instruction formats
+ */
+int lmode; /* listing mode
+ */
+char *ep; /* pointer into error list
+ * array eb[NERR]
+ */
+char eb[NERR]; /* array of generated error codes
+ */
+char *ip; /* pointer into the assembler-source
+ * text line in ib[]
+ */
+char ib[NINPUT]; /* assembler-source text line
+ */
+char *cp; /* pointer to assembler output
+ * array cb[]
+ */
+char cb[NCODE]; /* array of assembler output values
+ */
+int *cpt; /* pointer to assembler relocation type
+ * output array cbt[]
+ */
+int cbt[NCODE]; /* array of assembler relocation types
+ * describing the data in cb[]
+ */
+char tb[NTITL]; /* Title string buffer
+ */
+char stb[NSBTL]; /* Subtitle string buffer
+ */
+char optsdcc[NINPUT]; /* sdcc compile options
+ */
+int flat24Mode; /* non-zero if we are using DS390 24 bit
+ * flat mode (via .flat24 directive).
+ */
+
+char symtbl[] = { "Symbol Table" };
+char aretbl[] = { "Area Table" };
+
+char module[NCPS]; /* module name string
+ */
+
+/*
+ * The mne structure is a linked list of the assembler
+ * mnemonics and directives. The list of mnemonics and
+ * directives contained in the device dependent file
+ * xxxpst.c are hashed and linked into NHASH lists in
+ * module assym.c by syminit(). The structure contains
+ * the mnemonic/directive name, a subtype which directs
+ * the evaluation of this mnemonic/directive, a flag which
+ * is used to detect the end of the mnemonic/directive
+ * list in xxxpst.c, and a value which is normally
+ * associated with the assembler mnemonic base instruction
+ * value.
+ *
+ * struct mne
+ * {
+ * struct mne *m_mp; Hash link
+ * char m_id[NCPS]; Mnemonic
+ * char m_type; Mnemonic subtype
+ * char m_flag; Mnemonic flags
+ * Addr_T m_valu; Value
+ * };
+ */
+struct mne *mnehash[NHASH];
+
+/*
+ * The sym structure is a linked list of symbols defined
+ * in the assembler source files. The first symbol is "."
+ * defined here. The entry 'struct tsym *s_tsym'
+ * links any temporary symbols following this symbol and
+ * preceeding the next normal symbol. The structure also
+ * contains the symbol's name, type (USER or NEW), flag
+ * (global, assigned, and multiply defined), a pointer
+ * to the area structure defining where the symbol is
+ * located, a reference number assigned by outgsd() in
+ * asout.c, and the symbols address relative to the base
+ * address of the area where the symbol is located.
+ *
+ * struct sym
+ * {
+ * struct sym *s_sp; Hash link
+ * struct tsym *s_tsym; Temporary symbol link
+ * char *s_id; Symbol (JLH)
+ * char s_type; Symbol subtype
+ * char s_flag; Symbol flags
+ * struct area *s_area; Area line, 0 if absolute
+ * int s_ref; Ref. number
+ * Addr_T s_addr; Address
+ * };
+ */
+struct sym sym[] = {
+ {NULL, NULL, ".", S_USER, S_END, NULL, 0, 0}
+};
+
+struct sym *symp; /* pointer to a symbol structure
+ */
+struct sym *symhash[NHASH]; /* array of pointers to NHASH
+ * linked symbol lists
+ */
+
+/*
+ * The area structure contains the parameter values for a
+ * specific program or data section. The area structure
+ * is a linked list of areas. The initial default area
+ * is "_CODE" defined here, the next area structure
+ * will be linked to this structure through the structure
+ * element 'struct area *a_ep'. The structure contains the
+ * area name, area reference number ("_CODE" is 0) determined
+ * by the order of .area directives, area size determined
+ * from the total code and/or data in an area, area fuzz is
+ * an variable used to track pass to pass changes in the
+ * area size caused by variable length instruction formats,
+ * and area flags which specify the area's relocation type.
+ *
+ * struct area
+ * {
+ * struct area *a_ap; Area link
+ * char a_id[NCPS]; Area Name
+ * int a_ref; Reference number
+ * Addr_T a_size; Area size
+ * Addr_T a_fuzz; Area fuzz
+ * int a_flag; Area flags
+ * };
+ */
+struct area area[] = {
+ {NULL, "_CODE", 0, 0, 0, A_CON|A_REL}
+};
+
+struct area *areap; /* pointer to an area structure
+ */
+
+FILE *lfp; /* list output file handle
+ */
+FILE *ofp; /* relocation output file handle
+ */
+FILE *tfp; /* symbol table output file handle
+ */
+FILE *sfp[MAXFIL]; /* array of assembler-source file handles
+ */
+FILE *ifp[MAXINC]; /* array of include-file file handles
+ */
+
+/*
+ * array of character types, one per
+ * ASCII character
+ */
+unsigned char ctype[128] = {
+/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
+/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL,
+/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
+/*CAN*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
+/*SPC*/ SPACE, ETC, ETC, ETC, LETTER, BINOP, BINOP, ETC,
+/*(*/ ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, BINOP,
+/*0*/ DGT2, DGT2, DGT8, DGT8, DGT8, DGT8, DGT8, DGT8,
+/*8*/ DGT10, DGT10, ETC, ETC, BINOP, ETC, BINOP, ETC,
+/*@*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
+/*H*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*P*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*X*/ LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER,
+/*`*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
+/*h*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*p*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*x*/ LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC
+};
+
+/*
+ * an array of characters which
+ * perform the case translation function
+ */
+char ccase[128] = {
+/*NUL*/ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+/*DLE*/ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+/*CAN*/ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+/*SPC*/ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+/*(*/ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+/*0*/ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+/*8*/ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+/*@*/ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*H*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*P*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*X*/ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+/*`*/ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*h*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*p*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*x*/ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177'
+};
--- /dev/null
+ /* asexpr.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module asexpr.c
+ *
+ * The module asexpr.c contains the routines to evaluate
+ * arithmetic/numerical expressions. The functions in
+ * asexpr.c perform a recursive evaluation of the arithmetic
+ * expression read from the assembler-source text line.
+ * The expression may include binary/unary operators, brackets,
+ * symbols, labels, and constants in hexadecimal, decimal, octal
+ * and binary. Arithmetic operations are prioritized and
+ * evaluated by normal arithmetic conventions.
+ *
+ * asexpr.c contains the following functions:
+ * VOID abscheck()
+ * Addr_T absexpr()
+ * VOID clrexpr()
+ * int digit()
+ * VOID expr()
+ * int oprio()
+ * VOID term()
+ *
+ * asexpr.c contains no local/static variables
+ */
+
+/*)Function VOID expr(esp, n)
+ *
+ * expr * esp pointer to an expr structure
+ * int n a firewall priority; all top
+ * level calls (from the user)
+ * should be made with n set to 0.
+ *
+ * The function expr() evaluates an expression and
+ * stores its value and relocation information into
+ * the expr structure supplied by the user.
+ *
+ * local variables:
+ * int c current assembler-source
+ * text character
+ * int p current operator priority
+ * area * ap pointer to an area structure
+ * exp re internal expr structure
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ *
+ * functions called:
+ * VOID abscheck() asexpr.c
+ * VOID clrexpr() asexpr.c
+ * VOID expr() asexpr.c
+ * int getnb() aslex.c
+ * int oprio() asexpr.c
+ * VOID qerr() assubr.c
+ * VOID rerr() assubr.c
+ * VOID term() asexpr.c
+ * VOID unget() aslex.c
+ *
+ *
+ * side effects:
+ * An expression is evaluated modifying the user supplied
+ * expr structure, a sym structure maybe created for an
+ * undefined symbol, and the parse of the expression may
+ * terminate if a 'q' error occurs.
+ */
+
+VOID
+expr(esp, n)
+register struct expr *esp;
+int n;
+{
+ register int c, p;
+ struct area *ap;
+ struct expr re;
+
+ term(esp);
+ while (ctype[c = getnb()] & BINOP) {
+ /*
+ * Handle binary operators + - * / & | % ^ << >>
+ */
+ if ((p = oprio(c)) <= n)
+ break;
+ if ((c == '>' || c == '<') && c != get())
+ qerr();
+ clrexpr(&re);
+ expr(&re, p);
+ esp->e_rlcf |= re.e_rlcf;
+ if (c == '+') {
+ /*
+ * esp + re, at least one must be absolute
+ */
+ if (esp->e_base.e_ap == NULL) {
+ /*
+ * esp is absolute (constant),
+ * use area from re
+ */
+ esp->e_base.e_ap = re.e_base.e_ap;
+ } else
+ if (re.e_base.e_ap) {
+ /*
+ * re should be absolute (constant)
+ */
+ rerr();
+ }
+ if (esp->e_flag && re.e_flag)
+ rerr();
+ if (re.e_flag)
+ esp->e_flag = 1;
+ esp->e_addr += re.e_addr;
+ } else
+ if (c == '-') {
+ /*
+ * esp - re
+ */
+ if ((ap = re.e_base.e_ap) != NULL) {
+ if (esp->e_base.e_ap == ap) {
+ esp->e_base.e_ap = NULL;
+ } else {
+ rerr();
+ }
+ }
+ if (re.e_flag)
+ rerr();
+ esp->e_addr -= re.e_addr;
+ } else {
+ /*
+ * Both operands (esp and re) must be constants
+ */
+ /* SD :- moved the abscheck to each case
+ case and change the right shift operator.. if
+ right shift by 8 bits of a relocatable address then
+ the user wants the higher order byte. set the R_MSB
+ for the expression */
+ switch (c) {
+
+ case '*':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr *= re.e_addr;
+ break;
+
+ case '/':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr /= re.e_addr;
+ break;
+
+ case '&':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr &= re.e_addr;
+ break;
+
+ case '|':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr |= re.e_addr;
+ break;
+
+ case '%':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr %= re.e_addr;
+ break;
+
+ case '^':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr ^= re.e_addr;
+ break;
+
+ case '<':
+ abscheck(esp);
+ abscheck(&re);
+ esp->e_addr <<= re.e_addr;
+ break;
+
+ case '>':
+ /* SD change here */
+ abscheck(&re);
+ /* if the left is a relative address &
+ the right side is == 8 then */
+ if (esp->e_base.e_ap && re.e_addr == 8) {
+ esp->e_rlcf |= R_MSB ;
+ break;
+ }
+ else if (esp->e_base.e_ap && re.e_addr == 16)
+ {
+ if (flat24Mode)
+ {
+ esp->e_rlcf |= R_HIB;
+ }
+ else
+ {
+ warnBanner();
+ fprintf(stderr,
+ "(expr >> 16) is only meaningful in "
+ ".flat24 mode.\n");
+ qerr();
+ }
+
+ break;
+ }
+ /* else continue with the normal processing */
+ abscheck(esp);
+ esp->e_addr >>= re.e_addr;
+ break;
+
+ default:
+ qerr();
+ break;
+ }
+ }
+ }
+ unget(c);
+}
+
+/*)Function Addr_T absexpr()
+ *
+ * The function absexpr() evaluates an expression, verifies it
+ * is absolute (i.e. not position dependent or relocatable), and
+ * returns its value.
+ *
+ * local variables:
+ * expr e expr structure
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * VOID abscheck() asexpr.c
+ * VOID clrexpr() asexpr.c
+ * VOID expr() asexpr.c
+ *
+ * side effects:
+ * If the expression is not absolute then
+ * a 'r' error is reported.
+ */
+
+Addr_T
+absexpr()
+{
+ struct expr e;
+
+ clrexpr(&e);
+ expr(&e, 0);
+ abscheck(&e);
+ return (e.e_addr);
+}
+
+/*)Function VOID term(esp)
+ *
+ * expr * esp pointer to an expr structure
+ *
+ * The function term() evaluates a single constant
+ * or symbol value prefaced by any unary operator
+ * ( +, -, ~, ', ", >, or < ). This routine is also
+ * responsible for setting the relocation type to symbol
+ * based (e.flag != 0) on global references.
+ *
+ * local variables:
+ * int c current character
+ * char id[] symbol name
+ * char * jp pointer to assembler-source text
+ * int n constant evaluation running sum
+ * int r current evaluation radix
+ * sym * sp pointer to a sym structure
+ * tsym * tp pointer to a tsym structure
+ * int v current digit evaluation
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * sym * symp pointer to a symbol structure
+ *
+ * functions called:
+ * VOID abscheck() asexpr.c
+ * int digit() asexpr.c
+ * VOID err() assubr.c
+ * VOID expr() asexpr.c
+ * int is_abs() asexpr.c
+ * int get() aslex.c
+ * VOID getid() aslex.c
+ * int getmap() aslex.c
+ * int getnb() aslex.c
+ * sym * lookup() assym.c
+ * VOID qerr() assubr.c
+ * VOID unget() aslex.c
+ *
+ * side effects:
+ * An arithmetic term is evaluated, a symbol structure
+ * may be created, term evaluation may be terminated
+ * by a 'q' error.
+ */
+
+VOID
+term(esp)
+register struct expr *esp;
+{
+ register int c, n;
+ register char *jp;
+ char id[NCPS];
+ struct sym *sp;
+ struct tsym *tp;
+ int r=0, v;
+
+ c = getnb();
+ /*
+ * Discard the unary '+' at this point and
+ * also any reference to numerical arguments
+ * associated with the '#' prefix.
+ */
+ while (c == '+' || c == '#') { c = getnb(); }
+ /*
+ * Evaluate all binary operators
+ * by recursively calling expr().
+ */
+ if (c == LFTERM) {
+ expr(esp, 0);
+ if (getnb() != RTTERM)
+ qerr();
+ return;
+ }
+ if (c == '-') {
+ expr(esp, 100);
+ abscheck(esp);
+ esp->e_addr = 0-esp->e_addr;
+ return;
+ }
+ if (c == '~') {
+ expr(esp, 100);
+ abscheck(esp);
+ esp->e_addr = ~esp->e_addr;
+ return;
+ }
+ if (c == '\'') {
+ esp->e_mode = S_USER;
+ esp->e_addr = getmap(-1)&0377;
+ return;
+ }
+ if (c == '\"') {
+ esp->e_mode = S_USER;
+ if (hilo) {
+ esp->e_addr = (getmap(-1)&0377)<<8;
+ esp->e_addr |= (getmap(-1)&0377);
+ } else {
+ esp->e_addr = (getmap(-1)&0377);
+ esp->e_addr |= (getmap(-1)&0377)<<8;
+ }
+ return;
+ }
+ if (c == '>' || c == '<') {
+ expr(esp, 100);
+ if (is_abs (esp)) {
+ /*
+ * evaluate msb/lsb directly
+ */
+ if (c == '>')
+ esp->e_addr >>= 8;
+ esp->e_addr &= 0377;
+ return;
+ } else {
+ /*
+ * let linker perform msb/lsb, lsb is default
+ */
+ esp->e_rlcf |= R_BYT2;
+ if (c == '>')
+ esp->e_rlcf |= R_MSB;
+ return;
+ }
+ }
+ /*
+ * Evaluate digit sequences as local symbols
+ * if followed by a '$' or as constants.
+ */
+ if (ctype[c] & DIGIT) {
+ esp->e_mode = S_USER;
+ jp = ip;
+ while (ctype[(int)*jp] & RAD10) {
+ jp++;
+ }
+ if (*jp == '$') {
+ n = 0;
+ while ((v = digit(c, 10)) >= 0) {
+ n = 10*n + v;
+ c = get();
+ }
+ tp = symp->s_tsym;
+ while (tp) {
+ if (n == tp->t_num) {
+ esp->e_base.e_ap = tp->t_area;
+ esp->e_addr = tp->t_addr;
+ return;
+ }
+ tp = tp->t_lnk;
+ }
+ /* err('u'); */
+ return;
+ }
+ r = radix;
+ if (c == '0') {
+ c = get();
+ switch (c) {
+ case 'b':
+ case 'B':
+ r = 2;
+ c = get();
+ break;
+ case 'o':
+ case 'O':
+ case 'q':
+ case 'Q':
+ r = 8;
+ c = get();
+ break;
+ case 'd':
+ case 'D':
+ r = 10;
+ c = get();
+ break;
+ case 'h':
+ case 'H':
+ case 'x':
+ case 'X':
+ r = 16;
+ c = get();
+ break;
+ default:
+ break;
+ }
+ }
+ n = 0;
+ while ((v = digit(c, r)) >= 0) {
+ n = r*n + v;
+ c = get();
+ }
+ unget(c);
+ esp->e_addr = n;
+ return;
+ }
+ /*
+ * Evaluate '$' sequences as a temporary radix
+ * if followed by a '%', '&', '#', or '$'.
+ */
+ if (c == '$') {
+ c = get();
+ if (c == '%' || c == '&' || c == '#' || c == '$') {
+ switch (c) {
+ case '%':
+ r = 2;
+ break;
+ case '&':
+ r = 8;
+ break;
+ case '#':
+ r = 10;
+ break;
+ case '$':
+ r = 16;
+ break;
+ default:
+ break;
+ }
+ c = get();
+ n = 0;
+ while ((v = digit(c, r)) >= 0) {
+ n = r*n + v;
+ c = get();
+ }
+ unget(c);
+ esp->e_mode = S_USER;
+ esp->e_addr = n;
+ return;
+ }
+ unget(c);
+ c = '$';
+ }
+ /*
+ * Evaluate symbols and labels
+ */
+ if (ctype[c] & LETTER) {
+ esp->e_mode = S_USER;
+ getid(id, c);
+ sp = lookup(id);
+ if (sp->s_type == S_NEW) {
+ esp->e_addr = 0;
+ if (sp->s_flag&S_GBL) {
+ esp->e_flag = 1;
+ esp->e_base.e_sp = sp;
+ return;
+ }
+ /* err('u'); */
+ } else {
+ esp->e_mode = sp->s_type;
+ esp->e_addr = sp->s_addr;
+ esp->e_base.e_ap = sp->s_area;
+ }
+ return;
+ }
+ /*
+ * Else not a term.
+ */
+ qerr();
+}
+
+/*)Function int digit(c, r)
+ *
+ * int c digit character
+ * int r current radix
+ *
+ * The function digit() returns the value of c
+ * in the current radix r. If the c value is not
+ * a number of the current radix then a -1 is returned.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+digit(c, r)
+register int c, r;
+{
+ if (r == 16) {
+ if (ctype[c] & RAD16) {
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ return (c - '0');
+ }
+ } else
+ if (r == 10) {
+ if (ctype[c] & RAD10)
+ return (c - '0');
+ } else
+ if (r == 8) {
+ if (ctype[c] & RAD8)
+ return (c - '0');
+ } else
+ if (r == 2) {
+ if (ctype[c] & RAD2)
+ return (c - '0');
+ }
+ return (-1);
+}
+
+/*)Function VOID abscheck(esp)
+ *
+ * expr * esp pointer to an expr structure
+ *
+ * The function abscheck() tests the evaluation of an
+ * expression to verify it is absolute. If the evaluation
+ * is relocatable then an 'r' error is noted and the expression
+ * made absolute.
+ *
+ * Note: The area type (i.e. ABS) is not checked because
+ * the linker can be told to explicitly relocate an
+ * absolute area.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * VOID rerr() assubr.c
+ *
+ * side effects:
+ * The expression may be changed to absolute and the
+ * 'r' error invoked.
+ */
+
+VOID
+abscheck(esp)
+register struct expr *esp;
+{
+ if (esp->e_flag || esp->e_base.e_ap) {
+ esp->e_flag = 0;
+ esp->e_base.e_ap = NULL;
+ rerr();
+ }
+}
+
+/*)Function int is_abs(esp)
+ *
+ * expr * esp pointer to an expr structure
+ *
+ * The function is_abs() tests the evaluation of an
+ * expression to verify it is absolute. If the evaluation
+ * is absolute then 1 is returned, else 0 is returned.
+ *
+ * Note: The area type (i.e. ABS) is not checked because
+ * the linker can be told to explicitly relocate an
+ * absolute area.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+is_abs (esp)
+register struct expr *esp;
+{
+ if (esp->e_flag || esp->e_base.e_ap) {
+ return(0);
+ }
+ return(1);
+}
+
+/*)Function int oprio(c)
+ *
+ * int c operator character
+ *
+ * The function oprio() returns a relative priority
+ * for all valid unary and binary operators.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+oprio(c)
+register int c;
+{
+ if (c == '*' || c == '/' || c == '%')
+ return (10);
+ if (c == '+' || c == '-')
+ return (7);
+ if (c == '<' || c == '>')
+ return (5);
+ if (c == '^')
+ return (4);
+ if (c == '&')
+ return (3);
+ if (c == '|')
+ return (1);
+ return (0);
+}
+
+/*)Function VOID clrexpr(esp)
+ *
+ * expr * esp pointer to expression structure
+ *
+ * The function clrexpr() clears the expression structure.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * expression structure cleared.
+ */
+
+VOID
+clrexpr(esp)
+register struct expr *esp;
+{
+ esp->e_mode = 0;
+ esp->e_flag = 0;
+ esp->e_addr = 0;
+ esp->e_base.e_ap = NULL;
+ esp->e_rlcf = 0;
+}
--- /dev/null
+/* aslex.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH bug in getst(): sign extend on ~(SPACE|ILL)
+ * causes infinite loop
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module aslex.c
+ *
+ * The module aslex.c includes the general lexical
+ * analysis routines for the assembler.
+ *
+ * aslex.c contains the following functions:
+ * char endline()
+ * char get()
+ * VOID getid(id,c)
+ * int getline()
+ * int getmap()
+ * char getnb()
+ * VOID getst()
+ * int more()
+ * VOID unget(c)
+ *
+ * aslex.c contains no local/static variables
+ */
+
+/*)Function VOID getid(id,c)
+ *
+ * char * id a pointer to a string of
+ * maximum length NCPS
+ * int c mode flag
+ * >=0 this is first character to
+ * copy to the string buffer
+ * <0 skip white space, first
+ * character must be a LETTER
+ *
+ * The function getid() scans the current assembler-source text line
+ * from the current position copying the next LETTER | DIGIT string
+ * into the external string buffer (id). The string ends when a non
+ * LETTER or DIGIT character is found. The maximum number of
+ * characters copied is NCPS. If the input string is larger than
+ * NCPS characters then the string is truncated, if the input string
+ * is shorter than NCPS characters then the string is NULL filled.
+ * If the mode argument (c) is >=0 then (c) is the first character
+ * copied to the string buffer, if (c) is <0 then intervening white
+ * space (SPACES and TABS) are skipped and the first character found
+ * must be a LETTER else a 'q' error terminates the parse of this
+ * assembler-source text line.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() aslex.c
+ * char getnb() aslex.c
+ * VOID unget() aslex.c
+ *
+ * side effects:
+ * use of getnb(), get(), and unget() updates the
+ * global pointer ip, the position in the current
+ * assembler-source text line.
+ */
+
+VOID
+getid(id, c)
+register int c;
+char *id;
+{
+ register char *p;
+
+ if (c < 0) {
+ c = getnb();
+ if ((ctype[c] & LETTER) == 0)
+ qerr();
+ }
+ p = id;
+ do {
+ if (p < &id[NCPS])
+ *p++ = c;
+ } while (ctype[c=get()] & (LETTER|DIGIT));
+ unget(c);
+ while (p < &id[NCPS])
+ *p++ = 0;
+}
+
+/*)Function VOID getst(id,c)
+ *
+ * char * id a pointer to a string of
+ * maximum length NCPS
+ * int c mode flag
+ * >=0 this is first character to
+ * copy to the string buffer
+ * <0 skip white space, first
+ * character must be a LETTER
+ *
+ * The function getnbid() scans the current assembler-source text line
+ * from the current position copying the next character string into
+ * the external string buffer (id). The string ends when a SPACE or
+ * ILL character is found. The maximum number of
+ * characters copied is NCPS. If the input string is larger than
+ * NCPS characters then the string is truncated, if the input string
+ * is shorter than NCPS characters then the string is NULL filled.
+ * If the mode argument (c) is >=0 then (c) is the first character
+ * copied to the string buffer, if (c) is <0 then intervening white
+ * space (SPACES and TABS) are skipped and the first character found
+ * must be a LETTER else a 'q' error terminates the parse of this
+ * assembler-source text line.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() aslex.c
+ * char getnb() aslex.c
+ * VOID unget() aslex.c
+ *
+ * side effects:
+ * use of getnb(), get(), and unget() updates the
+ * global pointer ip, the position in the current
+ * assembler-source text line.
+ */
+
+VOID
+getst(id, c)
+register int c;
+char *id;
+{
+ register char *p;
+
+ if (c < 0) {
+ c = getnb();
+ if ((ctype[c] & LETTER) == 0)
+ qerr();
+ }
+ p = id;
+ do {
+ if (p < &id[NCPS])
+ *p++ = c;
+ } while (ctype[c=get()] & (0xFF - (SPACE|ILL)));
+ unget(c);
+ while (p < &id[NCPS])
+ *p++ = 0;
+}
+
+/*)Function char getnb()
+ *
+ * The function getnb() scans the current assembler-source
+ * text line returning the first character not a SPACE or TAB.
+ *
+ * local variables:
+ * int c current character from
+ * assembler-source text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char get() aslex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip, the position
+ * in the current assembler-source text line
+ */
+
+char
+getnb()
+{
+ register int c;
+
+ while ((c=get()) == ' ' || c == '\t')
+ ;
+ return (c);
+}
+
+/*)Function char get()
+ *
+ * The function get() returns the next character in the
+ * assembler-source text line, at the end of the line a
+ * NULL character is returned.
+ *
+ * local variables:
+ * int c current character from
+ * assembler-source text line
+ *
+ * global variables:
+ * char * ip pointer into the current
+ * assembler-source text line
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * updates ip to the next character position in the
+ * assembler-source text line. If ip is at the end of the
+ * line, ip is not updated.
+ */
+
+char
+get()
+{
+ register int c;
+
+ if ((c = *ip) != 0)
+ ++ip;
+ return (c);
+}
+
+/*)Function VOID unget(c)
+ *
+ * int c value of last character read from
+ * assembler-source text line
+ *
+ * If (c) is not a NULL character then the global pointer ip
+ * is updated to point to the preceeding character in the
+ * assembler-source text line.
+ *
+ * NOTE: This function does not push the character (c)
+ * back into the assembler-source text line, only
+ * the pointer ip is changed.
+ *
+ * local variables:
+ * int c last character read from
+ * assembler-source text line
+ *
+ * global variables:
+ * char * ip position into the current
+ * assembler-source text line
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * ip decremented by 1 character position
+ */
+
+VOID
+unget(c)
+{
+ if (c)
+ if (ip != ib)
+ --ip;
+}
+
+/*)Function int getmap(d)
+ *
+ * int d value to compare with the
+ * assembler-source text line character
+ *
+ * The function getmap() converts the 'C' style characters \b, \f,
+ * \n, \r, and \t to their equivalent ascii values and also
+ * converts 'C' style octal constants '\123' to their equivalent
+ * numeric values. If the first character is equivalent to (d) then
+ * a (-1) is returned, if the end of the line is detected then
+ * a 'q' error terminates the parse for this line, or if the first
+ * character is not a \ then the character value is returned.
+ *
+ * local variables:
+ * int c value of character from the
+ * assembler-source text line
+ * int n looping counter
+ * int v current value of numeric conversion
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char get() aslex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip the position
+ * in the current assembler-source text line
+ */
+
+int
+getmap(d)
+{
+ register int c, n, v;
+
+ if ((c=get()) == '\0')
+ qerr();
+ if (c == d)
+ return (-1);
+ if (c == '\\') {
+ c = get();
+ switch (c) {
+
+ case 'b':
+ c = '\b';
+ break;
+
+ case 'f':
+ c = '\f';
+ break;
+
+ case 'n':
+ c = '\n';
+ break;
+
+ case 'r':
+ c = '\r';
+ break;
+
+ case 't':
+ c = '\t';
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ n = 0;
+ v = 0;
+ while (++n<=3 && c>='0' && c<='7') {
+ v = (v<<3) + c - '0';
+ c = get();
+ }
+ unget(c);
+ c = v;
+ break;
+ }
+ }
+ return (c);
+}
+
+/*)Function int getline()
+ *
+ * The function getline() reads a line of assembler-source text
+ * from an assembly source text file or an include file.
+ * Lines of text are processed from assembler-source files until
+ * all files have been read. If an include file is opened then
+ * lines of text are read from the include file (or nested
+ * include file) until the end of the include file is found.
+ * The input text line is copied into the global string ib[]
+ * and converted to a NULL terminated string. The function
+ * getline() returns a (1) after succesfully reading a line
+ * or a (0) if all files have been read.
+ *
+ * local variables:
+ * int i string length
+ *
+ * global variables:
+ * char ib[] string buffer containing
+ * assembler-source text line
+ * char ifp[] array of file handles for
+ * include files
+ * int incfil index for ifp[] specifies
+ * active include file
+ * int incline[] array of include file
+ * line numbers
+ * char sfp[] array of file handles for
+ * assembler source files
+ * int cfile index for sfp[] specifies
+ * active source file
+ * int srcline[] array of source file
+ * line numbers
+ * int inpfil maximum input file index
+ *
+ * called functions:
+ * int fclose() c-library
+ * char * fgets() c-library
+ * int strlen() c-library
+ *
+ * side effects:
+ * include file will be closed at detection of end of file.
+ * the next sequential source file may be selected.
+ * the global file indexes incfil or cfile may be changed.
+ * The respective source line or include line counter
+ * will be updated.
+ */
+
+int
+getline()
+{
+loop: if (incfil >= 0) {
+ if (fgets(ib, sizeof ib, ifp[incfil]) == NULL) {
+ fclose(ifp[incfil--]);
+ lop = NLPP;
+ goto loop;
+ } else {
+ ++incline[incfil];
+ }
+ } else {
+ if (fgets(ib, sizeof ib, sfp[cfile]) == NULL) {
+ if (++cfile <= inpfil) {
+ srcline[cfile] = 0;
+ goto loop;
+ }
+ return (0);
+ } else {
+ ++srcline[cfile];
+ }
+ }
+ chop_crlf(ib);
+ return (1);
+}
+
+/*)Function int more()
+ *
+ * The function more() scans the assembler-source text line
+ * skipping white space (SPACES and TABS) and returns a (0)
+ * if the end of the line or a comment delimeter (;) is found,
+ * or a (1) if their are additional characters in the line.
+ *
+ * local variables:
+ * int c next character from the
+ * assembler-source text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char getnb() aslex.c
+ * VOID unget() aslex.c
+ *
+ * side effects:
+ * use of getnb() and unget() updates the global pointer ip
+ * the position in the current assembler-source text line
+ */
+
+int
+more()
+{
+ register int c;
+
+ c = getnb();
+ unget(c);
+ return( (c == '\0' || c == ';') ? 0 : 1 );
+}
+
+/*)Function char endline()
+ *
+ * The function endline() scans the assembler-source text line
+ * skipping white space (SPACES and TABS) and returns the next
+ * character or a (0) if the end of the line is found or a
+ * comment delimiter (;) is found.
+ *
+ * local variables:
+ * int c next character from the
+ * assembler-source text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char getnb() aslex.c
+ *
+ * side effects:
+ * use of getnb() updates the global pointer ip the
+ * position in the current assembler-source text line
+ */
+
+char
+endline()
+{
+ register int c;
+
+ c = getnb();
+ return( (c == '\0' || c == ';') ? 0 : c );
+}
+
+/*)Function VOID chop_crlf(str)
+ *
+ * char *str string to chop
+ *
+ * The function chop_crlf() removes trailing LF or CR/LF from
+ * str, if present.
+ *
+ * local variables:
+ * int i string length
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+VOID
+chop_crlf(str)
+char *str;
+{
+ register int i;
+
+ i = strlen(str);
+ if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
+ if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;
+}
--- /dev/null
+/* aslink.h */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - add proto for StoreString
+ * - change s_id from [NCPS] to pointer
+ * - change NCPS to 80
+ * - case sensitive
+ * - add R_J11 for 8051 assembler
+ * 31-Oct-97 JLH:
+ * - add jflag and jfp for NoICE output
+ * 30-Jan-98 JLH:
+ * - add memory space flags to a_flag for 8051
+ */
+
+#define VERSION "V01.70 + NoICE + SDCC Feb 1999"
+
+/*
+ * Case Sensitivity Flag
+ */
+#define CASE_SENSITIVE 1
+
+/*)Module asmlnk.h
+ *
+ * The module asmlnk.h contains the definitions for constants,
+ * structures, global variables, and LKxxxx functions
+ * contained in the LKxxxx.c files.
+ */
+
+/*)BUILD
+ $(PROGRAM) = ASLINK
+ $(INCLUDE) = ASLINK.H
+ $(FILES) = {
+ LKMAIN.C
+ LKLEX.C
+ LKAREA.C
+ LKHEAD.C
+ LKSYM.C
+ LKEVAL.C
+ LKDATA.C
+ LKLIST.C
+ LKRLOC.C
+ LKLIBR.C
+ LKS19.C
+ LKIHX.C
+ }
+ $(STACK) = 2000
+*/
+
+/* DECUS C void definition */
+/* File/extension seperator */
+
+#ifdef decus
+#define VOID char
+#define FSEPX '.'
+#endif
+
+/* PDOS C void definition */
+/* File/extension seperator */
+
+#ifdef PDOS
+#define VOID char
+#define FSEPX ':'
+#endif
+
+/* Default void definition */
+/* File/extension seperator */
+
+#ifndef VOID
+#define VOID void
+#define FSEPX '.'
+#define OTHERSYSTEM
+#endif
+
+/*
+ * PATH_MAX
+ */
+#include <limits.h>
+#ifndef PATH_MAX /* POSIX, but not required */
+ #if defined(__BORLANDC__) || defined(_MSC_VER)
+ #include <stdlib.h>
+ #define PATH_MAX _MAX_PATH
+ #else
+ #define PATH_MAX 255 /* define a reasonable value */
+ #endif
+#endif
+
+/*
+ * This file defines the format of the
+ * relocatable binary file.
+ */
+
+#define NCPS 80 /* characters per symbol (JLH: change from 8) */
+#define NDATA 16 /* actual data */
+#define NINPUT PATH_MAX /* Input buffer size */
+#define NHASH 64 /* Buckets in hash table */
+#define HMASK 077 /* Hash mask */
+#define NLPP 60 /* Lines per page */
+#define NTXT 16 /* T values */
+
+/*
+ * The "R_" relocation constants define values used in
+ * generating the assembler relocation output data for
+ * areas, symbols, and code.
+ *
+ *
+ * Relocation types.
+ *
+ * 7 6 5 4 3 2 1 0
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define R_WORD 0x00 /* 16 bit */
+#define R_BYTE 0x01 /* 8 bit */
+
+#define R_AREA 0x00 /* Base type */
+#define R_SYM 0x02
+
+#define R_NORM 0x00 /* PC adjust */
+#define R_PCR 0x04
+
+#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */
+#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */
+
+#define R_SGND 0x00 /* Signed Byte */
+#define R_USGN 0x10 /* Unsigned Byte */
+
+#define R_NOPAG 0x00 /* Page Mode */
+#define R_PAG0 0x20 /* Page '0' */
+#define R_PAG 0x40 /* Page 'nnn' */
+
+#define R_LSB 0x00 /* low byte */
+#define R_MSB 0x80 /* high byte */
+
+#define R_BYT3 0x100 /* if R_BYTE is set, this is a
+ * 3 byte address, of which
+ * the linker must select one byte.
+ */
+#define R_HIB 0x200 /* If R_BYTE & R_BYT3 are set, linker
+ * will select byte 3 of the relocated
+ * 24 bit address.
+ */
+
+#define R_J11 (R_WORD|R_BYT2) /* JLH: 11 bit JMP and CALL (8051) */
+#define R_J19 (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */
+#define R_C24 (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */
+#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB)
+
+#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19)
+#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11)
+#define IS_C24(x) (((x) & R_J19_MASK) == R_C24)
+
+#define R_ESCAPE_MASK 0xf0 /* Used to escape relocation modes
+ * greater than 0xff in the .rel
+ * file.
+ */
+
+/*
+ * Global symbol types.
+ */
+#define S_REF 1 /* referenced */
+#define S_DEF 2 /* defined */
+
+/*
+ * Area type flags
+ */
+#define A_CON 0000 /* concatenate */
+#define A_OVR 0004 /* overlay */
+#define A_REL 0000 /* relocatable */
+#define A_ABS 0010 /* absolute */
+#define A_NOPAG 0000 /* non-paged */
+#define A_PAG 0020 /* paged */
+
+/* Additional flags for 8051 address spaces */
+#define A_DATA 0000 /* data space (default)*/
+#define A_CODE 0040 /* code space */
+#define A_XDATA 0100 /* external data space */
+#define A_BIT 0200 /* bit addressable space */
+
+/*
+ * File types
+ */
+#define F_STD 1 /* stdin */
+#define F_LNK 2 /* File.lnk */
+#define F_REL 3 /* File.rel */
+
+/*
+ * General assembler address type
+ */
+typedef unsigned int Addr_T;
+
+/*
+ * The structures of head, area, areax, and sym are created
+ * as the REL files are read during the first pass of the
+ * linker. The struct head is created upon encountering a
+ * H directive in the REL file. The structure contains a
+ * link to a link file structure (struct lfile) which describes
+ * the file containing the H directive, the number of data/code
+ * areas contained in this header segment, the number of
+ * symbols referenced/defined in this header segment, a pointer
+ * to an array of pointers to areax structures (struct areax)
+ * created as each A directive is read, and a pointer to an
+ * array of pointers to symbol structures (struct sym) for
+ * all referenced/defined symbols. As H directives are read
+ * from the REL files a linked list of head structures is
+ * created by placing a link to the new head structure
+ * in the previous head structure.
+ */
+struct head
+{
+ struct head *h_hp; /* Header link */
+ struct lfile *h_lfile;/* Associated file */
+ int h_narea; /* # of areas */
+ struct areax **a_list; /* Area list */
+ int h_nglob; /* # of global symbols */
+ struct sym **s_list; /* Globle symbol list */
+ char m_id[NCPS]; /* Module name */
+};
+
+/*
+ * A structure area is created for each 'unique' data/code
+ * area definition found as the REL files are read. The
+ * struct area contains the name of the area, a flag byte
+ * which contains the area attributes (REL/CON/OVR/ABS),
+ * an area subtype (not used in this assembler), and the
+ * area base address and total size which will be filled
+ * in at the end of the first pass through the REL files.
+ * As A directives are read from the REL files a linked
+ * list of unique area structures is created by placing a
+ * link to the new area structure in the previous area structure.
+ */
+struct area
+{
+ struct area *a_ap; /* Area link */
+ struct areax *a_axp; /* Area extension link */
+ Addr_T a_addr; /* Beginning address of area */
+ Addr_T a_size; /* Total size of the area */
+ char a_type; /* Area subtype */
+ char a_flag; /* Flag byte */
+ char a_id[NCPS]; /* Name */
+};
+
+/*
+ * An areax structure is created for every A directive found
+ * while reading the REL files. The struct areax contains a
+ * link to the 'unique' area structure referenced by the A
+ * directive and to the head structure this area segment is
+ * a part of. The size of this area segment as read from the
+ * A directive is placed in the areax structure. The beginning
+ * address of this segment will be filled in at the end of the
+ * first pass through the REL files. As A directives are read
+ * from the REL files a linked list of areax structures is
+ * created for each unique area. The final areax linked
+ * list has at its head the 'unique' area structure linked
+ * to the linked areax structures (one areax structure for
+ * each A directive for this area).
+ */
+struct areax
+{
+ struct areax *a_axp; /* Area extension link */
+ struct area *a_bap; /* Base area link */
+ struct head *a_bhp; /* Base header link */
+ Addr_T a_addr; /* Beginning address of section */
+ Addr_T a_size; /* Size of the area in section */
+};
+
+/*
+ * A sym structure is created for every unique symbol
+ * referenced/defined while reading the REL files. The
+ * struct sym contains the symbol's name, a flag value
+ * (not used in this linker), a symbol type denoting
+ * referenced/defined, and an address which is loaded
+ * with the relative address within the area in which
+ * the symbol was defined. The sym structure also
+ * contains a link to the area where the symbol was defined.
+ * The sym structures are linked into linked lists using
+ * the symbol link element.
+ */
+struct sym
+{
+ struct sym *s_sp; /* Symbol link */
+ struct areax *s_axp; /* Symbol area link */
+ char s_type; /* Symbol subtype */
+ char s_flag; /* Flag byte */
+ Addr_T s_addr; /* Address */
+ char *s_id; /* Name: JLH change from [NCPS] */
+};
+
+/*
+ * The structure lfile contains a pointer to a
+ * file specification string, the file type, and
+ * a link to the next lfile structure.
+ */
+struct lfile
+{
+ struct lfile *f_flp; /* lfile link */
+ int f_type; /* File type */
+ char *f_idp; /* Pointer to file spec */
+};
+
+/*
+ * The struct base contains a pointer to a
+ * base definition string and a link to the next
+ * base structure.
+ */
+struct base
+{
+ struct base *b_base; /* Base link */
+ char *b_strp; /* String pointer */
+};
+
+/*
+ * The struct globl contains a pointer to a
+ * global definition string and a link to the next
+ * global structure.
+ */
+struct globl
+{
+ struct globl *g_globl; /* Global link */
+ char *g_strp; /* String pointer */
+};
+
+/*
+ * A structure sdp is created for each 'unique' paged
+ * area definition found as the REL files are read.
+ * As P directives are read from the REL files a linked
+ * list of unique sdp structures is created by placing a
+ * link to the new sdp structure in the previous area structure.
+ */
+struct sdp
+{
+ struct area *s_area; /* Paged Area link */
+ struct areax *s_areax; /* Paged Area Extension Link */
+ Addr_T s_addr; /* Page address offset */
+};
+
+/*
+ * The structure rerr is loaded with the information
+ * required to report an error during the linking
+ * process. The structure contains an index value
+ * which selects the areax structure from the header
+ * areax structure list, a mode value which selects
+ * symbol or area relocation, the base address in the
+ * area section, an area/symbol list index value, and
+ * an area/symbol offset value.
+ */
+struct rerr
+{
+ int aindex; /* Linking area */
+ int mode; /* Relocation mode */
+ Addr_T rtbase; /* Base address in section */
+ int rindex; /* Area/Symbol reloaction index */
+ Addr_T rval; /* Area/Symbol offset value */
+};
+
+/*
+ * The structure lbpath is created for each library
+ * path specification input by the -k option. The
+ * lbpath structures are linked into a list using
+ * the next link element.
+ */
+struct lbpath {
+ struct lbpath *next;
+ char *path;
+};
+
+/*
+ * The structure lbname is created for all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file. The element path points to
+ * the path string, element libfil points to the library
+ * file string, and the element libspc is the concatenation
+ * of the valid path and libfil strings.
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ *
+ * Each library file contains a list of object files
+ * that are contained in the particular library. e.g.:
+ *
+ * \iolib\termio
+ * \inilib\termio
+ *
+ * Only one specification per line is allowed.
+ */
+struct lbname {
+ struct lbname *next;
+ char *path;
+ char *libfil;
+ char *libspc;
+};
+
+/*
+ * The function fndsym() searches through all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file for a symbol definition.
+ *
+ * The structure lbfile is created for the first library
+ * object file which contains the definition for the
+ * specified undefined symbol.
+ *
+ * The element libspc points to the library file path specification
+ * and element relfil points to the object file specification string.
+ * The element filspc is the complete path/file specification for
+ * the library file to be imported into the linker. The
+ * file specicifation may be formed in one of two ways:
+ *
+ * (1) If the library file contained an absolute
+ * path/file specification then this becomes filspc.
+ * (i.e. C:\...)
+ *
+ * (2) If the library file contains a relative path/file
+ * specification then the concatenation of the path
+ * and this file specification becomes filspc.
+ * (i.e. \...)
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ */
+struct lbfile {
+ struct lbfile *next;
+ char *libspc;
+ char *relfil;
+ char *filspc;
+ long offset; /*>=0 if rel file is embedded in a lib file at this offset*/
+};
+
+/*
+ * External Definitions for all Global Variables
+ */
+
+extern char *_abs_; /* = { ". .ABS." };
+ */
+extern int lkerr; /* ASLink error flag
+ */
+extern char *ip; /* pointer into the REL file
+ * text line in ib[]
+ */
+extern char ib[NINPUT]; /* REL file text line
+ */
+extern char *rp; /* pointer into the LST file
+ * text line in rb[]
+ */
+extern char rb[NINPUT]; /* LST file text line being
+ * address relocated
+ */
+extern unsigned char ctype[]; /* array of character types, one per
+ * ASCII character
+ */
+
+extern char sdccopt[NINPUT];
+extern char sdccopt_module[NINPUT];
+extern char curr_module[NINPUT];
+
+/*
+ * Character Type Definitions
+ */
+#define SPACE 0000
+#define ETC 0000
+#define LETTER 0001
+#define DIGIT 0002
+#define BINOP 0004
+#define RAD2 0010
+#define RAD8 0020
+#define RAD10 0040
+#define RAD16 0100
+#define ILL 0200
+
+#define DGT2 DIGIT|RAD16|RAD10|RAD8|RAD2
+#define DGT8 DIGIT|RAD16|RAD10|RAD8
+#define DGT10 DIGIT|RAD16|RAD10
+#define LTR16 LETTER|RAD16
+
+#if CASE_SENSITIVE
+#else
+extern char ccase[]; /* an array of characters which
+ * perform the case translation function
+ */
+#endif
+
+extern struct lfile *filep; /* The pointers (lfile *) filep,
+ * (lfile *) cfp, and (FILE *) sfp
+ * are used in conjunction with
+ * the routine getline() to read
+ * asmlnk commands from
+ * (1) the standard input or
+ * (2) or a command file
+ * and to read the REL files
+ * sequentially as defined by the
+ * asmlnk input commands.
+ *
+ * The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ */
+extern struct lfile *cfp; /* The pointer *cfp points to the
+ * current lfile structure
+ */
+extern struct lfile *startp;/* asmlnk startup file structure
+ */
+extern struct lfile *linkp; /* pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ */
+extern struct lfile *lfp; /* pointer to current lfile structure
+ * being processed by parse()
+ */
+extern struct head *headp; /* The pointer to the first
+ * head structure of a linked list
+ */
+extern struct head *hp; /* Pointer to the current
+ * head structure
+ */
+extern struct area *areap; /* The pointer to the first
+ * area structure of a linked list
+ */
+extern struct area *ap; /* Pointer to the current
+ * area structure
+ */
+extern struct areax *axp; /* Pointer to the current
+ * areax structure
+ */
+extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
+ * linked symbol lists
+ */
+extern struct base *basep; /* The pointer to the first
+ * base structure
+ */
+extern struct base *bsp; /* Pointer to the current
+ * base structure
+ */
+extern struct globl *globlp;/* The pointer to the first
+ * globl structure
+ */
+extern struct globl *gsp; /* Pointer to the current
+ * globl structure
+ */
+extern struct sdp sdp; /* Base Paged structure
+ */
+extern struct rerr rerr; /* Structure containing the
+ * linker error information
+ */
+extern FILE *ofp; /* Linker Output file handle
+ */
+extern FILE *mfp; /* Map output file handle
+ */
+extern FILE *jfp; /* NoICE output file handle
+ */
+extern FILE *rfp; /* File handle for output
+ * address relocated ASxxxx
+ * listing file
+ */
+extern FILE *sfp; /* The file handle sfp points to the
+ * currently open file
+ */
+extern FILE *tfp; /* File handle for input
+ * ASxxxx listing file
+ */
+extern FILE *dfp; /* File handle for debug info output
+ */
+extern int dflag; /* Output debug information flag
+ */
+extern int oflag; /* Output file type flag
+ */
+extern int mflag; /* Map output flag
+ */
+extern int sflag; /* JCF: Memory usage output flag
+ */
+extern int jflag; /* NoICE output flag
+ */
+extern int xflag; /* Map file radix type flag
+ */
+extern int pflag; /* print linker command file flag
+ */
+extern int uflag; /* Listing relocation flag
+ */
+extern int rflag; /* Extended linear address record flag.
+ */
+extern int radix; /* current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ */
+extern int line; /* current line number
+ */
+extern int page; /* current page number
+ */
+extern int lop; /* current line number on page
+ */
+extern int pass; /* linker pass number
+ */
+extern int rtcnt; /* count of elements in the
+ * rtval[] and rtflg[] arrays
+ */
+extern Addr_T rtval[]; /* data associated with relocation
+ */
+extern int rtflg[]; /* indicates if rtval[] value is
+ * to be sent to the output file.
+ * (always set in this linker)
+ */
+extern int hilo; /* REL file byte ordering
+ */
+extern int gline; /* LST file relocation active
+ * for current line
+ */
+extern int gcntr; /* LST file relocation active
+ * counter
+ */
+extern struct lbpath *lbphead; /* pointer to the first
+ * library path structure
+ */
+extern struct lbname *lbnhead; /* pointer to the first
+ * library name structure
+ */
+extern struct lbfile *lbfhead; /* pointer to the first
+ * library file structure
+ */
+extern Addr_T iram_size; /* internal ram size
+ */
+extern long xram_size; /* external ram size
+ */
+extern long code_size; /* code size
+ */
+
+
+/* C Library function definitions */
+/* for reference only
+extern VOID exit();
+extern int fclose();
+extern char * fgets();
+extern FILE * fopen();
+extern int fprintf();
+extern VOID free();
+extern VOID * malloc();
+extern char putc();
+extern char * strcpy();
+extern int strlen();
+extern char * strncpy();
+*/
+
+/* Program function definitions */
+
+/* lkmain.c */
+extern FILE * afile();
+extern VOID bassav();
+extern VOID gblsav();
+extern VOID iramsav();
+extern VOID xramsav();
+extern VOID codesav();
+extern VOID iramcheck();
+extern VOID link_main();
+extern VOID lkexit();
+extern int main();
+extern VOID map();
+extern int parse();
+extern VOID setbas();
+extern VOID setgbl();
+extern VOID usage();
+extern VOID copyfile();
+
+/* lklex.c */
+extern char endline();
+extern char get();
+extern VOID getfid();
+extern VOID getid();
+extern VOID getSid();
+extern int getline();
+extern int getmap();
+extern char getnb();
+extern int more();
+extern VOID skip();
+extern VOID unget();
+extern VOID chop_crlf();
+
+/* lkarea.c */
+extern VOID lkparea();
+extern VOID lnkarea();
+extern VOID lnksect();
+extern VOID newarea();
+
+/* lkhead.c */
+extern VOID module();
+extern VOID newhead();
+
+/* lksym.c */
+extern int hash();
+extern struct sym * lkpsym();
+extern VOID * new();
+extern struct sym * newsym();
+extern VOID symdef();
+extern int symeq();
+extern VOID syminit();
+extern VOID symmod();
+extern Addr_T symval();
+
+/* lkeval.c */
+extern int digit();
+extern Addr_T eval();
+extern Addr_T expr();
+extern int oprio();
+extern Addr_T term();
+
+/* lklist.c */
+extern int dgt();
+extern VOID lkulist();
+extern VOID lkalist();
+extern VOID lkglist();
+extern VOID lstarea();
+extern VOID newpag();
+extern VOID slew();
+
+/* lkrloc.c */
+extern Addr_T adb_b();
+extern Addr_T adb_hi();
+extern Addr_T adb_lo();
+extern Addr_T adb_24_hi(Addr_T v, int i);
+extern Addr_T adb_24_mid(Addr_T v, int i);
+extern Addr_T adb_24_lo(Addr_T v, int i);
+extern Addr_T adw_w();
+extern Addr_T adw_24(Addr_T, int);
+extern Addr_T adw_hi();
+extern Addr_T adw_lo();
+extern Addr_T evword();
+extern VOID rele();
+extern VOID reloc();
+extern VOID relt();
+extern VOID relr();
+extern VOID relp();
+extern VOID relerr();
+extern char * errmsg[];
+extern VOID errdmp();
+extern VOID relerp();
+extern VOID erpdmp();
+extern VOID prntval();
+extern int lastExtendedAddress;
+
+/* lklibr.c */
+extern int addfile();
+extern VOID addlib();
+extern VOID addpath();
+extern int fndsym();
+extern VOID library();
+extern VOID loadfile();
+extern VOID search();
+
+/* lks19.c */
+extern VOID s19();
+
+/* lkihx.c */
+extern VOID ihx();
+extern VOID ihxEntendedLinearAddress(Addr_T);
+extern VOID newArea();
+
+/* lkstore.c */
+extern char *StoreString( char *str );
+
+/* lknoice.c */
+extern void DefineNoICE( char *name, Addr_T value, int page );
+
+/* JCF: lkmem.c */
+extern int summary(struct area * xp);
+
+/* JCF: lkaomf51.c */
+extern void SaveLinkedFilePath(char * filepath);
+extern void CreateAOMF51(void);
--- /dev/null
+ORIGIN = Symantec C++
+ORIGIN_VER = Version 7.00
+VERSION = RELEASE
+
+!IFDEF SUB_DEBUG
+DEBUG = $(SUB_DEBUG)
+NDEBUG = !$(SUB_DEBUG)
+!ELSE
+DEBUG = 0
+NDEBUG = 1
+!ENDIF
+
+PROJ = ASLINK
+APPTYPE = DOS EXE
+PROJTYPE = EXE
+
+CC = SC
+CPP = SPP
+MAKE = SMAKE
+RC = RCC
+HC = HC31
+ASM = SC
+DISASM = OBJ2ASM
+LNK = LINK
+DLLS =
+
+HEADERS = ..\linksrc\aslink.h
+
+DEFFILE = ASLINK.DEF
+
+!IF $(DEBUG)
+OUTPUTDIR = .
+CREATEOUTPUTDIR =
+TARGETDIR = .
+CREATETARGETDIR =
+
+LIBS =
+
+CFLAGS = -A -Jm -J -ms -o+time -S -2 -a2 -c
+LFLAGS = /PACKF
+DEFINES = -D_DEBUG=1
+!ELSE
+OUTPUTDIR = .
+CREATEOUTPUTDIR =
+TARGETDIR = .
+CREATETARGETDIR =
+
+LIBS =
+
+CFLAGS = -A -Jm -J -ms -o+time -S -2 -a2 -c
+LFLAGS = /PACKF
+DEFINES =
+!ENDIF
+
+HFLAGS = $(CFLAGS)
+MFLAGS = MASTERPROJ=$(PROJ)
+LIBFLAGS = /C
+RESFLAGS =
+DEBUGGERFLAGS = -LOADSYMBOLS
+AFLAGS = $(CFLAGS)
+HELPFLAGS =
+
+MODEL = S
+
+PAR = PROJS BATS OBJS
+
+RCDEFINES =
+
+LIBDIRS =
+
+INCLUDES = -Ic:\asxxxx\linksrc
+
+INCLUDEDOBJS =
+
+OBJS = $(OUTPUTDIR)\lkarea.OBJ $(OUTPUTDIR)\lkdata.OBJ $(OUTPUTDIR)\lkeval.OBJ \
+ $(OUTPUTDIR)\lkhead.OBJ $(OUTPUTDIR)\lkihx.OBJ $(OUTPUTDIR)\lklex.OBJ $(OUTPUTDIR)\lklibr.OBJ \
+ $(OUTPUTDIR)\lklist.OBJ $(OUTPUTDIR)\lkmain.OBJ $(OUTPUTDIR)\lkrloc.OBJ $(OUTPUTDIR)\lks19.OBJ \
+ $(OUTPUTDIR)\lksym.OBJ
+
+RCFILES =
+
+RESFILES =
+
+SYMS =
+
+HELPFILES =
+
+BATS =
+
+.SUFFIXES: .C .CP .CPP .CXX .CC .H .HPP .HXX .COM .EXE .DLL .LIB .RTF .DLG .ASM .RES .RC .OBJ
+
+.C.OBJ:
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.c
+
+.CPP.OBJ:
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cpp
+
+.CXX.OBJ:
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cxx
+
+.CC.OBJ:
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cc
+
+.CP.OBJ:
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.cp
+
+.H.SYM:
+ $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.h
+
+.HPP.SYM:
+ $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hpp
+
+.HXX.SYM:
+ $(CC) $(HFLAGS) $(DEFINES) $(INCLUDES) -HF -o$(*B).sym $*.hxx
+
+.C.EXP:
+ $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.c -o$*.lst
+
+.CPP.EXP:
+ $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cpp -o$*.lst
+
+.CXX.EXP:
+ $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cxx -o$*.lst
+
+.CP.EXP:
+ $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cp -o$*.lst
+
+.CC.EXP:
+ $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.cc -o$*.lst
+
+.ASM.EXP:
+ $(CPP) $(CFLAGS) $(DEFINES) $(INCLUDES) $*.asm -o$*.lst
+
+.OBJ.COD:
+ $(DISASM) $*.OBJ >$*.cod
+
+.OBJ.EXE:
+ $(LNK) $(LFLAGS) @$(PROJ).LNK
+
+.RTF.HLP:
+ $(HC) $(HELPFLAGS) $*.HPJ
+
+.ASM.OBJ:
+ $(ASM) $(AFLAGS) $(DEFINES) $(INCLUDES) -o$*.obj $*.asm
+
+.RC.RES:
+ $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $*.rc -o$*.res
+
+.DLG.RES:
+ echo ^#include "windows.h" >$$$*.rc
+ echo ^IF EXIST "$*.h" >>$$$*.rc
+ echo ^#include "$*.h" >>$$$*.rc
+ echo ^#include "$*.dlg" >>$$$*.rc
+ $(RC) $(RCDEFINES) $(RESFLAGS) $(INCLUDES) $$$*.rc
+ -del $*.res
+ -ren $$$*.res $*.res
+
+
+
+all: createdir $(PRECOMPILE) $(SYMS) $(OBJS) $(INCLUDEDOBJS) $(POSTCOMPILE) $(TARGETDIR)\$(PROJ).$(PROJTYPE) $(POSTLINK) _done
+
+createdir:
+ $(CREATEOUTPUTDIR)
+ $(CREATETARGETDIR)
+
+$(TARGETDIR)\$(PROJ).$(PROJTYPE): $(OBJS) $(INCLUDEDOBJS) $(RCFILES) $(RESFILES) $(HELPFILES)
+ $(LNK) $(LFLAGS) @$(PROJ).LNK;
+ -del $(TARGETDIR)\$(PROJ).$(PROJTYPE)
+ -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE)
+ -echo $(TARGETDIR)\$(PROJ).$(PROJTYPE) built
+
+_done:
+ -echo $(PROJ).$(PROJTYPE) done
+
+buildall: clean all
+
+
+clean:
+ -del $(TARGETDIR)\$$SCW$$.$(PROJTYPE)
+ -del $(TARGETDIR)\$(PROJ).CLE
+ -del $(OUTPUTDIR)\SCPH.SYM
+ -del $(OBJS)
+
+cleanres:
+
+res: cleanres $(RCFILES) all
+
+
+link:
+ $(LNK) $(LFLAGS) @$(PROJ).LNK;
+ -del $(TARGETDIR)\$(PROJ).$(PROJTYPE)
+ -ren $(TARGETDIR)\$$SCW$$.$(PROJTYPE) $(PROJ).$(PROJTYPE)
+
+
+
+
+!IF EXIST (ASLINK.dpd)
+!INCLUDE ASLINK.dpd
+!ENDIF
+
+
+
+$(OUTPUTDIR)\lkarea.OBJ: ..\linksrc\lkarea.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkarea.obj ..\linksrc\lkarea.c
+
+
+
+$(OUTPUTDIR)\lkdata.OBJ: ..\linksrc\lkdata.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkdata.obj ..\linksrc\lkdata.c
+
+
+
+$(OUTPUTDIR)\lkeval.OBJ: ..\linksrc\lkeval.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkeval.obj ..\linksrc\lkeval.c
+
+
+
+$(OUTPUTDIR)\lkhead.OBJ: ..\linksrc\lkhead.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkhead.obj ..\linksrc\lkhead.c
+
+
+
+$(OUTPUTDIR)\lkihx.OBJ: ..\linksrc\lkihx.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkihx.obj ..\linksrc\lkihx.c
+
+
+
+$(OUTPUTDIR)\lklex.OBJ: ..\linksrc\lklex.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklex.obj ..\linksrc\lklex.c
+
+
+
+$(OUTPUTDIR)\lklibr.OBJ: ..\linksrc\lklibr.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklibr.obj ..\linksrc\lklibr.c
+
+
+
+$(OUTPUTDIR)\lklist.OBJ: ..\linksrc\lklist.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lklist.obj ..\linksrc\lklist.c
+
+
+
+$(OUTPUTDIR)\lkmain.OBJ: ..\linksrc\lkmain.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkmain.obj ..\linksrc\lkmain.c
+
+
+
+$(OUTPUTDIR)\lkrloc.OBJ: ..\linksrc\lkrloc.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lkrloc.obj ..\linksrc\lkrloc.c
+
+
+
+$(OUTPUTDIR)\lks19.OBJ: ..\linksrc\lks19.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lks19.obj ..\linksrc\lks19.c
+
+
+
+$(OUTPUTDIR)\lksym.OBJ: ..\linksrc\lksym.c
+ $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o$(OUTPUTDIR)\lksym.obj ..\linksrc\lksym.c
+
+
+
+
--- /dev/null
+/* aslist.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - lstsym: show s_id as string rather than array [NCPS]
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdlib.h>
+#include "asm.h"
+
+/*)Module aslist.c
+ *
+ * The module aslist.c contains all the functions used
+ * to generate the assembler list and symbol output files.
+ *
+ * aslist.c contains the following functions:
+ * VOID list()
+ * VOID list1()
+ * VOID list2()
+ * VOID slew()
+ * VOID lstsym()
+ *
+ * The module aslist.c contains no local/static variables
+ */
+
+/*)Function VOID list()
+ *
+ * The function list() generates the listing output
+ * which includes the input source, line numbers,
+ * and generated code. Numerical output may be selected
+ * as hexadecimal, decimal, or octal.
+ *
+ * local variables:
+ * int * wp pointer to the assembled data bytes
+ * int * wpt pointer to the data byte mode
+ * int nb computed number of assembled bytes
+ *
+ * global variables:
+ * int cb[] array of assembler output values
+ * int cbt[] array of assembler relocation types
+ * describing the data in cb[]
+ * int * cp pointer to assembler output array cb[]
+ * int * cpt pointer to assembler relocation type
+ * output array cbt[]
+ * char eb[] array of generated error codes
+ * char * ep pointer into error list
+ * array eb[]
+ * char ib[] assembler-source text line
+ * FILE * lfp list output file handle
+ * int line current assembler source line number
+ * int lmode listing mode
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID list1() aslist.c
+ * int putc() c_library
+ * VOID slew() asslist.c
+ *
+ * side effects:
+ * Listing or symbol output updated.
+ */
+
+VOID
+list()
+{
+ register char *wp;
+ register int *wpt;
+ register int nb;
+
+ if (lfp == NULL || lmode == NLIST)
+ return;
+
+ /*
+ * Get Correct Line Number
+ */
+ if (incfil >= 0) {
+ line = incline[incfil];
+ if (line == 0) {
+ if (incfil > 0) {
+ line = incline[incfil-1];
+ } else {
+ line = srcline[cfile];
+ }
+ }
+ } else {
+ line = srcline[cfile];
+ }
+
+ /*
+ * Move to next line.
+ */
+ slew(lfp, pflag);
+
+ /*
+ * Output a maximum of NERR error codes with listing.
+ */
+ while (ep < &eb[NERR])
+ *ep++ = ' ';
+ fprintf(lfp, "%.2s", eb);
+
+ /*
+ * Source listing only option.
+ */
+ if (lmode == SLIST) {
+ fprintf(lfp, "%24s%5u %s\n", "", line, ib);
+ return;
+ }
+ if (lmode == ALIST) {
+ outchk(HUGE,HUGE);
+ }
+
+ /*
+ * HEX output Option.
+ */
+ if (xflag == 0) { /* HEX */
+ /*
+ * Equate only
+ */
+ if (lmode == ELIST) {
+ fprintf(lfp, "%18s%04X", "", laddr);
+ fprintf(lfp, " %5u %s\n", line, ib);
+ return;
+ }
+
+ /*
+ * Address (with allocation)
+ */
+ fprintf(lfp, " %04X", laddr);
+ if (lmode == ALIST || lmode == BLIST) {
+ fprintf(lfp, "%19s%5u %s\n", "", line, ib);
+ outdot();
+ return;
+ }
+ wp = cb;
+ wpt = cbt;
+ nb = (int) (cp - cb);
+
+ /*
+ * First line of output for this source line with data.
+ */
+ list1(wp, wpt, nb, 1);
+ fprintf(lfp, " %5u %s\n", line, ib);
+
+ /*
+ * Subsequent lines of output if more data.
+ */
+ while ((nb -= 6) > 0) {
+ wp += 6;
+ wpt += 6;
+ slew(lfp, 0);
+ fprintf(lfp, "%7s", "");
+ list1(wp, wpt, nb, 0);
+ putc('\n', lfp);
+ }
+ } else
+ /*
+ * OCTAL output Option.
+ */
+ if (xflag == 1) { /* OCTAL */
+ /*
+ * Equate only
+ */
+ if (lmode == ELIST) {
+ fprintf(lfp, "%16s%06o", "", laddr);
+ fprintf(lfp, " %5u %s\n", line, ib);
+ return;
+ }
+
+ /*
+ * Address (with allocation)
+ */
+ fprintf(lfp, " %06o", laddr);
+ if (lmode == ALIST || lmode == BLIST) {
+ fprintf(lfp, "%17s%5u %s\n", "", line, ib);
+ outdot();
+ return;
+ }
+ wp = cb;
+ wpt = cbt;
+ nb = (int) (cp - cb);
+
+ /*
+ * First line of output for this source line with data.
+ */
+ list1(wp, wpt, nb, 1);
+ fprintf(lfp, " %5u %s\n", line, ib);
+
+ /*
+ * Subsequent lines of output if more data.
+ */
+ while ((nb -= 4) > 0) {
+ wp += 4;
+ wpt += 4;
+ slew(lfp, 0);
+ fprintf(lfp, "%9s", "");
+ list1(wp, wpt, nb, 0);
+ putc('\n', lfp);
+ }
+ } else
+ /*
+ * DECIMAL output Option.
+ */
+ if (xflag == 2) { /* DECIMAL */
+ /*
+ * Equate only
+ */
+ if (lmode == ELIST) {
+ fprintf(lfp, "%16s%05u", "", laddr);
+ fprintf(lfp, " %5u %s\n", line, ib);
+ return;
+ }
+
+ /*
+ * Address (with allocation)
+ */
+ fprintf(lfp, " %05u", laddr);
+ if (lmode == ALIST || lmode == BLIST) {
+ fprintf(lfp, "%17s%5u %s\n", "", line, ib);
+ outdot();
+ return;
+ }
+ wp = cb;
+ wpt = cbt;
+ nb = (int) (cp - cb);
+
+ /*
+ * First line of output for this source line with data.
+ */
+ list1(wp, wpt, nb, 1);
+ fprintf(lfp, " %5u %s\n", line, ib);
+
+ /*
+ * Subsequent lines of output if more data.
+ */
+ while ((nb -= 4) > 0) {
+ wp += 4;
+ wpt += 4;
+ slew(lfp, 0);
+ fprintf(lfp, "%9s", "");
+ list1(wp, wpt, nb, 0);
+ putc('\n', lfp);
+ }
+ }
+}
+
+/*)Function VOID list1(wp, wpt, nw, f)
+ *
+ * int f fill blank fields (1)
+ * int nb number of data bytes
+ * int * wp pointer to data bytes
+ * int * wpt pointer to data byte mode
+ *
+ * local variables:
+ * int i loop counter
+ *
+ * global variables:
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * VOID list2() asslist.c
+ * int fprintf() c_library
+ *
+ * side effects:
+ * Data formatted and output to listing.
+ */
+
+VOID
+list1(wp, wpt, nb, f)
+register char *wp;
+register int *wpt, nb, f;
+{
+ register int i;
+
+ /*
+ * HEX output Option.
+ */
+ if (xflag == 0) { /* HEX */
+ /*
+ * Bound number of words to HEX maximum per line.
+ */
+ if (nb > 6)
+ nb = 6;
+
+ /*
+ * Output bytes.
+ */
+ for (i=0; i<nb; ++i) {
+ list2(*wpt++);
+ fprintf(lfp, "%02X", (*wp++)&0377);
+ }
+
+ /*
+ * Output blanks if required.
+ */
+ if (f) {
+ while (i < 6) {
+ fprintf(lfp, " ");
+ ++i;
+ }
+ }
+ } else
+ /*
+ * OCTAL output Option.
+ */
+ if (xflag == 1) { /* OCTAL */
+ /*
+ * Bound number of words to OCTAL maximum per line.
+ */
+ if (nb > 4)
+ nb = 4;
+
+ /*
+ * Output bytes.
+ */
+ for (i=0; i<nb; ++i) {
+ list2(*wpt++);
+ fprintf(lfp, "%03o", (*wp++)&0377);
+ }
+
+ /*
+ * Output blanks if required.
+ */
+ if (f) {
+ while (i < 4) {
+ fprintf(lfp, " ");
+ ++i;
+ }
+ }
+ } else
+ /*
+ * DECIMAL output Option.
+ */
+ if (xflag == 2) { /* DECIMAL */
+ /*
+ * Bound number of words to DECIMAL maximum per line.
+ */
+ if (nb > 4)
+ nb = 4;
+
+ /*
+ * Output bytes.
+ */
+ for (i=0; i<nb; ++i) {
+ list2(*wpt++);
+ fprintf(lfp, "%03u", (*wp++)&0377);
+ }
+
+ /*
+ * Output blanks if required.
+ */
+ if (f) {
+ while (i < 4) {
+ fprintf(lfp, " ");
+ ++i;
+ }
+ }
+ }
+}
+
+/*)Function VOID list2(wpt)
+ *
+ * int * wpt pointer to relocation mode
+ *
+ * The function list2() outputs the selected
+ * relocation flag as specified by fflag.
+ *
+ * local variables:
+ * int c relocation flag character
+ * int t relocation mode
+ *
+ * global variables:
+ * int fflag -f(f), relocations flagged flag
+ *
+ * functions called:
+ * int putc() c_library
+ *
+ * side effects:
+ * Relocation flag output to listing file.
+ */
+
+VOID
+list2(t)
+register int t;
+{
+ register int c;
+
+ c = ' ';
+
+ /*
+ * Designate a relocatable word by `.
+ */
+ if (fflag == 1) {
+ if (t & R_RELOC) {
+ c = '`';
+ }
+ } else
+ /*
+ * Designate a relocatable word by its mode:
+ * page0 or paged *
+ * unsigned u (v)
+ * operand offset p (q)
+ * relocatable symbol r (s)
+ */
+ if (fflag >= 2) {
+ if (t & R_RELOC) {
+ if (t & (R_PAG0|R_PAG)) {
+ c = '*';
+ } else if (t & R_USGN) {
+ c = 'u';
+ } else if (t & R_PCR) {
+ c = 'p';
+ } else {
+ c = 'r';
+ }
+ if (t & R_HIGH) c += 1;
+ }
+ }
+
+ /*
+ * Output the selected mode.
+ */
+ putc(c, lfp);
+}
+
+/*)Function VOID slew(fp, flag)
+ *
+ * FILE * fp file handle for listing
+ * int flag enable pagination
+ *
+ * The function slew() increments the page line count.
+ * If the page overflows and pagination is enabled:
+ * 1) put out a page skip,
+ * 2) a title,
+ * 3) a subtitle,
+ * 4) and reset the line count.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char cpu[] cpu type string
+ * int lop current line number on page
+ * int page current page number
+ * char stb[] Subtitle string buffer
+ * char tb[] Title string buffer
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * Increments page line counter, on overflow
+ * a new page header is output to the listing file.
+ */
+
+VOID
+slew(fp,flag)
+FILE *fp;
+int flag;
+{
+ if ((lop++ >= NLPP) && flag) {
+ fprintf(fp, "\fASxxxx Assembler %s (%s), page %u.\n",
+ VERSION, cpu, ++page);
+ fprintf(fp, "%s\n", tb);
+ fprintf(fp, "%s\n\n", stb);
+ lop = 5;
+ }
+}
+
+/* Used for qsort call in lstsym */
+static int _cmpSym(const void *p1, const void *p2)
+{
+ struct sym **s1 = (struct sym **)(p1);
+ struct sym **s2 = (struct sym **)(p2);
+ return strcmp((*s1)->s_id,(*s2)->s_id);
+}
+
+/*)Function VOID lstsym(fp)
+ *
+ * FILE * fp file handle for output
+ *
+ * The function lstsym() outputs alphabetically
+ * sorted symbol and area tables.
+ *
+ * local variables:
+ * int c temporary
+ * int i loop counter
+ * int j temporary
+ * int k temporary
+ * char * ptr pointer to an id string
+ * int nmsym number of symbols
+ * int narea number of areas
+ * sym * sp pointer to symbol structure
+ * sym ** p pointer to an array of
+ * pointers to symbol structures
+ * area * ap pointer to an area structure
+ *
+ * global variables:
+ * area * areap pointer to an area structure
+ * char aretbl[] string "Area Table"
+ * sym dot defined as sym[0]
+ * char stb[] Subtitle string buffer
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ * char symtbl[] string "Symbol Table"
+ * FILE * tfp symbol table output file handle
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * int putc() c_library
+ * VOID slew() aslist.c
+ * int strcmp() c_library
+ * char * strcpy() c_library
+ *
+ * side effects:
+ * Symbol and area tables output.
+ */
+
+VOID
+lstsym(fp)
+FILE *fp;
+{
+ register int c, i, j, k;
+ register char *ptr;
+ int nmsym, narea;
+ struct sym *sp;
+ struct sym **p;
+ struct area *ap;
+
+ /*
+ * Symbol Table Header
+ */
+ strcpy(stb, &symtbl[0]);
+ lop = NLPP;
+ if (fp == tfp)
+ page = 0;
+ slew(fp, 1);
+
+ /*
+ * Find number of symbols
+ */
+ nmsym = 0;
+ for (i=0; i<NHASH; i++) {
+ sp = symhash[i];
+ while (sp) {
+ if (sp != &dot)
+ ++nmsym;
+ sp = sp->s_sp;
+ }
+ }
+ if (nmsym == 0)
+ goto atable;
+
+ /*
+ * Allocate space for an array of pointers to symbols
+ * and load array.
+ */
+ if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
+ == NULL) {
+ fprintf(fp, "Insufficient space to build Symbol Table.\n");
+ return;
+ }
+ nmsym = 0;
+ for (i=0; i<NHASH; i++) {
+ sp = symhash[i];
+ while (sp) {
+ if (sp != &dot)
+ p[nmsym++] = sp;
+ sp = sp->s_sp;
+ }
+ }
+
+#if 0
+ /* BUBBLE SORT?? WTF??? */
+ /*
+ * Bubble Sort on Symbol Table Array
+ */
+ j = 1;
+ c = nmsym - 1;
+ while (j) {
+ j = 0;
+ for (i=0; i<c; ++i) {
+ if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
+ j = 1;
+ sp = p[i+1];
+ p[i+1] = p[i];
+ p[i] = sp;
+ }
+ }
+ }
+#else
+
+ qsort(p, nmsym, sizeof(struct sym *), _cmpSym);
+#endif
+
+ /*
+ * Symbol Table Output
+ */
+ for (i=0; i<nmsym;) {
+ sp = p[i];
+ if (sp->s_area) {
+ j = sp->s_area->a_ref;
+ if (xflag == 0) {
+ fprintf(fp, " %2X ", j);
+ } else
+ if (xflag == 1) {
+ fprintf(fp, "%3o ", j);
+ } else
+ if (xflag == 2) {
+ fprintf(fp, "%3u ", j);
+ }
+ } else {
+ fprintf(fp, " ");
+ }
+ ptr = &sp->s_id[0];
+ fprintf(fp, "%-60s", ptr ); /* JLH */
+
+ if (sp->s_flag & S_ASG) {
+ putc('=', fp);
+ } else {
+ putc(' ', fp);
+ }
+ if (sp->s_type == S_NEW) {
+ if (xflag == 0) {
+ fprintf(fp, " **** ");
+ } else
+ if (xflag == 1) {
+ fprintf(fp, "****** ");
+ } else
+ if (xflag == 2) {
+ fprintf(fp, " ***** ");
+ }
+ } else {
+ j = sp->s_addr;
+ if (xflag == 0) {
+ fprintf(fp, " %04X ", j);
+ } else
+ if (xflag == 1) {
+ fprintf(fp, "%06o ", j);
+ } else
+ if (xflag == 2) {
+ fprintf(fp, " %05u ", j);
+ }
+ }
+ j = 0;
+ if (sp->s_flag & S_GBL) {
+ putc('G', fp);
+ ++j;
+ }
+ if (sp->s_area != NULL) {
+ putc('R', fp);
+ ++j;
+ }
+ if (sp->s_type == S_NEW) {
+ putc('X', fp);
+ ++j;
+ }
+#if NCPS-8
+ putc('\n', fp);
+ slew(fp, 0);
+ ++i;
+#else
+ if (++i % 3 == 0) {
+ putc('\n', fp);
+ slew(fp, pflag);
+ } else
+ if (i < nmsym) {
+ while (j++ < 4)
+ putc(' ', fp);
+ fprintf(fp, "| ");
+ }
+#endif
+ }
+ putc('\n', fp);
+
+ /*
+ * Area Table Header
+ */
+
+atable:
+ strcpy(stb, &aretbl[0]);
+ lop = NLPP;
+ slew(fp, 1);
+
+ /*
+ * Area Table Output
+ */
+ narea = 0;
+ ap = areap;
+ while (ap) {
+ ++narea;
+ ap = ap->a_ap;
+ }
+ for (i=0; i<narea; ++i) {
+ ap = areap;
+ for (j=i+1; j<narea; ++j)
+ ap = ap->a_ap;
+ j = ap->a_ref;
+ if (xflag == 0) {
+ fprintf(fp, " %2X ", j);
+ } else
+ if (xflag == 1) {
+ fprintf(fp, " %3o ", j);
+ } else
+ if (xflag == 2) {
+ fprintf(fp, " %3u ", j);
+ }
+ ptr = &ap->a_id[0];
+ while (ptr < &ap->a_id[NCPS]) {
+ if ((c = *ptr++) != 0) {
+ putc(c, fp);
+ } else {
+ putc(' ', fp);
+ }
+ }
+ j = ap->a_size;
+ k = ap->a_flag;
+ if (xflag==0) {
+ fprintf(fp, " size %4X flags %X\n", j, k);
+ } else
+ if (xflag==1) {
+ fprintf(fp, " size %6o flags %o\n", j, k);
+ } else
+ if (xflag==2) {
+ fprintf(fp, " size %5u flags %u\n", j, k);
+ }
+ }
+}
--- /dev/null
+/* asm.h */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - add proto for StoreString
+ * - change s_id from [NCPS] to pointer
+ * - change m_id from [NCPS] to pointer
+ * - change NCPS to 80
+ * - case sensitive
+ * - add R_J11 for 8051 assembler
+ * - add outr11 prototype for 8051 assembler
+ * - always define "ccase"
+ * 2-Nov-97 JLH:
+ * - add jflag for debug control
+ * - prototypes for DefineNoICE_Line
+ * 30-Jan-98 JLH:
+ * - add memory space flags to a_flag for 8051
+ *
+ * 3-Feb-00 KV:
+ * - add DS80C390 flat mode support.
+ */
+
+#define VERSION "V01.70 + NoICE + SDCC mods + Flat24 Feb-1999"
+
+#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#include <unistd.h>
+#endif
+
+/*
+ * Case Sensitivity Flag
+ */
+#define CASE_SENSITIVE 1
+
+/*)Module asm.h
+ *
+ * The module asm.h contains the definitions for constants,
+ * structures, global variables, and ASxxxx functions
+ * contained in the ASxxxx.c files. The two functions
+ * and three global variables from the machine dependent
+ * files are also defined.
+ */
+
+/*
+ * compiler/operating system specific definitions
+ */
+
+/* DECUS C void definition */
+/* File/extension seperator */
+
+#ifdef decus
+#define VOID char
+#define FSEPX '.'
+#endif
+
+/* PDOS C void definition */
+/* File/extension seperator */
+
+#ifdef PDOS
+#define VOID char
+#define FSEPX ':'
+#endif
+
+/* Default void definition */
+/* File/extension seperator */
+
+#ifndef VOID
+#define VOID void
+#define FSEPX '.'
+#define OTHERSYSTEM
+#endif
+
+/*
+ * PATH_MAX
+ */
+#include <limits.h>
+#ifndef PATH_MAX /* POSIX, but not required */
+#if defined(_MSC_VER) || defined(__BORLANDC__) /* Microsoft C or Borland C*/
+#include <stdlib.h>
+#define PATH_MAX _MAX_PATH
+#else
+#define PATH_MAX /* define a reasonable value */
+#endif
+#endif
+
+/*
+ * Assembler definitions.
+ */
+#define LFTERM '(' /* Left expression delimeter */
+#define RTTERM ')' /* Right expression delimeter */
+
+#define NCPS 80 /* Chars. per symbol (JLH: change from 8) */
+#define HUGE 1000 /* A huge number */
+#define NERR 3 /* Errors per line */
+#define NINPUT 1024 /* Input buffer size (icodes need space) */
+#define NCODE 128 /* Listing code buffer size */
+#define NTITL 64 /* Title buffer size */
+#define NSBTL 64 /* SubTitle buffer size */
+#define NHASH 64 /* Buckets in hash table */
+#define HMASK 077 /* Hash mask */
+#define NLPP 60 /* Lines per page */
+#define MAXFIL 6 /* Maximum command line input files */
+#define MAXINC 6 /* Maximum nesting of include files */
+#define MAXIF 10 /* Maximum nesting of if/else/endif */
+
+#define NLIST 0 /* No listing */
+#define SLIST 1 /* Source only */
+#define ALIST 2 /* Address only */
+#define BLIST 3 /* Address only with allocation */
+#define CLIST 4 /* Code */
+#define ELIST 5 /* Equate only */
+
+#define dot sym[0] /* Dot, current loc */
+#define dca area[0] /* Dca, default code area */
+
+
+/* NB: for Flat24 extentions to work, Addr_T must be at least 24
+ * bits. This is checked at runtime when the .flat24 directive
+ * is processed.
+ */
+typedef unsigned int Addr_T;
+
+/*
+ * The area structure contains the parameter values for a
+ * specific program or data section. The area structure
+ * is a linked list of areas. The initial default area
+ * is "_CODE" defined in asdata.c, the next area structure
+ * will be linked to this structure through the structure
+ * element 'struct area *a_ap'. The structure contains the
+ * area name, area reference number ("_CODE" is 0) determined
+ * by the order of .area directives, area size determined
+ * from the total code and/or data in an area, area fuzz is
+ * a variable used to track pass to pass changes in the
+ * area size caused by variable length instruction formats,
+ * and area flags which specify the area's relocation type.
+ */
+struct area
+{
+ struct area *a_ap; /* Area link */
+ char a_id[NCPS]; /* Area Name */
+ int a_ref; /* Ref. number */
+ Addr_T a_size; /* Area size */
+ Addr_T a_fuzz; /* Area fuzz */
+ int a_flag; /* Area flags */
+};
+
+/*
+ * The "A_" area constants define values used in
+ * generating the assembler area output data.
+ *
+ * Area flags
+ *
+ * 7 6 5 4 3 2 1 0
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | BIT |XDATA|DATA | PAG | ABS | OVR | | |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define A_CON 0000 /* Concatenating */
+#define A_OVR 0004 /* Overlaying */
+#define A_REL 0000 /* Relocatable */
+#define A_ABS 0010 /* absolute */
+#define A_NOPAG 0000 /* Non-Paged */
+#define A_PAG 0020 /* Paged */
+
+/* Additional flags for 8051 address spaces */
+#define A_DATA 0000 /* data space (default)*/
+#define A_CODE 0040 /* code space */
+#define A_XDATA 0100 /* external data space */
+#define A_BIT 0200 /* bit addressable space */
+
+/*
+ * The "R_" relocation constants define values used in
+ * generating the assembler relocation output data for
+ * areas, symbols, and code.
+ *
+ * Relocation flags
+ *
+ * 7 6 5 4 3 2 1 0
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define R_WORD 0x00 /* 16 bit */
+#define R_BYTE 0x01 /* 8 bit */
+
+#define R_AREA 0x00 /* Base type */
+#define R_SYM 0x02
+
+#define R_NORM 0x00 /* PC adjust */
+#define R_PCR 0x04
+
+#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */
+#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */
+
+#define R_SGND 0x00 /* Signed Byte */
+#define R_USGN 0x10 /* Unsigned Byte */
+
+#define R_NOPAG 0x00 /* Page Mode */
+#define R_PAG0 0x20 /* Page '0' */
+#define R_PAG 0x40 /* Page 'nnn' */
+
+#define R_LSB 0x00 /* low byte */
+#define R_MSB 0x80 /* high byte */
+
+#define R_BYT3 0x100 /* if R_BYTE is set, this is a
+ * 3 byte address, of which
+ * the linker must select one byte.
+ */
+#define R_HIB 0x200 /* If R_BYTE & R_BYT3 are set, linker
+ * will select byte 3 of the relocated
+ * 24 bit address.
+ */
+
+#define R_J11 (R_WORD|R_BYT2) /* JLH: 11 bit JMP and CALL (8051) */
+#define R_J19 (R_WORD|R_BYT2|R_MSB) /* 19 bit JMP/CALL (DS80C390) */
+#define R_C24 (R_WORD|R_BYT1|R_MSB) /* 24 bit address (DS80C390) */
+#define R_J19_MASK (R_BYTE|R_BYT2|R_MSB)
+
+#define IS_R_J19(x) (((x) & R_J19_MASK) == R_J19)
+#define IS_R_J11(x) (((x) & R_J19_MASK) == R_J11)
+#define IS_C24(x) (((x) & R_J19_MASK) == R_C24)
+
+#define R_ESCAPE_MASK 0xf0 /* Used to escape relocation modes
+ * greater than 0xff in the .rel
+ * file.
+ */
+
+/*
+ * Listing Control Flags
+ */
+
+#define R_HIGH 0040000 /* High Byte */
+#define R_RELOC 0100000 /* Relocation */
+
+#define R_DEF 00 /* Global def. */
+#define R_REF 01 /* Global ref. */
+#define R_REL 00 /* Relocatable */
+#define R_ABS 02 /* Absolute */
+#define R_GBL 00 /* Global */
+#define R_LCL 04 /* Local */
+
+/*
+ * The mne structure is a linked list of the assembler
+ * mnemonics and directives. The list of mnemonics and
+ * directives contained in the device dependent file
+ * xxxpst.c are hashed and linked into NHASH lists in
+ * module assym.c by syminit(). The structure contains
+ * the mnemonic/directive name, a subtype which directs
+ * the evaluation of this mnemonic/directive, a flag which
+ * is used to detect the end of the mnemonic/directive
+ * list in xxxpst.c, and a value which is normally
+ * associated with the assembler mnemonic base instruction
+ * value.
+ */
+struct mne
+{
+ struct mne *m_mp; /* Hash link */
+ char *m_id; /* Mnemonic JLH: change from [NCPS] */
+ char m_type; /* Mnemonic subtype */
+ char m_flag; /* Mnemonic flags */
+ Addr_T m_valu; /* Value */
+};
+
+/*
+ * The sym structure is a linked list of symbols defined
+ * in the assembler source files. The first symbol is "."
+ * defined in asdata.c. The entry 'struct tsym *s_tsym'
+ * links any temporary symbols following this symbol and
+ * preceeding the next normal symbol. The structure also
+ * contains the symbol's name, type (USER or NEW), flag
+ * (global, assigned, and multiply defined), a pointer
+ * to the area structure defining where the symbol is
+ * located, a reference number assigned by outgsd() in
+ * asout.c, and the symbols address relative to the base
+ * address of the area where the symbol is located.
+ */
+struct sym
+{
+ struct sym *s_sp; /* Hash link */
+ struct tsym *s_tsym; /* Temporary symbol link */
+ char *s_id; /* Symbol: JLH change from [NCPS] */
+ char s_type; /* Symbol subtype */
+ char s_flag; /* Symbol flags */
+ struct area *s_area; /* Area line, 0 if absolute */
+ int s_ref; /* Ref. number */
+ Addr_T s_addr; /* Address */
+};
+
+#define S_GBL 01 /* Global */
+#define S_ASG 02 /* Assigned */
+#define S_MDF 04 /* Mult. def */
+#define S_END 010 /* End mark for pst. */
+
+#define S_NEW 0 /* New name */
+#define S_USER 1 /* User name */
+ /* unused slot */
+ /* unused slot */
+ /* unused slot */
+
+#define S_BYTE 5 /* .byte */
+#define S_WORD 6 /* .word */
+#define S_ASCII 7 /* .ascii */
+#define S_ASCIZ 8 /* .asciz */
+#define S_BLK 9 /* .blkb or .blkw */
+#define S_INCL 10 /* .include */
+#define S_DAREA 11 /* .area */
+#define S_ATYP 12 /* .area type */
+#define S_AREA 13 /* .area name */
+#define S_GLOBL 14 /* .globl */
+#define S_PAGE 15 /* .page */
+#define S_TITLE 16 /* .title */
+#define S_SBTL 17 /* .sbttl */
+#define S_IF 18 /* .if */
+#define S_ELSE 19 /* .else */
+#define S_ENDIF 20 /* .endif */
+#define S_EVEN 21 /* .even */
+#define S_ODD 22 /* .odd */
+#define S_RADIX 23 /* .radix */
+#define S_ORG 24 /* .org */
+#define S_MODUL 25 /* .module */
+#define S_ASCIS 26 /* .ascis */
+#define S_FLAT24 27 /* .flat24 */
+#define S_OPTSDCC 28 /* .optsdcc */
+
+
+/*
+ * The tsym structure is a linked list of temporary
+ * symbols defined in the assembler source files following
+ * a normal symbol. The structure contains the temporary
+ * symbols number, a flag (multiply defined), a pointer to the
+ * area structure defining where the temporary structure
+ * is located, and the temporary symbol's address relative
+ * to the base address of the area where the symbol
+ * is located.
+ */
+struct tsym
+{
+ struct tsym *t_lnk; /* Link to next */
+/* sandeep changed to 'int' from 'char' */
+/* this will increase the number temp symbols
+ that can be defined from 255 to INT_MAX */
+ int t_num; /* 0-INT_MAX$ */
+ int t_flg; /* flags */
+
+ struct area *t_area; /* Area */
+ Addr_T t_addr; /* Address */
+};
+
+/*
+ * External Definitions for all Global Variables
+ */
+
+extern int aserr; /* ASxxxx error counter
+ */
+extern jmp_buf jump_env; /* compiler dependent structure
+ * used by setjmp() and longjmp()
+ */
+extern int inpfil; /* count of assembler
+ * input files specified
+ */
+extern int incfil; /* current file handle index
+ * for include files
+ */
+extern int cfile; /* current file handle index
+ * of input assembly files
+ */
+extern int flevel; /* IF-ELSE-ENDIF flag will be non
+ * zero for false conditional case
+ */
+extern int tlevel; /* current conditional level
+ */
+extern int ifcnd[MAXIF+1]; /* array of IF statement condition
+ * values (0 = FALSE) indexed by tlevel
+ */
+extern int iflvl[MAXIF+1]; /* array of IF-ELSE-ENDIF flevel
+ * values indexed by tlevel
+ */
+extern char
+ afn[PATH_MAX]; /* afile() temporary filespec
+ */
+extern char
+ srcfn[MAXFIL][PATH_MAX]; /* array of source file names
+ */
+extern int
+ srcline[MAXFIL]; /* current source file line
+ */
+extern char
+ incfn[MAXINC][PATH_MAX]; /* array of include file names
+ */
+extern int
+ incline[MAXINC]; /* current include file line
+ */
+extern int radix; /* current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ */
+extern int line; /* current assembler source
+ * line number
+ */
+extern int page; /* current page number
+ */
+extern int lop; /* current line number on page
+ */
+extern int pass; /* assembler pass number
+ */
+extern int lflag; /* -l, generate listing flag
+ */
+extern int cflag; /* -c, generate sdcdb debug information
+ */
+extern int gflag; /* -g, make undefined symbols global flag
+ */
+extern int aflag; /* -a, make all symbols global flag
+ */
+extern int jflag; /* -j, generate debug information flag
+ */
+extern int oflag; /* -o, generate relocatable output flag
+ */
+extern int sflag; /* -s, generate symbol table flag
+ */
+extern int pflag; /* -p, enable listing pagination
+ */
+extern int xflag; /* -x, listing radix flag
+ */
+extern int fflag; /* -f(f), relocations flagged flag
+ */
+extern Addr_T laddr; /* address of current assembler line
+ * or value of .if argument
+ */
+extern Addr_T fuzz; /* tracks pass to pass changes in the
+ * address of symbols caused by
+ * variable length instruction formats
+ */
+extern int lmode; /* listing mode
+ */
+extern struct area area[]; /* array of 1 area
+ */
+extern struct area *areap; /* pointer to an area structure
+ */
+extern struct sym sym[]; /* array of 1 symbol
+ */
+extern struct sym *symp; /* pointer to a symbol structure
+ */
+extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
+ * linked symbol lists
+ */
+extern struct mne *mnehash[NHASH]; /* array of pointers to NHASH
+ * linked mnemonic/directive lists
+ */
+extern char *ep; /* pointer into error list
+ * array eb[NERR]
+ */
+extern char eb[NERR]; /* array of generated error codes
+ */
+extern char *ip; /* pointer into the assembler-source
+ * text line in ib[]
+ */
+extern char ib[NINPUT]; /* assembler-source text line
+ */
+extern char *cp; /* pointer to assembler output
+ * array cb[]
+ */
+extern char cb[NCODE]; /* array of assembler output values
+ */
+extern int *cpt; /* pointer to assembler relocation type
+ * output array cbt[]
+ */
+extern int cbt[NCODE]; /* array of assembler relocation types
+ * describing the data in cb[]
+ */
+extern char tb[NTITL]; /* Title string buffer
+ */
+extern char stb[NSBTL]; /* Subtitle string buffer
+ */
+extern char optsdcc[NINPUT]; /* sdcc compile options
+ */
+extern int flat24Mode; /* non-zero if we are using DS390 24 bit
+ * flat mode (via .flat24 directive).
+ */
+extern char symtbl[]; /* string "Symbol Table"
+ */
+extern char aretbl[]; /* string "Area Table"
+ */
+extern char module[NCPS]; /* module name string
+ */
+extern FILE *lfp; /* list output file handle
+ */
+extern FILE *ofp; /* relocation output file handle
+ */
+extern FILE *tfp; /* symbol table output file handle
+ */
+extern FILE *sfp[MAXFIL]; /* array of assembler-source file handles
+ */
+extern FILE *ifp[MAXINC]; /* array of include-file file handles
+ */
+extern unsigned char ctype[128]; /* array of character types, one per
+ * ASCII character
+ */
+
+extern char ccase[128]; /* an array of characters which
+ * perform the case translation function
+ */
+/*
+ * Definitions for Character Types
+ */
+#define SPACE 0000
+#define ETC 0000
+#define LETTER 0001
+#define DIGIT 0002
+#define BINOP 0004
+#define RAD2 0010
+#define RAD8 0020
+#define RAD10 0040
+#define RAD16 0100
+#define ILL 0200
+
+#define DGT2 DIGIT|RAD16|RAD10|RAD8|RAD2
+#define DGT8 DIGIT|RAD16|RAD10|RAD8
+#define DGT10 DIGIT|RAD16|RAD10
+#define LTR16 LETTER|RAD16
+
+/*
+ * The exp structure is used to return the evaluation
+ * of an expression. The structure supports three valid
+ * cases:
+ * (1) The expression evaluates to a constant,
+ * mode = S_USER, flag = 0, addr contains the
+ * constant, and base = NULL.
+ * (2) The expression evaluates to a defined symbol
+ * plus or minus a constant, mode = S_USER,
+ * flag = 0, addr contains the constant, and
+ * base = pointer to area symbol.
+ * (3) The expression evaluates to a external
+ * global symbol plus or minus a constant,
+ * mode = S_NEW, flag = 1, addr contains the
+ * constant, and base = pointer to symbol.
+ */
+struct expr
+{
+ char e_mode; /* Address mode */
+ char e_flag; /* Symbol flag */
+ Addr_T e_addr; /* Address */
+ union {
+ struct area *e_ap;
+ struct sym *e_sp;
+ } e_base; /* Rel. base */
+ int e_rlcf; /* Rel. flags */
+};
+
+/* C Library functions */
+/* for reference only
+extern VOID exit();
+extern int fclose();
+extern char * fgets();
+extern FILE * fopen();
+extern int fprintf();
+extern VOID longjmp();
+extern VOID * malloc();
+extern int printf();
+extern char putc();
+extern int rewind();
+extern int setjmp();
+extern int strcmp();
+extern char * strcpy();
+extern int strlen();
+extern char * strncpy();
+*/
+
+/* Machine independent functions */
+
+/* asmain.c */
+extern FILE * afile();
+extern VOID asexit();
+extern VOID asmbl();
+extern int main();
+extern VOID newdot();
+extern VOID phase();
+extern VOID usage();
+
+/* aslex.c */
+extern char endline();
+extern char get();
+extern VOID getid();
+extern int getline();
+extern int getmap();
+extern char getnb();
+extern VOID getst();
+extern int more();
+extern VOID unget();
+extern VOID chop_crlf();
+
+/* assym.c */
+extern struct area * alookup();
+extern struct mne * mlookup();
+extern int hash();
+extern struct sym * lookup();
+extern VOID * new();
+extern int symeq();
+extern VOID syminit();
+extern VOID symglob();
+extern VOID allglob();
+
+/* assubr.c */
+extern VOID aerr();
+extern VOID diag();
+extern VOID err();
+extern VOID warnBanner(void);
+extern char * geterr();
+extern VOID qerr();
+extern VOID rerr();
+
+/* asexpr.c */
+extern VOID abscheck();
+extern Addr_T absexpr();
+extern VOID clrexpr();
+extern int digit();
+extern int is_abs();
+extern VOID expr();
+extern int oprio();
+extern VOID term();
+
+/* aslist.c */
+extern VOID list();
+extern VOID list1();
+extern VOID list2();
+extern VOID lstsym();
+extern VOID slew();
+
+/* asout.c */
+extern int hibyte();
+extern int lobyte();
+extern int byte3(int);
+extern VOID out();
+extern VOID outab();
+extern VOID outarea();
+extern VOID outaw();
+extern VOID outall();
+extern VOID outdot();
+extern VOID outbuf();
+extern VOID outchk();
+extern VOID outgsd();
+extern VOID outrb();
+extern VOID outrw(struct expr *, int);
+extern VOID outr24(struct expr *, int);
+extern VOID outsym();
+extern VOID out_lb();
+extern VOID out_lw();
+extern VOID out_l24(int, int);
+extern VOID out_rw();
+extern VOID out_tw();
+extern VOID out_t24(int);
+extern VOID outr11(); /* JLH */
+extern VOID outr19(struct expr *, int, int);
+
+/* asstore.c */
+extern char *StoreString( char *str );
+
+/* asnoice.c */
+extern void DefineNoICE_Line();
+extern void DefineCDB_Line();
+
+/* Machine dependent variables */
+
+extern char * cpu;
+extern char * dsft;
+extern int hilo;
+extern struct mne mne[];
+
+/* Machine dependent functions */
+
+extern VOID minit();
+extern VOID machine(struct mne *);
--- /dev/null
+/* asmain.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 29-Oct-97 JLH pass ";!" comments to output file
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+
+#include "asm.h"
+#include "strcmpi.h"
+
+/*)Module asmain.c
+ *
+ * The module asmain.c includes the command argument parser,
+ * the three pass sequencer, and the machine independent
+ * assembler parsing code.
+ *
+ * asmain.c contains the following functions:
+ * VOID main(argc, argv)
+ * VOID asexit()
+ * VOID asmbl()
+ * FILE * afile(fn, ft, wf)
+ * VOID newdot(nap)
+ * VOID phase(ap, a)
+ * VOID usage()
+ *
+ * asmain.c contains the array char *usetxt[] which
+ * references the usage text strings printed by usage().
+ */
+
+/*)Function VOID main(argc, argv)
+ *
+ * int argc argument count
+ * char * argv array of pointers to argument strings
+ *
+ * The function main() is the entry point to the assembler.
+ * The purpose of main() is to (1) parse the command line
+ * arguments for options and source file specifications and
+ * (2) to process the source files through the 3 pass assembler.
+ * Before each assembler pass various variables are initialized
+ * and source files are rewound to their beginning. During each
+ * assembler pass each assembler-source text line is processed.
+ * After each assembler pass the assembler information is flushed
+ * to any opened output files and the if-else-endif processing
+ * is checked for proper termination.
+ *
+ * The function main() is also responsible for opening all
+ * output files (REL, LST, and SYM), sequencing the global (-g)
+ * and all-global (-a) variable definitions, and dumping the
+ * REL file header information.
+ *
+ * local variables:
+ * char * p pointer to argument string
+ * int c character from argument string
+ * int i argument loop counter
+ * area * ap pointer to area structure
+ *
+ * global variables:
+ * int aflag -a, make all symbols global flag
+ * char afn[] afile() constructed filespec
+ * area * areap pointer to an area structure
+ * int cb[] array of assembler output values
+ * int cbt[] array of assembler relocation types
+ * describing the data in cb[]
+ * int cfile current file handle index
+ * of input assembly files
+ * int * cp pointer to assembler output array cb[]
+ * int * cpt pointer to assembler relocation type
+ * output array cbt[]
+ * char eb[] array of generated error codes
+ * char * ep pointer into error list array eb[]
+ * int fflag -f(f), relocations flagged flag
+ * int flevel IF-ELSE-ENDIF flag will be non
+ * zero for false conditional case
+ * Addr_T fuzz tracks pass to pass changes in the
+ * address of symbols caused by
+ * variable length instruction formats
+ * int gflag -g, make undefined symbols global flag
+ * char ib[] assembler-source text line
+ * int inpfil count of assembler
+ * input files specified
+ * int ifcnd[] array of IF statement condition
+ * values (0 = FALSE) indexed by tlevel
+ * int iflvl[] array of IF-ELSE-ENDIF flevel
+ * values indexed by tlevel
+ * int incfil current file handle index
+ * for include files
+ * char * ip pointer into the assembler-source
+ * text line in ib[]
+ * jmp_buf jump_env compiler dependent structure
+ * used by setjmp() and longjmp()
+ * int lflag -l, generate listing flag
+ * int line current assembler source
+ * line number
+ * int lop current line number on page
+ * int oflag -o, generate relocatable output flag
+ * int jflag -j, generate debug info flag
+ * int page current page number
+ * int pflag enable listing pagination
+ * int pass assembler pass number
+ * int radix current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ * int sflag -s, generate symbol table flag
+ * char srcfn[][] array of source file names
+ * int srcline[] current source file line
+ * char stb[] Subtitle string buffer
+ * sym * symp pointer to a symbol structure
+ * int tlevel current conditional level
+ * int xflag -x, listing radix flag
+ * FILE * lfp list output file handle
+ * FILE * ofp relocation output file handle
+ * FILE * tfp symbol table output file handle
+ * FILE * sfp[] array of assembler-source file handles
+ *
+ * called functions:
+ * FILE * afile() asmain.c
+ * VOID allglob() assym.c
+ * VOID asexit() asmain.c
+ * VOID diag() assubr.c
+ * VOID err() assubr.c
+ * int fprintf() c-library
+ * int getline() aslex.c
+ * VOID list() aslist.c
+ * VOID lstsym() aslist.c
+ * VOID minit() ___mch.c
+ * VOID newdot() asmain.c
+ * VOID outchk() asout.c
+ * VOID outgsd() asout.c
+ * int rewind() c-library
+ * int setjmp() c-library
+ * VOID symglob() assym.c
+ * VOID syminit() assym.c
+ * VOID usage() asmain.c
+ *
+ * side effects:
+ * Completion of main() completes the assembly process.
+ * REL, LST, and/or SYM files may be generated.
+ */
+
+int fatalErrors=0;
+char relFile[128];
+
+int
+main(argc, argv)
+char *argv[];
+{
+ register char *p;
+ register int c, i;
+ struct area *ap;
+
+ /*fprintf(stdout, "\n");*/
+ inpfil = -1;
+ pflag = 1;
+ for (i=1; i<argc; ++i) {
+ p = argv[i];
+ if (*p == '-') {
+ if (inpfil >= 0)
+ usage();
+ ++p;
+ while ((c = *p++) != 0)
+ switch(c) {
+
+ case 'a':
+ case 'A':
+ ++aflag;
+ break;
+
+ case 'c':
+ case 'C':
+ ++cflag;
+ break;
+
+ case 'g':
+ case 'G':
+ ++gflag;
+ break;
+
+ case 'j': /* JLH: debug info */
+ case 'J':
+ ++jflag;
+ ++oflag; /* force object */
+ break;
+
+ case 'l':
+ case 'L':
+ ++lflag;
+ break;
+
+ case 'o':
+ case 'O':
+ ++oflag;
+ break;
+
+ case 's':
+ case 'S':
+ ++sflag;
+ break;
+
+ case 'p':
+ case 'P':
+ pflag = 0;
+ break;
+
+ case 'x':
+ case 'X':
+ xflag = 0;
+ break;
+
+ case 'q':
+ case 'Q':
+ xflag = 1;
+ break;
+
+ case 'd':
+ case 'D':
+ xflag = 2;
+ break;
+
+ case 'f':
+ case 'F':
+ ++fflag;
+ break;
+
+ default:
+ usage();
+ }
+ } else {
+ if (++inpfil == MAXFIL) {
+ fprintf(stderr, "too many input files\n");
+ asexit(1);
+ }
+ sfp[inpfil] = afile(p, "", 0);
+ strcpy(srcfn[inpfil],afn);
+ if (inpfil == 0) {
+ if (lflag)
+ lfp = afile(p, "lst", 1);
+ if (oflag) {
+ ofp = afile(p, "rel", 1);
+ // save the file name if we have to delete it on error
+ strcpy(relFile,afn);
+ }
+ if (sflag)
+ tfp = afile(p, "sym", 1);
+ }
+ }
+ }
+ if (inpfil < 0)
+ usage();
+ syminit();
+ for (pass=0; pass<3; ++pass) {
+ if (gflag && pass == 1)
+ symglob();
+ if (aflag && pass == 1)
+ allglob();
+ if (oflag && pass == 2)
+ outgsd();
+ flevel = 0;
+ tlevel = 0;
+ ifcnd[0] = 0;
+ iflvl[0] = 0;
+ radix = 10;
+ srcline[0] = 0;
+ page = 0;
+ stb[0] = 0;
+ lop = NLPP;
+ cfile = 0;
+ incfil = -1;
+ for (i = 0; i <= inpfil; i++)
+ rewind(sfp[i]);
+ ap = areap;
+ while (ap) {
+ ap->a_fuzz = 0;
+ ap->a_size = 0;
+ ap = ap->a_ap;
+ }
+ fuzz = 0;
+ dot.s_addr = 0;
+ dot.s_area = &dca;
+ symp = ˙
+ minit();
+ while (getline()) {
+ cp = cb;
+ cpt = cbt;
+ ep = eb;
+ ip = ib;
+
+ /* JLH: if line begins with ";!", then
+ * pass this comment on to the output file
+ */
+ if (oflag && (pass == 1) &&
+ (ip[0] == ';') && (ip[1] == '!'))
+ {
+ fprintf(ofp, "%s\n", ip );
+ }
+
+ if (setjmp(jump_env) == 0)
+ asmbl();
+
+ if (pass == 2) {
+ diag();
+ list();
+ }
+ }
+ newdot(dot.s_area); /* Flush area info */
+ if (flevel || tlevel)
+ err('i');
+ }
+ if (oflag)
+ outchk(HUGE, HUGE); /* Flush */
+ if (sflag) {
+ lstsym(tfp);
+ } else
+ if (lflag) {
+ lstsym(lfp);
+ }
+ //printf ("aserr: %d\n", aserr);
+ //printf ("fatalErrors: %d\n", fatalErrors);
+ asexit(fatalErrors);
+ return 0; // hush the compiler
+}
+
+/*)Function VOID asexit(i)
+ *
+ * int i exit code
+ *
+ * The function asexit() explicitly closes all open
+ * files and then terminates the program.
+ *
+ * local variables:
+ * int j loop counter
+ *
+ * global variables:
+ * FILE * ifp[] array of include-file file handles
+ * FILE * lfp list output file handle
+ * FILE * ofp relocation output file handle
+ * FILE * tfp symbol table output file handle
+ * FILE * sfp[] array of assembler-source file handles
+ *
+ * functions called:
+ * int fclose() c-library
+ * VOID exit() c-library
+ *
+ * side effects:
+ * All files closed. Program terminates.
+ */
+
+VOID
+asexit(i)
+int i;
+{
+ int j;
+
+ if (lfp != NULL) fclose(lfp);
+ if (ofp != NULL) fclose(ofp);
+ if (tfp != NULL) fclose(tfp);
+
+ for (j=0; j<MAXFIL && sfp[j] != NULL; j++) {
+ fclose(sfp[j]);
+ }
+
+ /*for (j=0; j<MAXINC && ifp[j] != NULL; j++) {
+ fclose(ifp[j]);
+ }*/
+ if (i) {
+ // remove output file
+ printf ("removing %s\n", relFile);
+ unlink(relFile);
+ }
+ exit(i);
+}
+
+/*)Function VOID asmbl()
+ *
+ * The function asmbl() scans the assembler-source text for
+ * (1) labels, global labels, equates, global equates, and local
+ * symbols, (2) .if, .else, .endif, and .page directives,
+ * (3) machine independent assembler directives, and (4) machine
+ * dependent mnemonics.
+ *
+ * local variables:
+ * mne * mp pointer to a mne structure
+ * sym * sp pointer to a sym structure
+ * tsym * tp pointer to a tsym structure
+ * int c character from assembler-source
+ * text line
+ * area * ap pointer to an area structure
+ * expr e1 expression structure
+ * char id[] id string
+ * char opt[] options string
+ * char fn[] filename string
+ * char * p pointer into a string
+ * int d temporary value
+ * int n temporary value
+ * int uaf user area options flag
+ * int uf area options
+ *
+ * global variables:
+ * area * areap pointer to an area structure
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * int flevel IF-ELSE-ENDIF flag will be non
+ * zero for false conditional case
+ * Addr_T fuzz tracks pass to pass changes in the
+ * address of symbols caused by
+ * variable length instruction formats
+ * int ifcnd[] array of IF statement condition
+ * values (0 = FALSE) indexed by tlevel
+ * int iflvl[] array of IF-ELSE-ENDIF flevel
+ * values indexed by tlevel
+ * FILE * ifp[] array of include-file file handles
+ * char incfn[][] array of include file names
+ * int incline[] current include file line
+ * int incfil current file handle index
+ * for include files
+ * Addr_T laddr address of current assembler line
+ * or value of .if argument
+ * int lmode listing mode
+ * int lop current line number on page
+ * char module[] module name string
+ * int pass assembler pass number
+ * int radix current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ * char stb[] Subtitle string buffer
+ * sym * symp pointer to a symbol structure
+ * char tb[] Title string buffer
+ * int tlevel current conditional level
+ *
+ * functions called:
+ * Addr_T absexpr() asexpr.c
+ * area * alookup() assym.c
+ * VOID clrexpr() asexpr.c
+ * int digit() asexpr.c
+ * char endline() aslex.c
+ * VOID err() assubr.c
+ * VOID expr() asexpr.c
+ * FILE * fopen() c-library
+ * char get() aslex.c
+ * VOID getid() aslex.c
+ * int getmap() aslex.c
+ * char getnb() aslex.c
+ * VOID getst() aslex.c
+ * sym * lookup() assym.c
+ * VOID machine() ___mch.c
+ * mne * mlookup() assym.c
+ * int more() aslex.c
+ * VOID * new() assym.c
+ * VOID newdot() asmain.c
+ * VOID outall() asout.c
+ * VOID outab() asout.c
+ * VOID outchk() asout.c
+ * VOID outrb() asout.c
+ * VOID outrw() asout.c
+ * VOID phase() asmain.c
+ * VOID qerr() assubr.c
+ * char * strcpy() c-library
+ * char * strncpy() c-library
+ * VOID unget() aslex.c
+ */
+
+VOID
+asmbl()
+{
+ register struct mne *mp;
+ register struct sym *sp;
+ register struct tsym *tp;
+ register int c;
+ struct area *ap;
+ struct expr e1;
+ char id[NCPS];
+ char opt[NCPS];
+ char fn[PATH_MAX];
+ char *p;
+ int d, n, uaf, uf;
+
+ laddr = dot.s_addr;
+ lmode = SLIST;
+loop:
+ if ((c=endline()) == 0) { return; }
+ /*
+ * If the first character is a digit then assume
+ * a local symbol is being specified. The symbol
+ * must end with $: to be valid.
+ * pass 0:
+ * Construct a tsym structure at the first
+ * occurance of the symbol. Flag the symbol
+ * as multiply defined if not the first occurance.
+ * pass 1:
+ * Load area, address, and fuzz values
+ * into structure tsym.
+ * pass 2:
+ * Check for assembler phase error and
+ * multiply defined error.
+ */
+ if (ctype[c] & DIGIT) {
+ if (flevel)
+ return;
+ n = 0;
+ while ((d = digit(c, 10)) >= 0) {
+ n = 10*n + d;
+ c = get();
+ }
+ if (c != '$' || get() != ':')
+ qerr();
+ tp = symp->s_tsym;
+ if (pass == 0) {
+ while (tp) {
+ if (n == tp->t_num) {
+ tp->t_flg |= S_MDF;
+ break;
+ }
+ tp = tp->t_lnk;
+ }
+ if (tp == NULL) {
+ tp=(struct tsym *) new (sizeof(struct tsym));
+ tp->t_lnk = symp->s_tsym;
+ tp->t_num = n;
+ tp->t_flg = 0;
+ tp->t_area = dot.s_area;
+ tp->t_addr = dot.s_addr;
+ symp->s_tsym = tp;
+ }
+ } else {
+ while (tp) {
+ if (n == tp->t_num) {
+ break;
+ }
+ tp = tp->t_lnk;
+ }
+ if (tp) {
+ if (pass == 1) {
+ fuzz = tp->t_addr - dot.s_addr;
+ tp->t_area = dot.s_area;
+ tp->t_addr = dot.s_addr;
+ } else {
+ phase(tp->t_area, tp->t_addr);
+ if (tp->t_flg & S_MDF)
+ err('m');
+ }
+ } else {
+ err('u');
+ }
+ }
+ lmode = ALIST;
+ goto loop;
+ }
+ /*
+ * If the first character is a letter then assume a lable,
+ * symbol, assembler directive, or assembler mnemonic is
+ * being processed.
+ */
+ if ((ctype[c] & LETTER) == 0) {
+ if (flevel) {
+ return;
+ } else {
+ qerr();
+ }
+ }
+ getid(id, c);
+ c = getnb();
+ /*
+ * If the next character is a : then a label is being processed.
+ * A double :: defines a global label. If this is new label
+ * then create a symbol structure.
+ * pass 0:
+ * Flag multiply defined labels.
+ * pass 1:
+ * Load area, address, and fuzz values
+ * into structure symp.
+ * pass 2:
+ * Check for assembler phase error and
+ * multiply defined error.
+ */
+ if (c == ':') {
+ if (flevel)
+ return;
+ if ((c = get()) != ':') {
+ unget(c);
+ c = 0;
+ }
+ symp = lookup(id);
+ if (symp == &dot)
+ err('.');
+ if (pass == 0)
+ if ((symp->s_type != S_NEW) &&
+ ((symp->s_flag & S_ASG) == 0))
+ symp->s_flag |= S_MDF;
+ if (pass != 2) {
+ fuzz = symp->s_addr - dot.s_addr;
+ symp->s_type = S_USER;
+ symp->s_area = dot.s_area;
+ symp->s_addr = dot.s_addr;
+ } else {
+ if (symp->s_flag & S_MDF)
+ err('m');
+ phase(symp->s_area, symp->s_addr);
+ }
+ if (c) {
+ symp->s_flag |= S_GBL;
+ }
+ lmode = ALIST;
+ goto loop;
+ }
+ /*
+ * If the next character is a = then an equate is being processed.
+ * A double == defines a global equate. If this is new variable
+ * then create a symbol structure.
+ */
+ if (c == '=') {
+ if (flevel)
+ return;
+ if ((c = get()) != '=') {
+ unget(c);
+ c = 0;
+ }
+ clrexpr(&e1);
+ expr(&e1, 0);
+ sp = lookup(id);
+ if (sp == &dot) {
+ outall();
+ if (e1.e_flag || e1.e_base.e_ap != dot.s_area)
+ err('.');
+ } else
+ if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) {
+ err('m');
+ }
+ sp->s_type = S_USER;
+ sp->s_area = e1.e_base.e_ap;
+ sp->s_addr = laddr = e1.e_addr;
+ sp->s_flag |= S_ASG;
+ if (c) {
+ sp->s_flag |= S_GBL;
+ }
+ lmode = ELIST;
+ goto loop;
+ }
+ unget(c);
+ lmode = flevel ? SLIST : CLIST;
+ if ((mp = mlookup(id)) == NULL) {
+ if (!flevel)
+ err('o');
+ return;
+ }
+ /*
+ * If we have gotten this far then we have found an
+ * assembler directive or an assembler mnemonic.
+ *
+ * Check for .if, .else, .endif, and .page directives
+ * which are not controlled by the conditional flags
+ */
+ switch (mp->m_type) {
+
+ case S_IF:
+ n = absexpr();
+ if (tlevel < MAXIF) {
+ ++tlevel;
+ ifcnd[tlevel] = n;
+ iflvl[tlevel] = flevel;
+ if (n == 0) {
+ ++flevel;
+ }
+ } else {
+ err('i');
+ }
+ lmode = ELIST;
+ laddr = n;
+ return;
+
+ case S_ELSE:
+ if (ifcnd[tlevel]) {
+ if (++flevel > (iflvl[tlevel]+1)) {
+ err('i');
+ }
+ } else {
+ if (--flevel < iflvl[tlevel]) {
+ err('i');
+ }
+ }
+ lmode = SLIST;
+ return;
+
+ case S_ENDIF:
+ if (tlevel) {
+ flevel = iflvl[tlevel--];
+ } else {
+ err('i');
+ }
+ lmode = SLIST;
+ return;
+
+ case S_PAGE:
+ lop = NLPP;
+ lmode = NLIST;
+ return;
+
+ default:
+ break;
+ }
+ if (flevel)
+ return;
+ /*
+ * If we are not in a false state for .if/.else then
+ * process the assembler directives here.
+ */
+ switch (mp->m_type) {
+
+ case S_EVEN:
+ outall();
+ laddr = dot.s_addr = (dot.s_addr + 1) & ~1;
+ lmode = ALIST;
+ break;
+
+ case S_ODD:
+ outall();
+ laddr = dot.s_addr |= 1;
+ lmode = ALIST;
+ break;
+
+ case S_BYTE:
+ case S_WORD:
+ do {
+ clrexpr(&e1);
+ expr(&e1, 0);
+ if (mp->m_type == S_BYTE) {
+ outrb(&e1, R_NORM);
+ } else {
+ outrw(&e1, R_NORM);
+ }
+ } while ((c = getnb()) == ',');
+ unget(c);
+ break;
+
+ case S_ASCII:
+ case S_ASCIZ:
+ if ((d = getnb()) == '\0')
+ qerr();
+ while ((c = getmap(d)) >= 0)
+ outab(c);
+ if (mp->m_type == S_ASCIZ)
+ outab(0);
+ break;
+
+ case S_ASCIS:
+ if ((d = getnb()) == '\0')
+ qerr();
+ c = getmap(d);
+ while (c >= 0) {
+ if ((n = getmap(d)) >= 0) {
+ outab(c);
+ } else {
+ outab(c | 0x80);
+ }
+ c = n;
+ }
+ break;
+
+ case S_BLK:
+ clrexpr(&e1);
+ expr(&e1, 0);
+ outchk(HUGE,HUGE);
+ dot.s_addr += e1.e_addr*mp->m_valu;
+ lmode = BLIST;
+ break;
+
+ case S_TITLE:
+ p = tb;
+ if ((c = getnb()) != 0) {
+ do {
+ if (p < &tb[NTITL-1])
+ *p++ = c;
+ } while ((c = get()) != 0);
+ }
+ *p = 0;
+ unget(c);
+ lmode = SLIST;
+ break;
+
+ case S_SBTL:
+ p = stb;
+ if ((c = getnb()) != 0) {
+ do {
+ if (p < &stb[NSBTL-1])
+ *p++ = c;
+ } while ((c = get()) != 0);
+ }
+ *p = 0;
+ unget(c);
+ lmode = SLIST;
+ break;
+
+ case S_MODUL:
+ getst(id, getnb()); // a module can start with a digit
+ if (pass == 0) {
+ if (module[0]) {
+ err('m');
+ } else {
+ strncpy(module, id, NCPS);
+ }
+ }
+ lmode = SLIST;
+ break;
+
+ case S_OPTSDCC:
+ p = optsdcc;
+ if ((c = getnb()) != 0) {
+ do {
+ if (p < &optsdcc[NINPUT-1])
+ *p++ = c;
+ } while ((c = get()) != 0);
+ }
+ *p = 0;
+ unget(c);
+ lmode = SLIST;
+ /*if (pass == 0) printf("optsdcc=%s\n", optsdcc);*/
+ break;
+
+ case S_GLOBL:
+ do {
+ getid(id, -1);
+ sp = lookup(id);
+ sp->s_flag |= S_GBL;
+ } while ((c = getnb()) == ',');
+ unget(c);
+ lmode = SLIST;
+ break;
+
+ case S_DAREA:
+ getid(id, -1);
+ uaf = 0;
+ uf = A_CON|A_REL;
+ if ((c = getnb()) == '(') {
+ do {
+ getid(opt, -1);
+ mp = mlookup(opt);
+ if (mp && mp->m_type == S_ATYP) {
+ ++uaf;
+ uf |= mp->m_valu;
+ } else {
+ err('u');
+ }
+ } while ((c = getnb()) == ',');
+ if (c != ')')
+ qerr();
+ } else {
+ unget(c);
+ }
+ if ((ap = alookup(id)) != NULL) {
+ if (uaf && uf != ap->a_flag)
+ err('m');
+ } else {
+ ap = (struct area *) new (sizeof(struct area));
+ ap->a_ap = areap;
+ strncpy(ap->a_id, id, NCPS);
+ ap->a_ref = areap->a_ref + 1;
+ ap->a_size = 0;
+ ap->a_fuzz = 0;
+ ap->a_flag = uaf ? uf : (A_CON|A_REL);
+ areap = ap;
+ }
+ newdot(ap);
+ lmode = SLIST;
+ break;
+
+ case S_ORG:
+ if (dot.s_area->a_flag & A_ABS) {
+ outall();
+ laddr = dot.s_addr = absexpr();
+ } else {
+ err('o');
+ }
+ outall();
+ lmode = ALIST;
+ break;
+
+ case S_RADIX:
+ if (more()) {
+ switch (getnb()) {
+ case 'b':
+ case 'B':
+ radix = 2;
+ break;
+ case '@':
+ case 'o':
+ case 'O':
+ case 'q':
+ case 'Q':
+ radix = 8;
+ break;
+ case 'd':
+ case 'D':
+ radix = 10;
+ break;
+ case 'h':
+ case 'H':
+ case 'x':
+ case 'X':
+ radix = 16;
+ break;
+ default:
+ radix = 10;
+ qerr();
+ break;
+ }
+ } else {
+ radix = 10;
+ }
+ lmode = SLIST;
+ break;
+
+ case S_INCL:
+ d = getnb();
+ p = fn;
+ while ((c = get()) != d) {
+ if (p < &fn[PATH_MAX-1]) {
+ *p++ = c;
+ } else {
+ break;
+ }
+ }
+ *p = 0;
+ if (++incfil == MAXINC ||
+ (ifp[incfil] = fopen(fn, "r")) == NULL) {
+ --incfil;
+ err('i');
+ } else {
+ lop = NLPP;
+ incline[incfil] = 0;
+ strcpy(incfn[incfil],fn);
+ }
+ lmode = SLIST;
+ break;
+
+ case S_FLAT24:
+ if (more())
+ {
+ getst(id, -1);
+
+ if (!as_strcmpi(id, "on"))
+ {
+ /* Quick sanity check: size of
+ * Addr_T must be at least 24 bits.
+ */
+ if (sizeof(Addr_T) < 3)
+ {
+ warnBanner();
+ fprintf(stderr,
+ "Cannot enable Flat24 mode: "
+ "host system must have 24 bit "
+ "or greater integers.\n");
+ }
+ else
+ {
+ flat24Mode = 1;
+ }
+ }
+ else if (!as_strcmpi(id, "off"))
+ {
+ flat24Mode = 0;
+ }
+ else
+ {
+ qerr();
+ }
+ }
+ else
+ {
+ qerr();
+ }
+ lmode = SLIST;
+ #if 0
+ printf("as8051: ds390 flat mode %sabled.\n",
+ flat24Mode ? "en" : "dis");
+ #endif
+ break;
+
+
+ /*
+ * If not an assembler directive then go to
+ * the machine dependent function which handles
+ * all the assembler mnemonics.
+ */
+ default:
+ machine(mp);
+ /* if cdb information the generate the line info */
+ if (cflag && (pass == 1))
+ DefineCDB_Line();
+
+ /* JLH: if -j, generate a line number symbol */
+ if (jflag && (pass == 1))
+ {
+ DefineNoICE_Line();
+ }
+
+ }
+ goto loop;
+}
+
+/*)Function FILE * afile(fn, ft, wf)
+ *
+ * char * fn file specification string
+ * char * ft file type string
+ * int wf read(0)/write(1) flag
+ *
+ * The function afile() opens a file for reading or writing.
+ * (1) If the file type specification string ft
+ * is not NULL then a file specification is
+ * constructed with the file path\name in fn
+ * and the extension in ft.
+ * (2) If the file type specification string ft
+ * is NULL then the file specification is
+ * constructed from fn. If fn does not have
+ * a file type then the default source file
+ * type dsft is appended to the file specification.
+ *
+ * afile() returns a file handle for the opened file or aborts
+ * the assembler on an open error.
+ *
+ * local variables:
+ * int c character value
+ * FILE * fp filehandle for opened file
+ * char * p1 pointer to filespec string fn
+ * char * p2 pointer to filespec string fb
+ * char * p3 pointer to filetype string ft
+ *
+ * global variables:
+ * char afn[] afile() constructed filespec
+ * char dsft[] default assembler file type string
+ * char afn[] constructed file specification string
+ *
+ * functions called:
+ * VOID asexit() asmain.c
+ * FILE * fopen() c_library
+ * int fprintf() c_library
+ *
+ * side effects:
+ * File is opened for read or write.
+ */
+
+FILE *
+afile(fn, ft, wf)
+char *fn;
+char *ft;
+int wf;
+{
+ register char *p2, *p3;
+ register int c;
+ FILE *fp;
+
+ p2 = afn;
+ p3 = ft;
+
+ strcpy (afn, fn);
+ p2 = strrchr (afn, FSEPX); // search last '.'
+ if (!p2)
+ p2 = afn + strlen (afn);
+ if (p2 > &afn[PATH_MAX-4]) // truncate filename, if it's too long
+ p2 = &afn[PATH_MAX-4];
+ *p2++ = FSEPX;
+
+ // choose a file-extension
+ if (*p3 == 0) { // extension supplied?
+ p3 = strrchr (fn, FSEPX); // no: extension in fn?
+ if (p3)
+ ++p3;
+ else
+ p3 = dsft; // no: default extension
+ }
+
+ while ((c = *p3++) != 0) { // strncpy
+ if (p2 < &afn[PATH_MAX-1])
+ *p2++ = c;
+ }
+ *p2++ = 0;
+
+ if ((fp = fopen(afn, wf?"w":"r")) == NULL) {
+ fprintf(stderr, "%s: cannot %s.\n", afn, wf?"create":"open");
+ asexit(1);
+ }
+ return (fp);
+}
+
+/*)Function VOID newdot(nap)
+ *
+ * area * nap pointer to the new area structure
+ *
+ * The function newdot():
+ * (1) copies the current values of fuzz and the last
+ * address into the current area referenced by dot
+ * (2) loads dot with the pointer to the new area and
+ * loads the fuzz and last address parameters
+ * (3) outall() is called to flush any remaining
+ * bufferred code from the old area to the output
+ *
+ * local variables:
+ * area * oap pointer to old area
+ *
+ * global variables:
+ * sym dot defined as sym[0]
+ * Addr_T fuzz tracks pass to pass changes in the
+ * address of symbols caused by
+ * variable length instruction formats
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * Current area saved, new area loaded, buffers flushed.
+ */
+
+VOID
+newdot(nap)
+register struct area *nap;
+{
+ register struct area *oap;
+
+ oap = dot.s_area;
+ /* fprintf (stderr, "%s dot.s_area->a_size: %d dot.s_addr: %d\n",
+ oap->a_id, dot.s_area->a_size, dot.s_addr); */
+ oap->a_fuzz = fuzz;
+ if (oap->a_flag & A_OVR) {
+ // the size of an overlay is the biggest size encountered
+ if (oap->a_size < dot.s_addr) {
+ oap->a_size = dot.s_addr;
+ }
+ } else {
+ oap->a_size = dot.s_addr;
+ }
+ if (nap->a_flag & A_OVR) {
+ // a new overlay starts at 0, no fuzz
+ dot.s_addr = 0;
+ fuzz = 0;
+ } else {
+ dot.s_addr = nap->a_size;
+ fuzz = nap->a_fuzz;
+ }
+ dot.s_area = nap;
+ outall();
+}
+
+/*)Function VOID phase(ap, a)
+ *
+ * area * ap pointer to area
+ * Addr_T a address in area
+ *
+ * Function phase() compares the area ap and address a
+ * with the current area dot.s_area and address dot.s_addr
+ * to determine if the position of the symbol has changed
+ * between assembler passes.
+ *
+ * local variables:
+ * none
+ *
+ * global varaibles:
+ * sym * dot defined as sym[0]
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * The p error is invoked if the area and/or address
+ * has changed.
+ */
+
+VOID
+phase(ap, a)
+struct area *ap;
+Addr_T a;
+{
+ if (ap != dot.s_area || a != dot.s_addr)
+ err('p');
+}
+
+char *usetxt[] = {
+ "Usage: [-dqxjgalopsf] file1 [file2 file3 ...]",
+ " d decimal listing",
+ " q octal listing",
+ " x hex listing (default)",
+ " j add line number and debug information to file", /* JLH */
+ " g undefined symbols made global",
+ " a all user symbols made global",
+ " l create list output file1[LST]",
+ " o create object output file1[REL]",
+ " s create symbol output file1[SYM]",
+ " p disable listing pagination",
+ " f flag relocatable references by ` in listing file",
+ " ff flag relocatable references by mode in listing file",
+ "",
+ 0
+};
+
+/*)Function VOID usage()
+ *
+ * The function usage() outputs to the stderr device the
+ * assembler name and version and a list of valid assembler options.
+ *
+ * local variables:
+ * char ** dp pointer to an array of
+ * text string pointers.
+ *
+ * global variables:
+ * char cpu[] assembler type string
+ * char * usetxt[] array of string pointers
+ *
+ * functions called:
+ * VOID asexit() asmain.c
+ * int fprintf() c_library
+ *
+ * side effects:
+ * program is terminated
+ */
+
+VOID
+usage()
+{
+ register char **dp;
+
+ fprintf(stderr, "\nASxxxx Assembler %s (%s)\n\n", VERSION, cpu);
+ for (dp = usetxt; *dp; dp++)
+ fprintf(stderr, "%s\n", *dp);
+ asexit(1);
+}
--- /dev/null
+/* asnoice.c */
+
+/*
+ * Extensions to CUG 292 assembler ASxxxx to produce NoICE debug files
+ *
+ * 3-Nov-1997 by John Hartman
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/* Return basic file name without path or extension */
+static char* BaseFileName( int fileNumber );
+
+char* BaseFileName( int fileNumber )
+{
+ static int prevFile = -1;
+ static char baseName[ PATH_MAX ];
+
+ char *p1, *p2;
+
+ if (fileNumber != prevFile)
+ {
+ prevFile = fileNumber;
+
+ p1 = srcfn[prevFile];
+
+ /* issue a FILE command with full path and extension */
+ fprintf( ofp, ";!FILE %s\n", p1 );
+
+ /* Name starts after any colon or backslash (DOS) */
+ p2 = strrchr( p1, '\\' );
+ if (p2 == NULL) p2 = strrchr( p1, '/' );
+ if (p2 == NULL) p2 = strrchr( p1, ':' );
+ if (p2 == NULL) p2 = p1-1;
+ strcpy( baseName, p2+1 );
+
+ /* Name ends at any separator */
+ p2 = strrchr( baseName, FSEPX );
+ if (p2 != NULL) *p2 = 0;
+ /* SD comment this out since not a ANSI Function */
+ /* strupr( baseName ); */
+ }
+ return baseName;
+}
+
+/* Define a symbol for current location: FILE.line# */
+void DefineNoICE_Line()
+{
+ char name[ NCPS ];
+ struct sym *pSym;
+
+ /* symbol is FILE.nnn */
+ sprintf( name, "%s.%u", BaseFileName( cfile ), srcline[ cfile ] );
+
+ pSym = lookup( name );
+ pSym->s_type = S_USER;
+ pSym->s_area = dot.s_area;
+ pSym->s_addr = laddr;
+ pSym->s_flag |= S_GBL;
+}
+
+/* Define a symbol for current location: A$FILE$line# */
+void DefineCDB_Line()
+{
+ char name[ NCPS ];
+ struct sym *pSym;
+
+ /* symbol is FILE.nnn */
+ sprintf( name, "A$%s$%u", BaseFileName( cfile ), srcline[ cfile ] );
+
+ pSym = lookup( name );
+ pSym->s_type = S_USER;
+ pSym->s_area = dot.s_area;
+ pSym->s_addr = laddr;
+ pSym->s_flag |= S_GBL;
+}
+
+#if 0
+OLD VERSION
+/* Define a symbol for current location: FILE.line# */
+void DefineNoICE_Line()
+{
+ static int prevFile = -1;
+ static struct area *pPrevArea = NULL;
+ static char baseName[ PATH_MAX ];
+
+ int j;
+ char *p1, *p2;
+
+ /* Get outfilename without extension for use as base symbol name */
+ if (baseName[0] == 0)
+ {
+ p1 = srcfn[0];
+ p2 = baseName;
+ while ((*p1 != 0) && (*p1 != FSEPX))
+ {
+ *p2++ = *p1++;
+ }
+ *p2 = 0;
+ /* SD Commented this out since it is not a
+ ASNI Function */
+ /* strupr( baseName ); */
+ }
+
+ if ((cfile != prevFile) || (dot.s_area != pPrevArea))
+ {
+ prevFile = cfile;
+ pPrevArea = dot.s_area;
+
+ /* file or area change: issue FILE command with base @ */
+ fprintf( ofp, ";!FILE %s %s_%s\n", srcfn[ cfile ],
+ baseName,
+ dot.s_area->a_id );
+ }
+
+ fprintf( ofp, ";!LINE %u. 0x%X\n", srcline[ cfile ], laddr );
+}
+
+#endif
--- /dev/null
+/* asout.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - outsym: show s_id as string rather than array [NCPS]
+ * - Added outr11 to support 8051's 11 bit destination address
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+
+/*)Module asout.c
+ *
+ * The module asout.c contains all the functions used to
+ * generate the .REL assembler output file.
+ *
+ *
+ * The assemblers' output object file is an ascii file containing
+ * the information needed by the linker to bind multiple object
+ * modules into a complete loadable memory image.
+ *
+ * The object module contains the following designators:
+ *
+ * [XDQ][HL]
+ * X Hexadecimal radix
+ * D Decimal radix
+ * Q Octal radix
+ *
+ * H Most significant byte first
+ * L Least significant byte first
+ *
+ * H Header
+ * M Module
+ * A Area
+ * S Symbol
+ * T Object code
+ * R Relocation information
+ * P Paging information
+ *
+ *
+ * (1) Radix Line
+ *
+ * The first line of an object module contains the [XDQ][HL]
+ * format specifier (i.e. XH indicates a hexadecimal file with
+ * most significant byte first) for the following designators.
+ *
+ *
+ * (2) Header Line
+ *
+ * H aa areas gg global symbols
+ *
+ * The header line specifies the number of areas(aa) and the
+ * number of global symbols(gg) defined or referenced in this ob-
+ * ject module segment.
+ *
+ *
+ * (3) Module Line
+ *
+ * M name
+ *
+ * The module line specifies the module name from which this
+ * header segment was assembled. The module line will not appear
+ * if the .module directive was not used in the source program.
+ *
+ *
+ * (4) Symbol Line
+ *
+ * S string Defnnnn
+ *
+ * or
+ *
+ * S string Refnnnn
+ *
+ * The symbol line defines (Def) or references (Ref) the symbol
+ * 'string' with the value nnnn. The defined value is relative to
+ * the current area base address. References to constants and ex-
+ * ternal global symbols will always appear before the first area
+ * definition. References to external symbols will have a value of
+ * zero.
+ *
+ *
+ * (5) Area Line
+ *
+ * A label size ss flags ff
+ *
+ * The area line defines the area label, the size (ss) of the
+ * area in bytes, and the area flags (ff). The area flags specify
+ * the ABS, REL, CON, OVR, and PAG parameters:
+ *
+ * OVR/CON (0x04/0x00 i.e. bit position 2)
+ *
+ * ABS/REL (0x08/0x00 i.e. bit position 3)
+ *
+ * PAG (0x10 i.e. bit position 4)
+ *
+ *
+ * (6) T Line
+ *
+ * T xx xx nn nn nn nn nn ...
+ *
+ * The T line contains the assembled code output by the assem-
+ * bler with xx xx being the offset address from the current area
+ * base address and nn being the assembled instructions and data in
+ * byte format.
+ *
+ *
+ * (7) R Line
+ *
+ * R 0 0 nn nn n1 n2 xx xx ...
+ *
+ * The R line provides the relocation information to the linker.
+ * The nn nn value is the current area index, i.e. which area the
+ * current values were assembled. Relocation information is en-
+ * coded in groups of 4 bytes:
+ *
+ * 1. n1 is the relocation mode and object format
+ * 1. bit 0 word(0x00)/byte(0x01)
+ * 2. bit 1 relocatable area(0x00)/symbol(0x02)
+ * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
+ * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
+ * byte data
+ * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
+ * 6. bit 5 normal(0x00)/page '0'(0x20) reference
+ * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
+ * 8. bit 7 normal(0x00)/MSB of value
+ *
+ * 2. n2 is a byte index into the corresponding (i.e. pre-
+ * ceeding) T line data (i.e. a pointer to the data to be
+ * updated by the relocation). The T line data may be
+ * 1-byte or 2-byte byte data format or 2-byte word
+ * format.
+ *
+ * 3. xx xx is the area/symbol index for the area/symbol be-
+ * ing referenced. the corresponding area/symbol is found
+ * in the header area/symbol lists.
+ *
+ *
+ * The groups of 4 bytes are repeated for each item requiring relo-
+ * cation in the preceeding T line.
+ *
+ *
+ * (8) P Line
+ *
+ * P 0 0 nn nn n1 n2 xx xx
+ *
+ * The P line provides the paging information to the linker as
+ * specified by a .setdp directive. The format of the relocation
+ * information is identical to that of the R line. The correspond-
+ * ing T line has the following information:
+ * T xx xx aa aa bb bb
+ *
+ * Where aa aa is the area reference number which specifies the
+ * selected page area and bb bb is the base address of the page.
+ * bb bb will require relocation processing if the 'n1 n2 xx xx' is
+ * specified in the P line. The linker will verify that the base
+ * address is on a 256 byte boundary and that the page length of an
+ * area defined with the PAG type is not larger than 256 bytes.
+ *
+ * The linker defaults any direct page references to the first
+ * area defined in the input REL file. All ASxxxx assemblers will
+ * specify the _CODE area first, making this the default page area.
+ *
+ *
+ * asout.c contains the following functions:
+ * int lobyte()
+ * int hibyte()
+ * VOID out()
+ * VOID outab()
+ * VOID outall()
+ * VOID outarea()
+ * VOID outaw()
+ * VOID outbuf()
+ * VOID outchk()
+ * VOID outdot()
+ * VOID outdp()
+ * VOID outgsd()
+ * VOID outrb()
+ * VOID outrw()
+ * VOID outsym()
+ * VOID out_lb()
+ * VOID out_lw()
+ * VOID out_rw()
+ * VOID out_tw()
+ *
+ * The module asout.c contains the following local variables:
+ * int rel[] relocation data for code/data array
+ * int * relp pointer to rel array
+ * int txt[] assembled code/data array
+ * int * txtp pointer to txt array
+ */
+
+#define NTXT 16
+#define NREL 16
+
+char txt[NTXT];
+char rel[NREL];
+
+char *txtp = { &txt[0] };
+char *relp = { &rel[0] };
+
+/*)Function VOID outab(b)
+ *
+ * int b assembler data word
+ *
+ * The function outab() processes a single word of
+ * assembled data in absolute format.
+ *
+ * local variables:
+ * int * txtp pointer to data word
+ *
+ * global variables:
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID outchk() asout.c
+ * VOID out_lb() asout.c
+ *
+ * side effects:
+ * The current assembly address is incremented by 1.
+ */
+
+VOID
+outab(b)
+{
+ if (pass == 2) {
+ out_lb(b,0);
+ if (oflag) {
+ outchk(1, 0);
+ *txtp++ = lobyte(b);
+ }
+ }
+ ++dot.s_addr;
+}
+
+/*)Function VOID outaw(w)
+ *
+ * int w assembler data word
+ *
+ * The function outaw() processes a single word of
+ * assembled data in absolute format.
+ *
+ * local variables:
+ * int * txtp pointer to data word
+ *
+ * global variables:
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID outchk() asout.c
+ * VOID out_lw() asout.c
+ *
+ * side effects:
+ * The current assembly address is incremented by 2.
+ */
+
+VOID
+outaw(w)
+{
+ if (pass == 2) {
+ out_lw(w,0);
+ if (oflag) {
+ outchk(2, 0);
+ out_tw(w);
+ }
+ }
+ dot.s_addr += 2;
+}
+
+/*)Function VOID write_rmode(r)
+ *
+ * int r relocation mode
+ *
+ * write_rmode puts the passed relocation mode into the
+ * output relp buffer, escaping it if necessary.
+ *
+ * global variables:
+ * int * relp pointer to rel array
+ *
+ * functions called:
+ * VOID rerr() assubr.c
+ *
+ * side effects:
+ * relp is incremented appropriately.
+ */
+VOID
+write_rmode(int r)
+{
+ /* We need to escape the relocation mode if it is greater
+ * than a byte, or if it happens to look like an escape.
+ * (I don't think that the latter case is legal, but
+ * better safe than sorry).
+ */
+ if ((r > 0xff) || ((r & R_ESCAPE_MASK) == R_ESCAPE_MASK))
+ {
+ /* Hack in up to an extra 4 bits of flags with escape. */
+ if (r > 0xfff)
+ {
+ /* uh-oh.. we have more than 4 extra bits. */
+ fprintf(stderr,
+ "Internal error: relocation mode 0x%X too big.\n",
+ r);
+ rerr();
+ }
+ /* printf("escaping relocation mode\n"); */
+ *relp++ = R_ESCAPE_MASK | (r >> 8);
+ *relp++ = r & 0xff;
+ }
+ else
+ {
+ *relp++ = r;
+ }
+}
+
+/*)Function VOID outrb(esp, r)
+ *
+ * expr * esp pointer to expr structure
+ * int r relocation mode
+ *
+ * The function outrb() processes a byte of generated code
+ * in either absolute or relocatable format dependent upon
+ * the data contained in the expr structure esp. If the
+ * .REL output is enabled then the appropriate information
+ * is loaded into the txt and rel buffers.
+ *
+ * local variables:
+ * int n symbol/area reference number
+ * int * relp pointer to rel array
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * sym dot defined as sym[0]
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID aerr() assubr.c
+ * VOID outchk() asout.c
+ * VOID out_lb() asout.c
+ * VOID out_rb() asout.c
+ * VOID out_tb() asout.c
+ *
+ * side effects:
+ * The current assembly address is incremented by 1.
+ */
+
+VOID
+outrb(struct expr *esp, int r)
+{
+ register int n;
+
+ if (pass == 2) {
+ if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+ /* This is a constant; simply write the
+ * const byte to the T line and don't
+ * generate any relocation info.
+ */
+ out_lb(lobyte(esp->e_addr),0);
+ if (oflag) {
+ outchk(1, 0);
+ *txtp++ = lobyte(esp->e_addr);
+ }
+ } else {
+ /* We are generating a single byte of relocatable
+ * info.
+ *
+ * In 8051 mode, we generate a 16 bit address. The
+ * linker will later select a single byte based on
+ * whether R_MSB is set.
+ *
+ * In flat24 mode, we generate a 24 bit address. The
+ * linker will select a single byte based on
+ * whether R_MSB or R_HIB is set.
+ */
+ if (!flat24Mode)
+ {
+ r |= R_BYTE | R_BYT2 | esp->e_rlcf;
+ if (r & R_MSB) {
+ out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
+ } else {
+ out_lb(lobyte(esp->e_addr),r|R_RELOC);
+ }
+ if (oflag) {
+ outchk(2, 5);
+ out_tw(esp->e_addr);
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+ write_rmode(r);
+ *relp++ = txtp - txt - 2;
+ out_rw(n);
+ }
+ }
+ else
+ {
+ /* 24 bit mode. */
+ r |= R_BYTE | R_BYT3 | esp->e_rlcf;
+ if (r & R_HIB)
+ {
+ /* Probably should mark this differently in the
+ * listing file.
+ */
+ out_lb(byte3(esp->e_addr),r|R_RELOC|R_HIGH);
+ }
+ else if (r & R_MSB) {
+ out_lb(hibyte(esp->e_addr),r|R_RELOC|R_HIGH);
+ } else {
+ out_lb(lobyte(esp->e_addr),r|R_RELOC);
+ }
+ if (oflag) {
+ outchk(3, 5);
+ out_t24(esp->e_addr);
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+ write_rmode(r);
+ *relp++ = txtp - txt - 3;
+ out_rw(n);
+ }
+ }
+ }
+ }
+ ++dot.s_addr;
+}
+
+/*)Function VOID outrw(esp, r)
+ *
+ * expr * esp pointer to expr structure
+ * int r relocation mode
+ *
+ * The function outrw() processes a word of generated code
+ * in either absolute or relocatable format dependent upon
+ * the data contained in the expr structure esp. If the
+ * .REL output is enabled then the appropriate information
+ * is loaded into the txt and rel buffers.
+ *
+ * local variables:
+ * int n symbol/area reference number
+ * int * relp pointer to rel array
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * sym dot defined as sym[0]
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID aerr() assubr.c
+ * VOID outchk() asout.c
+ * VOID out_lw() asout.c
+ * VOID out_rw() asout.c
+ * VOID out_tw() asout.c
+ *
+ * side effects:
+ * The current assembly address is incremented by 2.
+ */
+
+VOID
+outrw(struct expr *esp, int r)
+{
+ register int n;
+
+ if (pass == 2) {
+
+ if (esp->e_addr > 0xffff)
+ {
+ warnBanner();
+ fprintf(stderr,
+ "large constant 0x%x truncated to 16 bits\n",
+ esp->e_addr);
+ }
+ if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+ out_lw(esp->e_addr,0);
+ if (oflag) {
+ outchk(2, 0);
+ out_tw(esp->e_addr);
+ }
+ } else {
+ r |= R_WORD | esp->e_rlcf;
+ if (r & R_BYT2) {
+ rerr();
+ if (r & R_MSB) {
+ out_lw(hibyte(esp->e_addr),r|R_RELOC);
+ } else {
+ out_lw(lobyte(esp->e_addr),r|R_RELOC);
+ }
+ } else {
+ out_lw(esp->e_addr,r|R_RELOC);
+ }
+ if (oflag) {
+ outchk(2, 5);
+ out_tw(esp->e_addr);
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+
+ if (IS_C24(r))
+ {
+ /* If this happens, the linker will
+ * attempt to process this 16 bit field
+ * as 24 bits. That would be bad.
+ */
+ fprintf(stderr,
+ "***Internal error: C24 out in "
+ "outrw()\n");
+ rerr();
+ }
+ write_rmode(r);
+ *relp++ = txtp - txt - 2;
+ out_rw(n);
+ }
+ }
+ }
+ dot.s_addr += 2;
+}
+
+/*)Function VOID outr24(esp, r)
+ *
+ * expr * esp pointer to expr structure
+ * int r relocation mode
+ *
+ * The function outr24() processes 24 bits of generated code
+ * in either absolute or relocatable format dependent upon
+ * the data contained in the expr structure esp. If the
+ * .REL output is enabled then the appropriate information
+ * is loaded into the txt and rel buffers.
+ *
+ * local variables:
+ * int n symbol/area reference number
+ * int * relp pointer to rel array
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * sym dot defined as sym[0]
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID aerr() assubr.c
+ * VOID outchk() asout.c
+ * VOID out_l24() asout.c
+ * VOID out_rw() asout.c
+ * VOID out_t24() asout.c
+ *
+ * side effects:
+ * The current assembly address is incremented by 3.
+ */
+
+VOID
+outr24(struct expr *esp, int r)
+{
+ register int n;
+
+ if (pass == 2) {
+ if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+ /* This is a constant expression. */
+ out_l24(esp->e_addr,0);
+ if (oflag) {
+ outchk(3, 0);
+ out_t24(esp->e_addr);
+ }
+ } else {
+ /* This is a symbol. */
+ r |= R_WORD | esp->e_rlcf;
+ if (r & R_BYT2) {
+ /* I have no idea what this case is. */
+ rerr();
+ if (r & R_MSB) {
+ out_lw(hibyte(esp->e_addr),r|R_RELOC);
+ } else {
+ out_lw(lobyte(esp->e_addr),r|R_RELOC);
+ }
+ } else {
+ out_l24(esp->e_addr,r|R_RELOC);
+ }
+ if (oflag) {
+ outchk(3, 5);
+ out_t24(esp->e_addr);
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+
+ if (r & R_BYTE)
+ {
+ /* If this occurs, we cannot properly
+ * code the relocation data with the
+ * R_C24 flag. This means the linker
+ * will fail to do the 24 bit relocation.
+ * Which will suck.
+ */
+ fprintf(stderr,
+ "***Internal error: BYTE out in 24 "
+ "bit flat mode unexpected.\n");
+ rerr();
+ }
+
+ write_rmode(r | R_C24);
+ *relp++ = txtp - txt - 3;
+ out_rw(n);
+ }
+ }
+ }
+ dot.s_addr += 3;
+}
+
+/*)Function VOID outdp(carea, esp)
+ *
+ * area * carea pointer to current area strcuture
+ * expr * esp pointer to expr structure
+ *
+ * The function outdp() flushes the output buffer and
+ * outputs paging information to the .REL file.
+ *
+ * local variables:
+ * int n symbol/area reference number
+ * int r relocation mode
+ * int * relp pointer to rel array
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID outbuf() asout.c
+ * VOID outchk() asout.c
+ * VOID out_rw() asout.c
+ * VOID out_tw() asout.c
+ *
+ * side effects:
+ * Output buffer flushed to .REL fiel.
+ * Paging information dumped to .REL file.
+ */
+
+VOID
+outdp(carea, esp)
+register struct area *carea;
+register struct expr *esp;
+{
+ register int n, r;
+
+ if (oflag && pass==2) {
+ outchk(HUGE,HUGE);
+ out_tw(carea->a_ref);
+ out_tw(esp->e_addr);
+ if (esp->e_flag || esp->e_base.e_ap!=NULL) {
+ r = R_WORD;
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+ write_rmode(r);
+ *relp++ = txtp - txt - 2;
+ out_rw(n);
+ }
+ outbuf("P");
+ }
+}
+
+/*)Function VOID outall()
+ *
+ * The function outall() will output any bufferred assembled
+ * data and relocation information (during pass 2 if the .REL
+ * output has been enabled).
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * VOID outbuf() asout.c
+ *
+ * side effects:
+ * assembled data and relocation buffers will be cleared.
+ */
+
+VOID
+outall()
+{
+ if (oflag && pass==2)
+ outbuf("R");
+}
+
+/*)Function VOID outdot()
+ *
+ * The function outdot() outputs information about the
+ * current program counter value (during pass 2 if the .REL
+ * output has been enabled).
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int oflag -o, generate relocatable output flag
+ * int pass assembler pass number
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID out() asout.c
+ *
+ * side effects:
+ * assembled data and relocation buffers will be cleared.
+ */
+
+VOID
+outdot()
+{
+ if (oflag && pass==2) {
+ fprintf(ofp, "T");
+ out(txt,(int) (txtp-txt));
+ fprintf(ofp, "\n");
+ fprintf(ofp, "R");
+ out(rel,(int) (relp-rel));
+ fprintf(ofp, "\n");
+ txtp = txt;
+ relp = rel;
+ }
+}
+
+/*)Function outchk(nt, nr)
+ *
+ * int nr number of additional relocation words
+ * int nt number of additional data words
+ *
+ * The function outchk() checks the data and relocation buffers
+ * for space to insert the nt data words and nr relocation words.
+ * If space is not available then output the current data and
+ * initialize the data buffers to receive the new data.
+ *
+ * local variables:
+ * area * ap pointer to an area structure
+ * int * relp pointer to rel array
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * sym dot defined as sym[0]
+ *
+ * functions called:
+ * VOID outbuf() asout.c
+ *
+ * side effects:
+ * Data and relocation buffers may be emptied and initialized.
+ */
+
+VOID
+outchk(nt, nr)
+{
+ register struct area *ap;
+
+ if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) {
+ outbuf("R");
+ }
+ if (txtp == txt) {
+ out_tw(dot.s_addr);
+ if ((ap = dot.s_area) != NULL) {
+ write_rmode(R_WORD|R_AREA);
+ *relp++ = 0;
+ out_rw(ap->a_ref);
+ }
+ }
+}
+
+/*)Function VOID outbuf()
+ *
+ * The function outbuf() will output any bufferred data
+ * and relocation information to the .REL file. The output
+ * buffer pointers and counters are initialized.
+ *
+ * local variables:
+ * int rel[] relocation data for code/data array
+ * int * relp pointer to rel array
+ * int txt[] assembled code/data array
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * FILE * ofp relocation output file handle
+ *
+ * functions called:
+ * VOID out() asout.c
+ *
+ * side effects:
+ * All bufferred data written to .REL file and
+ * buffer pointers and counters initialized.
+ */
+
+VOID
+outbuf(s)
+char *s;
+{
+ if (txtp > &txt[2]) {
+ fprintf(ofp, "T");
+ out(txt,(int) (txtp-txt));
+ fprintf(ofp, "\n");
+ fprintf(ofp, "%s", s);
+ out(rel,(int) (relp-rel));
+ fprintf(ofp, "\n");
+ }
+ txtp = txt;
+ relp = rel;
+}
+
+/*)Function VOID outgsd()
+ *
+ * The function outgsd() performs the following:
+ * (1) outputs the .REL file radix
+ * (2) outputs the header specifying the number
+ * of areas and global symbols
+ * (3) outputs the module name
+ * (4) set the reference number and output a symbol line
+ * for all external global variables and absolutes
+ * (5) output an area name, set reference number and output
+ * a symbol line for all global relocatables in the area.
+ * Repeat this proceedure for all areas.
+ *
+ * local variables:
+ * area * ap pointer to an area structure
+ * sym * sp pointer to a sym structure
+ * int i loop counter
+ * int j loop counter
+ * int c string character value
+ * int narea number of code areas
+ * char * ptr string pointer
+ * int nglob number of global symbols
+ * int rn symbol reference number
+ *
+ * global variables:
+ * area * areap pointer to an area structure
+ * char module[] module name string
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID outarea() asout.c
+ * VOID outsym() asout.c
+ * int putc() c_library
+ *
+ * side effects:
+ * All symbols are given reference numbers, all symbol
+ * and area information is output to the .REL file.
+ */
+
+VOID
+outgsd()
+{
+ register struct area *ap;
+ register struct sym *sp;
+ register int i, j;
+ char *ptr;
+ int c, narea, nglob, rn;
+
+ /*
+ * Number of areas
+ */
+ narea = areap->a_ref + 1;
+
+ /*
+ * Number of global references/absolutes
+ */
+ nglob = 0;
+ for (i = 0; i < NHASH; ++i) {
+ sp = symhash[i];
+ while (sp) {
+ if (sp->s_flag&S_GBL)
+ ++nglob;
+ sp = sp->s_sp;
+ }
+ }
+
+ /*
+ * Output Radix and number of areas and symbols
+ */
+ if (xflag == 0) {
+ fprintf(ofp, "X%c\n", hilo ? 'H' : 'L');
+ fprintf(ofp, "H %X areas %X global symbols\n", narea, nglob);
+ } else
+ if (xflag == 1) {
+ fprintf(ofp, "Q%c\n", hilo ? 'H' : 'L');
+ fprintf(ofp, "H %o areas %o global symbols\n", narea, nglob);
+ } else
+ if (xflag == 2) {
+ fprintf(ofp, "D%c\n", hilo ? 'H' : 'L');
+ fprintf(ofp, "H %u areas %u global symbols\n", narea, nglob);
+ }
+
+ /*
+ * Module name
+ */
+ if (module[0]) {
+ fprintf(ofp, "M ");
+ ptr = &module[0];
+ while (ptr < &module[NCPS]) {
+ if ((c = *ptr++) != 0)
+ putc(c, ofp);
+ }
+ putc('\n', ofp);
+ }
+
+ /*
+ * Sdcc compile options
+ */
+ if (strlen(optsdcc)) fprintf(ofp, "O %s\n", optsdcc);
+
+ /*
+ * Global references and absolutes.
+ */
+ rn = 0;
+ for (i=0; i<NHASH; ++i) {
+ sp = symhash[i];
+ while (sp) {
+ if (sp->s_area==NULL && sp->s_flag&S_GBL) {
+ sp->s_ref = rn++;
+ outsym(sp);
+ }
+ sp = sp->s_sp;
+ }
+ }
+
+ /*
+ * Global relocatables.
+ */
+ for (i=0; i<narea; ++i) {
+ ap = areap;
+ while (ap->a_ref != i)
+ ap = ap->a_ap;
+ outarea(ap);
+ for (j=0; j<NHASH; ++j) {
+ sp = symhash[j];
+ while (sp) {
+ if (sp->s_area==ap && sp->s_flag&S_GBL) {
+ sp->s_ref = rn++;
+ outsym(sp);
+ }
+ sp = sp->s_sp;
+ }
+ }
+ }
+}
+
+/*)Function VOID outarea(ap)
+ *
+ * area * ap pointer to an area structure
+ *
+ * The function outarea() outputs the A line to the .REL
+ * file. The A line contains the area's name, size, and
+ * attributes.
+ *
+ * local variables:
+ * char * ptr pointer to area id string
+ * int c character value
+ *
+ * global variables:
+ * FILE * ofp relocation output file handle
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * int putc() c_library
+ *
+ * side effects:
+ * The A line is sent to the .REL file.
+ */
+
+VOID
+outarea(ap)
+register struct area *ap;
+{
+ register char *ptr;
+ register int c;
+
+ fprintf(ofp, "A ");
+ ptr = &ap->a_id[0];
+ while (ptr < &ap->a_id[NCPS]) {
+ if ((c = *ptr++) != 0)
+ putc(c, ofp);
+ }
+ if (xflag == 0) {
+ fprintf(ofp, " size %X flags %X\n", ap->a_size, ap->a_flag);
+ } else
+ if (xflag == 1) {
+ fprintf(ofp, " size %o flags %o\n", ap->a_size, ap->a_flag);
+ } else
+ if (xflag == 2) {
+ fprintf(ofp, " size %u flags %u\n", ap->a_size, ap->a_flag);
+ }
+}
+
+/*)Function VOID outsym(sp)
+ *
+ * sym * sp pointer to a sym structure
+ *
+ * The function outsym() outputs the S line to the .REL
+ * file. The S line contains the symbols name and whether the
+ * the symbol is defined or referenced.
+ *
+ * local variables:
+ * char * ptr pointer to symbol id string
+ * int c character value
+ *
+ * global variables:
+ * FILE * ofp relocation output file handle
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * int putc() c_library
+ *
+ * side effects:
+ * The S line is sent to the .REL file.
+ */
+
+VOID
+outsym(sp)
+register struct sym *sp;
+{
+ register char *ptr;
+
+ fprintf(ofp, "S ");
+ ptr = &sp->s_id[0];
+ fprintf(ofp, "%s", ptr );
+ fprintf(ofp, " %s", sp->s_type==S_NEW ? "Ref" : "Def");
+ if (xflag == 0) {
+ fprintf(ofp, "%04X\n", sp->s_addr);
+ } else
+ if (xflag == 1) {
+ fprintf(ofp, "%06o\n", sp->s_addr);
+ } else
+ if (xflag == 2) {
+ fprintf(ofp, "%05u\n", sp->s_addr);
+ }
+}
+
+/*)Function VOID out(p, n)
+ *
+ * int n number of words to output
+ * int * p pointer to data words
+ *
+ * The function out() outputs the data words to the .REL file
+ * int the specified radix.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * FILE * ofp relocation output file handle
+ * int xflag -x, listing radix flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * Data is sent to the .REL file.
+ */
+
+VOID
+out(char *p, int n)
+{
+ while (n--) {
+ if (xflag == 0) {
+ fprintf(ofp, " %02X", (*p++)&0xff);
+ } else
+ if (xflag == 1) {
+ fprintf(ofp, " %03o", (*p++)&0xff);
+ } else
+ if (xflag == 2) {
+ fprintf(ofp, " %03u", (*p++)&0xff);
+ }
+ }
+}
+
+/*)Function VOID out_lb(b, t)
+ *
+ * int b assembled data
+ * int t relocation type
+ *
+ * The function out_lb() copies the assembled data and
+ * its relocation type to the list data buffers.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int * cp pointer to assembler output array cb[]
+ * int * cpt pointer to assembler relocation type
+ * output array cbt[]
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * Pointers to data and relocation buffers incremented by 1.
+ */
+
+VOID
+out_lb(b,t)
+register int b,t;
+{
+ if (cp < &cb[NCODE]) {
+ *cp++ = b;
+ *cpt++ = t;
+ }
+}
+
+/*)Function VOID out_lw(n, t)
+ *
+ * int n assembled data
+ * int t relocation type
+ *
+ * The function out_lw() copies the assembled data and
+ * its relocation type to the list data buffers.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int * cp pointer to assembler output array cb[]
+ * int * cpt pointer to assembler relocation type
+ * output array cbt[]
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * Pointers to data and relocation buffers incremented by 2.
+ */
+
+VOID
+out_lw(n,t)
+register int n,t;
+{
+ if (hilo) {
+ out_lb(hibyte(n),t ? t|R_HIGH : 0);
+ out_lb(lobyte(n),t);
+ } else {
+ out_lb(lobyte(n),t);
+ out_lb(hibyte(n),t ? t|R_HIGH : 0);
+ }
+}
+
+/*)Function VOID out_l24(n, t)
+ *
+ * int n assembled data
+ * int t relocation type
+ *
+ * The function out_l24() copies the assembled data and
+ * its relocation type to the list data buffers.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int * cp pointer to assembler output array cb[]
+ * int * cpt pointer to assembler relocation type
+ * output array cbt[]
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * Pointers to data and relocation buffers incremented by 3.
+ */
+
+VOID
+out_l24(int n, int t)
+{
+ if (hilo) {
+ out_lb(byte3(n),t ? t|R_HIGH : 0);
+ out_lb(hibyte(n),t);
+ out_lb(lobyte(n),t);
+ } else {
+ out_lb(lobyte(n),t);
+ out_lb(hibyte(n),t);
+ out_lb(byte3(n),t ? t|R_HIGH : 0);
+ }
+}
+
+/*)Function VOID out_rw(n)
+ *
+ * int n data word
+ *
+ * The function out_rw() outputs the relocation (R)
+ * data word as two bytes ordered according to hilo.
+ *
+ * local variables:
+ * int * relp pointer to rel array
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * int lobyte() asout.c
+ * int hibyte() asout.c
+ *
+ * side effects:
+ * Pointer to relocation buffer incremented by 2.
+ */
+
+VOID
+out_rw(n)
+register int n;
+{
+ if (hilo) {
+ *relp++ = hibyte(n);
+ *relp++ = lobyte(n);
+ } else {
+ *relp++ = lobyte(n);
+ *relp++ = hibyte(n);
+ }
+}
+
+/*)Function VOID out_tw(n)
+ *
+ * int n data word
+ *
+ * The function out_tw() outputs the text (T)
+ * data word as two bytes ordered according to hilo.
+ *
+ * local variables:
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * int lobyte() asout.c
+ * int hibyte() asout.c
+ *
+ * side effects:
+ * Pointer to relocation buffer incremented by 2.
+ */
+
+VOID
+out_tw(n)
+register int n;
+{
+ if (hilo) {
+ *txtp++ = hibyte(n);
+ *txtp++ = lobyte(n);
+ } else {
+ *txtp++ = lobyte(n);
+ *txtp++ = hibyte(n);
+ }
+}
+
+/*)Function VOID out_t24(n)
+ *
+ * int n data word
+ *
+ * The function out_t24() outputs the text (T)
+ * data word as three bytes ordered according to hilo.
+ *
+ * local variables:
+ * int * txtp pointer to txt array
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * int lobyte() asout.c
+ * int hibyte() asout.c
+ *
+ * side effects:
+ * Pointer to relocation buffer incremented by 3.
+ */
+
+VOID
+out_t24(int n)
+{
+ if (hilo) {
+ *txtp++ = byte3(n);
+ *txtp++ = hibyte(n);
+ *txtp++ = lobyte(n);
+ } else {
+ *txtp++ = lobyte(n);
+ *txtp++ = hibyte(n);
+ *txtp++ = byte3(n);
+ }
+}
+
+/*)Function int lobyte(n)
+ *
+ * int n data word
+ *
+ * The function lobyte() returns the lower byte of
+ * integer n.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+lobyte(n)
+{
+ return (n&0377);
+}
+
+/*)Function int hibyte(n)
+ *
+ * int n data word
+ *
+ * The function hibyte() returns the higher byte of
+ * integer n.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+hibyte(n)
+{
+ return ((n>>8)&0377);
+}
+
+/*)Function int byte3(n)
+ *
+ * int n 24 bit data
+ *
+ * The function byte3() returns the MSB of the
+ * 24 bit integer n.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+int
+byte3(int n)
+{
+ return ((n >> 16) & 0xff);
+}
+
+/*
+ * JLH: Output relocatable 11 bit jump/call
+ *
+ * This function is derived from outrw(), adding the parameter for the
+ * 11 bit address. This form of address is used only on the 8051 and 8048.
+ */
+VOID
+outr11(esp, op, r)
+register struct expr *esp;
+int op;
+int r;
+{
+ register int n;
+
+ if (pass == 2) {
+ if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+ /* equated absolute destination. Assume value
+ * relative to current area */
+ esp->e_base.e_ap = dot.s_area;
+ }
+
+ /* Relocatable destination. Build THREE
+ * byte output: relocatable word, followed
+ * by op-code. Linker will combine them.
+ * Listing shows only the address.
+ */
+ r |= R_WORD | esp->e_rlcf;
+ out_lw(esp->e_addr,r|R_RELOC);
+ if (oflag) {
+ outchk(3, 5);
+ out_tw(esp->e_addr);
+ *txtp++ = op;
+
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+ write_rmode(r);
+ *relp++ = txtp - txt - 3;
+ out_rw(n);
+ }
+ }
+ dot.s_addr += 2;
+}
+
+/*
+ * Output relocatable 19 bit jump/call
+ *
+ * This function is derived from outrw(), adding the parameter for the
+ * 19 bit address. This form of address is used only in the DS80C390
+ * Flat24 mode.
+ */
+VOID
+outr19(struct expr * esp, int op, int r)
+{
+ register int n;
+
+ if (pass == 2) {
+ if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+ /* equated absolute destination. Assume value
+ * relative to current area */
+ esp->e_base.e_ap = dot.s_area;
+ }
+
+ /* Relocatable destination. Build FOUR
+ * byte output: relocatable 24-bit entity, followed
+ * by op-code. Linker will combine them.
+ * Listing shows only the address.
+ */
+ r |= R_WORD | esp->e_rlcf;
+ out_l24(esp->e_addr,r|R_RELOC);
+ if (oflag) {
+ outchk(4, 5);
+ out_t24(esp->e_addr);
+ *txtp++ = op;
+
+ if (esp->e_flag) {
+ n = esp->e_base.e_sp->s_ref;
+ r |= R_SYM;
+ } else {
+ n = esp->e_base.e_ap->a_ref;
+ }
+ write_rmode(r);
+ *relp++ = txtp - txt - 4;
+ out_rw(n);
+ }
+ }
+ dot.s_addr += 3;
+}
--- /dev/null
+/* strstore.c */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*
+ * Allocate space for "str", copy str into new space
+ * Return a pointer to the allocated name, or NULL if out of memory
+ */
+char *StoreString( char *str )
+{
+ /* To avoid wasting memory headers on small allocations, we
+ / allocate a big chunk and parcel it out as required.
+ / These static variables remember our hunk
+ */
+ #define STR_STORE_HUNK 2000
+ static char *pNextFree = NULL;
+ static int bytesLeft = 0;
+
+ int length;
+ char *pStoredString;
+
+ length = strlen( str ) + 1; /* what we need, including null */
+
+ if (length > bytesLeft)
+ {
+ /* no space. Allocate a new hunk. We lose the pointer to any
+ / old hunk. We don't care, as the names are never deleted.
+ */
+ pNextFree = (char*)new( STR_STORE_HUNK );
+ bytesLeft = STR_STORE_HUNK;
+ }
+
+ /* Copy the name and terminating null into the name store */
+ pStoredString = pNextFree;
+ memcpy( pStoredString, str, length );
+
+ pNextFree += length;
+ bytesLeft -= length;
+
+ return pStoredString;
+}
--- /dev/null
+/* assubr.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "asm.h"
+
+/*)Module assubr.c
+ *
+ * The module assubr.c contains the error
+ * processing routines.
+ *
+ * assubr.c contains the following functions:
+ * VOID aerr()
+ * VOID diag()
+ * VOID err()
+ * VOID qerr()
+ * VOID rerr()
+ *
+ * assubr.c contains the local array of *error[]
+ */
+
+/*)Function VOID err(c)
+ *
+ * int c error type character
+ *
+ * The function err() logs the error code character
+ * suppressing duplicate errors. If the error code
+ * is 'q' then the parse of the current assembler-source
+ * text line is terminated.
+ *
+ * local variables:
+ * char * p pointer to the error array
+ *
+ * global variables:
+ * char eb[] array of generated error codes
+ *
+ * functions called:
+ * VOID longjmp() c_library
+ *
+ * side effects:
+ * The error code may be inserted into the
+ * error code array eb[] or the parse terminated.
+ */
+
+VOID
+err(c)
+register int c;
+{
+ register char *p;
+
+ aserr++;
+ p = eb;
+ while (p < ep)
+ if (*p++ == c)
+ return;
+ if (p < &eb[NERR]) {
+ *p++ = c;
+ ep = p;
+ }
+ if (c == 'q')
+ longjmp(jump_env, -1);
+}
+
+/*)Function VOID diag()
+ *
+ * The function diag() prints any error codes and
+ * the source line number to the stderr output device.
+ *
+ * local variables:
+ * char * p pointer to error code array eb[]
+ *
+ * global variables:
+ * int cfile current source file index
+ * char eb[] array of generated error codes
+ * char * ep pointer into error list
+ * int incfile current include file index
+ * char incfn[] array of include file names
+ * int incline[] array of include line numbers
+ * char srcfn[] array of source file names
+ * int srcline[] array of source line numbers
+ * FILE * stderr c_library
+ *
+ * functions called:
+ * int fprintf() c_library
+ * char * geterr() assubr.c
+ *
+ * side effects:
+ * none
+ */
+
+extern int fatalErrors;
+
+VOID
+diag()
+{
+ register char *p,*errstr;
+
+ if (eb != ep) {
+ fatalErrors++;
+ p = eb;
+ fprintf(stderr, "?ASxxxx-Error-<");
+ while (p < ep) {
+ fprintf(stderr, "%c", *p++);
+ }
+ fprintf(stderr, "> in line ");
+ if (incfil >= 0) {
+ fprintf(stderr, "%d", incline[incfil]);
+ fprintf(stderr, " of %s\n", incfn[incfil]);
+ } else {
+ fprintf(stderr, "%d", srcline[cfile]);
+ fprintf(stderr, " of %s\n", srcfn[cfile]);
+ }
+ p = eb;
+ while (p < ep) {
+ if ((errstr = geterr(*p++)) != NULL) {
+ fprintf(stderr, " %s\n", errstr);
+ }
+ }
+ }
+}
+
+/*)Function VOID warnBanner()
+ *
+ * The function warnBanner() prints a generic warning message
+ * header (including the current source file/line) and positions
+ * the output for a more specific warning message.
+ *
+ * It is assumed that the call to warnBanner will be followed with
+ * a fprintf to stderr (or equivalent) with the specific warning
+ * text.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int cfile current source file index
+ * int incfile current include file index
+ * char incfn[] array of include file names
+ * int incline[] array of include line numbers
+ * char srcfn[] array of source file names
+ * int srcline[] array of source line numbers
+ * FILE * stderr c_library
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * none
+ */
+VOID
+warnBanner(void)
+{
+ fprintf(stderr, "?ASxxxx-Warning in line ");
+ if (incfil >= 0) {
+ fprintf(stderr, "%d", incline[incfil]);
+ fprintf(stderr, " of %s\n", incfn[incfil]);
+ } else {
+ fprintf(stderr, "%d", srcline[cfile]);
+ fprintf(stderr, " of %s\n", srcfn[cfile]);
+ }
+ fprintf(stderr, " ");
+}
+
+/*)Functions: VOID aerr()
+ * VOID qerr()
+ * VOID rerr()
+ *
+ * The functions aerr(), qerr(), and rerr() report their
+ * respective error type. These are included only for
+ * convenience.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * VOID err() assubr.c
+ *
+ * side effects:
+ * The appropriate error code is inserted into the
+ * error array and the parse may be terminated.
+ */
+
+/*
+ * Note an 'r' error.
+ */
+VOID
+rerr()
+{
+ err('r');
+}
+
+/*
+ * Note an 'a' error.
+ */
+VOID
+aerr()
+{
+ err('a');
+}
+
+/*
+ * Note a 'q' error.
+ */
+VOID
+qerr()
+{
+ err('q');
+}
+
+/*
+ * ASxxxx assembler errors
+ */
+char *errors[] = {
+ "<.> use \". = . + <arg>\" not \". = <arg>\"",
+ "<a> machine specific addressing or addressing mode error",
+ "<b> direct page boundary error",
+ "<d> direct page addressing error",
+ "<i> .include file error or an .if/.endif mismatch",
+ "<m> multiple definitions error",
+ "<o> .org in REL area or directive / mnemonic error",
+ "<p> phase error: label location changing between passes 2 and 3",
+ "<q> missing or improper operators, terminators, or delimiters",
+ "<r> relocation error",
+ "<u> undefined symbol encountered during assembly",
+ NULL
+};
+
+/*)Function: char *getarr(c)
+ *
+ * int c the error code character
+ *
+ * The function geterr() scans the list of errors returning the
+ * error string corresponding to the input error character.
+ *
+ * local variables:
+ * int i error index counter
+ *
+ * global variables:
+ * char *errors[] array of pointers to the
+ * error strings
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * A pointer to the appropriate
+ * error code string is returned.
+ */
+char *
+geterr(c)
+int c;
+{
+ int i;
+
+ for (i=0; errors[i]!=NULL; i++) {
+ if (c == errors[i][1]) {
+ return(errors[i]);
+ }
+ }
+ return(NULL);
+}
+
--- /dev/null
+/* assym.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - lookup: Use StoreString for sym construction
+ * - change symeq() to do length-independent string compare
+ * - change hash() to do length-independent hash calculation
+ * 29-Oct-97 JLH:
+ * - make mnemonics case insensitive ALWAYS
+ * - make hash() case-insensitive always
+ * - replace symeq() call in mlookup with strcmpi
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <alloc.h>
+#endif
+#include "asm.h"
+#include "strcmpi.h"
+
+/*)Module assym.c
+ *
+ * The module assym.c contains the functions that operate
+ * on the mnemonic/directive and symbol structures.
+ *
+ * assym.c contains the following functions:
+ * VOID allglob()
+ * area * alookup()
+ * int hash()
+ * sym * lookup()
+ * mne * mlookup()
+ * VOID * new()
+ * int symeq()
+ * VOID syminit()
+ * VOID symglob()
+ *
+ * assym.c contains no local/static variables.
+ */
+
+/*)Function VOID syminit()
+ *
+ * The function syminit() is called early in the game
+ * to set up the hashtables. First all buckets in a
+ * table are cleared. Then a pass is made through
+ * the respective symbol lists, linking them into
+ * their hash buckets. Finally the base area pointer
+ * is set to 'dca'.
+ *
+ * local variables:
+ * int h computed hash value
+ * mne * mp pointer to a mne structure
+ * mne ** mpp pointer to an array of
+ * mne structure pointers
+ * sym * sp pointer to a sym structure
+ * sym ** spp pointer to an array of
+ * sym structure pointers
+ *
+ * global variables:
+ * area area[] single elememt area array
+ * area dca defined as area[0]
+ * mne * mnehash[] array of pointers to NHASH
+ * linked mnemonic/directive lists
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * (1) The symbol hash tables are initialized,
+ * the only defined symbol is '.'.
+ * (2) The mnemonic/directive hash tables are
+ * initialized with the assembler directives
+ * and mnemonics found in the machine dependent
+ * file ___pst.c.
+ * (3) The area pointer is initialized to dca (area[0]).
+ */
+
+VOID
+syminit()
+{
+ register struct mne *mp;
+ struct mne **mpp;
+ register struct sym *sp;
+ struct sym **spp;
+ register int h;
+
+ mpp = &mnehash[0];
+ while (mpp < &mnehash[NHASH])
+ *mpp++ = NULL;
+ mp = &mne[0];
+ for (;;) {
+ h = hash(mp->m_id);
+ mp->m_mp = mnehash[h];
+ mnehash[h] = mp;
+ if (mp->m_flag&S_END)
+ break;
+ ++mp;
+ }
+
+ spp = &symhash[0];
+ while (spp < &symhash[NHASH])
+ *spp++ = NULL;
+ sp = &sym[0];
+ for (;;) {
+ h = hash(sp->s_id);
+ sp->s_sp = symhash[h];
+ symhash[h] = sp;
+ if (sp->s_flag&S_END)
+ break;
+ ++sp;
+ }
+
+ areap = &dca;
+}
+
+/*)Function area * alookup(id)
+ *
+ * char * id area name string
+ *
+ * The function alookup() searches the area list for a
+ * match with id. If the area is defined then a pointer
+ * to this area is returned else a NULL is returned.
+ *
+ * local variables:
+ * area * ap pointer to area structure
+ *
+ * global variables:
+ * area * areap pointer to an area structure
+ *
+ * functions called:
+ * int symeq() assym.c
+ *
+ * side effects:
+ * none
+ */
+
+struct area *
+alookup(id)
+char *id;
+{
+ register struct area *ap;
+
+ ap = areap;
+ while (ap) {
+ if (symeq(id, ap->a_id)) {
+ return (ap);
+ }
+ ap = ap->a_ap;
+ }
+ return(NULL);
+}
+
+/*)Function mne * mlookup(id)
+ *
+ * char * id mnemonic/directive name string
+ *
+ * The function mlookup() searches the mnemonic/directive
+ * hash tables for a match returning a pointer to the
+ * mne structure else it returns a NULL.
+ *
+ * local variables:
+ * mne * mp pointer to mne structure
+ * int h calculated hash value
+ *
+ * global variables:
+ * mne * mnehash[] array of pointers to NHASH
+ * linked mnemonic/directive lists
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+struct mne *
+mlookup(id)
+char *id;
+{
+ register struct mne *mp;
+ register int h;
+
+ h = hash(id);
+ mp = mnehash[h];
+ while (mp) {
+ if (as_strcmpi(id, mp->m_id) == 0) /* JLH: case insensitive */
+ return (mp);
+ mp = mp->m_mp;
+ }
+ return (NULL);
+}
+
+/*)Function sym * lookup(id)
+ *
+ * char * id symbol name string
+ *
+ * The function lookup() searches the symbol hash tables for
+ * a symbol name match returning a pointer to the sym structure.
+ * If the symbol is not found then a sym structure is created,
+ * initialized, and linked to the appropriate hash table.
+ * A pointer to this new sym structure is returned.
+ *
+ * local variables:
+ * int h computed hash value
+ * sym * sp pointer to a sym structure
+ *
+ * global varaibles:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * int hash() assym.c
+ * VOID * new() assym.c
+ * int symeq() assym.c
+ *
+ * side effects:
+ * If the function new() fails to allocate space
+ * for the new sym structure the assembly terminates.
+ */
+
+struct sym *
+lookup(id)
+char *id;
+{
+ register struct sym *sp;
+ register int h;
+
+ h = hash(id);
+ sp = symhash[h];
+ while (sp) {
+ if (symeq(id, sp->s_id))
+ return (sp);
+ sp = sp->s_sp;
+ }
+ sp = (struct sym *) new (sizeof(struct sym));
+ sp->s_sp = symhash[h];
+ symhash[h] = sp;
+ sp->s_tsym = NULL;
+ sp->s_id = StoreString( id ); /* JLH */
+ sp->s_type = S_NEW;
+ sp->s_flag = 0;
+ sp->s_area = NULL;
+ sp->s_ref = 0;
+ sp->s_addr = 0;
+ return (sp);
+}
+
+/*)Function VOID symglob()
+ *
+ * The function symglob() will mark all symbols of
+ * type S_NEW as global. Called at the beginning of pass 1
+ * if the assembly option -g was specified.
+ *
+ * local variables:
+ * sym * sp pointer to a sym structure
+ * int i loop index
+ *
+ * global variables:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * Symbol types changed.
+ */
+
+VOID
+symglob()
+{
+ register struct sym *sp;
+ register int i;
+
+ for (i=0; i<NHASH; ++i) {
+ sp = symhash[i];
+ while (sp != NULL) {
+ if (sp->s_type == S_NEW)
+ sp->s_flag |= S_GBL;
+ sp = sp->s_sp;
+ }
+ }
+}
+
+/*)Function VOID allglob()
+ *
+ * The function allglob() will mark all symbols of
+ * type S_USER as global. Called at the beginning of pass 1
+ * if the assembly option -a was specified.
+ *
+ * local variables:
+ * sym * sp pointer to a sym structure
+ * int i loop index
+ *
+ * global variables:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * Symbol types changed.
+ */
+
+VOID
+allglob()
+{
+ register struct sym *sp;
+ register int i;
+
+ for (i=0; i<NHASH; ++i) {
+ sp = symhash[i];
+ while (sp != NULL) {
+ if (sp != &dot && sp->s_type == S_USER)
+ sp->s_flag |= S_GBL;
+ sp = sp->s_sp;
+ }
+ }
+}
+
+/*)Function int symeq(p1, p2)
+ *
+ * char * p1 name string
+ * char * p2 name string
+ *
+ * The function symeq() compares the two name strings for a match.
+ * The return value is 1 for a match and 0 for no match.
+ *
+ * local variables:
+ * int h loop counter
+ *
+ * global variables:
+ * char ccase[] an array of characters which
+ * perform the case translation function
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ *
+ */
+
+int
+symeq(p1, p2)
+register char *p1, *p2;
+{
+#if CASE_SENSITIVE
+ return (strcmp( p1, p2 ) == 0);
+#else
+ return (as_strcmpi( p1, p2 ) == 0);
+#endif
+}
+
+/*)Function int hash(p)
+ *
+ * char * p pointer to string to hash
+ *
+ * The function hash() computes a hash code using the sum
+ * of all characters mod table size algorithm.
+ *
+ * local variables:
+ * int h accumulated character sum
+ * int n loop counter
+ *
+ * global variables:
+ * char ccase[] an array of characters which
+ * perform the case translation function
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+hash(p)
+register char *p;
+{
+ register int h;
+
+ h = 0;
+ while (*p) {
+ /* JLH: case insensitive hash: Doesn't much affect
+ * hashing, and allows same function for mnemonics and symbols
+ */
+ h += ccase[(int)*p++];
+ }
+ return (h&HMASK);
+}
+
+/*)Function VOID * new(n)
+ *
+ * unsigned int n allocation size in bytes
+ *
+ * The function new() allocates n bytes of space and returns
+ * a pointer to this memory. If no space is available the
+ * assembly is terminated.
+ *
+ * local variables:
+ * VOID * p a general pointer
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * VOID asexit() asmain.c
+ * int fprintf() c_library
+ * VOID * malloc() c_library
+ *
+ * side effects:
+ * Memory is allocated, if allocation fails
+ * the assembly is terminated.
+ */
+
+VOID *
+new(n)
+unsigned int n;
+{
+ register VOID *p;
+
+ if ((p = (VOID *) malloc(n)) == NULL) {
+ fprintf(stderr, "Out of space!\n");
+ asexit(1);
+ }
+ return (p);
+}
--- /dev/null
+# Deleting all files created by building the program
+# --------------------------------------------------
+include ../../Makefile.common
+PRJDIR = ../..
+
+clean:
+ rm -f *core *[%~] *.[oa]
+ rm -f .[a-z]*~
+ rm -f $(PRJDIR)/bin/as-hc08$(EXEEXT) $(PRJDIR)/bin/link-hc08$(EXEEXT) as-hc08$(EXEEXT) link-hc08$(EXEEXT)
+
+
+# Deleting all files created by configuring or building the program
+# -----------------------------------------------------------------
+distclean: clean
+ rm -f Makefile *.dep
+
+
+# Like clean but some files may still exist
+# -----------------------------------------
+mostlyclean: clean
+
+
+# Deleting everything that can reconstructed by this Makefile. It deletes
+# everything deleted by distclean plus files created by bison, etc.
+# -----------------------------------------------------------------------
+realclean: distclean
--- /dev/null
+#
+# Makefile targets to remake configuration
+#
+
+freshconf: Makefile
+
+Makefile: $(srcdir)/Makefile.in $(PRJDIR)/configure.in
+ cd $(PRJDIR) && $(SHELL) ./config.status
+
+# End of conf.mk
--- /dev/null
+/*-------------------------------------------------------------------------
+ lkaomf51.c - Create an absolute object memory format 51 file
+
+ Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+#define EQ(A,B) !strcmp((A),(B))
+#define MEMSIZE 0x10000
+//#define DODUMP 1
+
+typedef struct
+{
+ char PathName[PATH_MAX];
+ char ModuleName[PATH_MAX];
+} _infn;
+
+int numin=0;
+_infn * infn=NULL;
+
+char ihxFileName[PATH_MAX];
+char aomf51FileName[PATH_MAX];
+
+typedef struct
+{
+ char name[0x100];
+ int FileNameNumber;
+ int Procedure;//If the symbol belongs to a function
+ int Static; //If the symbol is only public on its file
+ int Address;
+ int UsageType;
+} _symbol;
+
+int numsym=0;
+_symbol * symbol=NULL;
+
+typedef struct
+{
+ char name[0x100];
+ int FileNameNumber;
+ int BeginAdd;
+ int EndAdd;
+} _procedure;
+
+int numproc=0;
+_procedure * procedure=NULL;
+
+typedef struct
+{
+ int Number;
+ int Address;
+ int Procedure;
+ int FileNameNumber;
+} _linenum;
+
+int numlinenum=0;
+_linenum * linenum=NULL;
+
+typedef struct
+{
+ char * name;
+ int usage;
+}
+_UsageType;
+
+_UsageType UsageType[]=
+{
+ {"CSEG", 0},
+ {"GSINIT", 0},
+ {"GSFINAL", 0},
+ {"HOME", 0},
+ {"XINIT", 0},
+ {"XSEG", 1},
+ {"XISEG", 1},
+ {"REG_BANK_0", 2},
+ {"REG_BANK_1", 2},
+ {"REG_BANK_2", 2},
+ {"REG_BANK_3", 2},
+ {"DSEG", 2},
+ {"OSEG", 2},
+ {"SSEG", 2},
+ {"ISEG", 3},
+ {"BSEG", 4},
+ {"", 5} /*A typeless number?*/
+};
+
+char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"};
+int AddNumber;
+unsigned char * ihxBuff=NULL;
+FILE * aomf51out;
+int GlobalChkSum=0;
+int HexSize, HexBegin=0x10000;
+
+
+void GetName(char * filepath, char * name)
+{
+ int j, k;
+ for(j=strlen(filepath); j>0; j--)
+ if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break;
+ for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++)
+ name[k]=filepath[j];
+ name[k]=0;
+}
+
+void SaveLinkedFilePath(char * filepath)
+{
+ int j;
+
+ if((dflag) && (!rflag))
+ {
+ infn=realloc(infn, sizeof(_infn)*(numin+1));
+
+ strcpy(infn[numin].PathName, filepath);
+ j=strlen(infn[numin].PathName);
+
+ /*If there is an extension remove it*/
+ if(j>=4)
+ {
+ if(EQ(&infn[numin].PathName[j-4], ".rel"))
+ {
+ infn[numin].PathName[j-4]=0;
+ }
+ }
+
+ /*Get the module name=filename, no drive, no dir, no ext*/
+ GetName(infn[numin].PathName, infn[numin].ModuleName);
+ //printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName);
+
+ /*Check if this filename is already in*/
+ for(j=0; j<numin; j++)
+ {
+ if(EQ(infn[numin].PathName, infn[j].PathName)) break;
+ }
+ if(j==numin) numin++;
+ }
+}
+
+void FreeAll(void)
+{
+ if(infn!=NULL)
+ {
+ free(infn);
+ numin=0;
+ infn=NULL;
+ }
+
+ if(symbol!=NULL)
+ {
+ free(symbol);
+ numsym=0;
+ symbol=NULL;
+ }
+
+ if(procedure!=NULL)
+ {
+ free(procedure);
+ numproc=0;
+ procedure=NULL;
+
+ }
+ if(linenum!=NULL)
+ {
+ free(linenum);
+ numlinenum=0;
+ linenum=NULL;
+ }
+
+ if(ihxBuff!=NULL)
+ {
+ free(ihxBuff);
+ ihxBuff=NULL;
+ }
+}
+
+void OutputByte(unsigned char value)
+{
+ GlobalChkSum+=value;
+ fwrite( &value, 1, 1, aomf51out );
+}
+
+void OutputWord(int value)
+{
+ OutputByte((unsigned char)(value%0x100));
+ OutputByte((unsigned char)(value/0x100));
+}
+
+void OutputName(char * name)
+{
+ int k;
+ OutputByte((unsigned char)strlen(name));
+ for(k=0; name[k]!=0; k++)
+ OutputByte((unsigned char)toupper(name[k]));
+}
+
+void OutputChkSum(void)
+{
+ OutputByte((unsigned char)(0x100-(GlobalChkSum%0x100)));
+ GlobalChkSum=0;
+}
+
+#ifdef DODUMP
+void DumpForDebug (void)
+{
+ char DumpFileName[PATH_MAX];
+ FILE * DumpFile;
+ int j, k;
+
+ strcpy(DumpFileName, infn[0].PathName);
+ strcat(DumpFileName, ".d51");
+
+ DumpFile=fopen(DumpFileName, "wb");
+ if(DumpFile==NULL)
+ {
+ printf("Couldn't create file %s\n", DumpFileName);
+ return;
+ }
+
+ fprintf(DumpFile,"SYMBOLS:\n");
+
+ for(j=0; j<numsym; j++)
+ {
+ k=symbol[j].UsageType&0xf;
+ fprintf(DumpFile, "%s, %s, %s, 0x%04x, %s\n",
+ symbol[j].name,
+ infn[symbol[j].FileNameNumber].PathName,
+ (symbol[j].Procedure>=0)?procedure[symbol[j].Procedure].name:"GLOBAL",
+ symbol[j].Address,
+ k<6?UsageTypeName[k]:"???");
+ }
+
+ fprintf(DumpFile,"\nPROCEDURES:\n");
+ for(j=0; j<numproc; j++)
+ {
+ fprintf(DumpFile, "%s, %s, 0x%04x-0x%04x\n",
+ procedure[j].name,
+ infn[procedure[j].FileNameNumber].PathName,
+ procedure[j].BeginAdd,
+ procedure[j].EndAdd);
+ }
+
+ fprintf(DumpFile,"\nLINE NUMBERS:\n");
+ for(j=0; j<numlinenum; j++)
+ {
+ fprintf(DumpFile, "%d:0x%04x, %s -> %s\n",
+ linenum[j].Number,
+ linenum[j].Address,
+ infn[linenum[j].FileNameNumber].PathName,
+ (linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know");
+ }
+
+ fclose(DumpFile);
+}
+#endif
+
+void OutputAOEMF51(void)
+{
+ int i, j, k, recsize;
+ char MHRname[0x100], Mname[0x100];
+
+ strcpy(aomf51FileName, infn[0].PathName);
+
+ aomf51out=fopen(aomf51FileName, "wb");
+ if(aomf51out==NULL)
+ {
+ printf("Couldn't create file %s\n", aomf51FileName);
+ return;
+ }
+
+ GetName(infn[0].PathName, MHRname);
+ GlobalChkSum=0;
+
+ /*Module header record*/
+ OutputByte(0x02);/*REC TYPE*/
+ OutputWord((strlen(MHRname)+1)+3);/*Record Length*/
+ OutputName(MHRname);/*Module Name*/
+ OutputByte(0xff);/*TRN ID: RL51?*/
+ OutputByte(0x00);
+ OutputChkSum();
+
+ for(j=0; j<numin; j++)
+ {
+ GetName(infn[j].PathName, Mname);
+
+ /*Scope Definition record: begin module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x00);/*BLK TYP: module block*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+
+ /*Public symbols defined in this module*/
+ recsize=2;
+ for(k=0; k<numsym; k++)/*Compute the record length*/
+ if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==-1) ) recsize+=((strlen(symbol[k].name)+1)+5);
+
+ if(recsize>2) /*If there are any symbols*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x01); /*DEF TYPE: Public symbols*/
+ for(k=0; k<numsym; k++)
+ {
+ if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==-1) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
+ OutputWord(symbol[k].Address);/*Offset*/
+ OutputByte(0x00);
+ OutputName(symbol[k].name);/*Symbol name*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Local symbols defined in this module*/
+ recsize=2;
+ for(k=0; k<numsym; k++)/*Compute the record length*/
+ if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==j) ) recsize+=((strlen(symbol[k].name)+1)+5);
+
+ if(recsize>2) /*If there are any symbols*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x00); /*DEF TYPE: Local symbols*/
+ for(k=0; k<numsym; k++)
+ {
+ if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
+ (symbol[k].Procedure==-1) &&
+ (symbol[k].Static==j) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
+ OutputWord(symbol[k].Address);/*Offset*/
+ OutputByte(0x00);
+ OutputName(symbol[k].name);/*Symbol name*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Output the procedures of this module*/
+
+ for(k=0; k<numproc; k++)
+ {
+ if(procedure[k].FileNameNumber==j)
+ {
+ /*Scope Definition record: begin PROCEDURE block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
+ OutputByte(0x02);/*BLK TYP: PROCEDURE block*/
+ OutputName(procedure[k].name);/*Module Name*/
+ OutputChkSum();
+
+ /*Content Record*/
+ OutputByte(0x06);/*REC TYPE*/
+ if(procedure[k].EndAdd==-1) procedure[k].EndAdd=HexSize;
+ recsize=procedure[k].EndAdd-procedure[k].BeginAdd+1+4;
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x00);/*SEG ID*/
+ OutputWord(procedure[k].BeginAdd); /*Offset*/
+ for(i=procedure[k].BeginAdd; i<=procedure[k].EndAdd; i++)
+ OutputByte(ihxBuff[i]);
+ OutputChkSum();
+
+ /*Local Symbols*/
+
+ recsize=2;
+ for(i=0; i<numsym; i++)/*Get the record length*/
+ if(symbol[i].Procedure==k)
+ recsize+=((strlen(symbol[i].name)+1)+5);
+
+ if(recsize>2) /*If there are any symbols*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x00); /*DEF TYPE: Local symbols*/
+ for(i=0; i<numsym; i++)
+ {
+ if ( (symbol[i].Procedure==k) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputByte((unsigned char)symbol[i].UsageType);/*SYM INFO*/
+ OutputWord(symbol[i].Address);/*Offset*/
+ OutputByte(0x00);
+ OutputName(symbol[i].name);/*Symbol name*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Line Numbers*/
+ recsize=2;
+ for(i=0; i<numlinenum; i++)/*Get the record length*/
+ if(linenum[i].Procedure==k) recsize+=5;
+
+ if(recsize>2) /*If there are any line numbers*/
+ {
+ OutputByte(0x12); /*REC TYPE*/
+ OutputWord(recsize);/*Record Length*/
+ OutputByte(0x03); /*DEF TYPE: Line numbers*/
+ for(i=0; i<numlinenum; i++)
+ {
+ if ( (linenum[i].Procedure==k) )
+ {
+ OutputByte(0x00);/*SEG ID*/
+ OutputWord(linenum[i].Address);/*Offset*/
+ OutputWord(linenum[i].Number);/*Line Number*/
+ }
+ }
+ OutputChkSum();
+ }
+
+ /*Scope Definition record: end PROCEDURE block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
+ OutputByte(0x05);/*BLK TYP: PROCEDURE end block*/
+ OutputName(procedure[k].name);/*Module Name*/
+ OutputChkSum();
+ }
+ }
+
+ /*Scope Definition record: end module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x03);/*BLK TYP: module end*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+ }
+
+ /*Content records for everything that is not in the above procedures*/
+ strcpy(Mname, "OTHER_SDCC_STUF");
+
+ /*Scope Definition record: begin module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x00);/*BLK TYP: module block*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+
+ for(j=-1; j<numproc; j++)
+ {
+ if(numproc)
+ {
+ if(j==-1)
+ {
+ i=HexBegin;
+ k=procedure[0].BeginAdd;
+ }
+ else if(j==(numproc-1))
+ {
+ i=procedure[j].EndAdd+1;
+ k=HexSize;
+ }
+ else
+ {
+ i=procedure[j].EndAdd+1;
+ k=procedure[j+1].BeginAdd;
+ }
+ }
+ else /*What, no procedures??? Ok, here it is the whole hex file*/
+ {
+ i=HexBegin;
+ k=HexSize;
+ }
+
+ if(i<k)
+ {
+ /*Content Record*/
+ OutputByte(0x06);/*REC TYPE*/
+ OutputWord(k-i+4);/*Record Length*/
+ OutputByte(0x00);/*SEG ID*/
+ OutputWord(i); /*Offset*/
+ for(; i<k; i++) OutputByte(ihxBuff[i]);
+ OutputChkSum();
+ }
+ }
+
+ /*Scope Definition record: end module block*/
+ OutputByte(0x10);/*REC TYPE*/
+ OutputWord((strlen(Mname)+1)+2);/*Record Length*/
+ OutputByte(0x03);/*BLK TYP: module end*/
+ OutputName(Mname);/*Module Name*/
+ OutputChkSum();
+
+ /*Module end record*/
+ OutputByte(0x04);/*REC TYPE*/
+ OutputWord((strlen(MHRname)+1)+5);/*Record Length*/
+ OutputName(MHRname);/*Module Name*/
+ OutputWord(0x00);
+ OutputByte(0x0f);/*REG MSK: All the register banks?*/
+ OutputByte(0x00);
+ OutputChkSum();
+
+ fclose(aomf51out);
+}
+
+void CollectInfoFromCDB(void)
+{
+ int i, j, k, CurrentModule;
+ FILE * CDBin;
+ char buff[0x1000];
+ char SourceName[PATH_MAX];
+
+ //"S:{G|F<filename>|L<functionName>}$<name>$<level>$<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>"
+ char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s";
+ char c;
+ char scope[0x100];
+ char name[0x100];
+ char level[0x100];
+ char block[0x100];
+ char Bfmt[]="%[^)] %c %c %c %c %d %c %d";
+ char TypeInfo[0x100];
+ char AddressSpace;
+ int OnStack;
+ int StackOffset;
+ int Address, CLine;
+
+ if(numin==0) return;
+
+ if (dfp != NULL)
+ {
+ fclose(dfp);
+ dfp=NULL;
+ }
+
+ /*Build the source filename*/
+ strcpy(SourceName, infn[0].PathName);
+ strcat(SourceName, ".cdb");
+ CDBin=fopen(SourceName, "r");
+ if(CDBin==NULL)
+ {
+ printf("Couldn't open file '%s'\n", SourceName);
+ lkexit(1);
+ }
+
+ CurrentModule=0; /*Set the active module as the first one*/
+ while(!feof(CDBin))
+ {
+ fgets(buff, sizeof(buff)-1, CDBin);
+
+ if(!feof(CDBin)) switch(buff[0])
+ {
+ /*Example: "M:adq"*/
+ case 'M':
+ sscanf(&buff[2], "%s", name);
+ for(j=0; j<numin; j++)
+ if(EQ(infn[j].ModuleName, name)) break;
+ if(j<numin) CurrentModule=j;
+ break;
+
+ /* Example:
+ "S:G$actual$0$0({7}ST__00010000:S),E,0,0"
+ "S:Lmain$j$1$1({2}SI:S),E,0,0"
+ "S:G$DS1306_Reset_SPI$0$0({2}DF,SV:S),C,0,0"
+ "S:G$main$0$0({2}DF,SV:S),C,0,0"
+ */
+
+ case 'S':
+ sscanf(buff, Sfmt,
+ scope, &c,
+ name, &c,
+ level, &c,
+ block);
+
+ /*<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>*/
+ sscanf(block, Bfmt,
+ TypeInfo, &c, &c,
+ &AddressSpace, &c,
+ &OnStack, &c,
+ &StackOffset);
+
+ i=-1; k=-1;
+ switch(scope[2])
+ {
+ case 'G': /*Global symbol*/
+ break;
+ case 'L': /*Local symbol of a procedure*/
+ for(j=0; j<numproc; j++)
+ {
+ if(EQ(&scope[3], procedure[j].name)) break;
+ }
+ if(j<numproc) k=j; /*Local symbol*/
+ break;
+ case 'F': /*Local symbol to a module*/
+ for(j=0; j<numin; j++)
+ {
+ if(EQ(&scope[3], infn[j].ModuleName)) break;
+ }
+ if(j<numin) i=j;
+ break;
+ }
+
+ /*This symbol may have been already defined*/
+ for(j=0; j<numsym; j++)
+ {
+ if( EQ(name, symbol[j].name) &&
+ (symbol[j].Procedure==k) &&
+ (symbol[j].Static==i) ) break;
+ }
+ if(j==numsym) /*New symbol*/
+ {
+ symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
+ symbol[numsym].FileNameNumber=CurrentModule;
+ strcpy(symbol[numsym].name, name);
+ symbol[numsym].Procedure=k;
+ symbol[numsym].Static=i;
+ symbol[numsym].Address=-1;/*Collected later*/
+
+ switch(AddressSpace)
+ {
+ case 'C': /*Code*/
+ case 'D': /*Code/static segment*/
+ case 'Z': /*Functions and undefined code space*/
+ symbol[numsym].UsageType=0x40;
+ break;
+
+ case 'F': /*External ram*/
+ case 'A': /*External stack*/
+ symbol[numsym].UsageType=0x41;
+ break;
+
+ case 'E': /*Internal ram (lower 128) bytes*/
+ case 'I': /*SFR space*/
+ case 'R': /*Register Space*/
+ symbol[numsym].UsageType=0x42;
+ break;
+
+ case 'B': /*Internal stack*/
+ case 'G': /*Internal ram*/
+ symbol[numsym].UsageType=0x43;
+ break;
+
+ case 'H': /*Bit addressable*/
+ case 'J': /*SBIT space*/
+ symbol[numsym].UsageType=0x44;
+ break;
+
+ default:
+ printf("Unknown scope information for: %s, AddressSpace:%c\n", symbol[numsym].name, AddressSpace);
+ break;
+ }
+ numsym++;
+ }
+ break;
+
+ /*Examples:
+ F:G$AsciiToHex$0$0({2}DF,SC:U),C,0,0,0,0,0
+ F:G$main$0$0({2}DF,SV:S),C,0,0,0,0,0 */
+
+ case 'F':
+ sscanf(buff, "%[^$] %c %[^$]", scope, &c, name);
+ /*The same may have been already defined */
+ for(j=0; j<numproc; j++)
+ {
+ if(EQ(name, procedure[j].name)) break;
+ }
+ if(j==numproc)
+ {
+ procedure=realloc(procedure, sizeof(_procedure)*(numproc+1));
+ strcpy(procedure[numproc].name, name);
+ procedure[numproc].FileNameNumber=CurrentModule;
+ procedure[numproc].BeginAdd=-1;/*To be collected latter*/
+ procedure[numproc].EndAdd=-1;/*To be collected latter*/
+ numproc++;
+ }
+
+ /*This function name is also a global symbol*/
+ for(j=0; j<numsym; j++)/*A global symbol may have been already defined*/
+ {
+ if( EQ(name, symbol[j].name) && (symbol[j].Procedure==-1) ) break;
+ }
+ if(j==numsym)
+ {
+ symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
+ symbol[numsym].FileNameNumber=CurrentModule;
+ strcpy(symbol[numsym].name, name);
+ symbol[numsym].UsageType=0x00;/*A procedure name symbol*/
+ symbol[numsym].Procedure=-1; /*Global symbol*/
+ symbol[numsym].Address=-1;/*Collected later*/
+ numsym++;
+ }
+ break;
+
+ case 'L':
+ switch(buff[2])
+ {
+ case 'G': /*Example L:G$P0$0$0:80*/
+ sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(j=0; j<numsym; j++)
+ {
+ if(EQ(symbol[j].name, name))
+ {
+ if( (symbol[j].Address==-1) && (symbol[j].Procedure==-1) )
+ {
+ symbol[j].Address=Address;
+ }
+
+ /*If the symbol is the name of a procedure, the address is also
+ the begining of such procedure*/
+ if((symbol[j].UsageType&0x0f)==0x00)
+ {
+ for(k=0; k<numproc; k++)
+ {
+ if(EQ(symbol[j].name, procedure[k].name))
+ {
+ if(procedure[k].BeginAdd==-1)
+ procedure[k].BeginAdd=Address;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ break;
+
+ case 'F': /*Example L:Fadq$_str_2$0$0:57A*/
+ sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(j=0; j<numsym; j++)
+ {
+ if(EQ(symbol[j].name, name))
+ {
+ if( (symbol[j].Address==-1) ) symbol[j].Address=Address;
+ break;
+ }
+ }
+
+ /*It could be also a static function*/
+ for(j=0; j<numproc; j++)
+ {
+ if(EQ(procedure[j].name, name))
+ {
+ if( (procedure[j].BeginAdd==-1) ) procedure[j].BeginAdd=Address;
+ break;
+ }
+ }
+
+ break;
+
+ case 'L': /*Example L:Lmain$j$1$1:29*/
+
+ /*
+ L:LDS1306_Write$Value$1$1:34
+ L:LDS1306_Burst_Read$count$1$1:35
+ L:LDS1306_Burst_Read$address$1$1:36
+ L:LDS1306_Burst_Write$count$1$1:37
+ L:LDS1306_Burst_Write$address$1$1:38
+ */
+ sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(k=0; k<numproc; k++)
+ {
+ if(EQ(procedure[k].name, scope)) break;
+ }
+
+ if(k<numproc) for(j=0; j<numsym; j++)
+ {
+ if( EQ(symbol[j].name, name) && (symbol[j].Procedure==k) )
+ {
+ if(symbol[j].Address==-1) symbol[j].Address=Address;
+ break;
+ }
+ }
+ break;
+
+ /*Line Numbers*/
+ case 'C': /*Example L:C$adq.c$38$1$1:3E*/ /*L:C$hwinit.c$29$1$1:7AD*/
+ sscanf(&buff[4], "%[^.] %[^$] %c %d %[^:] %c %x",
+ name, level, &c, &CLine, level, &c, &Address);
+
+ for(j=0; j<numin; j++)
+ if(EQ(infn[j].ModuleName, name)) break;
+ if(j<numin)
+ {
+ /*Check if this line is already defined*/
+ for(k=0; k<numlinenum; k++)
+ {
+ if( (linenum[k].Number==CLine) &&
+ (linenum[k].FileNameNumber==j) )break;
+ }
+ if(k==numlinenum) /*New line number*/
+ {
+ linenum=realloc(linenum, sizeof(_linenum)*(numlinenum+1));
+ linenum[numlinenum].Number=CLine;
+ linenum[numlinenum].FileNameNumber=j;
+ linenum[numlinenum].Procedure=-1;/*To be asigned later*/
+ linenum[numlinenum].Address=Address;
+ numlinenum++;
+ }
+ }
+ break;
+
+ case 'A': /*Example L:A$adq$424:40*/
+ /*No use for this one*/
+ break;
+
+ /*The end of a procedure*/
+ case 'X': /*Example L:XG$AsciiToHex$0$0:88*/
+ sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
+ scope, &c, name, &c, level, &c, &Address);
+
+ for(k=0; k<numproc; k++)
+ {
+ if(EQ(procedure[k].name, name))
+ {
+ if(procedure[k].EndAdd==-1) procedure[k].EndAdd=Address;
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*Make sure each procedure has an end*/
+ for(k=0; k<(numproc-1); k++)
+ {
+ if (procedure[k].EndAdd==-1) procedure[k].EndAdd=procedure[k+1].BeginAdd-1;
+ }
+ /*Asign each line number to a procedure*/
+ for(j=0; j<numlinenum; j++)
+ {
+ for(k=0; k<numproc; k++)
+ {
+ if ( (linenum[j].Address>=procedure[k].BeginAdd) &&
+ (linenum[j].Address<=procedure[k].EndAdd) &&
+ (linenum[j].FileNameNumber==procedure[k].FileNameNumber) )
+ {
+ linenum[j].Procedure=k;
+ }
+ }
+ }
+
+ fclose(CDBin);
+}
+
+int hex2dec (char hex_digit)
+{
+ int j;
+ j=toupper(hex_digit)-'0';
+ if (j>9) j -= 7;
+ return j;
+}
+
+unsigned char GetByte(char * buffer)
+{
+ return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]);
+}
+
+unsigned short GetWord(char * buffer)
+{
+ return hex2dec(buffer[0])*0x1000+
+ hex2dec(buffer[1])*0x100+
+ hex2dec(buffer[2])*0x10+
+ hex2dec(buffer[3]);
+}
+
+int ReadHexFile(int * Begin)
+{
+ char buffer[1024];
+ FILE * filein;
+ int j;
+ unsigned char linesize, recordtype, rchksum, value;
+ unsigned short address;
+ int MaxAddress=0;
+ int chksum;
+
+ /*If the hexfile is already open, close it*/
+ if(ofp!=NULL)
+ {
+ fclose(ofp);
+ ofp=NULL;
+ }
+
+ strcpy(ihxFileName, infn[0].PathName);
+ strcat(ihxFileName, ".ihx");
+
+ if ( (filein=fopen(ihxFileName, "r")) == NULL )
+ {
+ printf("Error: Can't open file `%s`.\r\n", ihxFileName);
+ return 0;
+ }
+
+ ihxBuff=calloc(MEMSIZE, sizeof(unsigned char));
+ if(ihxBuff==NULL)
+ {
+ printf("Insufficient memory\n");
+ fclose(filein);
+ return -1;
+ }
+
+ for(j=0; j<MEMSIZE; j++) ihxBuff[j]=0xff;
+
+ while(1)
+ {
+ if(fgets(buffer, sizeof(buffer), filein)==NULL)
+ {
+ printf("Error reading file '%s'\n", ihxFileName);
+ break;
+ }
+ if(buffer[0]==':')
+ {
+ linesize = GetByte(&buffer[1]);
+ address = GetWord(&buffer[3]);
+ recordtype = GetByte(&buffer[7]);
+ rchksum = GetByte(&buffer[9]+(linesize*2));
+ chksum=linesize+(address/0x100)+(address%0x100)+recordtype+rchksum;
+
+ if (recordtype==1) break; /*End of record*/
+
+ for(j=0; j<linesize; j++)
+ {
+ value=GetByte(&buffer[9]+(j*2));
+ chksum+=value;
+ ihxBuff[address+j]=value;
+ }
+ if(MaxAddress<(address+linesize-1)) MaxAddress=(address+linesize-1);
+ if(address<*Begin) *Begin=address;
+
+ if((chksum%0x100)!=0)
+ {
+ printf("ERROR: Bad checksum in file %s\n", ihxFileName);
+ fclose(filein);
+ return -1;
+ }
+ }
+ }
+ fclose(filein);
+
+ return MaxAddress;
+}
+
+void CreateAOMF51(void)
+{
+ if((dflag) && (!rflag))
+ {
+ CollectInfoFromCDB();
+ #ifdef DODUMP
+ DumpForDebug();
+ #endif
+ HexSize=ReadHexFile(&HexBegin)+1;
+ OutputAOEMF51();
+ FreeAll();
+ }
+}
--- /dev/null
+/* lkarea.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 3-Nov-97 JLH:
+ * - change lkparea to use a_type == 0 as "virgin area" flag
+ * 02-Apr-98 JLH: add code to link 8051 data spaces
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lkarea.c
+ *
+ * The module lkarea.c contains the functions which
+ * create and link together all area definitions read
+ * from the .rel file(s).
+ *
+ * lkarea.c contains the following functions:
+ * VOID lnkarea()
+ * VOID lnksect()
+ * VOID lkparea()
+ * VOID newarea()
+ *
+ * lkarea.c contains no global variables.
+ */
+
+/*)Function VOID newarea()
+ *
+ * The function newarea() creates and/or modifies area
+ * and areax structures for each A directive read from
+ * the .rel file(s). The function lkparea() is called
+ * to find tha area structure associated with this name.
+ * If the area does not yet exist then a new area
+ * structure is created and linked to any existing
+ * linked area structures. The area flags are copied
+ * into the area flag variable. For each occurence of
+ * an A directive an areax structure is created and
+ * linked to the areax structures associated with this
+ * area. The size of this area section is placed into
+ * the areax structure. The flag value for all subsequent
+ * area definitions for the same area are compared and
+ * flagged as an error if they are not identical.
+ * The areax structure created for every occurence of
+ * an A directive is loaded with a pointer to the base
+ * area structure and a pointer to the associated
+ * head structure. And finally, a pointer to this
+ * areax structure is loaded into the list of areax
+ * structures in the head structure. Refer to lkdata.c
+ * for details of the structures and their linkage.
+ *
+ * local variables:
+ * areax **halp pointer to an array of pointers
+ * int i counter, loop variable, value
+ * char id[] id string
+ * int narea number of areas in this head structure
+ * areax * taxp pointer to an areax structure
+ * to areax structures
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * areax *axp Pointer to the current
+ * areax structure
+ * head *hp Pointer to the current
+ * head structure
+ * int lkerr error flag
+ *
+ * functions called:
+ * Addr_T eval() lkeval.c
+ * VOID exit() c_library
+ * int fprintf() c_library
+ * VOID getid() lklex.c
+ * VOID lkparea() lkarea.c
+ * VOID skip() lklex.c
+ *
+ * side effects:
+ * The area and areax structures are created and
+ * linked with the appropriate head structures.
+ * Failure to allocate area or areax structure
+ * space will terminate the linker. Other internal
+ * errors most likely caused by corrupted .rel
+ * files will also terminate the linker.
+ */
+
+/*
+ * Create an area entry.
+ *
+ * A xxxxxx size nnnn flags mm
+ * | | |
+ * | | `-- ap->a_flag
+ * | `------------- axp->a_size
+ * `------------------------- ap->a_id
+ *
+ */
+VOID
+newarea()
+{
+ register int i, narea;
+ struct areax *taxp;
+ struct areax **halp;
+ char id[NCPS];
+
+ /*
+ * Create Area entry
+ */
+ getid(id, -1);
+ lkparea(id);
+ /*
+ * Evaluate area size
+ */
+ skip(-1);
+ axp->a_size = eval();
+ /*
+ * Evaluate flags
+ */
+ skip(-1);
+ i = 0;
+ taxp = ap->a_axp;
+ while (taxp->a_axp) {
+ ++i;
+ taxp = taxp->a_axp;
+ }
+ if (i == 0) {
+ ap->a_flag = eval();
+ } else {
+ i = eval();
+/* if (i && (ap->a_flag != i)) { */
+/* fprintf(stderr, "Conflicting flags in area %8s\n", id); */
+/* lkerr++; */
+/* } */
+ }
+ /*
+ * Place pointer in header area list
+ */
+ if (headp == NULL) {
+ fprintf(stderr, "No header defined\n");
+ lkexit(1);
+ }
+ narea = hp->h_narea;
+ halp = hp->a_list;
+ for (i=0; i < narea ;++i) {
+ if (halp[i] == NULL) {
+ halp[i] = taxp;
+ return;
+ }
+ }
+ fprintf(stderr, "Header area list overflow\n");
+ lkexit(1);
+}
+
+/*)Function VOID lkparea(id)
+ *
+ * char * id pointer to the area name string
+ *
+ * The function lkparea() searches the linked area structures
+ * for a name match. If the name is not found then an area
+ * structure is created. An areax structure is created and
+ * appended to the areax structures linked to the area structure.
+ * The associated base area and head structure pointers are
+ * loaded into the areax structure.
+ *
+ * local variables:
+ * area * tap pointer to an area structure
+ * areax * taxp pointer to an areax structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ * areax *axp Pointer to the current
+ * areax structure
+ *
+ * functions called:
+ * VOID * new() lksym()
+ * char * strcpy() c_library
+ * int symeq() lksym.c
+ *
+ * side effects:
+ * Area and/or areax structures are created.
+ * Failure to allocate space for created structures
+ * will terminate the linker.
+ */
+
+VOID
+lkparea(id)
+char *id;
+{
+ register struct area *tap;
+ register struct areax *taxp;
+
+ ap = areap;
+ axp = (struct areax *) new (sizeof(struct areax));
+ while (ap) {
+ if (symeq(id, ap->a_id)) {
+ taxp = ap->a_axp;
+ while (taxp->a_axp)
+ taxp = taxp->a_axp;
+ taxp->a_axp = axp;
+ axp->a_bap = ap;
+ axp->a_bhp = hp;
+ return;
+ }
+ ap = ap->a_ap;
+ }
+ ap = (struct area *) new (sizeof(struct area));
+ if (areap == NULL) {
+ areap = ap;
+ } else {
+ tap = areap;
+ while (tap->a_ap)
+ tap = tap->a_ap;
+ tap->a_ap = ap;
+ }
+ ap->a_axp = axp;
+ axp->a_bap = ap;
+ axp->a_bhp = hp;
+ strncpy(ap->a_id, id, NCPS);
+ ap->a_addr = 0;
+}
+
+/*)Function VOID lnkarea()
+ *
+ * The function lnkarea() resolves all area addresses.
+ * The function evaluates each area structure (and all
+ * the associated areax structures) in sequence. The
+ * linking process supports four (4) possible area types:
+ *
+ * ABS/OVR - All sections (each individual areax
+ * section) starts at the identical base
+ * area address overlaying all other
+ * areax sections for this area. The
+ * size of the area is largest of the area
+ * sections.
+ *
+ * ABS/CON - All sections (each individual areax
+ * section) are concatenated with the
+ * first section starting at the base
+ * area address. The size of the area
+ * is the sum of the section sizes.
+ *
+ * NOTE: Multiple absolute (ABS) areas are
+ * never concatenated with each other,
+ * thus absolute area A and absolute area
+ * B will overlay each other if they begin
+ * at the same location (the default is
+ * always address 0 for absolute areas).
+ *
+ * REL/OVR - All sections (each individual areax
+ * section) starts at the identical base
+ * area address overlaying all other
+ * areax sections for this area. The
+ * size of the area is largest of the area
+ * sections.
+ *
+ * REL/CON - All sections (each individual areax
+ * section) are concatenated with the
+ * first section starting at the base
+ * area address. The size of the area
+ * is the sum of the section sizes.
+ *
+ * NOTE: Relocatable (REL) areas ae always concatenated
+ * with each other, thus relocatable area B
+ * (defined after area A) will follow
+ * relocatable area A independent of the
+ * starting address of area A. Within a
+ * specific area each areax section may be
+ * overlayed or concatenated with other
+ * areax sections.
+ *
+ *
+ * If a base address for an area is specified then the
+ * area will start at that address. Any relocatable
+ * areas defined subsequently will be concatenated to the
+ * previous relocatable area if it does not have a base
+ * address specified.
+ *
+ * The names s_<areaname> and l_<areaname> are created to
+ * define the starting address and length of each area.
+ *
+ * local variables:
+ * Addr_T rloc ;current relocation address
+ * char temp[] ;temporary string
+ * struct symbol *sp ;symbol structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID lnksect() lkarea.c
+ * symbol *lkpsym() lksysm.c
+ * char * strncpy() c_library
+ * int symeq() lksysm.c
+ *
+ * side effects:
+ * All area and areax addresses and sizes are
+ * determined and saved in their respective
+ * structures.
+ */
+
+/*
+ * Resolve all area addresses.
+ */
+VOID
+lnkarea()
+{
+ Addr_T rloc[4];
+ int locIndex;
+ char temp[NCPS];
+ struct sym *sp;
+ /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
+ struct area *ta[5];
+ int j;
+
+ rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
+ ap = areap;
+ while (ap) {
+ if (ap->a_flag&A_ABS) {
+ /*
+ * Absolute sections
+ */
+ lnksect(ap);
+ } else {
+ /* Determine memory space */
+ locIndex = 0;
+ if (ap->a_flag & A_CODE) {
+ locIndex = 1;
+ }
+ if (ap->a_flag & A_XDATA) {
+ locIndex = 2;
+ }
+ if (ap->a_flag & A_BIT) {
+ locIndex = 3;
+ }
+ /*
+ * Relocatable sections
+ */
+ if (ap->a_type == 0) { /* JLH */
+ ap->a_addr = rloc[ locIndex ];
+ ap->a_type = 1;
+ }
+ lnksect(ap);
+ rloc[ locIndex ] = ap->a_addr + ap->a_size;
+ }
+
+ /*
+ * Create symbols called:
+ * s_<areaname> the start address of the area
+ * l_<areaname> the length of the area
+ */
+
+ if (! symeq(ap->a_id, _abs_)) {
+ strncpy(temp+2,ap->a_id,NCPS-2);
+ *(temp+1) = '_';
+
+ *temp = 's';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_addr ;
+ /* sp->s_axp = ap->a_axp; JLH: was NULL; */
+ sp->s_type |= S_DEF;
+
+ *temp = 'l';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_size;
+ sp->s_axp = NULL;
+ sp->s_type |= S_DEF;
+
+ }
+
+ /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
+ to compute the byte size of BSEG_BYTES: */
+ if (!strcmp(ap->a_id, "BSEG")) {
+ ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
+ }
+ else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
+ else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
+ else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
+ else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
+ else if (!strcmp(ap->a_id, "BSEG_BYTES"))
+ {
+ ta[4]=ap;
+ for(j=4; j>1; j--)
+ {
+ /*If upper register banks are not used roll back the rellocation counter*/
+ if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
+ {
+ rloc[0]-=8;
+ }
+ else break;
+ }
+ }
+ ap = ap->a_ap;
+ }
+}
+
+/*)Function VOID lnksect()
+ *
+ * area * tap pointer to an area structure
+ *
+ * The function lnksect() is the function called by
+ * lnkarea() to resolve the areax addresses. Refer
+ * to the function lnkarea() for more detail. Pageing
+ * boundary and length errors will be reported by this
+ * function.
+ *
+ * local variables:
+ * Addr_T size size of area
+ * Addr_T addr address of area
+ * areax * taxp pointer to an areax structure
+ *
+ * global variables:
+ * int lkerr error flag
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * All area and areax addresses and sizes area determined
+ * and linked into the structures.
+ */
+
+VOID
+lnksect(tap)
+register struct area *tap;
+{
+ register Addr_T size, addr;
+ register struct areax *taxp;
+
+ size = 0;
+ addr = tap->a_addr;
+ if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+ taxp = tap->a_axp;
+ if (tap->a_flag&A_OVR) {
+ /*
+ * Overlayed sections
+ */
+ while (taxp) {
+ taxp->a_addr = addr;
+ if (taxp->a_size > size)
+ size = taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ } else {
+ /*
+ * Concatenated sections
+ */
+ while (taxp) {
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ }
+ tap->a_size = size;
+ if ((tap->a_flag&A_PAG) && (size > 256)) {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
+ lkerr++;
+ }
+}
--- /dev/null
+/* lkdata.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - change s_id from [NCPS] to pointer (comment)
+ * 31-Oct-97 JLH:
+ * - add jflag and jfp for NoICE output
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lkdata.c
+ *
+ * The module lkdata contains the global variables
+ * and structures used in the linker aslink.
+ */
+
+/*
+ * Definitions for all Global Variables
+ */
+
+char *_abs_ = { ". .ABS." };
+
+int lkerr; /* Linker error flag
+ */
+char *ip; /* Pointer into the REL file text line in ib[]
+ */
+char ib[NINPUT]; /* REL file text line
+ */
+char *rp; /* pointer into the LST file
+ * text line in rb[]
+ */
+char rb[NINPUT]; /* LST file text line being
+ * address relocated
+ */
+
+char sdccopt[NINPUT]="";
+char sdccopt_module[NINPUT]="";
+char curr_module[NINPUT]="";
+
+int dflag; /* Debug information output flag
+ */
+int oflag; /* Output file type flag
+ */
+int mflag; /* Map output flag
+ */
+int sflag; /* JCF: Memory usage output flag
+ */
+int aflag; /* Overlapping area warning flag
+ */
+int jflag; /* NoICE output flag
+ */
+int xflag; /* Map file radix type flag
+ */
+int pflag; /* print linker command file flag
+ */
+int uflag; /* Listing relocation flag
+ */
+int rflag; /* Extended linear address record flag.
+ */
+int radix; /* current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ */
+int line; /* current line number
+ */
+int page; /* current page number
+ */
+int lop; /* current line number on page
+ */
+int pass; /* linker pass number
+ */
+int rtcnt; /* count of elements in the
+ * rtval[] and rtflg[] arrays
+ */
+Addr_T rtval[NTXT]; /* data associated with relocation
+ */
+int rtflg[NTXT]; /* indicates if rtval[] value is
+ * to be sent to the output file.
+ * (always set in this linker)
+ */
+int hilo; /* REL file byte ordering
+ */
+int gline; /* LST file relocation active
+ * for current line
+ */
+int gcntr; /* LST file relocation active
+ * counter
+ */
+Addr_T iram_size; /* internal ram size
+ */
+long xram_size=-1; /* external ram size
+ */
+long code_size=-1; /* code size
+ */
+
+/*
+ * The structure lfile contains a pointer to a
+ * file specification string, the file type, and
+ * a link to the next lfile structure.
+ *
+ * struct lfile
+ * {
+ * struct lfile *f_flp; lfile link
+ * int f_type; File type
+ * char *f_idp; Pointer to file spec
+ * };
+ */
+struct lfile *filep; /* The pointers (lfile *) filep,
+ * (lfile *) cfp, and (FILE *) sfp
+ * are used in conjunction with
+ * the routine getline() to read
+ * asmlnk commands from
+ * (1) the standard input or
+ * (2) or a command file
+ * and to read the REL files
+ * sequentially as defined by the
+ * asmlnk input commands.
+ *
+ * The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ */
+struct lfile *cfp; /* The pointer *cfp points to the
+ * current lfile structure
+ */
+struct lfile *startp;/* asmlnk startup file structure
+ */
+struct lfile *linkp; /* pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ */
+struct lfile *lfp; /* pointer to current lfile structure
+ * being processed by parse()
+ */
+FILE *ofp; /* Output file handle
+ * for word formats
+ */
+FILE *mfp; /* Map output file handle
+ */
+FILE *jfp; /* NoICE output file handle
+ */
+FILE *rfp; /* File handle for output
+ * address relocated ASxxxx
+ * listing file
+ */
+FILE *sfp; /* The file handle sfp points to the
+ * currently open file
+ */
+FILE *tfp; /* File handle for input
+ * ASxxxx listing file
+ */
+FILE *dfp = NULL ; /*
+ * File handle for debug
+ * information output file
+ */
+/*
+ * The structures of head, area, areax, and sym are created
+ * as the REL files are read during the first pass of the
+ * linker. The struct head is created upon encountering a
+ * H directive in the REL file. The structure contains a
+ * link to a link file structure (struct lfile) which describes
+ * the file containing the H directive, the number of data/code
+ * areas contained in this header segment, the number of
+ * symbols referenced/defined in this header segment, a pointer
+ * to an array of pointers to areax structures (struct areax)
+ * created as each A directive is read, and a pointer to an
+ * array of pointers to symbol structures (struct sym) for
+ * all referenced/defined symbols. As H directives are read
+ * from the REL files a linked list of head structures is
+ * created by placing a link to the new head structure
+ * in the previous head structure.
+ *
+ * struct head
+ * {
+ * struct head *h_hp; Header link
+ * struct lfile *h_lfile; Associated file
+ * int h_narea; # of areas
+ * struct areax **a_list; Area list
+ * int h_nglob; # of global symbols
+ * struct sym **s_list; Global symbol list
+ * char m_id[NCPS]; Module name
+ * };
+ */
+struct head *headp; /* The pointer to the first
+ * head structure of a linked list
+ */
+struct head *hp; /* Pointer to the current
+ * head structure
+ */
+
+/*
+ * A structure area is created for each 'unique' data/code
+ * area definition found as the REL files are read. The
+ * struct area contains the name of the area, a flag byte
+ * which contains the area attributes (REL/CON/OVR/ABS),
+ * an area subtype (not used in this assembler), and the
+ * area base address and total size which will be filled
+ * in at the end of the first pass through the REL files.
+ * As A directives are read from the REL files a linked
+ * list of unique area structures is created by placing a
+ * link to the new area structure in the previous area structure.
+ *
+ * struct area
+ * {
+ * struct area *a_ap; Area link
+ * struct areax *a_axp; Area extension link
+ * Addr_T a_addr; Beginning address of area
+ * Addr_T a_size; Total size of the area
+ * char a_type; Area subtype
+ * char a_flag; Flag byte
+ * char a_id[NCPS]; Name
+ * };
+ */
+struct area *areap; /* The pointer to the first
+ * area structure of a linked list
+ */
+struct area *ap; /* Pointer to the current
+ * area structure
+ */
+
+/*
+ * An areax structure is created for every A directive found
+ * while reading the REL files. The struct areax contains a
+ * link to the 'unique' area structure referenced by the A
+ * directive and to the head structure this area segment is
+ * a part of. The size of this area segment as read from the
+ * A directive is placed in the areax structure. The beginning
+ * address of this segment will be filled in at the end of the
+ * first pass through the REL files. As A directives are read
+ * from the REL files a linked list of areax structures is
+ * created for each unique area. The final areax linked
+ * list has at its head the 'unique' area structure linked
+ * to the linked areax structures (one areax structure for
+ * each A directive for this area).
+ *
+ * struct areax
+ * {
+ * struct areax *a_axp; Area extension link
+ * struct area *a_bap; Base area link
+ * struct head *a_bhp; Base header link
+ * Addr_T a_addr; Beginning address of section
+ * Addr_T a_size; Size of the area in section
+ * };
+ */
+struct areax *axp; /* Pointer to the current
+ * areax structure
+ */
+
+/*
+ * A sym structure is created for every unique symbol
+ * referenced/defined while reading the REL files. The
+ * struct sym contains the symbol's name, a flag value
+ * (not used in this linker), a symbol type denoting
+ * referenced/defined, and an address which is loaded
+ * with the relative address within the area in which
+ * the symbol was defined. The sym structure also
+ * contains a link to the area where the symbol was defined.
+ * The sym structures are linked into linked lists using
+ * the symbol link element.
+ *
+ * struct sym
+ * {
+ * struct sym *s_sp; Symbol link
+ * struct areax *s_axp; Symbol area link
+ * char s_type; Symbol subtype
+ * char s_flag; Flag byte
+ * Addr_T s_addr; Address
+ * char *s_id; Name (JLH)
+ * };
+ */
+struct sym *symhash[NHASH]; /* array of pointers to NHASH
+ * linked symbol lists
+ */
+/*
+ * The struct base contains a pointer to a
+ * base definition string and a link to the next
+ * base structure.
+ *
+ * struct base
+ * {
+ * struct base *b_base; Base link
+ * char *b_strp; String pointer
+ * };
+ */
+struct base *basep; /* The pointer to the first
+ * base structure
+ */
+struct base *bsp; /* Pointer to the current
+ * base structure
+ */
+
+/*
+ * The struct globl contains a pointer to a
+ * global definition string and a link to the next
+ * global structure.
+ *
+ * struct globl
+ * {
+ * struct globl *g_globl; Global link
+ * char *g_strp; String pointer
+ * };
+ */
+struct globl *globlp;/* The pointer to the first
+ * globl structure
+ */
+struct globl *gsp; /* Pointer to the current
+ * globl structure
+ */
+
+/*
+ * A structure sdp is created for each 'unique' paged
+ * area definition found as the REL files are read.
+ * As P directives are read from the REL files a linked
+ * list of unique sdp structures is created by placing a
+ * link to the new sdp structure in the previous area structure.
+ *
+ * struct sdp
+ * {
+ * struct area *s_area; Paged Area link
+ * struct areax *s_areax; Paged Area Extension Link
+ * Addr_T s_addr; Page address offset
+ * };
+ */
+struct sdp sdp; /* Base Page Structure */
+
+/*
+ * The structure rerr is loaded with the information
+ * required to report an error during the linking
+ * process. The structure contains an index value
+ * which selects the areax structure from the header
+ * areax structure list, a mode value which selects
+ * symbol or area relocation, the base address in the
+ * area section, an area/symbol list index value, and
+ * an area/symbol offset value.
+ *
+ * struct rerr
+ * {
+ * int aindex; Linking area
+ * int mode; Relocation mode
+ * Addr_T rtbase; Base address in section
+ * int rindex; Area/Symbol reloaction index
+ * Addr_T rval; Area/Symbol offset value
+ * };
+ */
+struct rerr rerr; /* Structure containing the
+ * linker error information
+ */
+
+/*
+ * The structure lbpath is created for each library
+ * path specification input by the -k option. The
+ * lbpath structures are linked into a list using
+ * the next link element.
+ *
+ * struct lbpath {
+ * struct lbpath *next;
+ * char *path;
+ * };
+ */
+struct lbpath *lbphead; /* pointer to the first
+ * library path structure
+ */
+
+/*
+ * The structure lbname is created for all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file. The element path points to
+ * the path string, element libfil points to the library
+ * file string, and the element libspc is the concatenation
+ * of the valid path and libfil strings.
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ *
+ * Each library file contains a list of object files
+ * that are contained in the particular library. e.g.:
+ *
+ * \iolib\termio
+ * \inilib\termio
+ *
+ * Only one specification per line is allowed.
+ *
+ * struct lbname {
+ * struct lbname *next;
+ * char *path;
+ * char *libfil;
+ * char *libspc;
+ * };
+ */
+struct lbname *lbnhead; /* pointer to the first
+ * library name structure
+ */
+
+/*
+ * The function fndsym() searches through all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file for a symbol definition.
+ *
+ * The structure lbfile is created for the first library
+ * object file which contains the definition for the
+ * specified undefined symbol.
+ *
+ * The element libspc points to the library file path specification
+ * and element relfil points to the object file specification string.
+ * The element filspc is the complete path/file specification for
+ * the library file to be imported into the linker. The
+ * file specicifation may be formed in one of two ways:
+ *
+ * (1) If the library file contained an absolute
+ * path/file specification then this becomes filspc.
+ * (i.e. C:\...)
+ *
+ * (2) If the library file contains a relative path/file
+ * specification then the concatenation of the path
+ * and this file specification becomes filspc.
+ * (i.e. \...)
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ *
+ * struct lbfile {
+ * struct lbfile *next;
+ * char *libspc;
+ * char *relfil;
+ * char *filspc;
+ * };
+ */
+struct lbfile *lbfhead; /* pointer to the first
+ * library file structure
+ */
+
+/*
+ * array of character types, one per
+ * ASCII character
+ */
+unsigned char ctype[128] = {
+/*NUL*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
+/*BS*/ ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL,
+/*DLE*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
+/*CAN*/ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL,
+/*SPC*/ SPACE, ETC, ETC, ETC, LETTER, BINOP, BINOP, ETC,
+/*(*/ ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, BINOP,
+/*0*/ DGT2, DGT2, DGT8, DGT8, DGT8, DGT8, DGT8, DGT8,
+/*8*/ DGT10, DGT10, ETC, ETC, BINOP, ETC, BINOP, ETC,
+/*@*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
+/*H*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*P*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*X*/ LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER,
+/*`*/ ETC, LTR16, LTR16, LTR16, LTR16, LTR16, LTR16, LETTER,
+/*h*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*p*/ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+/*x*/ LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC
+};
+
+/*
+ * an array of characters which
+ * perform the case translation function
+ */
+#if CASE_SENSITIVE
+#else
+char ccase[128] = {
+/*NUL*/ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+/*BS*/ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+/*DLE*/ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+/*CAN*/ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+/*SPC*/ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+/*(*/ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+/*0*/ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+/*8*/ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+/*@*/ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*H*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*P*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*X*/ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+/*`*/ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+/*h*/ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+/*p*/ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+/*x*/ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177'
+};
+#endif
--- /dev/null
+/* lkeval.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lkeval.c
+ *
+ * The module lkeval.c contains the routines to evaluate
+ * arithmetic/numerical expressions. The functions in
+ * lkeval.c perform a recursive evaluation of the arithmetic
+ * expression read from the input text line.
+ * The expression may include binary/unary operators, brackets,
+ * symbols, labels, and constants in hexadecimal, decimal, octal
+ * and binary. Arithmetic operations are prioritized and
+ * evaluated by normal arithmetic conventions.
+ *
+ * lkeval.c contains the following functions:
+ * int digit()
+ * Addr_T eval()
+ * Addr_T expr()
+ * int oprio()
+ * Addr_T term()
+ *
+ * lkeval.c contains no local/static variables
+ */
+
+/*)Function Addr_T eval()
+ *
+ * The function eval() evaluates a character string to a
+ * numerical value.
+ *
+ * local variables:
+ * int c character from input string
+ * int v value of character in current radix
+ * Addr_T n evaluation value
+ *
+ * global variables:
+ * int radix current number conversion radix
+ *
+ * functions called:
+ * int digit() lkeval.c
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * Input test is scanned and evaluated to a
+ * numerical value.
+ */
+
+Addr_T
+eval()
+{
+ register int c, v;
+ register Addr_T n;
+
+ c = getnb();
+ n = 0;
+ while ((v = digit(c, radix)) >= 0) {
+ n = n*radix + v;
+ c = get();
+ }
+ unget(c);
+ return(n);
+}
+
+/*)Function Addr_T expr(n)
+ *
+ * int n a firewall priority; all top
+ * level calls (from the user)
+ * should be made with n set to 0.
+ *
+ * The function expr() evaluates an expression and
+ * returns the value.
+ *
+ * local variables:
+ * int c current input text character
+ * int p current operator priority
+ * Addr_T v value returned by term()
+ * Addr_T ve value returned by a
+ * recursive call to expr()
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * int lkerr error flag
+ * FILE * stderr c_library
+ *
+ * functions called:
+ * VOID expr() lkeval.c
+ * int fprintf() c_library
+ * int getnb() lklex.c
+ * int oprio() lkeval.c
+ * VOID term() lkeval.c
+ * VOID unget() lklex.c
+ *
+ *
+ * side effects:
+ * An expression is evaluated by scanning the input
+ * text string.
+ */
+
+Addr_T
+expr (n)
+{
+ register int c, p;
+ register Addr_T v, ve;
+
+ v = term();
+ while (ctype[c = getnb()] & BINOP) {
+ if ((p = oprio(c)) <= n)
+ break;
+ if ((c == '>' || c == '<') && c != get()) {
+ fprintf(stderr, "Invalid expression");
+ lkerr++;
+ return(v);
+ }
+ ve = expr(p);
+ if (c == '+') {
+ v += ve;
+ } else
+ if (c == '-') {
+ v -= ve;
+ } else {
+ switch (c) {
+
+ case '*':
+ v *= ve;
+ break;
+
+ case '/':
+ v /= ve;
+ break;
+
+ case '&':
+ v &= ve;
+ break;
+
+ case '|':
+ v |= ve;
+ break;
+
+ case '%':
+ v %= ve;
+ break;
+
+ case '^':
+ v ^= ve;
+ break;
+
+ case '<':
+ v <<= ve;
+ break;
+
+ case '>':
+ v >>= ve;
+ break;
+ }
+ }
+ }
+ unget(c);
+ return(v);
+}
+
+/*)Function Addr_T term()
+ *
+ * The function term() evaluates a single constant
+ * or symbol value prefaced by any unary operator
+ * ( +, -, ~, ', ", >, or < ).
+ *
+ * local variables:
+ * int c current character
+ * char id[] symbol name
+ * int n value of digit in current radix
+ * int r current evaluation radix
+ * sym * sp pointer to a sym structure
+ * Addr_T v evaluation value
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * int lkerr error flag
+ *
+ * functions called:
+ * int digit() lkeval.c
+ * VOID expr() lkeval.c
+ * int fprintf() c_library
+ * int get() lklex.c
+ * VOID getid() lklex.c
+ * int getmap() lklex.c
+ * int getnb() lklex.c
+ * sym * lkpsym() lksym.c
+ * Addr_T symval() lksym.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * An arithmetic term is evaluated by scanning input text.
+ */
+
+Addr_T
+term()
+{
+ register int c, r, n;
+ register Addr_T v;
+ struct sym *sp;
+ char id[NCPS];
+
+ c = getnb();
+ if (c == '#') { c = getnb(); }
+ if (c == '(') {
+ v = expr(0);
+ if (getnb() != ')') {
+ fprintf(stderr, "Missing delimiter");
+ lkerr++;
+ }
+ return(v);
+ }
+ if (c == '-') {
+ return(0-expr(100));
+ }
+ if (c == '~') {
+ return(~expr(100));
+ }
+ if (c == '\'') {
+ return(getmap(-1)&0377);
+ }
+ if (c == '\"') {
+ if (hilo) {
+ v = (getmap(-1)&0377)<<8;
+ v |= getmap(-1)&0377;
+ } else {
+ v = getmap(-1)&0377;
+ v |= (getmap(-1)&0377)<<8;
+ }
+ return(v);
+ }
+ if (c == '>' || c == '<') {
+ v = expr(100);
+ if (c == '>')
+ v >>= 8;
+ return(v&0377);
+ }
+ if (ctype[c] & DIGIT) {
+ r = 10;
+ if (c == '0') {
+ c = get();
+ switch (c) {
+ case 'b':
+ case 'B':
+ r = 2;
+ c = get();
+ break;
+ case '@':
+ case 'o':
+ case 'O':
+ case 'q':
+ case 'Q':
+ r = 8;
+ c = get();
+ break;
+ case 'd':
+ case 'D':
+ r = 10;
+ c = get();
+ break;
+ case 'h':
+ case 'H':
+ case 'x':
+ case 'X':
+ r = 16;
+ c = get();
+ break;
+ default:
+ break;
+ }
+ }
+ v = 0;
+ while ((n = digit(c, r)) >= 0) {
+ v = r*v + n;
+ c = get();
+ }
+ unget(c);
+ return(v);
+ }
+ if (ctype[c] & LETTER) {
+ getid(id, c);
+ if ((sp = lkpsym(id, 0)) == NULL) {
+ fprintf(stderr, "Undefined symbol %8s\n", id);
+ lkerr++;
+ return(0);
+ } else {
+ return(symval(sp));
+ }
+ }
+ return(0);
+}
+
+/*)Function int digit(c, r)
+ *
+ * int c digit character
+ * int r current radix
+ *
+ * The function digit() returns the value of c
+ * in the current radix r. If the c value is not
+ * a number of the current radix then a -1 is returned.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+digit(c, r)
+register int c, r;
+{
+ if (r == 16) {
+ if (ctype[c] & RAD16) {
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ return (c - '0');
+ }
+ } else
+ if (r == 10) {
+ if (ctype[c] & RAD10)
+ return (c - '0');
+ } else
+ if (r == 8) {
+ if (ctype[c] & RAD8)
+ return (c - '0');
+ } else
+ if (r == 2) {
+ if (ctype[c] & RAD2)
+ return (c - '0');
+ }
+ return (-1);
+}
+
+/*)Function int oprio(c)
+ *
+ * int c operator character
+ *
+ * The function oprio() returns a relative priority
+ * for all valid unary and binary operators.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+oprio(c)
+register int c;
+{
+ if (c == '*' || c == '/' || c == '%')
+ return (10);
+ if (c == '+' || c == '-')
+ return (7);
+ if (c == '<' || c == '>')
+ return (5);
+ if (c == '^')
+ return (4);
+ if (c == '&')
+ return (3);
+ if (c == '|')
+ return (1);
+ return (0);
+}
--- /dev/null
+/* lkhead.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*Module lkhead.c
+ *
+ * The module lkhead.c contains the function newhead() which
+ * creates a head structure and the function module() which
+ * loads the module name into the current head structure.
+ *
+ * lkhead.c contains the following functions:
+ * VOID newhead()
+ * VOID module()
+ *
+ * lkhead.c contains no local variables.
+ */
+
+/*)Function VOID newhead()
+ *
+ * The function newhead() creates a head structure. All head
+ * structures are linked to form a linked list of head structures
+ * with the current head structure at the tail of the list.
+ *
+ * local variables:
+ * int i evaluation value
+ * head * thp temporary pointer
+ * to a header structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * lfile *cfp The pointer *cfp points to the
+ * current lfile structure
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * head *hp Pointer to the current
+ * head structure
+ *
+ * functions called:
+ * Addr_T expr() lkeval.c
+ * VOID * new() lksym.c
+ * VOID lkparea() lkarea.c
+ *
+ * side effects:
+ * A new head structure is created and linked to any
+ * existing linked head structure. The head structure
+ * parameters of file handle, number of areas, and number
+ * of global symbols are loaded into the structure.
+ * The default area "_abs_" is created when the first
+ * head structure is created and an areax structure is
+ * created for every head structure called.
+ */
+
+/*
+ * Create a new header entry.
+ *
+ * H n areas n global symbols
+ * | |
+ * | `---- hp->h_nglob
+ * `------------ hp->h_narea
+ *
+ */
+VOID
+newhead()
+{
+ register int i;
+ struct head *thp;
+
+ hp = (struct head *) new (sizeof(struct head));
+ if (headp == NULL) {
+ headp = hp;
+ } else {
+ thp = headp;
+ while (thp->h_hp)
+ thp = thp->h_hp;
+ thp->h_hp = hp;
+ }
+ /*
+ * Set file pointer
+ */
+ hp->h_lfile = cfp;
+ /*
+ * Evaluate and build Area pointer list
+ */
+ i = hp->h_narea = eval();
+ if (i)
+ hp->a_list = (struct areax **) new (i*sizeof(struct areax *));
+ /*
+ * Evaluate and build Global symbol pointer list
+ */
+ skip(-1);
+ i = hp->h_nglob = eval();
+ if (i)
+ hp->s_list = (struct sym **) new (i*sizeof(struct sym *));
+ /*
+ * Setup Absolute DEF linkage.
+ */
+ lkparea(_abs_);
+ ap->a_flag = A_ABS|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++;
+ }
+}
--- /dev/null
+/* lkihx.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lkihx.c
+ *
+ * The module lkihx.c contains the function to
+ * output the relocated object code in the
+ * Intel Hex format.
+ *
+ * lkihx.c contains the following functions:
+ * VOID hexRecord(addr, rtvalIndex)
+ * VOID ihx(i)
+ * VOID ihxEntendedLinearAddress(a)
+ *
+ * local variables: hexPageOverrun, lastHexAddr
+ */
+
+/*Intel Hex Format
+ * Record Mark Field - This field signifies the start of a
+ * record, and consists of an ascii colon
+ * (:).
+ *
+ * Record Length Field - This field consists of two ascii
+ * characters which indicate the number of
+ * data bytes in this record. The
+ * characters are the result of converting
+ * the number of bytes in binary to two
+ * ascii characters, high digit first. An
+ * End of File record contains two ascii
+ * zeros in this field.
+ *
+ * Load Address Field - This field consists of the four ascii
+ * characters which result from converting
+ * the the binary value of the address in
+ * which to begin loading this record. The
+ * order is as follows:
+ *
+ * High digit of high byte of address.
+ * Low digit of high byte of address.
+ * High digit of low byte of address.
+ * Low digit of low byte of address.
+ *
+ * In an End of File record this field con-
+ * sists of either four ascii zeros or the
+ * program entry address. Currently the
+ * entry address option is not supported.
+ *
+ * Record Type Field - This field identifies the record type,
+ * which is either 0 for data records or 1
+ * for an End of File record. It consists
+ * of two ascii characters, with the high
+ * digit of the record type first, followed
+ * by the low digit of the record type.
+ *
+ * Data Field - This field consists of the actual data,
+ * converted to two ascii characters, high
+ * digit first. There are no data bytes in
+ * the End of File record.
+ *
+ * Checksum Field - The checksum field is the 8 bit binary
+ * sum of the record length field, the load
+ * address field, the record type field,
+ * and the data field. This sum is then
+ * negated (2's complement) and converted
+ * to two ascii characters, high digit
+ * first.
+ */
+
+/* Static variable which holds the count of hex page overruns
+ * (crossings of the 64kB boundary). Cleared at explicit extended
+ * address output.
+ */
+static int hexPageOverrun = 0;
+
+/* Global which holds the last (16 bit) address of hex record.
+ * Cleared at begin of new area or when the extended address is output.
+ */
+unsigned int lastHexAddr = 0;
+
+
+/*)Function hexRecord(addr, rtvalIndex)
+ *
+ * unsigned addr starting address of hex record
+ * int rtvalIndex starting index into the rtval[] array
+ *
+ * The function hexRecord() outputs the relocated data
+ * in the standard Intel Hex format (with inserting
+ * the extended address record if necessary).
+ *
+ * local variables:
+ * Addr_T chksum byte checksum
+ * int i index for loops
+ * int overrun temporary storage for hexPageOverrun
+ * int bytes counter for bytes written
+ *
+ * global variables:
+ * FILE * ofp output file handle
+ * int rtcnt count of data words
+ * int rtflg[] output the data flag
+ * Addr_T rtval[] relocated data
+ *
+ * functions called:
+ * int fprintf() c_library
+ * ihxEntendedLinearAddress() lkihx.c
+ * hexRecord() lkihx.c (recursion)
+ *
+ * side effects:
+ * hexPageOverrun is eventually incremented,
+ * lastHexAddr is updated
+ */
+
+VOID
+hexRecord(unsigned addr, int rtvalIndex)
+{
+ Addr_T chksum;
+ int i, overrun, bytes;
+
+ for (i = rtvalIndex, chksum = 0; i < rtcnt; i++) {
+ if (rtflg[i]) {
+ if (addr + ++chksum > 0xffff)
+ break;
+ }
+ }
+ if (chksum == 0)
+ return; // nothing to output
+
+ if (lastHexAddr > addr) {
+ overrun = hexPageOverrun + 1;
+ ihxEntendedLinearAddress(lastExtendedAddress + overrun);
+ hexPageOverrun = overrun;
+ hexRecord(addr, rtvalIndex);
+ return;
+ }
+
+ lastHexAddr = addr;
+ fprintf(ofp, ":%02X%04X00", chksum, addr);
+ chksum += (addr >> 8) + (addr & 0xff);
+ for (i = rtvalIndex, bytes = 0; i < rtcnt; i++) {
+ if (rtflg[i]) {
+ fprintf(ofp, "%02X", rtval[i]);
+ chksum += rtval[i];
+#if 0
+ if (addr + ++bytes > 0xffff) {
+ if (rflag) {
+ fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
+ overrun = hexPageOverrun + 1;
+ ihxEntendedLinearAddress(lastExtendedAddress + overrun);
+ hexPageOverrun = overrun;
+ hexRecord(0, i + 1);
+ return;
+ } else {
+ fprintf(stderr,
+ "warning: extended linear address encountered; "
+ "you probably want the -r flag.\n");
+ }
+ }
+#endif
+ }
+ }
+ fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
+}
+
+/*)Function ihx(i)
+ *
+ * int i 0 - process data
+ * 1 - end of data
+ *
+ * The function ihx() calls the hexRecord() function for processing data
+ * or writes the End of Data record to the file defined by ofp.
+ *
+ * local variables:
+ * Addr_T n auxiliary variable
+ *
+ * global variables:
+ * int hilo byte order
+ * FILE * ofp output file handle
+ * Addr_T rtval[] relocated data
+ *
+ * functions called:
+ * VOID hexRecord() lkihx.c
+ * int fprintf() c_library
+ *
+ * side effects:
+ * The sequence of rtval[0], rtval[1] is eventually changed.
+ */
+
+VOID
+ihx(i)
+{
+ Addr_T n;
+ if (i) {
+ if (hilo == 0) {
+ n = rtval[0];
+ rtval[0] = rtval[1];
+ rtval[1] = n;
+ }
+ hexRecord((rtval[0]<<8) + rtval[1], 2);
+ } else {
+ fprintf(ofp, ":00000001FF\n");
+ }
+}
+
+/*)Function newArea(i)
+ * The function newArea() is called when processing of new area is started.
+ * It resets the value of lastHexAddr.
+ */
+
+VOID
+newArea()
+{
+ lastHexAddr = 0;
+}
+
+/*)Function ihxEntendedLinearAddress(i)
+ *
+ * Addr_T i 16 bit extended linear address.
+ *
+ * The function ihxEntendedLinearAddress() writes an extended
+ * linear address record (type 04) to the output file.
+ *
+ * local variables:
+ * Addr_T chksum byte checksum
+ *
+ * global variables:
+ * FILE * ofp output file handle
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * The data is output to the file defined by ofp.
+ * hexPageOverrun and lastHexAddr is cleared
+ */
+VOID
+ihxEntendedLinearAddress(Addr_T a)
+{
+ Addr_T chksum;
+
+ /* The checksum is the complement of the bytes in the
+ * record: the 2 is record length, 4 is the extended linear
+ * address record type, plus the two address bytes.
+ */
+ chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff);
+
+ fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (0-chksum) & 0xff);
+ hexPageOverrun = 0;
+ lastHexAddr = 0;
+}
--- /dev/null
+/* lklex.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lklex.c
+ *
+ * The module lklex.c contains the general lexical analysis
+ * functions used to scan the text lines from the .rel files.
+ *
+ * lklex.c contains the fllowing functions:
+ * char endline()
+ * char get()
+ * VOID getfid()
+ * VOID getid()
+ * VOID getSid()
+ * int getline()
+ * int getmap()
+ * char getnb()
+ * int more()
+ * VOID skip()
+ * VOID unget()
+ *
+ * lklex.c contains no local variables.
+ */
+
+/*)Function VOID getid(id,c)
+ *
+ * char * id a pointer to a string of
+ * maximum length NCPS
+ * int c mode flag
+ * >=0 this is first character to
+ * copy to the string buffer
+ * <0 skip white space
+ *
+ * The function getid() scans the current input text line
+ * from the current position copying the next LETTER | DIGIT string
+ * into the external string buffer (id). The string ends when a non
+ * LETTER or DIGIT character is found. The maximum number of
+ * characters copied is NCPS. If the input string is larger than
+ * NCPS characters then the string is truncated, if the input string
+ * is shorter than NCPS characters then the string is NULL filled.
+ * If the mode argument (c) is >=0 then (c) is the first character
+ * copied to the string buffer, if (c) is <0 then intervening white
+ * space (SPACES and TABS) are skipped.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of getnb(), get(), and unget() updates the
+ * global pointer ip the position in the current
+ * input text line.
+ */
+
+VOID
+getid(id, c)
+register int c;
+char *id;
+{
+ register char *p;
+
+ if (c < 0) {
+ c = getnb();
+ }
+ p = id;
+ do {
+ if (p < &id[NCPS])
+ *p++ = c;
+ } while (ctype[c=get()] & (LETTER|DIGIT));
+ unget(c);
+ while (p < &id[NCPS])
+ *p++ = 0;
+}
+
+/*)Function VOID getSid (char *id)
+ *
+ * char * id a pointer to a string of
+ * maximum length NCPS
+ *
+ * getSid is derived from getid. It is called from newsym()
+ * in lksym.c, when an S-record has to be scanned. getSid accepts
+ * much more characters than getid, which is necessary for SDCC.
+ *
+ * The function getSid() scans the current input text line
+ * from the current position copying the next string
+ * into the external string buffer (id). The string ends when a space
+ * character (space, tab, \0) is found. The maximum number of
+ * characters copied is NCPS. If the input string is larger than
+ * NCPS characters then the string is truncated, if the input string
+ * is shorter than NCPS characters then the string is NULL filled.
+ * Intervening white space (SPACES and TABS) are skipped.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of getnb(), get(), and unget() updates the
+ * global pointer ip the position in the current
+ * input text line.
+ */
+
+VOID
+getSid (id)
+char *id;
+{
+ register int c;
+ register char *p;
+
+ c = getnb();
+ p = id;
+ do {
+ if (p < &id[NCPS])
+ *p++ = c;
+ c = get();
+ } while (c != '\0' && c != ' ' && c != '\t');
+ unget(c);
+ while (p < &id[NCPS])
+ *p++ = 0;
+}
+
+/*)Function VOID getfid(fid,c)
+ *
+ * char * str a pointer to a string of
+ * maximum length PATH_MAX
+ * int c this is first character to
+ * copy to the string buffer
+ *
+ * The function getfid() scans the current input text line from
+ * the current position copying the next string into the external
+ * string buffer (str). The string ends when end of line is found.
+ * Trailing spacers are removed. The maximum number of characters
+ * copied is PATH_MAX. If the input string is larger than PATH_MAX
+ * characters then the string is truncated. The string is NULL
+ * terminated.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() lklex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip
+ * the position in the current input text line.
+ */
+
+VOID
+getfid(str, c)
+register int c;
+char *str;
+{
+ register char *p;
+
+ p = str;
+ do
+ {
+ if (p < &str[PATH_MAX-1])
+ *p++ = c;
+ c = get();
+ } while (c);
+ /* trim trailing spaces */
+ --p;
+ while (p >= str && ctype[(int)*p] == SPACE)
+ --p;
+ /* terminate the string */
+ *(++p) = '\0';
+}
+
+/*)Function char getnb()
+ *
+ * The function getnb() scans the current input text
+ * line returning the first character not a SPACE or TAB.
+ *
+ * local variables:
+ * int c current character from input
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char get() lklex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip, the position
+ * in the current input text line
+ */
+
+char
+getnb()
+{
+ register int c;
+
+ while ((c=get())==' ' || c=='\t')
+ ;
+ return (c);
+}
+
+/*)Function VOID skip()
+ *
+ * The function skip() scans the input text skipping all
+ * letters and digits.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ *
+ * functions called:
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * Input letters and digits are skipped.
+ */
+
+VOID
+skip(c)
+register int c;
+{
+ if (c < 0)
+ c = getnb();
+ while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
+ unget(c);
+}
+
+/*)Function char get()
+ *
+ * The function get() returns the next character in the
+ * input text line, at the end of the line a
+ * NULL character is returned.
+ *
+ * local variables:
+ * int c current character from
+ * input text line
+ *
+ * global variables:
+ * char * ip pointer into the current
+ * input text line
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * updates ip to the next character position in the
+ * input text line. If ip is at the end of the
+ * line, ip is not updated.
+ */
+
+char
+get()
+{
+ register int c;
+
+ if ((c = *ip) != 0)
+ ++ip;
+ return (c);
+}
+
+/*)Function VOID unget(c)
+ *
+ * int c value of last character
+ * read from input text line
+ *
+ * If (c) is not a NULL character then the global pointer ip
+ * is updated to point to the preceeding character in the
+ * input text line.
+ *
+ * NOTE: This function does not push the character (c)
+ * back into the input text line, only
+ * the pointer ip is changed.
+ *
+ * local variables:
+ * int c last character read
+ * from input text line
+ *
+ * global variables:
+ * char * ip position into the current
+ * input text line
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * ip decremented by 1 character position
+ */
+
+VOID
+unget(c)
+{
+ if (c != 0)
+ --ip;
+}
+
+/*)Function int getmap(d)
+ *
+ * int d value to compare with the
+ * input text line character
+ *
+ * The function getmap() converts the 'C' style characters \b, \f,
+ * \n, \r, and \t to their equivalent ascii values and also
+ * converts 'C' style octal constants '\123' to their equivalent
+ * numeric values. If the first character is equivalent to (d) then
+ * a (-1) is returned, if the end of the line is detected then
+ * a 'q' error terminates the parse for this line, or if the first
+ * character is not a \ then the character value is returned.
+ *
+ * local variables:
+ * int c value of character
+ * from input text line
+ * int n looping counter
+ * int v current value of numeric conversion
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char get() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip the position
+ * in the current input text line
+ */
+
+int
+getmap(d)
+{
+ register int c, n, v;
+
+ if ((c = get()) == '\0')
+ return (-1);
+ if (c == d)
+ return (-1);
+ if (c == '\\') {
+ c = get();
+ switch (c) {
+
+ case 'b':
+ c = '\b';
+ break;
+
+ case 'f':
+ c = '\f';
+ break;
+
+ case 'n':
+ c = '\n';
+ break;
+
+ case 'r':
+ c = '\r';
+ break;
+
+ case 't':
+ c = '\t';
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ n = 0;
+ v = 0;
+ while (++n<=3 && c>='0' && c<='7') {
+ v = (v<<3) + c - '0';
+ c = get();
+ }
+ unget(c);
+ c = v;
+ break;
+ }
+ }
+ return (c);
+}
+
+/*)Function int getline()
+ *
+ * The function getline() reads a line of input text from a
+ * .rel source text file, a .lnk command file or from stdin.
+ * Lines of text are processed from a single .lnk file or
+ * multiple .rel files until all files have been read.
+ * The input text line is copied into the global string ib[]
+ * and converted to a NULL terminated string. The function
+ * getline() returns a (1) after succesfully reading a line
+ * or a (0) if all files have been read.
+ * This function also opens each input .lst file and output
+ * .rst file as each .rel file is processed.
+ *
+ * local variables:
+ * int i string length
+ * int ftype file type
+ * char * fid file name
+ *
+ * global variables:
+ * lfile *cfp The pointer *cfp points to the
+ * current lfile structure
+ * lfile *filep The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ * int gline get a line from the LST file
+ * to translate for the RST file
+ * char ib[NINPUT] REL file text line
+ * int pass linker pass number
+ * int pflag print linker command file flag
+ * FILE *rfp The file handle to the current
+ * output RST file
+ * FILE *sfp The file handle sfp points to the
+ * currently open file
+ * FILE * stdin c_library
+ * FILE * stdout c_library
+ * FILE *tfp The file handle to the current
+ * LST file being scanned
+ * int uflag update listing flag
+ *
+ * called functions:
+ * FILE * afile() lkmain.c
+ * int fclose() c_library
+ * char * fgets() c_library
+ * int fprintf() c_library
+ * VOID lkulist() lklist.c
+ * VOID lkexit() lkmain.c
+ * int strlen() c_library
+ *
+ * side effects:
+ * The input stream is scanned. The .rel files will be
+ * opened and closed sequentially scanning each in turn.
+ */
+
+int
+getline()
+{
+ register int ftype;
+ register char *fid;
+
+loop: if (pflag && cfp && cfp->f_type == F_STD)
+ fprintf(stdout, "ASlink >> ");
+
+ if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
+ if (sfp) {
+ fclose(sfp);
+ sfp = NULL;
+ lkulist(0);
+ }
+ if (cfp == NULL) {
+ cfp = filep;
+ } else {
+ cfp = cfp->f_flp;
+ }
+ if (cfp) {
+ ftype = cfp->f_type;
+ fid = cfp->f_idp;
+ if (ftype == F_STD) {
+ sfp = stdin;
+ } else
+ if (ftype == F_LNK) {
+ sfp = afile(fid, "lnk", 0);
+ } else
+ if (ftype == F_REL) {
+ sfp = afile(fid, "rel", 0);
+ /* if a .cdb file exists then copy it over */
+ if (dflag && sfp && dfp && pass == 0) {
+ FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002
+ if (xfp) {
+ copyfile(dfp,xfp);
+ fclose(xfp);
+ }
+ }
+ if (uflag && pass != 0) {
+ SaveLinkedFilePath(fid); //Save the linked path for aomf51
+ if ((tfp = afile(fid, "lst", 0)) != NULL) {
+ if ((rfp = afile(fid, "rst", 1)) == NULL) {
+ fclose(tfp);
+ tfp = NULL;
+ }
+ }
+ }
+ gline = 1;
+ } else {
+ fprintf(stderr, "Invalid file type\n");
+ lkexit(1);
+ }
+ if (sfp == NULL) {
+ lkexit(1);
+ }
+ goto loop;
+ } else {
+ filep = NULL;
+ return(0);
+ }
+ }
+ chop_crlf(ib);
+ return (1);
+}
+
+/*)Function int more()
+ *
+ * The function more() scans the input text line
+ * skipping white space (SPACES and TABS) and returns a (0)
+ * if the end of the line or a comment delimeter (;) is found,
+ * or a (1) if their are additional characters in the line.
+ *
+ * local variables:
+ * int c next character from
+ * the input text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of getnb() and unget() updates the global pointer ip
+ * the position in the current input text line
+ */
+
+int
+more()
+{
+ register int c;
+
+ c = getnb();
+ unget(c);
+ return( (c == '\0' || c == ';') ? 0 : 1 );
+}
+
+/*)Function char endline()
+ *
+ * The function endline() scans the input text line
+ * skipping white space (SPACES and TABS) and returns the next
+ * character or a (0) if the end of the line is found or a
+ * comment delimiter (;) is found.
+ *
+ * local variables:
+ * int c next character from
+ * the input text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char getnb() lklex.c
+ *
+ * side effects:
+ * Use of getnb() updates the global pointer ip the
+ * position in the current input text line.
+ */
+
+char
+endline()
+{
+ register int c;
+
+ c = getnb();
+ return( (c == '\0' || c == ';') ? 0 : c );
+}
+
+/*)Function VOID chop_crlf(str)
+ *
+ * char *str string to chop
+ *
+ * The function chop_crlf() removes trailing LF or CR/LF from
+ * str, if present.
+ *
+ * local variables:
+ * int i string length
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+VOID
+chop_crlf(str)
+char *str;
+{
+ register int i;
+
+ i = strlen(str);
+ if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
+ if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;
+}
--- /dev/null
+/* lklibr.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * With contributions for the
+ * object libraries from
+ * Ken Hornstein
+ * kenh@cmf.nrl.navy.mil
+ *
+ */
+
+#define EQ(A,B) !strcmp((A),(B))
+#define MAXLINE 254 /*when using fgets*/
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <sys/types.h>
+#include <sys/malloc.h>
+#else
+#include <malloc.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lklibr.c
+ *
+ * The module lklibr.c contains the functions which
+ * (1) specify the path(s) to library files [.LIB]
+ * (2) specify the library file(s) [.LIB] to search
+ * (3) search the library files for specific symbols
+ * and link the module containing this symbol
+ *
+ * lklibr.c contains the following functions:
+ * VOID addpath()
+ * VOID addlib()
+ * VOID addfile()
+ * VOID search()
+ * VOID fndsym()
+ * VOID library()
+ * VOID loadfile()
+ *
+ */
+
+/*)Function VOID addpath()
+ *
+ * The function addpath() creates a linked structure containing
+ * the paths to various object module library files.
+ *
+ * local variables:
+ * lbpath *lbph pointer to new path structure
+ * lbpath *lbp temporary pointer
+ *
+ * global variables:
+ * lbpath *lbphead The pointer to the first
+ * path structure
+ *
+ * functions called:
+ * char getnb() lklex.c
+ * VOID * new() lksym.c
+ * int strlen() c_library
+ * char * strcpy() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * An lbpath structure may be created.
+ */
+
+VOID
+addpath()
+{
+ struct lbpath *lbph, *lbp;
+
+ lbph = (struct lbpath *) new (sizeof(struct lbpath));
+ if (lbphead == NULL) {
+ lbphead = lbph;
+ } else {
+ lbp = lbphead;
+ while (lbp->next)
+ lbp = lbp->next;
+ lbp->next = lbph;
+ }
+ unget(getnb());
+ lbph->path = (char *) new (strlen(ip)+1);
+ strcpy(lbph->path, ip);
+}
+
+/*)Function VOID addlib()
+ *
+ * The function addlib() tests for the existance of a
+ * library path structure to determine the method of
+ * adding this library file to the library search structure.
+ *
+ * This function calls the function addfile() to actually
+ * add the library file to the search list.
+ *
+ * local variables:
+ * lbpath *lbph pointer to path structure
+ *
+ * global variables:
+ * lbpath *lbphead The pointer to the first
+ * path structure
+ * ip a pointer to the library name
+ *
+ * functions called:
+ * VOID addfile() lklibr.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * The function addfile() may add the file to
+ * the library search list.
+ */
+
+VOID
+addlib()
+{
+ struct lbpath *lbph;
+ int foundcount=0;
+
+ unget(getnb());
+
+ if (lbphead == NULL)
+ {
+ foundcount=addfile(NULL, ip);
+ }
+ else
+ {
+ for (lbph=lbphead; lbph; lbph=lbph->next)
+ {
+ foundcount+=addfile(lbph->path, ip);
+ }
+ }
+ if(foundcount == 0)
+ {
+ printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
+ }
+}
+
+/*)Function int addfile(path,libfil)
+ *
+ * char *path library path specification
+ * char *libfil library file specification
+ *
+ * The function addfile() searches for the library file
+ * by concatenating the path and libfil specifications.
+ * if the library is found, an lbname structure is created
+ * and linked to any previously defined structures. This
+ * linked list is used by the function fndsym() to attempt
+ * to find any undefined symbols.
+ *
+ * The function does not give report an error on invalid
+ * path / file specifications or if the file is not found.
+ *
+ * local variables:
+ * lbname *lbnh pointer to new name structure
+ * lbname *lbn temporary pointer
+ *
+ * global variables:
+ * lbname *lbnhead The pointer to the first
+ * path structure
+ *
+ * functions called:
+ * char getnb() lklex.c
+ * VOID * new() lksym.c
+ * int strlen() c_library
+ * char * strcpy() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * An lbname structure may be created.
+ *
+ * return:
+ * 1: the library was found
+ * 0: the library was not found
+ */
+
+int addfile(char * path, char * libfil)
+{
+ FILE *fp;
+ char *str;
+ struct lbname *lbnh, *lbn;
+#ifdef OTHERSYSTEM
+ int libfilinc=0;
+#endif
+
+ if (path != NULL)
+ {
+ str = (char *) new (strlen(path) + strlen(libfil) + 6);
+ strcpy(str,path);
+#ifdef OTHERSYSTEM
+ if (str[strlen(str)-1] != '/')
+ {
+ strcat(str,"/");
+ }
+#endif
+ }
+ else
+ {
+ str = (char *) new (strlen(libfil) + 5);
+ }
+
+#ifdef OTHERSYSTEM
+ if (libfil[0] == '/')
+ {
+ libfil++;
+ libfilinc=1;
+ }
+#endif
+
+ strcat(str, libfil);
+ if(strchr(libfil, FSEPX) == NULL)
+ {
+ sprintf(&str[strlen(str)], "%clib", FSEPX);
+ }
+
+ fp=fopen(str, "r");
+ if(fp == NULL)
+ {
+ /*Ok, that didn't work. Try with the 'libfil' name only*/
+#ifdef OTHERSYSTEM
+ if(libfilinc) libfil--;
+#endif
+ fp=fopen(libfil, "r");
+ if(fp != NULL)
+ {
+ /*Bingo! 'libfil' is the absolute path of the library*/
+ strcpy(str, libfil);
+ path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
+ }
+ }
+
+ if(path==NULL)
+ {
+ /*'path' can not be null since it is needed to find the '.rel' files associated with
+ the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
+ That way putting 'path' and 'libfil' together will result into the original filepath
+ as contained in 'str'.*/
+ int j;
+ path = (char *) new (strlen(str));
+ strcpy(path, str);
+ for(j=strlen(path)-1; j>=0; j--)
+ {
+ if((path[j]=='\\')||(path[j]=='/'))
+ {
+ strcpy(libfil, &path[j+1]);
+ path[j+1]=0;
+ break;
+ }
+ }
+ if(j<=0) path[0]=0;
+ }
+
+ if (fp != NULL)
+ {
+ fclose(fp);
+ lbnh = (struct lbname *) new (sizeof(struct lbname));
+ if (lbnhead == NULL)
+ {
+ lbnhead = lbnh;
+ }
+ else
+ {
+ lbn = lbnhead;
+ while (lbn->next)
+ lbn = lbn->next;
+ lbn->next = lbnh;
+ }
+
+ lbnh->path = path;
+ lbnh->libfil = (char *) new (strlen(libfil) + 1);
+ strcpy(lbnh->libfil,libfil);
+ lbnh->libspc = str;
+ return 1;
+ }
+ else
+ {
+ free(str);
+ return 0;
+ }
+}
+
+/*)Function VOID search()
+ *
+ * The function search() looks through all the symbol tables
+ * at the end of pass 1. If any undefined symbols are found
+ * then the function fndsym() is called. Function fndsym()
+ * searches any specified library files to automagically
+ * import the object modules containing the needed symbol.
+ *
+ * After a symbol is found and imported by the function
+ * fndsym() the symbol tables are again searched. The
+ * symbol tables are search until no more symbols can be
+ * resolved within the library files. This ensures that
+ * back references from one library module to another are
+ * also resolved.
+ *
+ * local variables:
+ * int i temporary counter
+ * sym *sp pointer to a symbol structure
+ * int symfnd found a symbol flag
+ *
+ * global variables:
+ * sym *symhash[] array of pointers to symbol tables
+ *
+ * functions called:
+ * int fndsym() lklibr.c
+ *
+ * side effects:
+ * If a symbol is found then the library object module
+ * containing the symbol will be imported and linked.
+ */
+
+VOID
+search()
+{
+ register struct sym *sp;
+ register int i,symfnd;
+
+ /*
+ * Look for undefined symbols. Keep
+ * searching until no more symbols are resolved.
+ */
+ symfnd = 1;
+ while (symfnd) {
+ symfnd = 0;
+ /*
+ * Look through all the symbols
+ */
+ for (i=0; i<NHASH; ++i) {
+ sp = symhash[i];
+ while (sp) {
+ /* If we find an undefined symbol
+ * (one where S_DEF is not set), then
+ * try looking for it. If we find it
+ * in any of the libraries then
+ * increment symfnd. This will force
+ * another pass of symbol searching and
+ * make sure that back references work.
+ */
+ if ((sp->s_type & S_DEF) == 0) {
+ if (fndsym(sp->s_id)) {
+ symfnd++;
+ }
+ }
+ sp = sp->s_sp;
+ }
+ }
+ }
+}
+
+/*Load a .rel file embedded in a sdcclib file*/
+void LoadRel(FILE * libfp, char * ModName)
+{
+ char str[NINPUT+2];
+ int state=0;
+
+ while (fgets(str, NINPUT, libfp) != NULL)
+ {
+ str[NINPUT+1] = '\0';
+ chop_crlf(str);
+ switch(state)
+ {
+ case 0:
+ if(EQ(str, "<FILE>"))
+ {
+ fgets(str, NINPUT, libfp);
+ str[NINPUT+1] = '\0';
+ chop_crlf(str);
+ if(EQ(str, ModName)) state=1;
+ else
+ {
+ printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
+ lkexit(1);
+ }
+ }
+ break;
+ case 1:
+ if(EQ(str, "<REL>")) state=2;
+ break;
+ case 2:
+ if(EQ(str, "</REL>")) return;
+ ip = str;
+ link_main();
+ break;
+ }
+ }
+}
+
+/*Load an .adb file embedded in a sdcclib file. If there is
+something between <ADB> and </ADB> returns 1, otherwise returns 0.
+This way the aomf51 will not have uselless empty modules. */
+
+int LoadAdb(FILE * libfp)
+{
+ char str[MAXLINE+1];
+ int state=0;
+ int ToReturn=0;
+
+ while (fgets(str, MAXLINE, libfp) != NULL)
+ {
+ str[NINPUT+1] = '\0';
+ chop_crlf(str);
+ switch(state)
+ {
+ case 0:
+ if(EQ(str, "<ADB>")) state=1;
+ break;
+ case 1:
+ if(EQ(str, "</ADB>")) return ToReturn;
+ fprintf(dfp, "%s\n", str);
+ ToReturn=1;
+ break;
+ }
+ }
+ return ToReturn;
+}
+
+/*Check for a symbol in a SDCC library. If found, add the embedded .rel and
+.adb files from the library. The library must be created with the SDCC
+librarian 'sdcclib' since the linking process depends on the correct file offsets
+embedded in the library file.*/
+
+int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
+{
+ struct lbfile *lbfh, *lbf;
+ char ModName[NCPS]="";
+ char FLine[MAXLINE+1];
+ int state=0;
+ long IndexOffset=0, FileOffset;
+
+ while(!feof(libfp))
+ {
+ FLine[0]=0;
+ fgets(FLine, MAXLINE, libfp);
+ chop_crlf(FLine);
+
+ switch(state)
+ {
+ case 0:
+ if(EQ(FLine, "<INDEX>"))
+ {
+ /*The next line has the size of the index*/
+ FLine[0]=0;
+ fgets(FLine, MAXLINE, libfp);
+ chop_crlf(FLine);
+ IndexOffset=atol(FLine);
+ state=1;
+ }
+ break;
+ case 1:
+ if(EQ(FLine, "<MODULE>"))
+ {
+ /*The next line has the name of the module and the offset
+ of the corresponding embedded file in the library*/
+ FLine[0]=0;
+ fgets(FLine, MAXLINE, libfp);
+ chop_crlf(FLine);
+ sscanf(FLine, "%s %ld", ModName, &FileOffset);
+ state=2;
+ }
+ else if(EQ(FLine, "</INDEX>"))
+ {
+ /*Reached the end of the index. The symbol is not in this library.*/
+ return 0;
+ }
+ break;
+ case 2:
+ if(EQ(FLine, "</MODULE>"))
+ {
+ /*The symbol is not in this module, try the next one*/
+ state=1;
+ }
+ else
+ {
+ /*Check if this is the symbol we are looking for.*/
+ if (strncmp(SymName, FLine, NCPS)==0)
+ {
+ /*The symbol is in this module.*/
+
+ /*As in the original library format, it is assumed that the .rel
+ files reside in the same directory as the lib files.*/
+ strcat(DirLib, ModName);
+ sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
+
+ /*If this module has been loaded already don't load it again.*/
+ lbf = lbfhead;
+ while (lbf)
+ {
+ if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
+ lbf=lbf->next;
+ }
+
+ /*Add the embedded file to the list of files to be loaded in
+ the second pass. That is performed latter by the function
+ library() below.*/
+ lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+ if (lbfhead == NULL)
+ {
+ lbfhead = lbfh;
+ }
+ else
+ {
+ lbf = lbfhead;
+ while (lbf->next)
+ lbf = lbf->next;
+ lbf->next = lbfh;
+ }
+
+ lbfh->libspc = PathLib;
+ lbfh->filspc = DirLib;
+ lbfh->relfil = (char *) new (strlen(ModName) + 1);
+ strcpy(lbfh->relfil, ModName);
+ /*Library embedded file, so lbfh->offset must be >=0*/
+ lbfh->offset = IndexOffset+FileOffset;
+
+ /*Jump to where the .rel begins and load it.*/
+ fseek(libfp, lbfh->offset, SEEK_SET);
+ LoadRel(libfp, ModName);
+
+ /* if cdb information required & .adb file present */
+ if (dflag && dfp)
+ {
+ if(LoadAdb(libfp))
+ SaveLinkedFilePath(DirLib);
+ }
+ return 1; /*Found the symbol, so success!*/
+ }
+ }
+ break;
+
+ default:
+ return 0; /*It should never reach this point, but just in case...*/
+ break;
+ }
+ }
+
+ return 0; /*The symbol is not in this library*/
+}
+
+/*)Function VOID fndsym(name)
+ *
+ * char *name symbol name to find
+ *
+ * The function fndsym() searches through all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file.
+ *
+ * The file specicifation may be formed in one of two ways:
+ *
+ * (1) If the library file contained an absolute
+ * path/file specification then this becomes filspc.
+ * (i.e. C:\...)
+ *
+ * (2) If the library file contains a relative path/file
+ * specification then the concatenation of the path
+ * and this file specification becomes filspc.
+ * (i.e. \...)
+ *
+ * The structure lbfile is created for the first library
+ * object file which contains the definition for the
+ * specified undefined symbol.
+ *
+ * If the library file [.LIB] contains file specifications for
+ * non existant files, no errors are returned.
+ *
+ * local variables:
+ * char buf[] [.REL] file input line
+ * char c [.REL] file input character
+ * FILE *fp file handle for object file
+ * lbfile *lbf temporary pointer
+ * lbfile *lbfh pointer to lbfile structure
+ * FILE *libfp file handle for library file
+ * lbname *lbnh pointer to lbname structure
+ * char *path file specification path
+ * char relfil[] [.REL] file specification
+ * char *str combined path and file specification
+ * char symname[] [.REL] file symbol string
+ *
+ * global variables:
+ * lbname *lbnhead The pointer to the first
+ * name structure
+ * lbfile *lbfhead The pointer to the first
+ * file structure
+ *
+ * functions called:
+ * int fclose() c_library
+ * int fgets() c_library
+ * FILE *fopen() c_library
+ * VOID free() c_library
+ * char getnb() lklex.c
+ * VOID lkexit() lkmain.c
+ * VOID loadfile() lklibr.c
+ * VOID * new() lksym.c
+ * char * sprintf() c_library
+ * int sscanf() c_library
+ * char * strcat() c_library
+ * char * strchr() c_library
+ * char * strcpy() c_library
+ * int strlen() c_library
+ * int strncmp() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * If the symbol is found then a new lbfile structure
+ * is created and added to the linked list of lbfile
+ * structures. The file containing the found symbol
+ * is linked.
+ */
+
+int
+fndsym(name)
+char *name;
+{
+ FILE *libfp, *fp;
+ struct lbname *lbnh;
+ struct lbfile *lbfh, *lbf;
+ char relfil[NINPUT+2];
+ char buf[NINPUT+2];
+ char symname[NINPUT];
+ char *path,*str;
+ char c;
+ int result;
+
+ /*
+ * Search through every library in the linked list "lbnhead".
+ */
+
+ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
+ {
+ if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
+ {
+ fprintf(stderr, "Cannot open library file %s\n",
+ lbnh->libspc);
+ lkexit(1);
+ }
+ path = lbnh->path;
+
+ /*
+ * Read in a line from the library file.
+ * This is the relative file specification
+ * for a .REL file in this library.
+ */
+
+ while (fgets(relfil, NINPUT, libfp) != NULL)
+ {
+ relfil[NINPUT+1] = '\0';
+ chop_crlf(relfil);
+ if (path != NULL)
+ {
+ str = (char *) new (strlen(path)+strlen(relfil)+6);
+ strcpy(str,path);
+#ifdef OTHERSYSTEM
+ if (str[strlen(str)-1] != '/')
+ {
+ strcat(str,"/");
+ }
+#endif
+ }
+ else
+ {
+ str = (char *) new (strlen(relfil) + 5);
+ }
+
+ if(strcmp(relfil, "<SDCCLIB>")==0)
+ {
+ result=SdccLib(lbnh->libspc, libfp, str, name);
+ fclose(libfp);
+ if(result) return(1); /*Found the symbol*/
+ free(str);
+ /*The symbol is not in the current library,
+ check the next library in the list*/
+ break;
+ }
+
+ /*From here down is the support for libraries in the original format*/
+ if (relfil[0] == '\\')
+ {
+ strcat(str,relfil+1);
+ }
+ else
+ {
+ strcat(str,relfil);
+ }
+
+ if(strchr(relfil, FSEPX) == NULL)
+ {
+ sprintf(&str[strlen(str)], "%crel", FSEPX);
+ }
+
+ if ((fp = fopen(str, "r")) != NULL)
+ {
+
+ /*
+ * Read in the object file. Look for lines that
+ * begin with "S" and end with "D". These are
+ * symbol table definitions. If we find one, see
+ * if it is our symbol. Make sure we only read in
+ * our object file and don't go into the next one.
+ */
+
+ while (fgets(buf, NINPUT, fp) != NULL)
+ {
+ buf[NINPUT+1] = '\0';
+ chop_crlf(buf);
+ /*
+ * Skip everything that's not a symbol record.
+ */
+ if (buf[0] != 'S') continue;
+
+ /*
+ * When a 'T line' is found terminate file scan.
+ * All 'S line's preceed 'T line's in .REL files.
+ */
+ if (buf[0] == 'T') break;
+
+ sscanf(buf, "S %s %c", symname, &c);
+
+ /*
+ * If we find a symbol definition for the
+ * symbol we're looking for, load in the
+ * file and add it to lbfhead so it gets
+ * loaded on pass number 2.
+ */
+ if (strncmp(symname, name, NCPS) == 0 && c == 'D')
+ {
+ lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+ if (lbfhead == NULL)
+ {
+ lbfhead = lbfh;
+ }
+ else
+ {
+ lbf = lbfhead;
+ while (lbf->next)
+ lbf = lbf->next;
+ lbf->next = lbfh;
+ }
+
+ lbfh->libspc = lbnh->libspc;
+ lbfh->filspc = str;
+ lbfh->relfil = (char *) new (strlen(relfil) + 1);
+ lbfh->offset = -1; /*Stand alone rel file*/
+ strcpy(lbfh->relfil,relfil);
+ fclose(fp);
+ fclose(libfp);
+
+ /* if cdb information required & adb file present */
+ if (dflag && dfp)
+ {
+ FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
+ if (xfp)
+ {
+ SaveLinkedFilePath(str);
+ copyfile(dfp,xfp);
+ fclose(xfp);
+ }
+ }
+ loadfile(str);
+ return (1);
+ }
+ }
+ fclose(fp);
+ }
+ free(str);
+ }
+ fclose(libfp);
+ }
+ return(0);
+}
+
+void loadfile_SdccLib(char * libspc, char * module, long offset)
+{
+ FILE *fp;
+
+ if ((fp = fopen(libspc,"r")) != NULL)
+ {
+ fseek(fp, offset, SEEK_SET);
+ LoadRel(fp, module);
+ fclose(fp);
+ }
+}
+
+/*)Function VOID library()
+ *
+ * The function library() links all the library object files
+ * contained in the lbfile structures.
+ *
+ * local variables:
+ * lbfile *lbfh pointer to lbfile structure
+ *
+ * global variables:
+ * lbfile *lbfhead pointer to first lbfile structure
+ *
+ * functions called:
+ * VOID loadfile lklibr.c
+ *
+ * side effects:
+ * Links all files contained in the lbfile structures.
+ */
+
+VOID
+library()
+{
+ struct lbfile *lbfh;
+
+ for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
+ {
+ if(lbfh->offset<0)
+ {
+ /*Stand alone rel file (original lib format)*/
+ loadfile(lbfh->filspc);
+ }
+ else
+ {
+ /*rel file embedded in lib (new lib format)*/
+ loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+ }
+ }
+}
+
+/*)Function VOID loadfile(filspc)
+ *
+ * char *filspc library object file specification
+ *
+ * The function loadfile() links the library object module.
+ *
+ * local variables:
+ * FILE *fp file handle
+ * int i input line length
+ * char str[] file input line
+ *
+ * global variables:
+ * char *ip pointer to linker input string
+ *
+ * functions called:
+ * int fclose() c_library
+ * int fgets() c_library
+ * FILE * fopen() c_library
+ * VOID link_main() lkmain.c
+ * int strlen() c_library
+ *
+ * side effects:
+ * If file exists it is linked.
+ */
+
+VOID
+loadfile(filspc)
+char *filspc;
+{
+ FILE *fp;
+ char str[NINPUT+2];
+
+ if ((fp = fopen(filspc,"r")) != NULL) {
+ while (fgets(str, NINPUT, fp) != NULL) {
+ str[NINPUT+1] = '\0';
+ chop_crlf(str);
+ ip = str;
+ link_main();
+ }
+ fclose(fp);
+ }
+}
--- /dev/null
+/* lklist.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - lstarea: show s_id as string rather than array [NCPS]
+ * - lstarea: show a_id as string rather than array [NCPS]
+ * 31-Oct-97 JLH: add NoICE output file genration in lstarea
+ * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+/*)Module lklist.c
+ *
+ * The module lklist.c contains the functions which
+ * output the linker .map file and produce a relocated
+ * listing .rst file.
+ *
+ * lklist.c contains the following functions:
+ * int dgt()
+ * VOID lstarea()
+ * VOID lkulist()
+ * VOID lkalist()
+ * VOID lkglist()
+ * VOID newpag()
+ * VOID slew()
+ *
+ * lklist.c contains no local variables.
+ */
+
+/*)Function VOID slew(fp)
+ *
+ * FILE * fp output file handle
+ *
+ * The function slew() increments the page line counter.
+ * If the number of lines exceeds the maximum number of
+ * lines per page then a page skip and a page header are
+ * output.
+ *
+ * local variables:
+ * int i loop counter
+ *
+ * global variables:
+ * int lop current line number on page
+ * int xflag Map file radix type flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID newpag() lklist.c
+ *
+ * side effects:
+ * The page line and the page count may be updated.
+ */
+
+VOID
+slew(fp)
+FILE *fp;
+{
+ register int i;
+
+ if (lop++ >= NLPP) {
+ newpag(fp);
+ if (xflag == 0) {
+ fprintf(fp, "Hexadecimal\n\n");
+ } else
+ if (xflag == 1) {
+ fprintf(fp, "Octal\n\n");
+ } else
+ if (xflag == 2) {
+ fprintf(fp, "Decimal\n\n");
+ }
+ fprintf(fp, "Area Addr Size");
+ fprintf(fp, " Decimal Bytes (Attributes)\n");
+ for(i=0;i<4;++i)
+ fprintf(fp, " Value--Global");
+ fprintf(fp, "\n\n");
+ lop += 6;
+ }
+}
+
+/*)Function VOID newpag()
+ *
+ * The function newpag() outputs a page skip, writes the
+ * first page header line, sets the line count to 1, and
+ * increments the page counter.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * int lop current line number on page
+ * int page current page number
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * The page and line counters are updated.
+ */
+
+VOID
+newpag(fp)
+FILE *fp;
+{
+ fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page);
+ lop = 1;
+}
+
+/* Used for qsort call in lstsym */
+static int _cmpSymByAddr(const void *p1, const void *p2)
+{
+ struct sym **s1 = (struct sym **)(p1);
+ struct sym **s2 = (struct sym **)(p2);
+ int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) -
+ ((*s2)->s_addr + (*s2)->s_axp->a_addr);
+
+ /* Sort first by address, then by name. */
+ if (delta)
+ {
+ return delta;
+ }
+ return strcmp((*s1)->s_id,(*s2)->s_id);
+}
+
+
+#if NCPS-8
+
+/* NCPS != 8 */
+/*)Function VOID lstarea(xp)
+ *
+ * area * xp pointer to an area structure
+ *
+ * The function lstarea() creates the linker map output for
+ * the area specified by pointer xp. The generated output
+ * area header includes the area name, starting address,
+ * size of area, number of words (in decimal), and the
+ * area attributes. The symbols defined in this area are
+ * sorted by ascending address and output one per line
+ * in the selected radix.
+ *
+ * local variables:
+ * areax * oxp pointer to an area extension structure
+ * int c character value
+ * int i loop counter
+ * int j bubble sort update status
+ * char * ptr pointer to an id string
+ * int nmsym number of symbols in area
+ * Addr_T a0 temporary
+ * Addr_T ai temporary
+ * Addr_T aj temporary
+ * sym * sp pointer to a symbol structure
+ * sym ** p pointer to an array of
+ * pointers to symbol structures
+ *
+ * global variables:
+ * FILE *mfp Map output file handle
+ * sym *symhash[NHASH] array of pointers to NHASH
+ * linked symbol lists
+ * int xflag Map file radix type flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID free() c_library
+ * char * malloc() c_library
+ * char putc() c_library
+ * VOID slew() lklist.c
+ *
+ * side effects:
+ * Map output generated.
+ */
+
+VOID
+lstarea(xp)
+struct area *xp;
+{
+ register struct areax *oxp;
+ register int i;
+ /* int j; */
+ register char *ptr;
+ int nmsym;
+ /* Addr_T a0; */
+ Addr_T ai, aj;
+ struct sym *sp;
+ struct sym **p;
+ int memPage;
+
+ putc('\n', mfp);
+ if (xflag == 0) {
+ fprintf(mfp, "Hexadecimal\n\n");
+ } else
+ if (xflag == 1) {
+ fprintf(mfp, "Octal\n\n");
+ } else
+ if (xflag == 2) {
+ fprintf(mfp, "Decimal\n\n");
+ }
+ fprintf(mfp, "Area ");
+ fprintf(mfp, "Addr Size Decimal %s (Attributes)\n",
+ (xp->a_flag & A_BIT)?"Bits ":"Bytes");/* JCF: For BIT print bits...*/
+ fprintf(mfp, "-------------------------------- ");
+ fprintf(mfp, "---- ---- ------- ----- ------------\n");
+ /*
+ * Output Area Header
+ */
+ ptr = &xp->a_id[0];
+ fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */
+ ai = xp->a_addr;
+ aj = xp->a_size;
+ if (xflag == 0) {
+ fprintf(mfp, " %04X %04X", ai, aj);
+ } else
+ if (xflag == 1) {
+ fprintf(mfp, " %06o %06o", ai, aj);
+ } else
+ if (xflag == 2) {
+ fprintf(mfp, " %05u %05u", ai, aj);
+ }
+ fprintf(mfp, " = %6u. %s ", aj,
+ (xp->a_flag & A_BIT)?"bits ":"bytes"); /* JCF: For BIT print bits...*/
+ if (xp->a_flag & A_ABS) {
+ fprintf(mfp, "(ABS");
+ } else {
+ fprintf(mfp, "(REL");
+ }
+ if (xp->a_flag & A_OVR) {
+ fprintf(mfp, ",OVR");
+ } else {
+ fprintf(mfp, ",CON");
+ }
+ if (xp->a_flag & A_PAG) {
+ fprintf(mfp, ",PAG");
+ }
+
+ memPage = 0x00;
+ if (xp->a_flag & A_CODE) {
+ fprintf(mfp, ",CODE");
+ memPage = 0x0C;
+ }
+ if (xp->a_flag & A_XDATA) {
+ fprintf(mfp, ",XDATA");
+ memPage = 0x0D;
+ }
+ if (xp->a_flag & A_BIT) {
+ fprintf(mfp, ",BIT");
+ memPage = 0x0B;
+ }
+ fprintf(mfp, ")");
+ if (xp->a_flag & A_PAG) {
+ ai = (ai & 0xFF);
+ aj = (aj > 256);
+ if (ai || aj) { fprintf(mfp, " "); }
+ if (ai) { fprintf(mfp, " Boundary"); }
+ if (ai & aj) { fprintf(mfp, " /"); }
+ if (aj) { fprintf(mfp, " Length"); }
+ if (ai || aj) { fprintf(mfp, " Error"); }
+ }
+
+ /*
+ * Find number of symbols in area
+ */
+ nmsym = 0;
+ oxp = xp->a_axp;
+ while (oxp) {
+ for (i=0; i<NHASH; i++) {
+ sp = symhash[i];
+ while (sp != NULL) {
+ if (oxp == sp->s_axp)
+ ++nmsym;
+ sp = sp->s_sp;
+ }
+ }
+ oxp = oxp->a_axp;
+ }
+ if (nmsym == 0) {
+ putc('\n', mfp);
+ return;
+ }
+
+ /*
+ * Allocate space for an array of pointers to symbols
+ * and load array.
+ */
+ if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
+ == NULL) {
+ fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
+ return;
+ }
+ nmsym = 0;
+ oxp = xp->a_axp;
+ while (oxp) {
+ for (i=0; i<NHASH; i++) {
+ sp = symhash[i];
+ while (sp != NULL) {
+ if (oxp == sp->s_axp) {
+ p[nmsym++] = sp;
+ }
+ sp = sp->s_sp;
+ }
+ }
+ oxp = oxp->a_axp;
+ }
+
+#if 0
+ /*
+ * Bubble Sort of Addresses in Symbol Table Array
+ */
+ j = 1;
+ while (j) {
+ j = 0;
+ sp = p[0];
+ a0 = sp->s_addr + sp->s_axp->a_addr;
+ for (i=1; i<nmsym; ++i) {
+ sp = p[i];
+ ai = sp->s_addr + sp->s_axp->a_addr;
+ if (a0 > ai) {
+ j = 1;
+ p[i] = p[i-1];
+ p[i-1] = sp;
+ }
+ a0 = ai;
+ }
+ }
+#else
+ qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
+#endif
+
+ /*
+ * Symbol Table Output
+ */
+
+ i = 0;
+ fprintf(mfp, "\n\n");
+ fprintf(mfp, " Value Global\n");
+ fprintf(mfp, " -------- --------------------------------");
+ while (i < nmsym) {
+ fprintf(mfp, "\n");
+ if (memPage != 0)
+ fprintf(mfp, " %02X:", memPage);
+ else
+ fprintf(mfp, " ");
+
+ sp = p[i];
+ aj = sp->s_addr + sp->s_axp->a_addr;
+ if (xflag == 0) {
+ fprintf(mfp, "%04X ", aj);
+ } else
+ if (xflag == 1) {
+ fprintf(mfp, "%06o ", aj);
+ } else
+ if (xflag == 2) {
+ fprintf(mfp, "%05u ", aj);
+ }
+ ptr = &sp->s_id[0];
+ fprintf(mfp, "%s", ptr );
+
+ /* if cdb flag set the output cdb Information
+ and the symbol has a '$' sign in it then */
+ if (dflag &&
+ strchr(ptr,'$'))
+ fprintf(dfp,"L:%s:%X\n",ptr,aj);
+
+ /* NoICE output of symbol */
+ if (jflag) DefineNoICE( ptr, aj, memPage );
+
+ i++;
+ }
+ putc('\n', mfp);
+ free(p);
+}
+
+#else
+
+/* NCPS == 8 */
+/*)Function VOID lstarea(xp)
+ *
+ * area * xp pointer to an area structure
+ *
+ * The function lstarea() creates the linker map output for
+ * the area specified by pointer xp. The generated output
+ * area header includes the area name, starting address,
+ * size of area, number of words (in decimal), and the
+ * area attributes. The symbols defined in this area are
+ * sorted by ascending address and output four per line
+ * in the selected radix.
+ *
+ * local variables:
+ * areax * oxp pointer to an area extension structure
+ * int c character value
+ * int i loop counter
+ * int j bubble sort update status
+ * char * ptr pointer to an id string
+ * int nmsym number of symbols in area
+ * Addr_T a0 temporary
+ * Addr_T ai temporary
+ * Addr_T aj temporary
+ * sym * sp pointer to a symbol structure
+ * sym ** p pointer to an array of
+ * pointers to symbol structures
+ *
+ * global variables:
+ * FILE *mfp Map output file handle
+ * sym *symhash[NHASH] array of pointers to NHASH
+ * linked symbol lists
+ * int xflag Map file radix type flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID free() c_library
+ * char * malloc() c_library
+ * char putc() c_library
+ * VOID slew() lklist.c
+ *
+ * side effects:
+ * Map output generated.
+ */
+
+VOID
+lstarea(xp)
+struct area *xp;
+{
+ register struct areax *oxp;
+ register c, i, j;
+ register char *ptr;
+ int nmsym;
+ Addr_T a0, ai, aj;
+ struct sym *sp;
+ struct sym **p;
+ int page;
+
+ putc('\n', mfp);
+ slew(mfp);
+ /*
+ * Output Area Header
+ */
+ ptr = &xp->a_id[0];
+ while (ptr < &xp->a_id[NCPS]) {
+ if ((c = *ptr++) != 0) {
+ putc(c, mfp);
+ } else {
+ putc(' ', mfp);
+ }
+ }
+ ai = xp->a_addr;
+ aj = xp->a_size;
+ if (xflag == 0) {
+ fprintf(mfp, " %04X %04X", ai, aj);
+ } else
+ if (xflag == 1) {
+ fprintf(mfp, " %06o %06o", ai, aj);
+ } else
+ if (xflag == 2) {
+ fprintf(mfp, " %05u %05u", ai, aj);
+ }
+ fprintf(mfp, " = %6u. bytes ", aj);
+ if (xp->a_flag & A_ABS) {
+ fprintf(mfp, "(ABS");
+ } else {
+ fprintf(mfp, "(REL");
+ }
+ if (xp->a_flag & A_OVR) {
+ fprintf(mfp, ",OVR");
+ } else {
+ fprintf(mfp, ",CON");
+ }
+ if (xp->a_flag & A_PAG) {
+ fprintf(mfp, ",PAG");
+ }
+
+ page = 0x00;
+ if (xp->a_flag & A_CODE) {
+ fprintf(mfp, ",CODE");
+ memPage = 0x0C;
+ }
+ if (xp->a_flag & A_XDATA) {
+ fprintf(mfp, ",XDATA");
+ memPage = 0x0D;
+ }
+ if (xp->a_flag & A_BIT) {
+ fprintf(mfp, ",BIT");
+ memPage = 0x0B;
+ }
+ fprintf(mfp, ")");
+ if (xp->a_flag & A_PAG) {
+ ai = (ai & 0xFF);
+ aj = (aj > 256);
+ if (ai || aj) { fprintf(mfp, " "); }
+ if (ai) { fprintf(mfp, " Boundary"); }
+ if (ai & aj) { fprintf(mfp, " /"); }
+ if (aj) { fprintf(mfp, " Length"); }
+ if (ai || aj) { fprintf(mfp, " Error"); }
+ }
+
+ /*
+ * Find number of symbols in area
+ */
+ nmsym = 0;
+ oxp = xp->a_axp;
+ while (oxp) {
+ for (i=0; i<NHASH; i++) {
+ sp = symhash[i];
+ while (sp != NULL) {
+ if (oxp == sp->s_axp)
+ ++nmsym;
+ sp = sp->s_sp;
+ }
+ }
+ oxp = oxp->a_axp;
+ }
+ if (nmsym == 0) {
+ putc('\n', mfp);
+ slew(mfp);
+ return;
+ }
+
+ /*
+ * Allocate space for an array of pointers to symbols
+ * and load array.
+ */
+ if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
+ == NULL) {
+ fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
+ slew(mfp);
+ return;
+ }
+ nmsym = 0;
+ oxp = xp->a_axp;
+ while (oxp) {
+ for (i=0; i<NHASH; i++) {
+ sp = symhash[i];
+ while (sp != NULL) {
+ if (oxp == sp->s_axp) {
+ p[nmsym++] = sp;
+ }
+ sp = sp->s_sp;
+ }
+ }
+ oxp = oxp->a_axp;
+ }
+
+#if 0
+ /*
+ * Bubble Sort of Addresses in Symbol Table Array
+ */
+ j = 1;
+ while (j) {
+ j = 0;
+ sp = p[0];
+ a0 = sp->s_addr + sp->s_axp->a_addr;
+ for (i=1; i<nmsym; ++i) {
+ sp = p[i];
+ ai = sp->s_addr + sp->s_axp->a_addr;
+ if (a0 > ai) {
+ j = 1;
+ p[i] = p[i-1];
+ p[i-1] = sp;
+ }
+ a0 = ai;
+ }
+ }
+#else
+ qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
+#endif
+
+ /*
+ * Symbol Table Output
+ */
+ i = 0;
+ while (i < nmsym) {
+ fprintf(mfp, "\n");
+ slew(mfp);
+ fprintf(mfp, " ");
+ sp = p[i];
+ aj = sp->s_addr + sp->s_axp->a_addr;
+ if (xflag == 0) {
+ fprintf(mfp, " %04X ", aj);
+ } else
+ if (xflag == 1) {
+ fprintf(mfp, "%06o ", aj);
+ } else
+ if (xflag == 2) {
+ fprintf(mfp, " %05u ", aj);
+ }
+ ptr = &sp->s_id[0];
+ fprintf(mfp, "%s", ptr );
+
+ /* NoICE output of symbol */
+ if (jflag) DefineNoICE( ptr, aj, memPage );
+ }
+ putc('\n', mfp);
+ free(p);
+ slew(mfp);
+}
+#endif
+
+/*)Function VOID lkulist(i)
+ *
+ * int i i # 0 process LST to RST file
+ * i = 0 copy remainder of LST file
+ * to RST file and close files
+ *
+ * The function lkulist() creates a relocated listing (.rst)
+ * output file from the ASxxxx assembler listing (.lst)
+ * files. The .lst file's program address and code bytes
+ * are changed to reflect the changes made by ASlink as
+ * the .rel files are combined into a single relocated
+ * output file.
+ *
+ * local variables:
+ * Addr_T pc current program counter address
+ *
+ * global variables:
+ * int hilo byte order
+ * int gline get a line from the LST file
+ * to translate for the RST file
+ * char rb[] read listing file text line
+ * FILE *rfp The file handle to the current
+ * output RST file
+ * int rtcnt count of data words
+ * int rtflg[] output the data flag
+ * Addr_T rtval[] relocated data
+ * FILE *tfp The file handle to the current
+ * LST file being scanned
+ *
+ * functions called:
+ * int fclose() c_library
+ * int fgets() c_library
+ * int fprintf() c_library
+ * VOID lkalist() lklist.c
+ * VOID lkglist() lklist.c
+ *
+ * side effects:
+ * A .rst file is created for each available .lst
+ * file associated with a .rel file.
+ */
+
+VOID
+lkulist(i)
+int i;
+{
+ Addr_T pc;
+
+ /*
+ * Exit if listing file is not open
+ */
+ if (tfp == NULL)
+ return;
+
+ /*
+ * Normal processing of LST to RST
+ */
+ if (i) {
+ /*
+ * Evaluate current code address
+ */
+ if (hilo == 0) {
+ pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
+ } else {
+ pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
+ }
+
+ /*
+ * Line with only address
+ */
+ if (rtcnt == 2) {
+ lkalist(pc);
+
+ /*
+ * Line with address and code
+ */
+ } else {
+ for (i=2; i < rtcnt; i++) {
+ if (rtflg[i]) {
+ lkglist(pc++, rtval[i] & 0xFF);
+ }
+ }
+ }
+
+ /*
+ * Copy remainder of LST to RST
+ */
+ } else {
+ if (gline == 0)
+ fprintf(rfp, "%s", rb);
+
+ while (fgets(rb, sizeof(rb), tfp) != 0) {
+ fprintf(rfp, "%s", rb);
+ }
+ fclose(tfp);
+ tfp = NULL;
+ fclose(rfp);
+ rfp = NULL;
+ }
+}
+
+/*)Function VOID lkalist(pc)
+ *
+ * int pc current program counter value
+ *
+ * The function lkalist() performs the following functions:
+ *
+ * (1) if the value of gline = 0 then the current listing
+ * file line is copied to the relocated listing file output.
+ *
+ * (2) the listing file is read line by line and copied to
+ * the relocated listing file until a valid source
+ * line number and a program counter value of the correct
+ * radix is found. The new relocated pc value is substituted
+ * and the line is written to the RST file.
+ *
+ * local variables:
+ * int i loop counter
+ * char str[] temporary string
+ *
+ * global variables:
+ * int gcntr data byte counter
+ * int gline get a line from the LST file
+ * to translate for the RST file
+ * char rb[] read listing file text line
+ * char *rp pointer to listing file text line
+ * FILE *rfp The file handle to the current
+ * output RST file
+ * FILE *tfp The file handle to the current
+ * LST file being scanned
+ *
+ * functions called:
+ * int dgt() lklist.c
+ * int fclose() c_library
+ * int fgets() c_library
+ * int fprintf() c_library
+ * int sprintf() c_library
+ * char * strncpy() c_library
+ *
+ * side effects:
+ * Lines of the LST file are copied to the RST file,
+ * the last line copied has the code address
+ * updated to reflect the program relocation.
+ */
+
+VOID
+lkalist(pc)
+Addr_T pc;
+{
+ char str[8];
+ int i;
+
+ /*
+ * Exit if listing file is not open
+ */
+loop: if (tfp == NULL)
+ return;
+
+ /*
+ * Copy current LST to RST
+ */
+ if (gline == 0) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ }
+
+ /*
+ * Clear text line buffer
+ */
+ for (i=0,rp=rb; i<sizeof(rb); i++) {
+ *rp++ = 0;
+ }
+
+ /*
+ * Get next LST text line
+ */
+ if (fgets(rb, sizeof(rb), tfp) == NULL) {
+ fclose(tfp);
+ tfp = NULL;
+ fclose(rfp);
+ rfp = NULL;
+ return;
+ }
+
+ /*
+ * Must have an ASxxxx Listing line number
+ */
+ if (!dgt(RAD10, &rb[30], 1)) {
+ fprintf(rfp, "%s", rb);
+ goto loop;
+ }
+
+ /*
+ * Must have an address in the expected radix
+ */
+ if (radix == 16) {
+ if (!dgt(RAD16, &rb[3], 4)) {
+ fprintf(rfp, "%s", rb);
+ goto loop;
+ }
+ sprintf(str, "%04X", pc);
+ strncpy(&rb[3], str, 4);
+ } else
+ if (radix == 10) {
+ if (!dgt(RAD10, &rb[3], 5)) {
+ fprintf(rfp, "%s", rb);
+ goto loop;
+ }
+ sprintf(str, "%05d", pc);
+ strncpy(&rb[3], str, 5);
+ } else
+ if (radix == 8) {
+ if (!dgt(RAD8, &rb[3], 6)) {
+ fprintf(rfp, "%s", rb);
+ goto loop;
+ }
+ sprintf(str, "%06o", pc);
+ strncpy(&rb[3], str, 6);
+ }
+
+ /*
+ * Copy updated LST text line to RST
+ */
+ fprintf(rfp, "%s", rb);
+ gcntr = 0;
+}
+
+/*)Function VOID lkglist(pc,v)
+ *
+ * int pc current program counter value
+ * int v value of byte at this address
+ *
+ * The function lkglist() performs the following functions:
+ *
+ * (1) if the value of gline = 1 then the listing file
+ * is read line by line and copied to the
+ * relocated listing file until a valid source
+ * line number and a program counter value of the correct
+ * radix is found.
+ *
+ * (2) The new relocated values and code address are
+ * substituted and the line may be written to the RST file.
+ *
+ * local variables:
+ * int i loop counter
+ * char str[] temporary string
+ *
+ * global variables:
+ * int gcntr data byte counter
+ * set to -1 for a continuation line
+ * int gline get a line from the LST file
+ * to translate for the RST file
+ * char rb[] read listing file text line
+ * char *rp pointer to listing file text line
+ * FILE *rfp The file handle to the current
+ * output RST file
+ * FILE *tfp The file handle to the current
+ * LST file being scanned
+ *
+ * functions called:
+ * int dgt() lklist.c
+ * int fclose() c_library
+ * int fgets() c_library
+ * int fprintf() c_library
+ * int sprintf() c_library
+ * char * strncpy() c_library
+ *
+ * side effects:
+ * Lines of the LST file are copied to the RST file
+ * with updated data values and code addresses.
+ */
+
+VOID
+lkglist(pc,v)
+Addr_T pc;
+int v;
+{
+ char str[8];
+ int i;
+
+ /*
+ * Exit if listing file is not open
+ */
+loop: if (tfp == NULL)
+ return;
+
+ /*
+ * Get next LST text line
+ */
+ if (gline) {
+ /*
+ * Clear text line buffer
+ */
+ for (i=0,rp=rb; i<sizeof(rb); i++) {
+ *rp++ = 0;
+ }
+
+ /*
+ * Get next LST text line
+ */
+ if (fgets(rb, sizeof(rb), tfp) == NULL) {
+ fclose(tfp);
+ tfp = NULL;
+ fclose(rfp);
+ rfp = NULL;
+ return;
+ }
+
+ /*
+ * Check for a listing line number if required
+ */
+ if (gcntr != -1) {
+ if (!dgt(RAD10, &rb[30], 1)) {
+ fprintf(rfp, "%s", rb);
+ goto loop;
+ }
+ gcntr = 0;
+ }
+ gline = 0;
+ }
+
+ /*
+ * Hex Listing
+ */
+ if (radix == 16) {
+ /*
+ * Data Byte Pointer
+ */
+ if (gcntr == -1) {
+ rp = &rb[8];
+ } else {
+ rp = &rb[8 + (3 * gcntr)];
+ }
+ /*
+ * Number must be of proper radix
+ */
+ if (!dgt(RAD16, rp, 2)) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ goto loop;
+ }
+ /*
+ * Output new data value, overwrite relocation codes
+ */
+ sprintf(str, " %02X", v);
+ strncpy(rp-1, str, 3);
+ if (gcntr == -1) {
+ gcntr = 0;
+ }
+ /*
+ * Output relocated code address
+ */
+ if (gcntr == 0) {
+ if (dgt(RAD16, &rb[3], 4)) {
+ sprintf(str, "%04X", pc);
+ strncpy(&rb[3], str, 4);
+ }
+ }
+ /*
+ * Output text line when updates finished
+ */
+ if (++gcntr == 6) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ gcntr = -1;
+ }
+ } else
+ /*
+ * Decimal Listing
+ */
+ if (radix == 10) {
+ /*
+ * Data Byte Pointer
+ */
+ if (gcntr == -1) {
+ rp = &rb[9];
+ } else {
+ rp = &rb[9 + (3 * gcntr)];
+ }
+ /*
+ * Number must be of proper radix
+ */
+ if (!dgt(RAD10, rp, 3)) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ goto loop;
+ }
+ /*
+ * Output new data value, overwrite relocation codes
+ */
+ sprintf(str, " %03d", v);
+ strncpy(rp-1, str, 4);
+ if (gcntr == -1) {
+ gcntr = 0;
+ }
+ /*
+ * Output relocated code address
+ */
+ if (gcntr == 0) {
+ if (dgt(RAD10, &rb[3], 5)) {
+ sprintf(str, "%05d", pc);
+ strncpy(&rb[3], str, 5);
+ }
+ }
+ /*
+ * Output text line when updates finished
+ */
+ if (++gcntr == 4) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ gcntr = -1;
+ }
+ } else
+ /*
+ * Octal Listing
+ */
+ if (radix == 8) {
+ /*
+ * Data Byte Pointer
+ */
+ if (gcntr == -1) {
+ rp = &rb[10];
+ } else {
+ rp = &rb[10 + (3 * gcntr)];
+ }
+ /*
+ * Number must be of proper radix
+ */
+ if (!dgt(RAD8, rp, 3)) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ goto loop;
+ }
+ /*
+ * Output new data value, overwrite relocation codes
+ */
+ sprintf(str, " %03o", v);
+ strncpy(rp-1, str, 4);
+ if (gcntr == -1) {
+ gcntr = 0;
+ }
+ /*
+ * Output relocated code address
+ */
+ if (gcntr == 0) {
+ if (dgt(RAD8, &rb[3], 6)) {
+ sprintf(str, "%06o", pc);
+ strncpy(&rb[3], str, 6);
+ }
+ }
+ /*
+ * Output text line when updates finished
+ */
+ if (++gcntr == 4) {
+ fprintf(rfp, "%s", rb);
+ gline = 1;
+ gcntr = -1;
+ }
+ }
+}
+
+/*)Function int dgt(rdx,str,n)
+ *
+ * int rdx radix bit code
+ * char *str pointer to the test string
+ * int n number of characters to check
+ *
+ * The function dgt() verifies that the string under test
+ * is of the specified radix.
+ *
+ * local variables:
+ * int i loop counter
+ *
+ * global variables:
+ * ctype[] array of character types
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+dgt(rdx, str, n)
+int rdx, n;
+char *str;
+{
+ int i;
+
+ for (i=0; i<n; i++) {
+ if ((ctype[(int)*str++] & rdx) == 0)
+ return(0);
+ }
+ return(1);
+}
--- /dev/null
+/* lkmain.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 31-Oct-97 JLH:
+ * - add jflag and jfp to control NoICE output file genration
+ * 3-Nov-97 JLH:
+ * - use a_type == 0 as "virgin area" flag: set == 1 if -b
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+#ifdef WIN32T
+#include <time.h>
+
+void Timer(int action, char * message)
+{
+ static double start, end, total=0.0;
+ static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+
+ if(action==0) start=clock()*secs_per_tick;
+ else if(action==1)
+ {
+ end=clock() * secs_per_tick;
+ printf("%s \t%f seconds.\n", message, (end-start));
+ total+=end-start;
+ }
+ else
+ {
+ printf("Total time: \t%f seconds.\n", total);
+ total=0.0;
+ }
+}
+#endif
+
+/* yuck - but including unistd.h causes problems on Cygwin by redefining
+ * Addr_T.
+ */
+extern int unlink(const char *);
+
+/*)Module lkmain.c
+ *
+ * The module lkmain.c contains the functions which
+ * (1) input the linker options, parameters, and specifications
+ * (2) perform a two pass link
+ * (3) produce the appropriate linked data output and/or
+ * link map file and/or relocated listing files.
+ *
+ * lkmain.c contains the following functions:
+ * FILE * afile(fn,ft,wf)
+ * VOID bassav()
+ * VOID gblsav()
+ * VOID link_main()
+ * VOID lkexit()
+ * VOID main(argc,argv)
+ * VOID map()
+ * int parse()
+ * VOID setbas()
+ * VOID setgbl()
+ * VOID usage()
+ *
+ * lkmain.c contains the following local variables:
+ * char * usetext[] array of pointers to the
+ * command option tect lines
+ *
+ */
+
+/*JCF: Creates some of the default areas so they are allocated in the right order.*/
+void Areas51 (void)
+{
+ char * rel[]={
+ "XH",
+ "H 7 areas 0 global symbols",
+ "A _CODE size 0 flags 0", /*Each .rel has one, so...*/
+ "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/
+ "A REG_BANK_1 size 0 flags 4",
+ "A REG_BANK_2 size 0 flags 4",
+ "A REG_BANK_3 size 0 flags 4",
+ "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/
+ "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/
+ ""
+ };
+ int j;
+
+ for (j=0; rel[j][0]!=0; j++)
+ {
+ ip=rel[j];
+ link_main();
+ }
+
+ /*Set the start address of the default areas:*/
+ for(ap=areap; ap; ap=ap->a_ap)
+ {
+ /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr=0x00; ap->a_type=1; }
+ else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr=0x08; ap->a_type=1; }
+ else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; }
+ else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; }
+ else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; }
+ }
+}
+
+/*)Function VOID main(argc,argv)
+ *
+ * int argc number of command line arguments + 1
+ * char * argv[] array of pointers to the command line
+ * arguments
+ *
+ * The function main() evaluates the command line arguments to
+ * determine if the linker parameters are to input through 'stdin'
+ * or read from a command file. The functiond getline() and parse()
+ * are to input and evaluate the linker parameters. The linking process
+ * proceeds by making the first pass through each .rel file in the order
+ * presented to the linker. At the end of the first pass the setbase(),
+ * lnkarea(), setgbl(), and symdef() functions are called to evaluate
+ * the base address terms, link all areas, define global variables,
+ * and look for undefined symbols. Following these routines a linker
+ * map file may be produced and the linker output files may be opened.
+ * The second pass through the .rel files will output the linked data
+ * in one of the four supported formats.
+ *
+ * local variables:
+ * char * p pointer to an argument string
+ * int c character from argument string
+ * int i loop counter
+ *
+ * global variables:
+ * text line in ib[]
+ * lfile *cfp The pointer *cfp points to the
+ * current lfile structure
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * lfile *filep The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ * head *hp Pointer to the current
+ * head structure
+ * char ib[NINPUT] .rel file text line
+ * char *ip pointer into the .rel file
+ * lfile *linkp pointer to first lfile structure
+ * containing an input .rel file
+ * specification
+ * int lkerr error flag
+ * int mflag Map output flag
+ * int oflag Output file type flag
+ * FILE *ofp Output file handle
+ * for word formats
+ * FILE *ofph Output file handle
+ * for high byte format
+ * FILE *ofpl Output file handle
+ * for low byte format
+ * int pass linker pass number
+ * int pflag print linker command file flag
+ * int radix current number conversion radix
+ * FILE *sfp The file handle sfp points to the
+ * currently open file
+ * lfile *startp asmlnk startup file structure
+ * FILE * stdin c_library
+ * FILE * stdout c_library
+ *
+ * functions called:
+ * FILE * afile() lkmain.c
+ * int fclose() c_library
+ * int fprintf() c_library
+ * int getline() lklex.c
+ * VOID library() lklibr.c
+ * VOID link_main() lkmain.c
+ * VOID lkexit() lkmain.c
+ * VOID lnkarea() lkarea.c
+ * VOID map() lkmain.c
+ * VOID new() lksym.c
+ * int parse() lkmain.c
+ * VOID reloc() lkreloc.c
+ * VOID search() lklibr.c
+ * VOID setbas() lkmain.c
+ * VOID setgbl() lkmain.c
+ * VOID symdef() lksym.c
+ * VOID usage() lkmain.c
+ *
+ * side effects:
+ * Completion of main() completes the linking process
+ * and may produce a map file (.map) and/or a linked
+ * data files (.ihx or .s19) and/or one or more
+ * relocated listing files (.rst).
+ */
+
+int
+main(argc, argv)
+char *argv[];
+{
+ register char *p;
+ register int c, i;
+
+#ifdef WIN32T
+ Timer(0, "");
+#endif
+
+ startp = (struct lfile *) new (sizeof (struct lfile));
+
+ pflag = 1;
+ for (i=1; i<argc; ++i) {
+ p = argv[i];
+ if (*p == '-') {
+ while (ctype[c = *(++p)] & LETTER) {
+ switch(c) {
+
+ case 'c':
+ case 'C':
+ startp->f_type = F_STD;
+ break;
+
+ case 'f':
+ case 'F':
+ startp->f_type = F_LNK;
+ break;
+
+ case 'n':
+ case 'N':
+ pflag = 0;
+ break;
+
+ case 'p':
+ case 'P':
+ pflag = 1;
+ break;
+
+ default:
+ usage();
+ }
+ }
+ } else {
+ if (startp->f_type == F_LNK) {
+ startp->f_idp = p;
+ }
+ }
+ }
+ if (startp->f_type == 0)
+ usage();
+ if (startp->f_type == F_LNK && startp->f_idp == NULL)
+ usage();
+
+ cfp = NULL;
+ sfp = NULL;
+ filep = startp;
+ while (1) {
+ ip = ib;
+ if (getline() == 0)
+ break;
+ if (pflag && sfp != stdin)
+ fprintf(stdout, "%s\n", ip);
+ if (*ip == '\0' || parse())
+ break;
+ }
+
+ if (sfp) {
+ fclose(sfp);
+ sfp = NULL;
+ }
+
+ if (linkp == NULL)
+ usage();
+
+ syminit();
+
+ if (dflag){
+ //dfp = afile("temp", "cdb", 1);
+ SaveLinkedFilePath(linkp->f_idp); //Must be the first one...
+ dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002
+ if (dfp == NULL)
+ lkexit(1);
+ }
+
+ for (pass=0; pass<2; ++pass) {
+ cfp = NULL;
+ sfp = NULL;
+ filep = linkp;
+ hp = NULL;
+ radix = 10;
+
+ Areas51(); /*JCF: Create the default 8051 areas in the right order*/
+
+ while (getline()) {
+ ip = ib;
+
+ /* pass any "magic comments" to NoICE output */
+ if ((ip[0] == ';') && (ip[1] == '!') && jfp) {
+ fprintf( jfp, "%s\n", &ip[2] );
+ }
+ link_main();
+ }
+ if (pass == 0) {
+ /*
+ * Search libraries for global symbols
+ */
+ search();
+ /*
+ * Set area base addresses.
+ */
+ setbas();
+ /*
+ * Link all area addresses.
+ */
+ lnkarea();
+ /*
+ * Process global definitions.
+ */
+ setgbl();
+ /*
+ * Check for undefined globals.
+ */
+ symdef(stderr);
+
+ /* Open NoICE output file if requested */
+ if (jflag) {
+ jfp = afile(linkp->f_idp, "NOI", 1);
+ if (jfp == NULL) {
+ lkexit(1);
+ }
+ }
+
+ /*
+ * Output Link Map if requested,
+ * or if NoICE output requested (since NoICE
+ * file is generated in part by map() processing)
+ */
+ if (mflag || jflag)
+ map();
+
+ if (sflag) /*JCF: memory usage summary output*/
+ if(summary(areap))lkexit(1);
+
+ if (iram_size)
+ iramcheck();
+
+ /*
+ * Open output file
+ */
+ if (oflag == 1) {
+ ofp = afile(linkp->f_idp, "ihx", 1);
+ if (ofp == NULL) {
+ lkexit(1);
+ }
+ /* include NoICE command to load hex file */
+ if (jfp) fprintf( jfp, "LOAD %s.IHX\n", linkp->f_idp );
+
+ } else
+ if (oflag == 2) {
+ ofp = afile(linkp->f_idp, "S19", 1);
+ if (ofp == NULL) {
+ lkexit(1);
+ }
+ /* include NoICE command to load hex file */
+ if (jfp) fprintf( jfp, "LOAD %s.S19\n", linkp->f_idp );
+ }
+ } else {
+ /*
+ * Link in library files
+ */
+ library();
+ reloc('E');
+ }
+ }
+ //JCF:
+ CreateAOMF51();
+
+#ifdef WIN32T
+ Timer(1, "Linker execution time");
+#endif
+
+ lkexit(lkerr);
+ return 0;
+}
+
+/*)Function VOID lkexit(i)
+ *
+ * int i exit code
+ *
+ * The function lkexit() explicitly closes all open
+ * files and then terminates the program.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * FILE * mfp file handle for .map
+ * FILE * ofp file handle for .ihx/.s19
+ * FILE * rfp file hanlde for .rst
+ * FILE * sfp file handle for .rel
+ * FILE * tfp file handle for .lst
+ *
+ * functions called:
+ * int fclose() c_library
+ * VOID exit() c_library
+ *
+ * side effects:
+ * All files closed. Program terminates.
+ */
+
+VOID
+lkexit(i)
+int i;
+{
+ if (mfp != NULL) fclose(mfp);
+ if (jfp != NULL) fclose(jfp);
+ if (ofp != NULL) fclose(ofp);
+ if (rfp != NULL) fclose(rfp);
+ if (sfp != NULL) fclose(sfp);
+ if (tfp != NULL) fclose(tfp);
+ if (dfp != NULL) fclose(dfp);
+ /*if (dfp != NULL)
+ FILE *xfp = afile(linkp->f_idp,"cdb",1);
+ dfp = freopen("temp.cdb","r",dfp);
+ copyfile(xfp,dfp);
+ fclose(xfp);
+ fclose(dfp);
+ unlink("temp.cdb");
+ }*/
+ exit(i);
+}
+
+/*)Function link_main()
+ *
+ * The function link_main() evaluates the directives for each line of
+ * text read from the .rel file(s). The valid directives processed
+ * are:
+ * X, D, Q, H, M, A, S, T, R, and P.
+ *
+ * local variables:
+ * int c first non blank character of a line
+ *
+ * global variables:
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * head *hp Pointer to the current
+ * head structure
+ * int pass linker pass number
+ * int radix current number conversion radix
+ *
+ * functions called:
+ * char endline() lklex.c
+ * VOID module() lkhead.c
+ * VOID newarea() lkarea.c
+ * VOID newhead() lkhead.c
+ * sym * newsym() lksym.c
+ * VOID reloc() lkreloc.c
+ *
+ * side effects:
+ * Head, area, and symbol structures are created and
+ * the radix is set as the .rel file(s) are read.
+ */
+
+VOID
+link_main()
+{
+ register int c;
+
+ if ((c=endline()) == 0) { return; }
+ switch (c) {
+
+ case 'O': /*For some important sdcc options*/
+ if (pass == 0)
+ {
+ if(strlen(sdccopt)==0)
+ {
+ strcpy(sdccopt, &ip[1]);
+ strcpy(sdccopt_module, curr_module);
+ }
+ else
+ {
+ if(strcmp(sdccopt, &ip[1])!=0)
+ {
+ fprintf(stderr,
+ "?ASlink-Warning-Conflicting sdcc options:\n"
+ " \"%s\" in module \"%s\" and\n"
+ " \"%s\" in module \"%s\".\n",
+ sdccopt, sdccopt_module, &ip[1], curr_module);
+ lkerr++;
+ }
+ }
+ }
+ break;
+
+ case 'X':
+ radix = 16;
+ break;
+
+ case 'D':
+ radix = 10;
+ break;
+
+ case 'Q':
+ radix = 8;
+ break;
+
+ case 'H':
+ if (pass == 0) {
+ newhead();
+ } else {
+ if (hp == 0) {
+ hp = headp;
+ } else {
+ hp = hp->h_hp;
+ }
+ }
+ sdp.s_area = NULL;
+ sdp.s_areax = NULL;
+ sdp.s_addr = 0;
+ break;
+
+ case 'M':
+ if (pass == 0)
+ {
+ strcpy(curr_module, &ip[1]);
+ module();
+ }
+ break;
+
+ case 'A':
+ if (pass == 0)
+ newarea();
+ if (sdp.s_area == NULL) {
+ sdp.s_area = areap;
+ sdp.s_areax = areap->a_axp;
+ sdp.s_addr = 0;
+ }
+ break;
+
+ case 'S':
+ if (pass == 0)
+ newsym();
+ break;
+
+ case 'T':
+ case 'R':
+ case 'P':
+ if (pass == 0)
+ break;
+ reloc(c);
+ break;
+
+ default:
+ break;
+ }
+ if (c == 'X' || c == 'D' || c == 'Q') {
+ if ((c = get()) == 'H') {
+ hilo = 1;
+ } else
+ if (c == 'L') {
+ hilo = 0;
+ }
+ }
+}
+
+
+/*)Function VOID map()
+ *
+ * The function map() opens the output map file and calls the various
+ * routines to
+ * (1) output the variables in each area,
+ * (2) list the files processed with module names,
+ * (3) list the libraries file processed,
+ * (4) list base address definitions,
+ * (5) list global variable definitions, and
+ * (6) list any undefined variables.
+ *
+ * local variables:
+ * int i counter
+ * head * hdp pointer to head structure
+ * lbfile *lbfh pointer to library file structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ * base *basep The pointer to the first
+ * base structure
+ * base *bsp Pointer to the current
+ * base structure
+ * lfile *filep The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ * globl *globlp The pointer to the first
+ * globl structure
+ * globl *gsp Pointer to the current
+ * globl structure
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * lbfile *lbfhead The pointer to the first
+ * lbfile structure of a linked list
+ * lfile *linkp pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ * int lop current line number on page
+ * FILE *mfp Map output file handle
+ * int page current page number
+ *
+ * functions called:
+ * FILE * afile() lkmain.c
+ * int fprintf() c_library
+ * VOID lkexit() lkmain.c
+ * VOID lstarea() lklist.c
+ * VOID newpag() lklist.c
+ * VOID symdef() lksym.c
+ *
+ * side effects:
+ * The map file is created.
+ */
+
+VOID
+map()
+{
+ register int i;
+ register struct head *hdp;
+ register struct lbfile *lbfh;
+
+ /*
+ * Open Map File
+ */
+ mfp = afile(linkp->f_idp, "map", 1);
+ if (mfp == NULL) {
+ lkexit(1);
+ }
+
+ /*
+ * Output Map Area Lists
+ */
+ page = 0;
+ lop = NLPP;
+ ap = areap;
+ while (ap) {
+ lstarea(ap);
+ ap = ap->a_ap;
+ }
+ /*
+ * List Linked Files
+ */
+ newpag(mfp);
+ fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n");
+ hdp = headp;
+ filep = linkp;
+ while (filep) {
+ fprintf(mfp, "%-16s", filep->f_idp);
+ i = 0;
+ while ((hdp != NULL) && (hdp->h_lfile == filep)) {
+ if (i % 5) {
+ fprintf(mfp, ", %8.8s", hdp->m_id);
+ } else {
+ if (i) {
+ fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
+ } else {
+ fprintf(mfp, " [ %8.8s", hdp->m_id);
+ }
+ }
+ hdp = hdp->h_hp;
+ i++;
+ }
+ if (i)
+ fprintf(mfp, " ]");
+ fprintf(mfp, "\n");
+ filep = filep->f_flp;
+ }
+ /*
+ * List Linked Libraries
+ */
+ if (lbfhead != NULL) {
+ fprintf(mfp,
+ "\nLibraries Linked [ object file ]\n\n");
+ for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
+ fprintf(mfp, "%-32s [ %16.16s ]\n",
+ lbfh->libspc, lbfh->relfil);
+ }
+ fprintf(mfp, "\n");
+ }
+ /*
+ * List Base Address Definitions
+ */
+ if (basep) {
+ newpag(mfp);
+ fprintf(mfp, "\nUser Base Address Definitions\n\n");
+ bsp = basep;
+ while (bsp) {
+ fprintf(mfp, "%s\n", bsp->b_strp);
+ bsp = bsp->b_base;
+ }
+ }
+ /*
+ * List Global Definitions
+ */
+ if (globlp) {
+ newpag(mfp);
+ fprintf(mfp, "\nUser Global Definitions\n\n");
+ gsp = globlp;
+ while (gsp) {
+ fprintf(mfp, "%s\n", gsp->g_strp);
+ gsp = gsp->g_globl;
+ }
+ }
+ fprintf(mfp, "\n\f");
+ symdef(mfp);
+}
+
+/*)Function int parse()
+ *
+ * The function parse() evaluates all command line or file input
+ * linker directives and updates the appropriate variables.
+ *
+ * local variables:
+ * int c character value
+ * char fid[] file id string
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * lfile *lfp pointer to current lfile structure
+ * being processed by parse()
+ * lfile *linkp pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ * int mflag Map output flag
+ * int oflag Output file type flag
+ * int pflag print linker command file flag
+ * FILE * stderr c_library
+ * int uflag Relocated listing flag
+ * int xflag Map file radix type flag
+ *
+ * Functions called:
+ * VOID addlib() lklibr.c
+ * VOID addpath() lklibr.c
+ * VOID bassav() lkmain.c
+ * int fprintf() c_library
+ * VOID gblsav() lkmain.c
+ * VOID getfid() lklex.c
+ * char getnb() lklex.c
+ * VOID lkexit() lkmain.c
+ * char * strcpy() c_library
+ * int strlen() c_library
+ *
+ * side effects:
+ * Various linker flags are updated and the linked
+ * structure lfile is created.
+ */
+
+int
+parse()
+{
+ register int c;
+ char fid[NINPUT];
+
+ while ((c = getnb()) != 0) {
+ if ( c == '-') {
+ while (ctype[c=get()] & LETTER) {
+ switch(c) {
+
+ case 'i':
+ case 'I':
+ oflag = 1;
+ break;
+
+ case 's':
+ case 'S':
+ oflag = 2;
+ break;
+
+ case 'm':
+ case 'M':
+ ++mflag;
+ break;
+
+ case 'y': /*JCF: memory usage summary output*/
+ case 'Y':
+ ++sflag;
+ break;
+
+ case 'j':
+ case 'J':
+ jflag = 1;
+ break;
+
+ case 'u':
+ case 'U':
+ uflag = 1;
+ break;
+ case 'r':
+ case 'R':
+ rflag = 1;
+ break;
+ case 'x':
+ case 'X':
+ xflag = 0;
+ break;
+
+ case 'q':
+ case 'Q':
+ xflag = 1;
+ break;
+
+ case 'd':
+ case 'D':
+ xflag = 2;
+ break;
+
+ case 'e':
+ case 'E':
+ return(1);
+
+ case 'n':
+ case 'N':
+ pflag = 0;
+ break;
+
+ case 'p':
+ case 'P':
+ pflag = 1;
+ break;
+
+ case 'b':
+ case 'B':
+ bassav();
+ return(0);
+
+ case 'g':
+ case 'G':
+ gblsav();
+ return(0);
+
+ case 'k':
+ case 'K':
+ addpath();
+ return(0);
+
+ case 'l':
+ case 'L':
+ addlib();
+ return(0);
+
+ case 'a':
+ case 'A':
+ iramsav();
+ return(0);
+
+ case 'v':
+ case 'V':
+ xramsav();
+ return(0);
+
+ case 'w':
+ case 'W':
+ codesav();
+ return(0);
+
+ case 'z':
+ case 'Z':
+ dflag = 1;
+ return(0);
+ default:
+ fprintf(stderr, "Invalid option\n");
+ lkexit(1);
+ }
+ }
+ } else
+ if (ctype[c] & ILL) {
+ fprintf(stderr, "Invalid input");
+ lkexit(1);
+ } else {
+ if (linkp == NULL) {
+ linkp = (struct lfile *)
+ new (sizeof (struct lfile));
+ lfp = linkp;
+ } else {
+ lfp->f_flp = (struct lfile *)
+ new (sizeof (struct lfile));
+ lfp = lfp->f_flp;
+ }
+ getfid(fid, c);
+ lfp->f_idp = (char *) new (strlen(fid)+1);
+ strcpy(lfp->f_idp, fid);
+ lfp->f_type = F_REL;
+ }
+ }
+ return(0);
+}
+
+/*)Function VOID bassav()
+ *
+ * The function bassav() creates a linked structure containing
+ * the base address strings input to the linker.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * base *basep The pointer to the first
+ * base structure
+ * base *bsp Pointer to the current
+ * base structure
+ * char *ip pointer into the REL file
+ * text line in ib[]
+ *
+ * functions called:
+ * char getnb() lklex.c
+ * VOID * new() lksym.c
+ * int strlen() c_library
+ * char * strcpy() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * The basep structure is created.
+ */
+
+VOID
+bassav()
+{
+ if (basep == NULL) {
+ basep = (struct base *)
+ new (sizeof (struct base));
+ bsp = basep;
+ } else {
+ bsp->b_base = (struct base *)
+ new (sizeof (struct base));
+ bsp = bsp->b_base;
+ }
+ unget(getnb());
+ bsp->b_strp = (char *) new (strlen(ip)+1);
+ strcpy(bsp->b_strp, ip);
+}
+
+/*)Function VOID setbas()
+ *
+ * The function setbas() scans the base address lines in hte
+ * basep structure, evaluates the arguments, and sets beginning
+ * address of the specified areas.
+ *
+ * local variables:
+ * int v expression value
+ * char id[] base id string
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ * base *basep The pointer to the first
+ * base structure
+ * base *bsp Pointer to the current
+ * base structure
+ * char *ip pointer into the REL file
+ * text line in ib[]
+ * int lkerr error flag
+ *
+ * functions called:
+ * Addr_T expr() lkeval.c
+ * int fprintf() c_library
+ * VOID getid() lklex.c
+ * char getnb() lklex.c
+ * int symeq() lksym.c
+ *
+ * side effects:
+ * The base address of an area is set.
+ */
+
+VOID
+setbas()
+{
+ register int v;
+ char id[NCPS];
+
+ bsp = basep;
+ while (bsp) {
+ ip = bsp->b_strp;
+ getid(id, -1);
+ if (getnb() == '=') {
+ v = expr(0);
+ for (ap = areap; ap != NULL; ap = ap->a_ap) {
+ if (symeq(id, ap->a_id))
+ break;
+ }
+ if (ap == NULL) {
+ fprintf(stderr,
+ "ASlink-Warning-No definition of area %s\n", id);
+ lkerr++;
+ } else {
+ ap->a_addr = v;
+ ap->a_type = 1; /* JLH: value set */
+ }
+ } else {
+ fprintf(stderr, "ASlink-Warning-No '=' in base expression");
+ lkerr++;
+ }
+ bsp = bsp->b_base;
+ }
+}
+
+/*)Function VOID gblsav()
+ *
+ * The function gblsav() creates a linked structure containing
+ * the global variable strings input to the linker.
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * globl *globlp The pointer to the first
+ * globl structure
+ * globl *gsp Pointer to the current
+ * globl structure
+ * char *ip pointer into the REL file
+ * text line in ib[]
+ * int lkerr error flag
+ *
+ * functions called:
+ * char getnb() lklex.c
+ * VOID * new() lksym.c
+ * int strlen() c_library
+ * char * strcpy() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * The globlp structure is created.
+ */
+
+VOID
+gblsav()
+{
+ if (globlp == NULL) {
+ globlp = (struct globl *)
+ new (sizeof (struct globl));
+ gsp = globlp;
+ } else {
+ gsp->g_globl = (struct globl *)
+ new (sizeof (struct globl));
+ gsp = gsp->g_globl;
+ }
+ unget(getnb());
+ gsp->g_strp = (char *) new (strlen(ip)+1);
+ strcpy(gsp->g_strp, ip);
+}
+
+/*)Function VOID setgbl()
+ *
+ * The function setgbl() scans the global variable lines in hte
+ * globlp structure, evaluates the arguments, and sets a variable
+ * to this value.
+ *
+ * local variables:
+ * int v expression value
+ * char id[] base id string
+ * sym * sp pointer to a symbol structure
+ *
+ * global variables:
+ * char *ip pointer into the REL file
+ * text line in ib[]
+ * globl *globlp The pointer to the first
+ * globl structure
+ * globl *gsp Pointer to the current
+ * globl structure
+ * FILE * stderr c_library
+ * int lkerr error flag
+ *
+ * functions called:
+ * Addr_T expr() lkeval.c
+ * int fprintf() c_library
+ * VOID getid() lklex.c
+ * char getnb() lklex.c
+ * sym * lkpsym() lksym.c
+ *
+ * side effects:
+ * The value of a variable is set.
+ */
+
+VOID
+setgbl()
+{
+ register int v;
+ register struct sym *sp;
+ char id[NCPS];
+
+ gsp = globlp;
+ while (gsp) {
+ ip = gsp->g_strp;
+ getid(id, -1);
+ if (getnb() == '=') {
+ v = expr(0);
+ sp = lkpsym(id, 0);
+ if (sp == NULL) {
+ fprintf(stderr,
+ "No definition of symbol %s\n", id);
+ lkerr++;
+ } else {
+ if (sp->s_flag & S_DEF) {
+ fprintf(stderr,
+ "Redefinition of symbol %s\n", id);
+ lkerr++;
+ sp->s_axp = NULL;
+ }
+ sp->s_addr = v;
+ sp->s_type |= S_DEF;
+ }
+ } else {
+ fprintf(stderr, "No '=' in global expression");
+ lkerr++;
+ }
+ gsp = gsp->g_globl;
+ }
+}
+
+/*)Function FILE * afile(fn,, ft, wf)
+ *
+ * char * fn file specification string
+ * char * ft file type string
+ * int wf read(0)/write(1) flag
+ *
+ * The function afile() opens a file for reading or writing.
+ * (1) If the file type specification string ft
+ * is not NULL then a file specification is
+ * constructed with the file path\name in fn
+ * and the extension in ft.
+ * (2) If the file type specification string ft
+ * is NULL then the file specification is
+ * constructed from fn. If fn does not have
+ * a file type then the default .rel file
+ * type is appended to the file specification.
+ *
+ * afile() returns a file handle for the opened file or aborts
+ * the assembler on an open error.
+ *
+ * local variables:
+ * char fb[] constructed file specification string
+ * FILE * fp filehandle for opened file
+ *
+ * global variables:
+ * int lkerr error flag
+ *
+ * functions called:
+ * FILE * fopen() c_library
+ * int fprintf() c_library
+ *
+ * side effects:
+ * File is opened for read or write.
+ */
+
+FILE *
+afile(fn, ft, wf)
+char *fn;
+char *ft;
+{
+ FILE *fp;
+ char fb[PATH_MAX];
+ char *omode = (wf ? (wf == 2 ? "a" : "w") : "r");
+ int i;
+
+ /*Look backward the name path and get rid of the extension, if any*/
+ i=strlen(fn);
+ for(; (fn[i]!='.')&&(fn[i]!='\\')&&(fn[i]!='/')&&(i>=0); i--);
+ if( (fn[i]=='.') && strcmp(ft, "lnk") )
+ {
+ strncpy(fb, fn, i);
+ fb[i]=0;
+ }
+ else
+ {
+ strcpy(fb, fn);
+ }
+
+ /*Add the extension*/
+ strcat(fb, ".");
+ strcat(fb, strlen(ft)?ft:"rel");
+
+ fp = fopen(fb, omode);
+ if (fp==NULL)
+ {
+ if (strcmp(ft,"adb"))/*Do not complaint for optional adb files*/
+ {
+ fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
+ lkerr++;
+ }
+ }
+ return (fp);
+}
+
+/*)Function VOID iramsav()
+ *
+ * The function iramsav() stores the size of the chip's internal RAM.
+ * This is used after linking to check that variable assignment to this
+ * dataspace didn't overflow into adjoining segments. Variables in the
+ * DSEG, OSEG, and ISEG are assigned to this dataspace.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char *ip pointer into the REL file
+ * text line in ib[]
+ * unsigned int size of chip's internal
+ * iram_size RAM segment
+ *
+ * functions called:
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ * Addr_T expr() lkeval.c
+ *
+ * side effects:
+ * The iram_size may be modified.
+ */
+
+VOID
+iramsav()
+{
+ unget(getnb());
+ if (ip && *ip)
+ //iram_size = atoi(ip);
+ iram_size = expr(0); /* evaluate size expression */
+ else
+ iram_size = 128; /* Default is 128 (0x80) bytes */
+}
+
+/*Similar to iramsav but for xram memory*/
+VOID
+xramsav()
+{
+ unget(getnb());
+ if (ip && *ip)
+ xram_size = expr(0); /* evaluate size expression */
+ else
+ xram_size = rflag?0x1000000:0x10000;
+}
+
+/*Similar to iramsav but for code memory*/
+VOID
+codesav()
+{
+ unget(getnb());
+ if (ip && *ip)
+ code_size = expr(0); /* evaluate size expression */
+ else
+ code_size = rflag?0x1000000:0x10000;
+}
+
+
+/*)Function VOID iramcheck()
+ *
+ * The function iramcheck() is used at the end of linking to check that
+ * the internal RAM area wasn't overflowed by too many variable
+ * assignments. Variables in the DSEG, ISEG, and OSEG are assigned to
+ * the chip's internal RAM.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * unsigned int size of chip's internal
+ * iram_size RAM segment
+ * struct area linked list of memory
+ * *areap areas
+ *
+ * functions called:
+ *
+ * side effects:
+ */
+
+VOID
+iramcheck()
+{
+ register unsigned int last_addr;
+ register struct area *ap;
+
+ for (ap = areap; ap; ap=ap->a_ap) {
+ if ((ap->a_size != 0) &&
+ (!strcmp(ap->a_id, "DSEG") ||
+ !strcmp(ap->a_id, "OSEG") ||
+ !strcmp(ap->a_id, "ISEG")
+ )
+ )
+ {
+ last_addr = ap->a_addr + ap->a_size - 1;
+ if (last_addr >= iram_size)
+ fprintf(stderr,
+ "\nWARNING! Segment %s extends past the end\n"
+ " of internal RAM. Check map file.\n",
+ ap->a_id);
+ }
+ }
+}
+
+char *usetxt[] = {
+ "Startup:",
+ " -c Command line input",
+ " -f file[LNK] File input",
+ " -p Prompt and echo of file[LNK] to stdout (default)",
+ " -n No echo of file[LNK] to stdout",
+/* "Usage: [-Options] file [file ...]", */
+ "Libraries:",
+ " -k Library path specification, one per -k",
+ " -l Library file specification, one per -l",
+ "Relocation:",
+ " -b area base address = expression",
+ " -g global symbol = expression",
+ "Map format:",
+ " -m Map output generated as file[MAP]",
+ " -x Hexadecimal (default), -d Decimal, -q Octal",
+ "Output:",
+ " -i Intel Hex as file[IHX]",
+ " -s Motorola S19 as file[S19]",
+ " -j Produce NoICE debug as file[NOI]",
+ " -z Produce SDCdb debug as file[cdb]",
+/* "List:", */
+ " -u Update listing file(s) with link data as file(s)[.RST]",
+ "Miscellaneous:\n"
+ " -a [iram-size] Check for internal RAM overflow",
+ " -v [xram-size] Check for external RAM overflow",
+ " -w [code-size] Check for code overflow",
+ "End:",
+ " -e or null line terminates input",
+ 0
+};
+
+/*)Function VOID usage()
+ *
+ * The function usage() outputs to the stderr device the
+ * assembler name and version and a list of valid assembler options.
+ *
+ * local variables:
+ * char ** dp pointer to an array of
+ * text string pointers.
+ *
+ * global variables:
+ * FILE * stderr c_library
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * none
+ */
+
+VOID
+usage()
+{
+ register char **dp;
+
+ fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
+ for (dp = usetxt; *dp; dp++)
+ fprintf(stderr, "%s\n", *dp);
+ lkexit(1);
+}
+
+/*)Function VOID copyfile()
+ *
+ * FILE *dest destination file
+ * FILE *src source file
+ *
+ * function will copy source file to destination file
+ *
+ *
+ * functions called:
+ * int fgetc() c_library
+ * int fputc() c_library
+ *
+ * side effects:
+ * none
+ */
+VOID copyfile (dest,src)
+FILE *src,*dest ;
+{
+ int ch;
+ while ((ch = fgetc(src)) != EOF) {
+
+ fputc(ch,dest);
+ }
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+ lkmem.c - Create a memory summary file with extension .mem
+
+ Written By - Jesus Calvino-Fraga, jesusc@ieee.org (2002)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+#include "strcmpi.h"
+
+int summary(struct area * areap)
+{
+ #define EQ(A,B) !as_strcmpi((A),(B))
+ #define MIN_STACK 16
+ #define REPORT_ERROR(A, H) \
+ {\
+ fprintf(of, "%s%s", (H)?"*** ERROR: ":"", (A)); \
+ fprintf(stderr, "%s%s", (H)?"\n?ASlink-Error-":"",(A)); \
+ toreturn=1; \
+ }
+
+ #define REPORT_WARNING(A, H) \
+ { \
+ fprintf(of, "%s%s", (H)?"*** WARNING: ":"", (A)); \
+ fprintf(stderr, "%s%s",(H)?"\n?ASlink-Warning-":"", (A)); \
+ }
+
+ char buff[128];
+ int j, toreturn=0;
+ unsigned int Total_Last=0, k;
+
+ struct area * xp;
+ FILE * of;
+
+ /*Artifacts used for printing*/
+ char start[15], end[15], size[15], max[15];
+ char format[]=" %-16.16s %-8.8s %-8.8s %-8.8s %-8.8s\n";
+ char line[]="---------------------";
+
+ typedef struct
+ {
+ unsigned long Start;
+ unsigned long Size;
+ unsigned long Max;
+ char Name[NCPS];
+ unsigned long flag;
+ } _Mem;
+
+ unsigned int dram[0x100];
+ _Mem Ram[]={
+ {0, 0, 0, "REG_BANK_0", 0x0001},
+ {0x0, 0, 0, "REG_BANK_1", 0x0002},
+ {0x0, 0, 0, "REG_BANK_2", 0x0004},
+ {0x0, 0, 0, "REG_BANK_3", 0x0008},
+ {0x0, 0, 0, "BSEG_BYTES", 0x0010},
+ {0, 0, 256, "UNUSED", 0x0000},
+ {0xff, 0, 256, "DATA", 0x0020},
+ {0, 0, 256, "TOTAL:", 0x0000}
+ };
+
+ _Mem IRam= {0xff, 0, 0, "INDIRECT RAM", 0x0080};
+ _Mem Stack={0xff, 0, 1, "STACK", 0x0000};
+ _Mem XRam= {0xffff, 0, 65536, "EXTERNAL RAM", 0x0100};
+ _Mem Rom= {0xffff, 0, 65536, "ROM/EPROM/FLASH", 0x0200};
+
+#if 0
+ if(rflag) /*For the DS390*/
+ {
+ XRam.Max=0x1000000; /*24 bits*/
+ XRam.Start=0xffffff;
+ Rom.Max=0x1000000;
+ Rom.Start=0xffffff;
+ }
+
+ if((iram_size<=0)||(iram_size>0x100)) /*Default: 8052 like memory*/
+ {
+ Ram[5].Max=0x80;
+ Ram[6].Max=0x80;
+ Ram[7].Max=0x80;
+ IRam.Max=0x80;
+ iram_size=0x100;
+ }
+ else if(iram_size<0x80)
+ {
+ Ram[5].Max=iram_size;
+ Ram[6].Max=iram_size;
+ Ram[7].Max=iram_size;
+ IRam.Max=0;
+ }
+ else
+ {
+ Ram[5].Max=0x80;
+ Ram[6].Max=0x80;
+ Ram[7].Max=0x80;
+ IRam.Max=iram_size-0x80;
+ }
+#endif
+
+ for(j=0; j<(int)iram_size; j++) dram[j]=0;
+ for(; j<0x100; j++) dram[j]=0x8000; /*Memory not available*/
+
+ /* Open Memory Summary File*/
+ of = afile(linkp->f_idp, "mem", 1);
+ if (of == NULL)
+ {
+ lkexit(1);
+ }
+
+ xp=areap;
+ while (xp)
+ {
+ /**/ if (EQ(xp->a_id, "REG_BANK_0"))
+ {
+ Ram[0].Size=xp->a_size;
+ }
+ else if (EQ(xp->a_id, "REG_BANK_1"))
+ {
+ Ram[1].Size=xp->a_size;
+ }
+ else if (EQ(xp->a_id, "REG_BANK_2"))
+ {
+ Ram[2].Size=xp->a_size;
+ }
+ else if (EQ(xp->a_id, "REG_BANK_3"))
+ {
+ Ram[3].Size=xp->a_size;
+ }
+ else if (EQ(xp->a_id, "BSEG_BYTES"))
+ {
+ Ram[4].Size=xp->a_size;
+ }
+ else if ( EQ(xp->a_id, "DSEG") || EQ(xp->a_id, "OSEG") )
+ {
+ Ram[6].Size+=xp->a_size;
+ if(xp->a_addr<Ram[6].Start) Ram[6].Start=xp->a_addr;
+ }
+
+ else if( EQ(xp->a_id, "CSEG") || EQ(xp->a_id, "GSINIT") ||
+ EQ(xp->a_id, "GSFINAL") || EQ(xp->a_id, "HOME") )
+ {
+ Rom.Size+=xp->a_size;
+ if(xp->a_addr<Rom.Start) Rom.Start=xp->a_addr;
+ }
+
+ else if (EQ(xp->a_id, "SSEG"))
+ {
+ Stack.Size+=xp->a_size;
+ if(xp->a_addr<Stack.Start) Stack.Start=xp->a_addr;
+ }
+
+ else if (EQ(xp->a_id, "XSEG") || EQ(xp->a_id, "XISEG"))
+ {
+ XRam.Size+=xp->a_size;
+ if(xp->a_addr<XRam.Start) XRam.Start=xp->a_addr;
+ }
+
+ else if (EQ(xp->a_id, "ISEG"))
+ {
+ IRam.Size+=xp->a_size;
+ if(xp->a_addr<IRam.Start) IRam.Start=xp->a_addr;
+ }
+ xp=xp->a_ap;
+ }
+
+ for(j=0; j<7; j++)
+ for(k=Ram[j].Start; (k<(Ram[j].Start+Ram[j].Size))&&(k<0x100); k++)
+ dram[k]|=Ram[j].flag; /*Mark as used*/
+
+#if 0
+ for(k=IRam.Start; (k<(IRam.Start+IRam.Size))&&(k<0x100); k++)
+ dram[k]|=IRam.flag; /*Mark as used*/
+#endif
+
+ /*Compute the amount of unused memory in direct data Ram. This is the
+ gap between the last register bank or bit segment and the data segment.*/
+ for(k=Ram[6].Start-1; (dram[k]==0) && (k>0); k--);
+ Ram[5].Start=k+1;
+ Ram[5].Size=Ram[6].Start-Ram[5].Start; /*It may be zero (which is good!)*/
+
+ /*Compute the data Ram totals*/
+ for(j=0; j<7; j++)
+ {
+ if(Ram[7].Start>Ram[j].Start) Ram[7].Start=Ram[j].Start;
+ Ram[7].Size+=Ram[j].Size;
+ }
+ Total_Last=Ram[6].Size+Ram[6].Start-1;
+
+ /*Report the Ram totals*/
+ fprintf(of, "Direct Internal RAM:\n");
+ fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+
+ for(j=0; j<8; j++)
+ {
+ if((j==0) || (j==7)) fprintf(of, format, line, line, line, line, line);
+ if((j!=5) || (Ram[j].Size>0))
+ {
+ sprintf(start, "0x%02lx", Ram[j].Start);
+ if(Ram[j].Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%02lx", j==7?Total_Last:Ram[j].Size+Ram[j].Start-1);
+ sprintf(size, "%5lu", Ram[j].Size);
+ sprintf(max, "%5lu", Ram[j].Max);
+ fprintf(of, format, Ram[j].Name, start, end, size, max);
+ }
+ }
+
+#if 0
+ for(k=Ram[6].Start; (k<(Ram[6].Start+Ram[6].Size))&&(k<0x100); k++)
+ {
+ if(dram[k]!=Ram[6].flag)
+ {
+ sprintf(buff, "Internal memory overlap starting at 0x%02x.\n", k);
+ REPORT_ERROR(buff, 1);
+ break;
+ }
+ }
+
+
+ if(Ram[4].Size>Ram[4].Max)
+ {
+ k=Ram[4].Size-Ram[4].Max;
+ sprintf(buff, "Insufficient bit addressable memory. "
+ "%d byte%s short.\n", k, (k==1)?"":"s");
+ REPORT_ERROR(buff, 1);
+ }
+
+ if(Ram[5].Size!=0)
+ {
+ sprintf(buff, "%ld bytes in data memory wasted. "
+ "SDCC link could use: --data-loc 0x%02lx\n",
+ Ram[5].Size, Ram[6].Start-Ram[5].Size);
+ REPORT_WARNING(buff, 1);
+ }
+
+ if((Ram[6].Start+Ram[6].Size)>Ram[6].Max)
+ {
+ k=(Ram[6].Start+Ram[6].Size)-Ram[6].Max;
+ sprintf(buff, "Insufficient space in data memory. "
+ "%d byte%s short.\n", k, (k==1)?"":"s");
+ REPORT_ERROR(buff, 1);
+ }
+#endif
+ /*Report the position of the begining of the stack*/
+ fprintf(of, "\n%stack starts at: 0x%02lx (sp set to 0x%02lx)",
+ rflag ? "16 bit mode initial s" : "S", Stack.Start, Stack.Start-1);
+
+#if 0
+ /*Check that the stack pointer is landing in a safe place:*/
+ if( (dram[Stack.Start] & 0x8000) == 0x8000 )
+ {
+ fprintf(of, ".\n");
+ sprintf(buff, "Stack set to unavailable memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ else if(dram[Stack.Start])
+ {
+ fprintf(of, ".\n");
+ sprintf(buff, "Stack overlaps area ");
+ REPORT_ERROR(buff, 1);
+ for(j=0; j<7; j++)
+ {
+ if(dram[Stack.Start]&Ram[j].flag)
+ {
+ sprintf(buff, "'%s'\n", Ram[j].Name);
+ break;
+ }
+ }
+ if(dram[Stack.Start]&IRam.flag)
+ {
+ sprintf(buff, "'%s'\n", IRam.Name);
+ }
+ REPORT_ERROR(buff, 0);
+ }
+ else
+ {
+ for(j=Stack.Start, k=0; (j<(int)iram_size)&&(dram[j]==0); j++, k++);
+ fprintf(of, " with %d bytes available\n", k);
+ if (k<MIN_STACK)
+ {
+ sprintf(buff, "Only %d byte%s available for stack.\n",
+ k, (k==1)?"":"s");
+ REPORT_WARNING(buff, 1);
+ }
+ }
+#endif
+
+ fprintf(of, "\nOther memory:\n");
+ fprintf(of, format, "Name", "Start", "End", "Size", "Max");
+ fprintf(of, format, line, line, line, line, line);
+
+ /*Report IRam totals:*/
+ sprintf(start, "0x%02lx", IRam.Start);
+ if(IRam.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%02lx", IRam.Size+IRam.Start-1);
+ sprintf(size, "%5lu", IRam.Size);
+ sprintf(max, "%5lu", IRam.Max);
+ fprintf(of, format, IRam.Name, start, end, size, max);
+
+ /*Report XRam totals:*/
+ sprintf(start, "0x%04lx", XRam.Start);
+ if(XRam.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%04lx", XRam.Size+XRam.Start-1);
+ sprintf(size, "%5lu", XRam.Size);
+ sprintf(max, "%5lu", xram_size<0?XRam.Max:xram_size);
+ fprintf(of, format, XRam.Name, start, end, size, max);
+
+ /*Report Rom/Flash totals:*/
+ sprintf(start, "0x%04lx", Rom.Start);
+ if(Rom.Size==0)
+ end[0]=0;/*Empty string*/
+ else
+ sprintf(end, "0x%04lx", Rom.Size+Rom.Start-1);
+ sprintf(size, "%5lu", Rom.Size);
+ sprintf(max, "%5lu", code_size<0?Rom.Max:code_size);
+ fprintf(of, format, Rom.Name, start, end, size, max);
+
+ /*Report any excess:*/
+#if 0
+ if((IRam.Start+IRam.Size)>(IRam.Max+0x80))
+ {
+ sprintf(buff, "Insufficient INDIRECT RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+#endif
+ if( ((XRam.Start+XRam.Size)>XRam.Max) ||
+ (((int)XRam.Size>xram_size)&&(xram_size>=0)) )
+ {
+ sprintf(buff, "Insufficient EXTERNAL RAM memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+ if( ((Rom.Start+Rom.Size)>Rom.Max) ||
+ (((int)Rom.Size>code_size)&&(code_size>=0)) )
+ {
+ sprintf(buff, "Insufficient ROM/EPROM/FLASH memory.\n");
+ REPORT_ERROR(buff, 1);
+ }
+
+ fclose(of);
+ return toreturn;
+}
--- /dev/null
+/* lknoice.c */
+
+/*
+ * Extensions to CUG 292 linker ASLINK to produce NoICE debug files
+ *
+ * 31-Oct-1997 by John Hartman
+ * 30-Jan-98 JLH add page to DefineNoICE for 8051
+ * 2-Feb-98 JLH Allow optional .nest on local vars - C scoping rules...
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "aslink.h"
+#include "strcmpi.h"
+
+static void DefineGlobal( char *name, Addr_T value, int page );
+static void DefineScoped( char *name, Addr_T value, int page );
+static void DefineFile( char *name, Addr_T value, int page );
+static void DefineFunction( char *name, Addr_T value, int page );
+static void DefineStaticFunction( char *name, Addr_T value, int page );
+static void DefineEndFunction( Addr_T value, int page );
+static void DefineLine( char *lineString, Addr_T value, int page );
+static void PagedAddress( Addr_T value, int page );
+
+/*
+ * Called from lstarea in lklist.c for each symbol.
+ *
+ * Generates appropriate NoICE commands into output file, if any is open
+ *
+ */
+void DefineNoICE( char *name, Addr_T value, int page )
+{
+ char token1[NCPS]; /* parse for file.function.symbol */
+ char token2[NCPS];
+ char token3[NCPS];
+ // char token4[NCPS];
+ char sep1, sep2;
+ int j, level;
+
+ /* no output if file is not open */
+ if (jfp == NULL) return;
+
+ j = sscanf( name, "%[^.]%c%[^.]%c%s",
+ token1, &sep1, token2, &sep2, token3 );
+ switch (j)
+ {
+ /* file.function.symbol, or file.function..SPECIAL */
+ case 5:
+ DefineFile( token1, 0, 0 );
+ if (token3[0] == '.')
+ {
+ if (strcmp( token3, ".FN" ) == 0)
+ {
+ /* Global function */
+ DefineFunction( token2, value, page );
+ }
+ else if (strcmp( token3, ".SFN" ) == 0)
+ {
+ /* Static (file-scope) function */
+ DefineStaticFunction( token2, value, page );
+ }
+ else if (strcmp( token3, ".EFN" ) == 0)
+ {
+ /* End of function */
+ DefineEndFunction( value, page );
+ }
+ }
+ else
+ {
+ /* Function-scope var. */
+ DefineFunction( token2, 0, 0 );
+
+ /* Look for optional level integer */
+ j = sscanf( token3, "%[^.]%c%u", token1, &sep1, &level );
+ if ((j == 3) && (level != 0))
+ {
+ sprintf( &token1[ strlen(token1) ], "_%u", level );
+ }
+ DefineScoped( token1, value, page );
+ }
+ break;
+
+ /* file.func. is illegal */
+ case 4:
+ break;
+
+ /* either file.symbol or file.line# */
+ case 3:
+ DefineFile( token1, 0, 0 );
+ if ((token2[0] >= '0') && (token2[0] <= '9'))
+ {
+ /* Line number */
+ DefineLine( token2, value, page );
+ }
+ else
+ {
+ /* File-scope symbol. (Kill any function) */
+ DefineEndFunction( 0, 0 );
+ DefineScoped( token2, value, page );
+ }
+ break;
+
+ /* symbol. is illegal */
+ case 2:
+ break;
+
+ /* just a symbol */
+ case 1:
+ DefineGlobal( token1, value, page );
+ break;
+ }
+}
+
+static char currentFile[NCPS];
+static char currentFunction[NCPS];
+
+/*
+ * static function:
+ * Define "name" as a global symbol
+ */
+void DefineGlobal( char *name, Addr_T value, int page )
+{
+ fprintf( jfp, "DEF %s ", name );
+ PagedAddress( value, page );
+}
+
+/*
+ * static function:
+ * Define "name" as a static (scoped) symbol
+ */
+void DefineScoped( char *name, Addr_T value, int page )
+{
+ fprintf( jfp, "DEFS %s ", name );
+ PagedAddress( value, page );
+}
+
+/*
+ * static function:
+ * Define "name" as the current file
+ */
+void DefineFile( char *name, Addr_T value, int page )
+{
+ if (as_strcmpi( name, currentFile ) != 0)
+ {
+ strcpy( currentFile, name );
+ if (value != 0)
+ {
+ fprintf( jfp, "FILE %s ", name );
+ PagedAddress( value, page );
+ }
+ else
+ {
+ fprintf( jfp, "FILE %s\n", name );
+ }
+ }
+}
+
+/*
+ * static function:
+ * Define "name" as the current function
+ */
+void DefineFunction( char *name, Addr_T value, int page )
+{
+ if (as_strcmpi( name, currentFunction ) != 0)
+ {
+ strcpy( currentFunction, name );
+ if (value != 0)
+ {
+ fprintf( jfp, "DEF %s ", name );
+ PagedAddress( value, page );
+ fprintf( jfp, "FUNC %s ", name );
+ PagedAddress( value, page );
+ }
+ else
+ {
+ fprintf( jfp, "FUNC %s\n", name );
+ }
+ }
+}
+
+/*
+ * static function:
+ * Define "name" as the current static (scoped) function
+ */
+void DefineStaticFunction( char *name, Addr_T value, int page )
+{
+ if (as_strcmpi( name, currentFunction ) != 0)
+ {
+ strcpy( currentFunction, name );
+ if (value != 0)
+ {
+ fprintf( jfp, "DEFS %s ", name );
+ PagedAddress( value, page );
+ fprintf( jfp, "SFUNC %s ", name );
+ PagedAddress( value, page );
+ }
+ else
+ {
+ fprintf( jfp, "SFUNC %s\n", name );
+ }
+ }
+}
+
+/*
+ * static function:
+ * Define the end of the current function
+ */
+void DefineEndFunction( Addr_T value, int page )
+{
+ if (currentFunction[0] != 0)
+ {
+ if (value != 0)
+ {
+ fprintf( jfp, "ENDF " );
+ PagedAddress( value, page );
+ }
+ else
+ {
+ fprintf( jfp, "ENDF\n" );
+ }
+
+ currentFunction[0] = 0;
+ }
+}
+
+/*
+ * static function:
+ * Define "lineNumber" as a line in the current file
+ */
+void DefineLine( char *lineString, Addr_T value, int page )
+{
+ int indigit, lineNumber = 0;
+
+ while( (indigit=digit( *lineString++, 10 )) >= 0)
+ {
+ lineNumber = 10*lineNumber + indigit;
+ }
+ fprintf( jfp, "LINE %u ", lineNumber );
+ PagedAddress( value, page );
+}
+
+void PagedAddress( Addr_T value, int page )
+{
+ fprintf( jfp, "%X:0x%X\n", page, value );
+}
--- /dev/null
+/* lkrloc.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 29-Oct-97 JLH:
+ * - errdmp: show s_id as string rather than array [NCPS]
+ * - relr: add support for 11 bit 8051 addressing
+ * 02-Apr-98 JLH: don't output empty hex records
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lkrloc.c
+ *
+ * The module lkrloc.c contains the functions which
+ * perform the relocation calculations.
+ *
+ * lkrloc.c contains the following functions:
+ * Addr_T adb_b()
+ * Addr_T adb_lo()
+ * Addr_T adb_hi()
+ * Addr_T adw_w()
+ * Addr_T adw_lo()
+ * Addr_T adw_hi()
+ * VOID erpdmp()
+ * VOID errdmp()
+ * Addr_T evword()
+ * VOID prntval()
+ * VOID rele()
+ * VOID relerr()
+ * VOID relerp()
+ * VOID reloc()
+ * VOID relp()
+ * VOID relr()
+ * VOID relt()
+ *
+ * lkrloc.c the local variable errmsg[].
+ *
+ */
+
+/* Global which holds the upper 16 bits of the last 32 bit area adress
+ * output. Useful only for iHex mode.
+ */
+int lastExtendedAddress=-1;
+
+/* Static variable which holds the index of last processed area.
+ * Useful only for iHex mode.
+ */
+static int lastAreaIndex = -1;
+
+/*)Function VOID reloc(c)
+ *
+ * char c process code
+ *
+ * The function reloc() calls a particular relocation
+ * function determined by the process code.
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * int lkerr error flag
+ *
+ * called functions:
+ * int fprintf() c_library
+ * VOID rele() lkrloc.c
+ * VOID relp() lkrloc.c
+ * VOID relr() lkrloc.c
+ * VOId relt() lkrloc.c
+ *
+ * side effects:
+ * Refer to the called relocation functions.
+ *
+ */
+
+VOID
+reloc(c)
+char c;
+{
+ switch(c) {
+
+ case 'T':
+ relt();
+ break;
+
+ case 'R':
+ relr();
+ break;
+
+ case 'P':
+ relp();
+ break;
+
+ case 'E':
+ rele();
+ break;
+
+ default:
+ fprintf(stderr, "Undefined Relocation Operation\n");
+ lkerr++;
+ break;
+
+ }
+}
+
+
+/*)Function VOID relt()
+ *
+ * The function relt() evaluates a T line read by
+ * the linker. Each byte value read is saved in the
+ * rtval[] array, rtflg[] is set, and the number of
+ * evaluations is maintained in rtcnt.
+ *
+ * T Line
+ *
+ * T xx xx nn nn nn nn nn ...
+ *
+ *
+ * In: "T n0 n1 n2 n3 ... nn"
+ *
+ * Out: 0 1 2 .. rtcnt
+ * +----+----+----+----+----+
+ * rtval | n0 | n1 | n2 | .. | nn |
+ * +----+----+----+----+----+
+ * rtflag| 1 | 1 | 1 | 1 | 1 |
+ * +----+----+----+----+----+
+ *
+ * The T line contains the assembled code output by the assem-
+ * bler with xx xx being the offset address from the current area
+ * base address and nn being the assembled instructions and data in
+ * byte format.
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * int rtcnt number of values evaluated
+ * int rtflg[] array of evaluation flags
+ * int rtval[] array of evaluation values
+ *
+ * called functions:
+ * int eval() lkeval.c
+ * int more() lklex.c
+ *
+ * side effects:
+ * Linker input T line evaluated.
+ *
+ */
+
+VOID
+relt()
+{
+ rtcnt = 0;
+ while (more()) {
+ if (rtcnt < NTXT) {
+ rtval[rtcnt] = eval();
+ rtflg[rtcnt] = 1;
+ rtcnt++;
+ }
+ }
+}
+
+/*)Function VOID relr()
+ *
+ * The function relr() evaluates a R line read by
+ * the linker. The R line data is combined with the
+ * previous T line data to perform the relocation of
+ * code and data bytes. The S19 / IHX output and
+ * translation of the LST files to RST files may be
+ * performed.
+ *
+ * R Line
+ *
+ * R 0 0 nn nn n1 n2 xx xx ...
+ *
+ * The R line provides the relocation information to the linker.
+ * The nn nn value is the current area index, i.e. which area the
+ * current values were assembled. Relocation information is en-
+ * coded in groups of 4 bytes:
+ *
+ * 1. n1 is the relocation mode and object format
+ * 1. bit 0 word(0x00)/byte(0x01)
+ * 2. bit 1 relocatable area(0x00)/symbol(0x02)
+ * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
+ * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
+ * byte data
+ * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
+ * 6. bit 5 normal(0x00)/page '0'(0x20) reference
+ * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
+ *
+ * 2. n2 is a byte index into the corresponding (i.e. pre-
+ * ceeding) T line data (i.e. a pointer to the data to be
+ * updated by the relocation). The T line data may be
+ * 1-byte or 2-byte byte data format or 2-byte word
+ * format.
+ *
+ * 3. xx xx is the area/symbol index for the area/symbol be-
+ * ing referenced. the corresponding area/symbol is found
+ * in the header area/symbol lists.
+ *
+ * The groups of 4 bytes are repeated for each item requiring relo-
+ * cation in the preceeding T line.
+ *
+ * local variable:
+ * areax **a pointer to array of area pointers
+ * int aindex area index
+ * char *errmsg[] array of pointers to error strings
+ * int error error code
+ * int lkerr error flag
+ * int mode relocation mode
+ * adrr_t paga paging base area address
+ * Addr_T pags paging symbol address
+ * Addr_T pc relocated base address
+ * Addr_T r PCR relocation value
+ * Addr_T reli relocation initial value
+ * Addr_T relv relocation final value
+ * int rindex symbol / area index
+ * Addr_T rtbase base code address
+ * Addr_T rtofst rtval[] index offset
+ * int rtp index into T data
+ * sym **s pointer to array of symbol pointers
+ *
+ * global variables:
+ * head *hp pointer to the head structure
+ * rerr rerr linker error structure
+ * FILE *stderr standard error device
+ *
+ * called functions:
+ * Addr_T adb_b() lkrloc.c
+ * Addr_T adb_lo() lkrloc.c
+ * Addr_T adb_hi() lkrloc.c
+ * Addr_T adw_w() lkrloc.c
+ * Addr_T evword() lkrloc.c
+ * int eval() lkeval.c
+ * int fprintf() c_library
+ * VOID ihx() lkihx.c
+ * int lkulist lklist.c
+ * int more() lklex.c
+ * VOID relerr() lkrloc.c
+ * VOID s19() lks19.c
+ * int symval() lksym.c
+ *
+ * side effects:
+ * The R and T lines are combined to produce
+ * relocated code and data. Output S19 / IHX
+ * and relocated listing files may be produced.
+ *
+ */
+
+VOID
+relr()
+{
+ register int mode;
+ register Addr_T reli, relv;
+ int aindex, rindex, rtp, error;
+ Addr_T r, rtbase, rtofst, paga, pags, pc;
+ struct areax **a;
+ struct sym **s;
+
+ /*
+ * Get area and symbol lists
+ */
+ a = hp->a_list;
+ s = hp->s_list;
+
+ /*
+ * Verify Area Mode
+ */
+ if (eval() != (R_WORD | R_AREA) || eval()) {
+ fprintf(stderr, "R input error\n");
+ lkerr++;
+ }
+
+ /*
+ * Get area pointer
+ */
+ aindex = evword();
+ if (aindex >= hp->h_narea) {
+ fprintf(stderr, "R area error\n");
+ lkerr++;
+ return;
+ }
+
+ /*
+ * Base values
+ */
+ rtbase = adw_w(0, 0);
+ rtofst = 2;
+
+ /*
+ * Relocate address
+ */
+ pc = adw_w(a[aindex]->a_addr, 0);
+
+ #if 0
+ printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex,
+ a[aindex]->a_addr, a[aindex]->a_size, rtbase);
+ #endif
+ /*
+ * Do remaining relocations
+ */
+ while (more()) {
+ error = 0;
+ mode = eval();
+
+ if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK)
+ {
+ mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval();
+ /* printf("unescaping rmode\n"); */
+ }
+
+ rtp = eval();
+ rindex = evword();
+
+ /*
+ * R_SYM or R_AREA references
+ */
+ if (mode & R_SYM) {
+ if (rindex >= hp->h_nglob) {
+ fprintf(stderr, "R symbol error\n");
+ lkerr++;
+ return;
+ }
+ reli = symval(s[rindex]);
+ } else {
+ if (rindex >= hp->h_narea) {
+ fprintf(stderr, "R area error\n");
+ lkerr++;
+ return;
+ }
+ reli = a[rindex]->a_addr;
+ }
+
+ /*
+ * R_PCR addressing
+ */
+ if (mode & R_PCR) {
+ if (mode & R_BYTE) {
+ reli -= (pc + (rtp-rtofst) + 1);
+ } else {
+ reli -= (pc + (rtp-rtofst) + 2);
+ }
+ }
+
+ /*
+ * R_PAG0 or R_PAG addressing
+ */
+ if (mode & (R_PAG0 | R_PAG)) {
+ paga = sdp.s_area->a_addr;
+ pags = sdp.s_addr;
+ reli -= paga + pags;
+ }
+
+ /*
+ * R_BYTE or R_WORD operation
+ */
+ if (mode & R_BYTE) {
+ if (mode & R_BYT3)
+ {
+ /* This is a three byte address, of which
+ * we will select one byte.
+ */
+ if (mode & R_HIB)
+ {
+ /* printf("24 bit address selecting hi byte.\n"); */
+ relv = adb_24_hi(reli, rtp);
+ }
+ else if (mode & R_MSB)
+ {
+ /* Note that in 24 bit mode, R_MSB
+ * is really the middle byte, not
+ * the most significant byte.
+ *
+ * This is ugly and I can only apologize
+ * for any confusion.
+ */
+ /* printf("24 bit address selecting middle byte.\n"); */
+ relv = adb_24_mid(reli, rtp);
+ }
+ else
+ {
+ /* printf("24 bit address selecting lo byte.\n"); */
+ relv = adb_24_lo(reli, rtp);
+ }
+ }
+ else if (mode & R_BYT2) {
+ /* This is a two byte address, of
+ * which we will select one byte.
+ */
+ if (mode & R_MSB) {
+ relv = adb_hi(reli, rtp);
+ } else {
+ relv = adb_lo(reli, rtp);
+ }
+ } else {
+ relv = adb_b(reli, rtp);
+ }
+ } else if (IS_R_J11(mode)) {
+ /* JLH: 11 bit jump destination for 8051. Forms
+ / two byte instruction with op-code bits
+ / in the MIDDLE!
+ / rtp points at 3 byte locus: first two
+ / will get the instructiion. third one
+ / has raw op-code.
+ */
+
+ /* Calculate absolute destination
+ / relv must be on same 2K page as pc
+ */
+ relv = adw_w(reli, rtp);
+
+ if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
+ error = 2;
+ }
+
+ /* Merge MSB (byte 0) with op-code, ignoring
+ / top 5 bits of address. Then hide the op-code
+ */
+ rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
+ rtflg[rtp+2] = 0;
+ rtofst += 1;
+ }
+ else if (IS_R_J19(mode)) {
+ /* 19 bit jump destination for DS80C390. Forms
+ / three byte instruction with op-code bits
+ / in the MIDDLE!
+ / rtp points at 4 byte locus: first three
+ / will get the instructiion. fourth one
+ / has raw op-code.
+ */
+
+ /* Calculate absolute destination
+ / relv must be on same 512K page as pc
+ */
+ relv = adw_24(reli, rtp);
+
+ if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) {
+ error = 2;
+ }
+
+ /* Merge MSB (byte 0) with op-code, ignoring
+ / top 5 bits of address. Then hide the op-code
+ */
+ rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3];
+ rtflg[rtp+3] = 0;
+ rtofst += 1;
+ }
+ else if (IS_C24(mode))
+ {
+ /* 24 bit address */
+ relv = adw_24(reli, rtp);
+ }
+ else
+ {
+ /* 16 bit address. */
+ relv = adw_w(reli, rtp);
+ }
+
+ /*
+ * R_BYTE with R_BYT2 offset adjust
+ */
+ if (mode & R_BYTE) {
+ if (mode & R_BYT2) {
+ rtofst += 1;
+ }
+ }
+
+ /*
+ * Unsigned Byte Checking
+ */
+ if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
+ error = 1;
+
+ /*
+ * PCR Relocation Error Checking
+ */
+ if (mode & R_PCR && mode & R_BYTE) {
+ r = relv & ~0x7F;
+ if (r != (Addr_T) ~0x7F && r != 0)
+ error = 2;
+ }
+
+ /*
+ * Page Relocation Error Checking
+ */
+ /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
+ error = 3;*/
+ if (mode & R_PAG && (relv & ~0xFF))
+ error = 4;
+
+ /*
+ * Error Processing
+ */
+ if (error) {
+ rerr.aindex = aindex;
+ rerr.mode = mode;
+ rerr.rtbase = rtbase + rtp - rtofst - 1;
+ rerr.rindex = rindex;
+ rerr.rval = relv - reli;
+ relerr(errmsg[error-1]);
+ }
+ }
+ if (uflag != 0) {
+ lkulist(1);
+ }
+
+
+ /* JLH: output only if data (beyond two byte address) */
+ if ((oflag == 1) && (rtcnt > 2)) {
+ int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff;
+
+ /* Boy, is this a hack: for ABS sections, the
+ * base address is stored as zero, and the T records
+ * indicate the offset from zero.
+ *
+ * Since T records can only indicate a 16 bit offset, this
+ * obviously creates a problem for ABS segments located
+ * above 64K (this is only meaningful in flat24 mode).
+ *
+ * However, the size of an ABS area is stored as
+ * base address + section size (I suspect this is a bug,
+ * but it's a handy one right now). So the upper 8 bits of
+ * the 24 bit address are stored in the size record.
+ * Thus we add it in.
+ *
+ * This is another reason why we can't have areas greater
+ * than 64K yet, even in flat24 mode.
+ */
+ // extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff);
+ // commented out by jr
+
+ if (lastAreaIndex != aindex) {
+ lastAreaIndex = aindex;
+ newArea();
+ }
+
+#if 0
+ if (extendedAddress != lastExtendedAddress)
+ {
+
+ if (lastExtendedAddress!=-1) {
+ printf("output extended linear address record 0x%x 0x%x\n",
+ extendedAddress, lastExtendedAddress);
+ }
+
+ if (rflag)
+ {
+ ihxEntendedLinearAddress(extendedAddress);
+ }
+ else if (extendedAddress)
+ {
+ /* Not allowed to generate extended address records,
+ * but one is called for here...
+ */
+ fprintf(stderr,
+ "warning: extended linear address encountered; "
+ "you probably want the -r flag.\n");
+ }
+ lastExtendedAddress = extendedAddress;
+ }
+#endif
+ ihx(1);
+ } else
+ if ((oflag == 2) && (rtcnt > 2)) {
+ s19(1);
+ }
+}
+
+char *errmsg[] = {
+ "Unsigned Byte error",
+ "Byte PCR relocation error",
+ "Page0 relocation error",
+ "Page Mode relocation error"
+};
+
+
+/*)Function VOID relp()
+ *
+ * The function relp() evaluates a P line read by
+ * the linker. The P line data is combined with the
+ * previous T line data to set the base page address
+ * and test the paging boundary and length.
+ *
+ * P Line
+ *
+ * P 0 0 nn nn n1 n2 xx xx
+ *
+ * The P line provides the paging information to the linker as
+ * specified by a .setdp directive. The format of the relocation
+ * information is identical to that of the R line. The correspond-
+ * ing T line has the following information:
+ * T xx xx aa aa bb bb
+ *
+ * Where aa aa is the area reference number which specifies the
+ * selected page area and bb bb is the base address of the page.
+ * bb bb will require relocation processing if the 'n1 n2 xx xx' is
+ * specified in the P line. The linker will verify that the base
+ * address is on a 256 byte boundary and that the page length of an
+ * area defined with the PAG type is not larger than 256 bytes.
+ *
+ * local variable:
+ * areax **a pointer to array of area pointers
+ * int aindex area index
+ * int mode relocation mode
+ * Addr_T relv relocation value
+ * int rindex symbol / area index
+ * int rtp index into T data
+ * sym **s pointer to array of symbol pointers
+ *
+ * global variables:
+ * head *hp pointer to the head structure
+ * int lkerr error flag
+ * sdp sdp base page structure
+ * FILE *stderr standard error device
+ *
+ * called functions:
+ * Addr_T adw_w() lkrloc.c
+ * Addr_T evword() lkrloc.c
+ * int eval() lkeval.c
+ * int fprintf() c_library
+ * int more() lklex.c
+ * int symval() lksym.c
+ *
+ * side effects:
+ * The P and T lines are combined to set
+ * the base page address and report any
+ * paging errors.
+ *
+ */
+
+VOID
+relp()
+{
+ register int aindex, rindex;
+ int mode, rtp;
+ Addr_T relv;
+ struct areax **a;
+ struct sym **s;
+
+ /*
+ * Get area and symbol lists
+ */
+ a = hp->a_list;
+ s = hp->s_list;
+
+ /*
+ * Verify Area Mode
+ */
+ if (eval() != (R_WORD | R_AREA) || eval()) {
+ fprintf(stderr, "P input error\n");
+ lkerr++;
+ }
+
+ /*
+ * Get area pointer
+ */
+ aindex = evword();
+ if (aindex >= hp->h_narea) {
+ fprintf(stderr, "P area error\n");
+ lkerr++;
+ return;
+ }
+
+ /*
+ * Do remaining relocations
+ */
+ while (more()) {
+ mode = eval();
+ rtp = eval();
+ rindex = evword();
+
+ /*
+ * R_SYM or R_AREA references
+ */
+ if (mode & R_SYM) {
+ if (rindex >= hp->h_nglob) {
+ fprintf(stderr, "P symbol error\n");
+ lkerr++;
+ return;
+ }
+ relv = symval(s[rindex]);
+ } else {
+ if (rindex >= hp->h_narea) {
+ fprintf(stderr, "P area error\n");
+ lkerr++;
+ return;
+ }
+ relv = a[rindex]->a_addr;
+ }
+ adw_w(relv, rtp);
+ }
+
+ /*
+ * Paged values
+ */
+ aindex = adw_w(0,2);
+ if (aindex >= hp->h_narea) {
+ fprintf(stderr, "P area error\n");
+ lkerr++;
+ return;
+ }
+ sdp.s_areax = a[aindex];
+ sdp.s_area = sdp.s_areax->a_bap;
+ sdp.s_addr = adw_w(0,4);
+ if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
+ relerp("Page Definition Boundary Error");
+}
+
+/*)Function VOID rele()
+ *
+ * The function rele() closes all open output files
+ * at the end of the linking process.
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * int oflag output type flag
+ * int uflag relocation listing flag
+ *
+ * called functions:
+ * VOID ihx() lkihx.c
+ * VOID lkulist() lklist.c
+ * VOID s19() lks19.c
+ *
+ * side effects:
+ * All open output files are closed.
+ *
+ */
+
+VOID
+rele()
+{
+ if (uflag != 0) {
+ lkulist(0);
+ }
+ if (oflag == 1) {
+ ihx(0);
+ } else
+ if (oflag == 2) {
+ s19(0);
+ }
+}
+
+/*)Function Addr_T evword()
+ *
+ * The function evword() combines two byte values
+ * into a single word value.
+ *
+ * local variable:
+ * Addr_T v temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * int eval() lkeval.c
+ *
+ * side effects:
+ * Relocation text line is scanned to combine
+ * two byte values into a single word value.
+ *
+ */
+
+Addr_T
+evword()
+{
+ register Addr_T v;
+
+ if (hilo) {
+ v = (eval() << 8);
+ v += eval();
+ } else {
+ v = eval();
+ v += (eval() << 8);
+ }
+ return(v);
+}
+
+/*)Function Addr_T adb_b(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_b() adds the value of v to
+ * the single byte value contained in rtval[i].
+ * The new value of rtval[i] is returned.
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ *
+ */
+
+Addr_T
+adb_b(v, i)
+register Addr_T v;
+register int i;
+{
+ return(rtval[i] += v);
+}
+
+/*)Function Addr_T adb_lo(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_lo() adds the value of v to the
+ * double byte value contained in rtval[i] and rtval[i+1].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The MSB rtflg[] is cleared.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The rtflg[] value corresponding to the
+ * MSB of the word value is cleared to reflect
+ * the fact that the LSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_lo(v, i)
+Addr_T v;
+int i;
+{
+ register Addr_T j;
+
+ j = adw_w(v, i);
+ /*
+ * Remove Hi byte
+ */
+ if (hilo) {
+ rtflg[i] = 0;
+ } else {
+ rtflg[i+1] = 0;
+ }
+ return (j);
+}
+
+/*)Function Addr_T adb_hi(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_hi() adds the value of v to the
+ * double byte value contained in rtval[i] and rtval[i+1].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The LSB rtflg[] is cleared.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The rtflg[] value corresponding to the
+ * LSB of the word value is cleared to reflect
+ * the fact that the MSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_hi(v, i)
+Addr_T v;
+int i;
+{
+ register Addr_T j;
+
+ j = adw_w(v, i);
+ /*
+ * Remove Lo byte
+ */
+ if (hilo) {
+ rtflg[i+1] = 0;
+ } else {
+ rtflg[i] = 0;
+ }
+ return (j);
+}
+
+/*)Function Addr_T adb_24_hi(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_24_hi() adds the value of v to the
+ * 24 bit value contained in rtval[i] - rtval[i+2].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The LSB & middle byte rtflg[] is cleared.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The rtflg[] value corresponding to the
+ * LSB & middle byte of the word value is cleared to
+ * reflect the fact that the MSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_24_hi(Addr_T v, int i)
+{
+ register Addr_T j;
+
+ j = adw_24(v, i);
+
+ /* Remove the lower two bytes. */
+ if (hilo)
+ {
+ rtflg[i+2] = 0;
+ }
+ else
+ {
+ rtflg[i] = 0;
+ }
+ rtflg[i+1] = 0;
+
+ return (j);
+}
+
+/*)Function Addr_T adb_24_mid(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_24_mid() adds the value of v to the
+ * 24 bit value contained in rtval[i] - rtval[i+2].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The LSB & MSB byte rtflg[] is cleared.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The rtflg[] value corresponding to the
+ * LSB & MSB of the 24 bit value is cleared to reflect
+ * the fact that the middle byte is the selected byte.
+ *
+ */
+
+Addr_T
+adb_24_mid(Addr_T v, int i)
+{
+ register Addr_T j;
+
+ j = adw_24(v, i);
+
+ /* remove the MSB & LSB. */
+ rtflg[i+2] = 0;
+ rtflg[i] = 0;
+
+ return (j);
+}
+
+/*)Function Addr_T adb_24_lo(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adb_24_lo() adds the value of v to the
+ * 24 bit value contained in rtval[i] - rtval[i+2].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The MSB & middle byte rtflg[] is cleared.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The rtflg[] value corresponding to the
+ * MSB & middle byte of the word value is cleared to
+ * reflect the fact that the LSB is the selected byte.
+ *
+ */
+
+Addr_T
+adb_24_lo(Addr_T v, int i)
+{
+ register Addr_T j;
+
+ j = adw_24(v, i);
+
+ /* Remove the upper two bytes. */
+ if (hilo)
+ {
+ rtflg[i] = 0;
+ }
+ else
+ {
+ rtflg[i+2] = 0;
+ }
+ rtflg[i+1] = 0;
+
+ return (j);
+}
+
+/*)Function Addr_T adw_w(v, i)
+ *
+ * int v value to add to word
+ * int i rtval[] index
+ *
+ * The function adw_w() adds the value of v to the
+ * word value contained in rtval[i] and rtval[i+1].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The word value of rtval[] is changed.
+ *
+ */
+
+Addr_T
+adw_w(v, i)
+register Addr_T v;
+register int i;
+{
+ register Addr_T j;
+
+ if (hilo) {
+ j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
+ rtval[i] = (j >> 8) & 0xff;
+ rtval[i+1] = j & 0xff;
+ } else {
+ j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
+ rtval[i] = j & 0xff;
+ rtval[i+1] = (j >> 8) & 0xff;
+ }
+ return(j);
+}
+
+/*)Function Addr_T adw_24(v, i)
+ *
+ * int v value to add to word
+ * int i rtval[] index
+ *
+ * The function adw_w() adds the value of v to the
+ * 24 bit value contained in rtval[i] - rtval[i+2].
+ * The new value of rtval[i] - rtval[i+2] is returned.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The word value of rtval[] is changed.
+ *
+ */
+Addr_T
+adw_24(Addr_T v, int i)
+{
+ register Addr_T j;
+
+ if (hilo) {
+ j = v + ((rtval[i] & 0xff) << 16)
+ + ((rtval[i+1] & 0xff) << 8)
+ + (rtval[i+2] & 0xff);
+ rtval[i] = (j >> 16) & 0xff;
+ rtval[i+1] = (j >> 8) & 0xff;
+ rtval[i+2] = j & 0xff;
+ } else {
+ j = v + (rtval[i] & 0xff)
+ + ((rtval[i+1] & 0xff) << 8)
+ + ((rtval[i+2] & 0xff) << 16);
+ rtval[i] = j & 0xff;
+ rtval[i+1] = (j >> 8) & 0xff;
+ rtval[i+2] = (j >> 16) & 0xff;
+ }
+ return(j);
+}
+
+/*)Function Addr_T adw_lo(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adw_lo() adds the value of v to the
+ * double byte value contained in rtval[i] and rtval[i+1].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The MSB rtval[] is zeroed.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The MSB of the word value is cleared to reflect
+ * the fact that the LSB is the selected byte.
+ *
+ */
+
+Addr_T
+adw_lo(v, i)
+Addr_T v;
+int i;
+{
+ register Addr_T j;
+
+ j = adw_w(v, i);
+ /*
+ * Clear Hi byte
+ */
+ if (hilo) {
+ rtval[i] = 0;
+ } else {
+ rtval[i+1] = 0;
+ }
+ return (j);
+}
+
+/*)Function Addr_T adw_hi(v, i)
+ *
+ * int v value to add to byte
+ * int i rtval[] index
+ *
+ * The function adw_hi() adds the value of v to the
+ * double byte value contained in rtval[i] and rtval[i+1].
+ * The new value of rtval[i] / rtval[i+1] is returned.
+ * The MSB and LSB values are interchanged.
+ * The MSB rtval[] is zeroed.
+ *
+ * local variable:
+ * Addr_T j temporary evaluation variable
+ *
+ * global variables:
+ * hilo byte ordering parameter
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * The value of rtval[] is changed.
+ * The MSB and LSB values are interchanged and
+ * then the MSB cleared.
+ *
+ */
+
+Addr_T
+adw_hi(v, i)
+Addr_T v;
+int i;
+{
+ register Addr_T j;
+
+ j = adw_w(v, i);
+ /*
+ * LSB = MSB, Clear MSB
+ */
+ if (hilo) {
+ rtval[i+1] = rtval[i];
+ rtval[i] = 0;
+ } else {
+ rtval[i] = rtval[i+1];
+ rtval[i+1] = 0;
+ }
+ return (j);
+}
+
+/*)Function VOID relerr(str)
+ *
+ * char *str error string
+ *
+ * The function relerr() outputs the error string to
+ * stderr and to the map file (if it is open).
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * FILE *mfp handle for the map file
+ *
+ * called functions:
+ * VOID errdmp() lkrloc.c
+ *
+ * side effects:
+ * Error message inserted into map file.
+ *
+ */
+
+VOID
+relerr(str)
+char *str;
+{
+ errdmp(stderr, str);
+ if (mfp)
+ errdmp(mfp, str);
+}
+
+/*)Function VOID errdmp(fptr, str)
+ *
+ * FILE *fptr output file handle
+ * char *str error string
+ *
+ * The function errdmp() outputs the error string str
+ * to the device specified by fptr. Additional information
+ * is output about the definition and referencing of
+ * the symbol / area error.
+ *
+ * local variable:
+ * int mode error mode
+ * int aindex area index
+ * int lkerr error flag
+ * int rindex error index
+ * sym **s pointer to array of symbol pointers
+ * areax **a pointer to array of area pointers
+ * areax *raxp error area extension pointer
+ *
+ * global variables:
+ * sdp sdp base page structure
+ *
+ * called functions:
+ * int fprintf() c_library
+ * VOID prntval() lkrloc.c
+ *
+ * side effects:
+ * Error reported.
+ *
+ */
+
+VOID
+errdmp(fptr, str)
+FILE *fptr;
+char *str;
+{
+ int mode, aindex, rindex;
+ struct sym **s;
+ struct areax **a;
+ struct areax *raxp;
+
+ a = hp->a_list;
+ s = hp->s_list;
+
+ mode = rerr.mode;
+ aindex = rerr.aindex;
+ rindex = rerr.rindex;
+
+ /*
+ * Print Error
+ */
+ fprintf(fptr, "\n?ASlink-Warning-%s", str);
+ lkerr++;
+
+ /*
+ * Print symbol if symbol based
+ */
+ if (mode & R_SYM) {
+ fprintf(fptr, " for symbol %s\n",
+ &s[rindex]->s_id[0]);
+ } else {
+ fprintf(fptr, "\n");
+ }
+
+ /*
+ * Print Ref Info
+ */
+ fprintf(fptr,
+ " file module area offset\n");
+ fprintf(fptr,
+ " Refby %-8.8s %-8.8s %-8.8s ",
+ hp->h_lfile->f_idp,
+ &hp->m_id[0],
+ &a[aindex]->a_bap->a_id[0]);
+ prntval(fptr, rerr.rtbase);
+
+ /*
+ * Print Def Info
+ */
+ if (mode & R_SYM) {
+ raxp = s[rindex]->s_axp;
+ } else {
+ raxp = a[rindex];
+ }
+ fprintf(fptr,
+ " Defin %-8.8s %-8.8s %-8.8s ",
+ raxp->a_bhp->h_lfile->f_idp,
+ &raxp->a_bhp->m_id[0],
+ &raxp->a_bap->a_id[0]);
+ if (mode & R_SYM) {
+ prntval(fptr, s[rindex]->s_addr);
+ } else {
+ prntval(fptr, rerr.rval);
+ }
+}
+
+/*)Function VOID prntval(fptr, v)
+ *
+ * FILE *fptr output file handle
+ * Addr_T v value to output
+ *
+ * The function prntval() outputs the value v, in the
+ * currently selected radix, to the device specified
+ * by fptr.
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * int xflag current radix
+ *
+ * called functions:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * none
+ *
+ */
+
+VOID
+prntval(fptr, v)
+FILE *fptr;
+Addr_T v;
+{
+ if (xflag == 0) {
+ fprintf(fptr, "%04X\n", v);
+ } else
+ if (xflag == 1) {
+ fprintf(fptr, "%06o\n", v);
+ } else
+ if (xflag == 2) {
+ fprintf(fptr, "%05u\n", v);
+ }
+}
+
+/*)Function VOID relerp(str)
+ *
+ * char *str error string
+ *
+ * The function relerp() outputs the paging error string to
+ * stderr and to the map file (if it is open).
+ *
+ * local variable:
+ * none
+ *
+ * global variables:
+ * FILE *mfp handle for the map file
+ *
+ * called functions:
+ * VOID erpdmp() lkrloc.c
+ *
+ * side effects:
+ * Error message inserted into map file.
+ *
+ */
+
+VOID
+relerp(str)
+char *str;
+{
+ erpdmp(stderr, str);
+ if (mfp)
+ erpdmp(mfp, str);
+}
+
+/*)Function VOID erpdmp(fptr, str)
+ *
+ * FILE *fptr output file handle
+ * char *str error string
+ *
+ * The function erpdmp() outputs the error string str
+ * to the device specified by fptr.
+ *
+ * local variable:
+ * head *thp pointer to head structure
+ *
+ * global variables:
+ * int lkerr error flag
+ * sdp sdp base page structure
+ *
+ * called functions:
+ * int fprintf() c_library
+ * VOID prntval() lkrloc.c
+ *
+ * side effects:
+ * Error reported.
+ *
+ */
+
+VOID
+erpdmp(fptr, str)
+FILE *fptr;
+char *str;
+{
+ register struct head *thp;
+
+ thp = sdp.s_areax->a_bhp;
+
+ /*
+ * Print Error
+ */
+ fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
+ lkerr++;
+
+ /*
+ * Print PgDef Info
+ */
+ fprintf(fptr,
+ " file module pgarea pgoffset\n");
+ fprintf(fptr,
+ " PgDef %-8.8s %-8.8s %-8.8s ",
+ thp->h_lfile->f_idp,
+ &thp->m_id[0],
+ &sdp.s_area->a_id[0]);
+ prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);
+}
--- /dev/null
+/* lks19.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lks19.c
+ *
+ * The module lks19.c contains the function to
+ * output the relocated object code in the
+ * Motorola S19 format.
+ *
+ * lks19.c contains the following function:
+ * VOID s19(i)
+ *
+ * lks19.c contains no local variables.
+ */
+
+/*)S19 Format
+ * Record Type Field - This field signifies the start of a
+ * record and identifies the the record
+ * type as follows:
+ *
+ * Ascii S1 - Data Record
+ * Ascii S9 - End of File Record
+ *
+ * Record Length Field - This field specifies the record length
+ * which includes the address, data, and
+ * checksum fields. The 8 bit record
+ * length value is converted to two ascii
+ * characters, high digit first.
+ *
+ * Load Address Field - This field consists of the four ascii
+ * characters which result from converting
+ * the the binary value of the address in
+ * which to begin loading this record. The
+ * order is as follows:
+ *
+ * High digit of high byte of address.
+ * Low digit of high byte of address.
+ * High digit of low byte of address.
+ * Low digit of low byte of address.
+ *
+ * In an End of File record this field con-
+ * sists of either four ascii zeros or the
+ * program entry address. Currently the
+ * entry address option is not supported.
+ *
+ * Data Field - This field consists of the actual data,
+ * converted to two ascii characters, high
+ * digit first. There are no data bytes in
+ * the End of File record.
+ *
+ * Checksum Field - The checksum field is the 8 bit binary
+ * sum of the record length field, the load
+ * address field, and the data field. This
+ * sum is then complemented (1's comple-
+ * ment) and converted to two ascii
+ * characters, high digit first.
+ */
+
+/*)Function s19(i)
+ *
+ * int i 0 - process data
+ * 1 - end of data
+ *
+ * The function s19() outputs the relocated data
+ * in the standard Motorola S19 format.
+ *
+ * local variables:
+ * Addr_T chksum byte checksum
+ *
+ * global variables:
+ * int hilo byte order
+ * FILE * ofp output file handle
+ * int rtcnt count of data words
+ * int rtflg[] output the data flag
+ * Addr_T rtval[] relocated data
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * The data is output to the file defined by ofp.
+ */
+
+VOID
+s19(i)
+{
+ register Addr_T chksum;
+
+ if (i) {
+ if (hilo == 0) {
+ chksum = rtval[0];
+ rtval[0] = rtval[1];
+ rtval[1] = chksum;
+ }
+ for (i = 0, chksum = 1; i < rtcnt; i++) {
+ if (rtflg[i])
+ chksum++;
+ }
+ fprintf(ofp, "S1%02X", chksum);
+ for (i = 0; i < rtcnt ; i++) {
+ if (rtflg[i]) {
+ fprintf(ofp, "%02X", rtval[i]);
+ chksum += rtval[i];
+ }
+ }
+ fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff);
+ } else {
+ fprintf(ofp, "S9030000FC\n");
+ }
+}
--- /dev/null
+/* lkstore.c */
+
+/*
+ * Allocated string storage module.
+ *
+ * 31-Oct-1997 by John Hartman
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include "aslink.h"
+
+/*
+ * Allocate space for "str", copy str into new space
+ * Return a pointer to the allocated name, or NULL if out of memory
+ */
+char *StoreString( char *str )
+{
+ /* To avoid wasting memory headers on small allocations, we
+ / allocate a big chunk and parcel it out as required.
+ / These static variables remember our hunk
+ */
+ #define STR_STORE_HUNK 2000
+ static char *pNextFree = NULL;
+ static int bytesLeft = 0;
+
+ int length;
+ char *pStoredString;
+
+ length = strlen( str ) + 1; /* what we need, including null */
+
+ if (length > bytesLeft)
+ {
+ /* no space. Allocate a new hunk. We lose the pointer to any
+ / old hunk. We don't care, as the names are never deleted.
+ */
+ pNextFree = (char*)new( STR_STORE_HUNK );
+ bytesLeft = STR_STORE_HUNK;
+ }
+
+ /* Copy the name and terminating null into the name store */
+ pStoredString = pNextFree;
+ memcpy( pStoredString, str, length );
+
+ pNextFree += length;
+ bytesLeft -= length;
+
+ return pStoredString;
+}
--- /dev/null
+/* lksym.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * 28-Oct-97 JLH:
+ * - lkpsym: Use StoreString for sym construction
+ * - change symeq() to do length-independent string compare
+ * - change hash() to do length-independent hash calculation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#if defined(_MSC_VER)
+#include <malloc.h>
+#else
+#include <alloc.h>
+#endif
+#include "aslink.h"
+
+/*)Module lksym.c
+ *
+ * The module lksym.c contains the functions that operate
+ * on the symbol structures.
+ *
+ * lksym.c contains the following functions:
+ * int hash()
+ * sym * lkpsym()
+ * VOID * new()
+ * sym * newsym()
+ * VOID symdef()
+ * int symeq()
+ * VOID syminit()
+ * VOID symmod()
+ * Addr_T symval()
+ *
+ * lksym.c contains no local/static variables.
+ */
+
+/*)Function VOID syminit()
+ *
+ * The function syminit() is called to clear the hashtable.
+ *
+ * local variables:
+ * int h computed hash value
+ * sym ** spp pointer to an array of
+ * sym structure pointers
+ *
+ * global variables:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * (1) The symbol hash tables are cleared
+ */
+
+VOID
+syminit()
+{
+ // register int h;
+ struct sym **spp;
+
+ spp = &symhash[0];
+ while (spp < &symhash[NHASH])
+ *spp++ = NULL;
+}
+
+/*)Function sym * newsym()
+ *
+ * The function newsym() is called to evaluate the symbol
+ * definition/reference directive from the .rel file(s).
+ * If the symbol is not found in the symbol table a new
+ * symbol structure is created. Evaluation of the
+ * directive determines if this is a reference or a definition.
+ * Multiple definitions of the same variable will be flagged
+ * as an error if the values are not identical. A symbol
+ * definition places the symbol value and area extension
+ * into the symbols data structure. And finally, a pointer
+ * to the symbol structure is placed into the head structure
+ * symbol list. Refer to the description of the header, symbol,
+ * area, and areax structures in lkdata.c for structure and
+ * linkage details.
+ *
+ * local variables:
+ * int c character from input text
+ * int i evaluation value
+ * char id[] symbol name
+ * int nglob number of symbols in this header
+ * sym * tsp pointer to symbol structure
+ * sym ** s list of pointers to symbol structures
+ *
+ * global variables:
+ * areax *axp Pointer to the current
+ * areax structure
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * int lkerr error flag
+ *
+ * functions called:
+ * Addr_T eval() lkeval.c
+ * VOID exit() c_library
+ * int fprintf() c_library
+ * char getSid() lklex.c
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * sym * lkpsym() lksym.c
+ *
+ * side effects:
+ * A symbol structure is created and/or modified.
+ * If structure space allocation fails linker will abort.
+ * Several severe errors (these are internal errors
+ * indicating a corrupted .rel file or corrupted
+ * assembler or linker) will terminated the linker.
+ */
+
+/*
+ * Find/Create a global symbol entry.
+ *
+ * S xxxxxx Defnnnn
+ * | | |
+ * | | `-- sp->s_addr
+ * | `----- sp->s_type
+ * `------------ sp->s_id
+ *
+ */
+struct sym *
+newsym()
+{
+ register unsigned i ;
+ register unsigned nglob ;
+ register int c ;
+ struct sym *tsp;
+ struct sym **s;
+ char id[NCPS];
+
+ getSid(id); // old: getid(id, -1);
+ tsp = lkpsym(id, 1);
+ c = getnb();get();get();
+ if (c == 'R') {
+ tsp->s_type |= S_REF;
+ if (eval()) {
+ fprintf(stderr, "Non zero S_REF\n");
+ lkerr++;
+ }
+ } else
+ if (c == 'D') {
+ i = eval();
+ if (tsp->s_type & S_DEF && tsp->s_addr != i) {
+ fprintf(stderr, "Multiple definition of %8s\n", id);
+ lkerr++;
+ }
+ tsp->s_type |= S_DEF;
+ /*
+ * Set value and area extension link.
+ */
+ tsp->s_addr = i;
+ tsp->s_axp = axp;
+ } else {
+ fprintf(stderr, "Invalid symbol type %c for %8s\n", c, id);
+ lkexit(1);
+ }
+ /*
+ * Place pointer in header symbol list
+ */
+ if (headp == NULL) {
+ fprintf(stderr, "No header defined\n");
+ lkexit(1);
+ }
+ nglob = hp->h_nglob;
+ s = hp->s_list;
+ for (i=0; i < nglob ;++i) {
+ if (s[i] == NULL) {
+ s[i] = tsp;
+ return(tsp);
+ }
+ }
+ fprintf(stderr, "Header symbol list overflow\n");
+ lkexit(1);
+ return(0);
+}
+
+/*)Function sym * lkpsym(id,f)
+ *
+ * char * id symbol name string
+ * int f f == 0, lookup only
+ * f != 0, create if not found
+ *
+ * The function lookup() searches the symbol hash tables for
+ * a symbol name match returning a pointer to the sym structure.
+ * If the symbol is not found then a sym structure is created,
+ * initialized, and linked to the appropriate hash table if f != 0.
+ * A pointer to this new sym structure is returned or a NULL
+ * pointer is returned if f == 0.
+ *
+ * local variables:
+ * int h computed hash value
+ * sym * sp pointer to a sym structure
+ *
+ * global varaibles:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * int hash() lksym.c
+ * VOID * new() lksym.c
+ * int symeq() lksym.c
+ *
+ * side effects:
+ * If the function new() fails to allocate space
+ * for the new sym structure the linker terminates.
+ */
+
+struct sym *
+lkpsym(id, f)
+char *id;
+{
+ register struct sym *sp;
+ register int h;
+
+ h = hash(id);
+ sp = symhash[h];
+ while (sp != NULL) {
+ if (symeq(id, sp->s_id))
+ return (sp);
+ sp = sp->s_sp;
+ }
+ if (f == 0)
+ return (NULL);
+ sp = (struct sym *) new (sizeof(struct sym));
+ sp->s_sp = symhash[h];
+ symhash[h] = sp;
+ sp->s_id = StoreString( id ); /* JLH */
+ return (sp);
+}
+
+/*)Function Addr_T symval(tsp)
+ *
+ * sym * tsp pointer to a symbol structure
+ *
+ * The function symval() returns the value of the
+ * relocated symbol by adding the variable definition
+ * value to the areax base address.
+ *
+ * local variables:
+ * Addr_T val relocated address value
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+Addr_T
+symval(tsp)
+register struct sym *tsp;
+{
+ register Addr_T val;
+
+ val = tsp->s_addr;
+ if (tsp->s_axp) {
+ val += tsp->s_axp->a_addr;
+ }
+ return(val);
+}
+
+/*)Function VOID symdef(fp)
+ *
+ * FILE * fp file handle for output
+ *
+ * The function symdef() scans the hashed symbol table
+ * searching for variables referenced but not defined.
+ * Undefined variables are linked to the default
+ * area "_CODE" and reported as referenced by the
+ * appropriate module.
+ *
+ * local variables:
+ * int i hash table index loop variable
+ * sym * sp pointer to linked symbol structure
+ *
+ * global variables:
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ * sym *symhash[NHASH] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * symmod() lksym.c
+ *
+ * side effects:
+ * Undefined variables have their areas set to "_CODE".
+ */
+
+VOID
+symdef(fp)
+FILE *fp;
+{
+ register struct sym *sp;
+ register int i;
+
+ for (i=0; i<NHASH; ++i) {
+ sp = symhash[i];
+ while (sp) {
+ if (sp->s_axp == NULL)
+ sp->s_axp = areap->a_axp;
+ if ((sp->s_type & S_DEF) == 0)
+ symmod(fp, sp);
+ sp = sp->s_sp;
+ }
+ }
+}
+
+/*)Function VOID symmod(fp,tsp)
+ *
+ * FILE * fp output file handle
+ * sym * tsp pointer to a symbol structure
+ *
+ * The function symmod() scans the header structures
+ * searching for a reference to the symbol structure
+ * pointer to by tsp. The function then generates an error
+ * message whichs names the module having referenced the
+ * undefined variable.
+ *
+ * local variables:
+ * int i loop counter
+ * sym ** p pointer to a list of pointers
+ * to symbol structures
+ *
+ * global variables:
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * head *hp Pointer to the current
+ * head structure
+ * int lkerr error flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * Error output generated.
+ */
+
+VOID
+symmod(fp, tsp)
+FILE *fp;
+struct sym *tsp;
+{
+ register int i;
+ struct sym **p;
+
+ if ((hp = headp) != NULL) {
+ while(hp) {
+ p = hp->s_list;
+ for (i=0; i<hp->h_nglob; ++i) {
+ if (p[i] == tsp) {
+ fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id);
+ fprintf(fp, "referenced by module '%s'\n", hp->m_id);
+ lkerr++;
+ }
+ }
+ hp = hp->h_hp;
+ }
+ }
+}
+
+/*)Function int symeq(p1, p2)
+ *
+ * char * p1 name string
+ * char * p2 name string
+ *
+ * The function symeq() compares the two name strings for a match.
+ * The return value is 1 for a match and 0 for no match.
+ *
+ * local variables:
+ * int h loop counter
+ *
+ * global variables:
+ * char ccase[] an array of characters which
+ * perform the case translation function
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ *
+ */
+
+int
+symeq(p1, p2)
+register char *p1, *p2;
+{
+#if CASE_SENSITIVE
+ return (strcmp( p1, p2 ) == 0);
+#else
+ return (as_strcmpi( p1, p2 ) == 0);
+#endif
+}
+
+/*)Function int hash(p)
+ *
+ * char * p pointer to string to hash
+ *
+ * The function hash() computes a hash code using the sum
+ * of all characters mod table size algorithm.
+ *
+ * local variables:
+ * int h accumulated character sum
+ * int n loop counter
+ *
+ * global variables:
+ * char ccase[] an array of characters which
+ * perform the case translation function
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ *
+ */
+
+int
+hash(p)
+register char *p;
+{
+ register int h;
+
+ h = 0;
+ while (*p) {
+
+#if CASE_SENSITIVE
+ h += *p++;
+#else
+ h += ccase[*p++];
+#endif
+
+ };
+ return (h&HMASK);
+}
+
+/*)Function VOID * new(n)
+ *
+ * unsigned int n allocation size in bytes
+ *
+ * The function new() allocates n bytes of space and returns
+ * a pointer to this memory. If no space is available the
+ * linker is terminated.
+ *
+ * local variables:
+ * char * p a general pointer
+ * char * q a general pointer
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID * malloc() c_library
+ *
+ * side effects:
+ * Memory is allocated, if allocation fails
+ * the linker is terminated.
+ */
+
+VOID *
+new(n)
+unsigned int n;
+{
+ register char *p;
+
+ if ((p = (char *) calloc(n, 1)) == NULL) {
+ fprintf(stderr, "Out of space!\n");
+ lkexit(1);
+ }
+ return (p);
+}
--- /dev/null
+/* m08adr.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+int
+addr(esp)
+register struct expr *esp;
+{
+ register int c;
+ register struct area *espa;
+ register Addr_T espv;
+ char *tcp;
+
+ if ((c = getnb()) == '#') {
+ expr(esp, 0);
+ esp->e_mode = S_IMMED;
+ } else if (c == ',') {
+ switch(admode(axs)) {
+ default:
+ aerr();
+
+ case S_X:
+ c = S_IX;
+ break;
+
+ case S_S:
+ c = S_IS;
+ break;
+
+ case S_XP:
+ c = S_IXP;
+ break;
+ }
+ esp->e_mode = c;
+ } else if (c == '*') {
+ expr(esp, 0);
+ esp->e_mode = S_DIR;
+ if (esp->e_addr & ~0xFF)
+ err('d');
+ if (more()) {
+ comma();
+ tcp = ip;
+ switch(admode(axs)) {
+ case S_X:
+ esp->e_mode = S_IX1;
+ break;
+
+ case S_S:
+ esp->e_mode = S_SP1;
+ break;
+
+ case S_XP:
+ esp->e_mode = S_IX1P;
+ break;
+
+ default:
+ ip = --tcp;
+ }
+ }
+ } else {
+ unget(c);
+ if ((esp->e_mode = admode(axs)) != 0) {
+ ;
+ } else {
+ expr(esp, 0);
+ espa = esp->e_base.e_ap;
+ espv = esp->e_addr;
+ if (more()) {
+ comma();
+ c = admode(axs);
+ if (esp->e_flag == 0 &&
+ espa == NULL &&
+ (espv & ~0xFF) == 0) {
+ switch(c) {
+ default:
+ aerr();
+
+ case S_X:
+ c = S_IX1;
+ break;
+
+ case S_S:
+ c = S_SP1;
+ break;
+
+ case S_XP:
+ c = S_IX1P;
+ break;
+ }
+ } else {
+ switch(c) {
+ default:
+ aerr();
+
+ case S_X:
+ c = S_IX2;
+ break;
+
+ case S_S:
+ c = S_SP2;
+ break;
+
+ case S_XP:
+ c = S_IX2P;
+ break;
+ }
+ }
+ esp->e_mode = c;
+ } else {
+ esp->e_mode = S_EXT;
+ }
+ }
+ }
+ return (esp->e_mode);
+}
+
+/*
+ * Enter admode() to search a specific addressing mode table
+ * for a match. Return the addressing value on a match or
+ * zero for no match.
+ */
+int
+admode(sp)
+register struct adsym *sp;
+{
+ register char *ptr;
+ register int i;
+ register char *ips;
+
+ ips = ip;
+ unget(getnb());
+
+ i = 0;
+ while ( *(ptr = &sp[i].a_str[0]) ) {
+ if (srch(ptr)) {
+ return(sp[i].a_val);
+ }
+ i++;
+ }
+ ip = ips;
+ return(0);
+}
+
+/*
+ * srch --- does string match ?
+ */
+int
+srch(str)
+register char *str;
+{
+ register char *ptr;
+ ptr = ip;
+
+ while (*ptr && *str) {
+ if(ccase[*ptr & 0x007F] != ccase[*str & 0x007F])
+ break;
+ ptr++;
+ str++;
+ }
+ if (ccase[*ptr & 0x007F] == ccase[*str & 0x007F]) {
+ ip = ptr;
+ return(1);
+ }
+
+ if (!*str)
+ if (any(*ptr," \t\n,];")) {
+ ip = ptr;
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * any --- does str contain c?
+ */
+int
+any(c,str)
+int c;
+char*str;
+{
+ while (*str)
+ if(*str++ == c)
+ return(1);
+ return(0);
+}
+
+struct adsym axs[] = { /* a, x, or s registers */
+ { "a", S_A },
+ { "x", S_X },
+ { "s", S_S },
+ { "x+", S_XP },
+ { "", 0x00 }
+};
--- /dev/null
+/* m08ext.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+char *cpu = "Motorola 68HC08";
+int hilo = 1;
+char *dsft = "asm";
--- /dev/null
+/* m08mch.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+/*
+ * Process a machine op.
+ */
+VOID
+machine(mp)
+struct mne *mp;
+{
+ register int op, t1, t2, type;
+ struct expr e1, e2, e3;
+ Addr_T espv;
+ struct area *espa;
+ char id[NCPS];
+ int c, v1;
+
+ clrexpr(&e1);
+ clrexpr(&e2);
+ clrexpr(&e3);
+ op = mp->m_valu;
+ type = mp->m_type;
+ switch (type) {
+
+ case S_SDP:
+ espa = NULL;
+ if (more()) {
+ expr(&e1, 0);
+ if (e1.e_flag == 0 && e1.e_base.e_ap == NULL) {
+ if (e1.e_addr) {
+ err('b');
+ }
+ }
+ if ((c = getnb()) == ',') {
+ getid(id, -1);
+ espa = alookup(id);
+ if (espa == NULL) {
+ err('u');
+ }
+ } else {
+ unget(c);
+ }
+ }
+ if (espa) {
+ outdp(espa, &e1);
+ } else {
+ outdp(dot.s_area, &e1);
+ }
+ lmode = SLIST;
+ break;
+
+ case S_INH:
+ outab(op);
+ break;
+
+ case S_BRA:
+ expr(&e1, 0);
+ outab(op);
+ if (mchpcr(&e1)) {
+ v1 = e1.e_addr - dot.s_addr - 1;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e1, R_PCR);
+ }
+ if (e1.e_mode != S_USER)
+ rerr();
+ break;
+
+ case S_TYP1:
+ t1 = addr(&e1);
+ if (t1 == S_A) {
+ outab(op+0x10);
+ break;
+ }
+ if (t1 == S_X) {
+ outab(op+0x20);
+ break;
+ }
+ if (t1 == S_DIR || t1 == S_EXT) {
+ outab(op);
+ outrb(&e1, R_PAG0);
+ break;
+ }
+ if (t1 == S_IX) {
+ outab(op+0x40);
+ break;
+ }
+ if (t1 == S_IX1 || t1 == S_IX2) {
+ if (chkindx(&e1))
+ aerr();
+ outab(op+0x30);
+ outrb(&e1, R_USGN);
+ break;
+ }
+ if (t1 == S_SP1 || t1 == S_SP2) {
+ if (chkindx(&e1))
+ aerr();
+ outab(0x9e);
+ outab(op+0x30);
+ outrb(&e1, R_USGN);
+ break;
+ }
+ aerr();
+ break;
+
+ case S_TYP2:
+ t1 = addr(&e1);
+ if (t1 == S_IMMED) {
+ if ((op == 0xA7) || (op == 0xAC) ||
+ (op == 0xAD) || (op == 0xAF))
+ aerr();
+ outab(op);
+ outrb(&e1, 0);
+ break;
+ }
+ if (t1 == S_DIR) {
+ outab(op+0x10);
+ outrb(&e1, R_PAG0);
+ break;
+ }
+ if (t1 == S_EXT) {
+ outab(op+0x20);
+ outrw(&e1, 0);
+ break;
+ }
+ if (t1 == S_IX) {
+ outab(op+0x50);
+ break;
+ }
+ if (t1 == S_IX1) {
+ outab(op+0x40);
+ outrb(&e1, R_USGN);
+ break;
+ }
+ if (t1 == S_IX2) {
+ outab(op+0x30);
+ outrw(&e1, 0);
+ break;
+ }
+ if (t1 == S_SP1) {
+ if (op == 0xAC || op == 0xAD)
+ aerr();
+ outab(0x9e);
+ outab(op+0x40);
+ outrb(&e1, R_USGN);
+ break;
+ }
+ if (t1 == S_SP2) {
+ if (op == 0xAC || op == 0xAD)
+ aerr();
+ outab(0x9e);
+ outab(op+0x30);
+ outrw(&e1, 0);
+ break;
+ }
+ aerr();
+ break;
+
+ case S_TYP3:
+ t1 = addr(&e1);
+ espv = e1.e_addr;
+ if (t1 != S_IMMED || espv & ~0x07)
+ aerr();
+ comma();
+ t2 = addr(&e2);
+ if (t2 != S_DIR)
+ aerr();
+ outab(op + 2*(espv&0x07));
+ outrb(&e2, R_PAG0);
+ break;
+
+ case S_TYP4:
+ t1 = addr(&e1);
+ espv = e1.e_addr;
+ if (t1 != S_IMMED || espv & ~0x07)
+ aerr();
+ comma();
+ t2 = addr(&e2);
+ if (t2 != S_DIR)
+ aerr();
+ comma();
+ expr(&e3, 0);
+ outab(op + 2*(espv&0x07));
+ outrb(&e2, R_PAG0);
+ if (mchpcr(&e3)) {
+ v1 = e3.e_addr - dot.s_addr - 1;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e3, R_PCR);
+ }
+ if (e3.e_mode != S_USER)
+ rerr();
+ break;
+
+ case S_TYPAI:
+ t1 = addr(&e1);
+ if (t1 == S_IMMED) {
+ outab(op);
+ if (e1.e_flag == 0 && e1.e_base.e_ap == NULL) {
+ v1 = e1.e_addr;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e1, 0);
+ }
+ break;
+ }
+ aerr();
+ break;
+
+ case S_TYPHX:
+ t1 = addr(&e1);
+ if (t1 == S_IMMED) {
+ if (op == 0x25)
+ aerr();
+ outab(op);
+ outrw(&e1, 0);
+ break;
+ }
+ if (t1 == S_DIR || t1 == S_EXT) {
+ outab(op | 0x10);
+ outrb(&e1, R_PAG0);
+ break;
+ }
+ aerr();
+ break;
+
+ case S_CBEQ:
+ t1 = addr(&e1);
+ comma();
+ expr(&e2, 0);
+ if (t1 == S_IMMED) {
+ outab(op);
+ outrb(&e1, 0);
+ } else
+ if (t1 == S_DIR || t1 == S_EXT) {
+ outab(op);
+ outrb(&e1, R_PAG0);
+ } else
+ if (t1 == S_IXP) {
+ outab(op+0x40);
+ } else
+ if (t1 == S_IX1P || t1 == S_IX2P) {
+ if (chkindx(&e1))
+ aerr();
+ outab(op+0x30);
+ outrb(&e1, R_USGN);
+ } else
+ if (t1 == S_SP1 || t1 == S_SP2) {
+ if (chkindx(&e1))
+ aerr();
+ outab(0x9E);
+ outab(op+0x30);
+ outrb(&e1, R_USGN);
+ } else {
+ aerr();
+ break;
+ }
+ if (mchpcr(&e2)) {
+ v1 = e2.e_addr - dot.s_addr - 1;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e2, R_PCR);
+ }
+ if (e2.e_mode != S_USER)
+ rerr();
+ break;
+
+ case S_CQAX:
+ t1 = addr(&e1);
+ if (t1 != S_IMMED)
+ aerr();
+ comma();
+ expr(&e2, 0);
+ outab(op);
+ outrb(&e1, 0);
+ if (mchpcr(&e2)) {
+ v1 = e2.e_addr - dot.s_addr - 1;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e2, R_PCR);
+ }
+ if (e2.e_mode != S_USER)
+ rerr();
+ break;
+
+ case S_DBNZ:
+ t1 = addr(&e1);
+ comma();
+ expr(&e2, 0);
+ if (t1 == S_DIR || t1 == S_EXT) {
+ outab(op);
+ outrb(&e1, R_PAG0);
+ } else
+ if (t1 == S_IX) {
+ outab(op+0x40);
+ } else
+ if (t1 == S_IX1 || t1 == S_IX2) {
+ if (chkindx(&e1))
+ aerr();
+ outab(op+0x30);
+ outrb(&e1, R_USGN);
+ } else
+ if (t1 == S_SP1 || t1 == S_SP2) {
+ if (chkindx(&e1))
+ aerr();
+ outab(0x9E);
+ outab(op+0x30);
+ outrb(&e1, R_USGN);
+ } else {
+ aerr();
+ break;
+ }
+ if (mchpcr(&e2)) {
+ v1 = e2.e_addr - dot.s_addr - 1;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e2, R_PCR);
+ }
+ if (e2.e_mode != S_USER)
+ rerr();
+ break;
+
+ case S_DZAX:
+ expr(&e1, 0);
+ outab(op);
+ if (mchpcr(&e1)) {
+ v1 = e1.e_addr - dot.s_addr - 1;
+ if ((v1 < -128) || (v1 > 127))
+ aerr();
+ outab(v1);
+ } else {
+ outrb(&e1, R_PCR);
+ }
+ if (e1.e_mode != S_USER)
+ rerr();
+ break;
+
+ case S_MOV:
+ t1 = addr(&e1);
+ if (t1 == S_IX1P || t1 == S_IX2P) {
+ if (chkindx(&e1))
+ aerr();
+ outab(op+0x10);
+ outrb(&e1, R_PAG0);
+ break;
+ }
+ comma();
+ t2 = addr(&e2);
+ if (t1 == S_IMMED) {
+ if (t2 == S_DIR || t2 == S_EXT) {
+ outab(op+0x20);
+ outrb(&e1, 0);
+ outrb(&e2, R_PAG0);
+ break;
+ }
+ }
+ if (t1 == S_DIR || t1 == S_EXT) {
+ if (t2 == S_DIR || t2 == S_EXT) {
+ outab(op);
+ outrb(&e1, R_PAG0);
+ outrb(&e2, R_PAG0);
+ break;
+ }
+ }
+ if (t1 == S_IXP) {
+ if (t2 == S_DIR || t2 == S_EXT) {
+ outab(op+0x30);
+ outrb(&e2, R_PAG0);
+ break;
+ }
+ }
+ aerr();
+ break;
+
+ default:
+ err('o');
+ }
+}
+
+/*
+ * Check index byte
+ */
+int
+chkindx(exp)
+struct expr *exp;
+{
+ if (exp->e_flag == 0 && exp->e_base.e_ap == NULL) {
+ if (exp->e_addr & ~0xFF) {
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/*
+ * Branch/Jump PCR Mode Check
+ */
+int
+mchpcr(esp)
+register struct expr *esp;
+{
+ if (esp->e_base.e_ap == dot.s_area) {
+ return(1);
+ }
+ if (esp->e_flag==0 && esp->e_base.e_ap==NULL) {
+ /*
+ * Absolute Destination
+ *
+ * Use the global symbol '.__.ABS.'
+ * of value zero and force the assembler
+ * to use this absolute constant as the
+ * base value for the relocation.
+ */
+ esp->e_flag = 1;
+ esp->e_base.e_sp = &sym[1];
+ }
+ return(0);
+}
+
+/*
+ * The next character must be a
+ * comma.
+ */
+int
+comma()
+{
+ if (getnb() != ',')
+ qerr();
+ return(1);
+}
+
+/*
+ * Machine specific initialization.
+ */
+VOID
+minit()
+{
+}
--- /dev/null
+/* m08pst.c */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include "asm.h"
+#include "m6808.h"
+
+struct mne mne[] = {
+
+ /* machine */
+
+ { NULL, ".setdp", S_SDP, 0, 0 },
+
+ /* system */
+
+ { NULL, "CON", S_ATYP, 0, A_CON },
+ { NULL, "OVR", S_ATYP, 0, A_OVR },
+ { NULL, "REL", S_ATYP, 0, A_REL },
+ { NULL, "ABS", S_ATYP, 0, A_ABS|A_OVR },
+ { NULL, "NOPAG", S_ATYP, 0, A_NOPAG },
+ { NULL, "PAG", S_ATYP, 0, A_PAG },
+
+ { NULL, ".byte", S_BYTE, 0, 1 },
+ { NULL, ".db", S_BYTE, 0, 1 },
+ { NULL, ".word", S_WORD, 0, 2 },
+ { NULL, ".dw", S_WORD, 0, 2 },
+ { NULL, ".ascii", S_ASCII, 0, 0 },
+ { NULL, ".asciz", S_ASCIZ, 0, 0 },
+ { NULL, ".blkb", S_BLK, 0, 1 },
+ { NULL, ".ds", S_BLK, 0, 1 },
+ { NULL, ".blkw", S_BLK, 0, 2 },
+ { NULL, ".page", S_PAGE, 0, 0 },
+ { NULL, ".title", S_TITLE, 0, 0 },
+ { NULL, ".sbttl", S_SBTL, 0, 0 },
+ { NULL, ".globl", S_GLOBL, 0, 0 },
+ { NULL, ".area", S_DAREA, 0, 0 },
+ { NULL, ".even", S_EVEN, 0, 0 },
+ { NULL, ".odd", S_ODD, 0, 0 },
+ { NULL, ".if", S_IF, 0, 0 },
+ { NULL, ".else", S_ELSE, 0, 0 },
+ { NULL, ".endif", S_ENDIF, 0, 0 },
+ { NULL, ".include", S_INCL, 0, 0 },
+ { NULL, ".radix", S_RADIX, 0, 0 },
+ { NULL, ".org", S_ORG, 0, 0 },
+ { NULL, ".module", S_MODUL, 0, 0 },
+ { NULL, ".ascis", S_ASCIS, 0, 0 },
+// { NULL, ".assume", S_ERROR, 0, 0 },
+// { NULL, ".error", S_ERROR, 0, 1 },
+
+ /* 68HC08 */
+
+ { NULL, "neg", S_TYP1, 0, 0x30 },
+ { NULL, "com", S_TYP1, 0, 0x33 },
+ { NULL, "lsr", S_TYP1, 0, 0x34 },
+ { NULL, "ror", S_TYP1, 0, 0x36 },
+ { NULL, "asr", S_TYP1, 0, 0x37 },
+ { NULL, "asl", S_TYP1, 0, 0x38 },
+ { NULL, "lsl", S_TYP1, 0, 0x38 },
+ { NULL, "rol", S_TYP1, 0, 0x39 },
+ { NULL, "dec", S_TYP1, 0, 0x3A },
+ { NULL, "inc", S_TYP1, 0, 0x3C },
+ { NULL, "tst", S_TYP1, 0, 0x3D },
+ { NULL, "clr", S_TYP1, 0, 0x3F },
+
+ { NULL, "sub", S_TYP2, 0, 0xA0 },
+ { NULL, "cmp", S_TYP2, 0, 0xA1 },
+ { NULL, "sbc", S_TYP2, 0, 0xA2 },
+ { NULL, "cpx", S_TYP2, 0, 0xA3 },
+ { NULL, "and", S_TYP2, 0, 0xA4 },
+ { NULL, "bit", S_TYP2, 0, 0xA5 },
+ { NULL, "lda", S_TYP2, 0, 0xA6 },
+ { NULL, "sta", S_TYP2, 0, 0xA7 },
+ { NULL, "eor", S_TYP2, 0, 0xA8 },
+ { NULL, "adc", S_TYP2, 0, 0xA9 },
+ { NULL, "ora", S_TYP2, 0, 0xAA },
+ { NULL, "add", S_TYP2, 0, 0xAB },
+ { NULL, "jmp", S_TYP2, 0, 0xAC },
+ { NULL, "jsr", S_TYP2, 0, 0xAD },
+ { NULL, "ldx", S_TYP2, 0, 0xAE },
+ { NULL, "stx", S_TYP2, 0, 0xAF },
+
+ { NULL, "bset", S_TYP3, 0, 0x10 },
+ { NULL, "bclr", S_TYP3, 0, 0x11 },
+
+ { NULL, "brset", S_TYP4, 0, 0x00 },
+ { NULL, "brclr", S_TYP4, 0, 0x01 },
+
+ { NULL, "ais", S_TYPAI, 0, 0xA7 },
+ { NULL, "aix", S_TYPAI, 0, 0xAF },
+
+ { NULL, "sthx", S_TYPHX, 0, 0x25 },
+ { NULL, "ldhx", S_TYPHX, 0, 0x45 },
+ { NULL, "cphx", S_TYPHX, 0, 0x65 },
+
+ { NULL, "cbeq", S_CBEQ, 0, 0x31 },
+ { NULL, "cbeqa", S_CQAX, 0, 0x41 },
+ { NULL, "cbeqx", S_CQAX, 0, 0x51 },
+
+ { NULL, "dbnz", S_DBNZ, 0, 0x3B },
+ { NULL, "dbnza", S_DZAX, 0, 0x4B },
+ { NULL, "dbnzx", S_DZAX, 0, 0x5B },
+
+ { NULL, "mov", S_MOV, 0, 0x4E },
+
+ { NULL, "bra", S_BRA, 0, 0x20 },
+ { NULL, "brn", S_BRA, 0, 0x21 },
+ { NULL, "bhi", S_BRA, 0, 0x22 },
+ { NULL, "bls", S_BRA, 0, 0x23 },
+ { NULL, "bcc", S_BRA, 0, 0x24 },
+ { NULL, "bhs", S_BRA, 0, 0x24 },
+ { NULL, "bcs", S_BRA, 0, 0x25 },
+ { NULL, "blo", S_BRA, 0, 0x25 },
+ { NULL, "bne", S_BRA, 0, 0x26 },
+ { NULL, "beq", S_BRA, 0, 0x27 },
+ { NULL, "bhcc", S_BRA, 0, 0x28 },
+ { NULL, "bhcs", S_BRA, 0, 0x29 },
+ { NULL, "bpl", S_BRA, 0, 0x2A },
+ { NULL, "bmi", S_BRA, 0, 0x2B },
+ { NULL, "bmc", S_BRA, 0, 0x2C },
+ { NULL, "bms", S_BRA, 0, 0x2D },
+ { NULL, "bil", S_BRA, 0, 0x2E },
+ { NULL, "bih", S_BRA, 0, 0x2F },
+ { NULL, "bge", S_BRA, 0, 0x90 },
+ { NULL, "blt", S_BRA, 0, 0x91 },
+ { NULL, "bgt", S_BRA, 0, 0x92 },
+ { NULL, "ble", S_BRA, 0, 0x93 },
+ { NULL, "bsr", S_BRA, 0, 0xAD },
+
+ { NULL, "nega", S_INH, 0, 0x40 },
+ { NULL, "mul", S_INH, 0, 0x42 },
+ { NULL, "coma", S_INH, 0, 0x43 },
+ { NULL, "lsra", S_INH, 0, 0x44 },
+ { NULL, "rora", S_INH, 0, 0x46 },
+ { NULL, "asra", S_INH, 0, 0x47 },
+ { NULL, "asla", S_INH, 0, 0x48 },
+ { NULL, "lsla", S_INH, 0, 0x48 },
+ { NULL, "rola", S_INH, 0, 0x49 },
+ { NULL, "deca", S_INH, 0, 0x4A },
+ { NULL, "inca", S_INH, 0, 0x4C },
+ { NULL, "tsta", S_INH, 0, 0x4D },
+ { NULL, "clra", S_INH, 0, 0x4F },
+
+ { NULL, "negx", S_INH, 0, 0x50 },
+ { NULL, "div", S_INH, 0, 0x52 },
+ { NULL, "comx", S_INH, 0, 0x53 },
+ { NULL, "lsrx", S_INH, 0, 0x54 },
+ { NULL, "rorx", S_INH, 0, 0x56 },
+ { NULL, "asrx", S_INH, 0, 0x57 },
+ { NULL, "aslx", S_INH, 0, 0x58 },
+ { NULL, "lslx", S_INH, 0, 0x58 },
+ { NULL, "rolx", S_INH, 0, 0x59 },
+ { NULL, "decx", S_INH, 0, 0x5A },
+ { NULL, "incx", S_INH, 0, 0x5C },
+ { NULL, "tstx", S_INH, 0, 0x5D },
+ { NULL, "clrx", S_INH, 0, 0x5F },
+
+ { NULL, "nsa", S_INH, 0, 0x62 },
+
+ { NULL, "daa", S_INH, 0, 0x72 },
+
+ { NULL, "rti", S_INH, 0, 0x80 },
+ { NULL, "rts", S_INH, 0, 0x81 },
+ { NULL, "swi", S_INH, 0, 0x83 },
+ { NULL, "tap", S_INH, 0, 0x84 },
+ { NULL, "tpa", S_INH, 0, 0x85 },
+ { NULL, "pula", S_INH, 0, 0x86 },
+ { NULL, "psha", S_INH, 0, 0x87 },
+ { NULL, "pulx", S_INH, 0, 0x88 },
+ { NULL, "pshx", S_INH, 0, 0x89 },
+ { NULL, "pulh", S_INH, 0, 0x8A },
+ { NULL, "pshh", S_INH, 0, 0x8B },
+ { NULL, "clrh", S_INH, 0, 0x8C },
+ { NULL, "stop", S_INH, 0, 0x8E },
+ { NULL, "wait", S_INH, 0, 0x8F },
+
+ { NULL, "txs", S_INH, 0, 0x94 },
+ { NULL, "tsx", S_INH, 0, 0x95 },
+ { NULL, "tax", S_INH, 0, 0x97 },
+ { NULL, "clc", S_INH, 0, 0x98 },
+ { NULL, "sec", S_INH, 0, 0x99 },
+ { NULL, "cli", S_INH, 0, 0x9A },
+ { NULL, "sei", S_INH, 0, 0x9B },
+ { NULL, "rsp", S_INH, 0, 0x9C },
+ { NULL, "nop", S_INH, 0, 0x9D },
+ { NULL, "txa", S_INH, S_END, 0x9F }
+};
--- /dev/null
+/* m6808.h */
+
+/*
+ * (C) Copyright 1993-2002
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+/*)BUILD
+ $(PROGRAM) = AS6808
+ $(INCLUDE) = {
+ ASM.H
+ M6808.H
+ }
+ $(FILES) = {
+ M08EXT.C
+ M08MCH.C
+ M08ADR.C
+ M08PST.C
+ ASMAIN.C
+ ASLEX.C
+ ASSYM.C
+ ASSUBR.C
+ ASEXPR.C
+ ASDATA.C
+ ASLIST.C
+ ASOUT.C
+ }
+ $(STACK) = 3000
+*/
+
+struct adsym
+{
+ char a_str[4]; /* addressing string */
+ int a_val; /* addressing mode value */
+};
+
+/*
+ * Addressing types
+ */
+#define S_IMMED 30
+#define S_DIR 31
+#define S_EXT 32
+#define S_IX 33
+#define S_IXP 34
+#define S_IX1 35
+#define S_IX1P 36
+#define S_IX2 37
+#define S_IX2P 38
+#define S_IS 39
+#define S_SP1 40
+#define S_SP2 41
+#define S_A 42
+#define S_X 43
+#define S_S 44
+#define S_XP 45
+
+/*
+ * Instruction types
+ */
+#define S_INH 60
+#define S_BRA 61
+#define S_TYP1 62
+#define S_TYP2 63
+#define S_TYP3 64
+#define S_TYP4 65
+#define S_TYPAI 66
+#define S_TYPHX 67
+#define S_CBEQ 68
+#define S_CQAX 69
+#define S_DBNZ 70
+#define S_DZAX 71
+#define S_MOV 72
+
+/*
+ * Set Direct Pointer
+ */
+#define S_SDP 80
+
+
+ /* machine dependent functions */
+
+#ifdef OTHERSYSTEM
+
+ /* m08adr.c */
+extern struct adsym axs[];
+extern int addr(struct expr *esp);
+extern int admode(struct adsym *sp);
+extern int any(int c, char *str);
+extern int srch(char *str);
+
+ /* m08mch.c */
+extern VOID machine(struct mne *mp);
+extern int chkindx(struct expr *exp);
+extern int mchpcr(struct expr *esp);
+extern VOID minit(void);
+extern int comma(void);
+
+#else
+
+ /* m08adr.c */
+extern struct adsym axs[];
+extern int addr();
+extern int admode();
+extern int any();
+extern int srch();
+
+ /* m08mch.c */
+extern VOID machine();
+extern int chkindx();
+extern int mchpcr();
+extern VOID minit();
+extern int comma();
+
+#endif
+
--- /dev/null
+/* strcmpi.c */
+
+/*
+ * Compare two strings ignoring case.
+ *
+ * Taken from GLIBC 2.2.5. Original code is copyrighted "Free
+ * Software Foundation" and published under the GNU Lesser General
+ * Public License.
+ *
+ */
+
+#include <ctype.h>
+#include "strcmpi.h"
+
+int as_strcmpi (const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2)
+ return 0;
+
+ do
+ {
+ c1 = tolower (*p1++);
+ c2 = tolower (*p2++);
+ if (c1 == '\0')
+ break;
+ }
+ while (c1 == c2);
+
+ return c1 - c2;
+}
+
--- /dev/null
+/* strcmpi.h */
+
+int as_strcmpi (const char *s1, const char *s2);