+2006-09-14 Maarten Brock <sourceforge.brock AT dse.nl>
+
+ * as/link,
+ * as/link/Makefile.in,
+ * as/link/z80/linkgbz80.dsp,
+ * as/link/z80/linkz80.dsp,
+ * configure,
+ * link,
+ * link/clean.mk,
+ * link/Makefile.in,
+ * link/README,
+ * link/z80,
+ * link/z80/aslink.h,
+ * link/z80/clean.mk,
+ * link/z80/conf.mk,
+ * link/z80/linkgbz80.dsp,
+ * link/z80/linkz80.dsp,
+ * link/z80/lkarea.c,
+ * link/z80/lkdata.c,
+ * link/z80/lkeval.c,
+ * link/z80/lkgb.c,
+ * link/z80/lkgg.c,
+ * link/z80/lkhead.c,
+ * link/z80/lkihx.c,
+ * link/z80/lklex.c,
+ * link/z80/lklibr.c,
+ * link/z80/lklist.c,
+ * link/z80/lkmain.c,
+ * link/z80/lkrloc.c,
+ * link/z80/lks19.c,
+ * link/z80/lksym.c,
+ * link/z80/Makefile.in,
+ * Makefile.in,
+ * sdcc.dsw: moved link/ to as/link/
+
2006-09-11 Maarten Brock <sourceforge.brock AT dse.nl>
* as/mcs51/i51mch.c (machine): fixed warning
endif
ifeq ($(OPT_DISABLE_Z80), 0)
-SDCC_ASLINK += as link
+SDCC_ASLINK += as as/link
endif
ifeq ($(OPT_DISABLE_UCSIM), 0)
--- /dev/null
+VPATH = @srcdir@
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+
+include $(top_builddir)Makefile.common
+
+PORTS = z80 gbz80
+
+all:
+ $(MAKE) -C z80 _link-z80 _link-gbz80 E=$(E) BUILDDIR=../../../bin/
+
+install: all
+ $(INSTALL) $(top_builddir)bin/link-z80$(EXEEXT) `echo $(DESTDIR)$(bindir)/link-z80$(EXEEXT)|sed '$(transform)'`
+ $(STRIP) `echo $(DESTDIR)$(bindir)/link-z80$(EXEEXT)|sed '$(transform)'`
+ $(INSTALL) $(top_builddir)bin/link-gbz80$(EXEEXT) `echo $(DESTDIR)$(bindir)/link-gbz80$(EXEEXT)|sed '$(transform)'`
+ $(STRIP) `echo $(DESTDIR)$(bindir)/link-gbz80$(EXEEXT)|sed '$(transform)'`
+
+uninstall:
+ cd $(DESTDIR)$(bindir); rm -f link-z80$(EXEEXT) link-gbz80$(EXEEXT)
+
+include $(srcdir)/clean.mk
--- /dev/null
+sdcc/link
+---------
+
+In gbdk the linker and assembler were split into seperate packages.
+
+For now I'm keeping that split, and leaving the mcs51 version as is.
+
+-- Michael
--- /dev/null
+clean:
+ $(MAKE) -C z80 clean
+
+distclean: clean
+ $(MAKE) -C z80 distclean
+ rm -f Makefile
--- /dev/null
+VPATH = @srcdir@
+srcdir = @srcdir@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+include $(top_builddir)Makefile.common
+
+OBJDIR = obj/$(EXT)
+
+SLIBSRC = NewAlloc.c
+
+SRC = lkarea.c lkdata.c lkeval.c lkhead.c lkihx.c lklex.c \
+ lklibr.c lklist.c lkmain.c lkrloc.c lks19.c lksym.c \
+ lkgb.c lkgg.c
+
+OBJS = $(SRC:%.c=$(OBJDIR)/%.o)
+SLIBOBJS = $(SLIBSRC:%.c=$(OBJDIR)/%.o)
+
+BINS = $(BUILDDIR)link$(EXT)$(EXEEXT)
+
+CFLAGS += $(CPPFLAGS) $(OPTS) -DINDEXLIB -DMLH_MAP -DUNIX -DSDK
+CFLAGS += -funsigned-char -DUNIX
+CFLAGS += -I$(top_builddir)as/$(PORT) -I$(SLIB)
+
+LDFLAGS += -lm $(EXTRALIBS)
+
+all: $(BINS)
+
+$(BINS): $(OBJDIR) $(OBJS) $(SLIBOBJS)
+ $(CC) -g -o $(BINS) $(OBJS) $(SLIBOBJS) $(LDFLAGS)
+
+$(OBJDIR):
+ mkdir -p $(OBJDIR)
+
+$(OBJDIR)/%.o: %.c
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(OBJDIR)/%.o: $(SLIB)/%.c
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+_link-z80:
+ $(MAKE) EXT=-z80$(E) PORT=z80
+
+_link-gbz80:
+ $(MAKE) EXT=-gbz80$(E) OPTS=-DGAMEBOY PORT=z80
+
+include $(srcdir)/clean.mk
--- /dev/null
+/* aslink.h */
+
+/*
+ * (C) Copyright 1989-1996
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+/*
+ * Extensions: P. Felber
+ */
+#define VERSION "V01.75"
+
+/*
+ * Case Sensitivity Flag
+ */
+#define CASE_SENSITIVE 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.
+ */
+
+#ifdef SDK
+#define NCPS 80 /* characters per symbol. Used to be 32... */
+#else /* SDK */
+#define NCPS 8 /* characters per symbol */
+#endif /* SDK */
+/* #define NCPS 32 */ /* characters per symbol */
+#define NDATA 16 /* actual data */
+#define NINPUT PATH_MAX /* Input buffer size */
+#define NHASH 64 /* Buckets in hash table */
+#define HMASK 077 /* Hash mask */
+#define NLPP 60 /* Lines per page */
+#define NTXT 16 /* T values */
+#define FILSPC PATH_MAX /* File spec length */
+
+/*
+ * The "R_" relocation constants define values used in
+ * generating the assembler relocation output data for
+ * areas, symbols, and code.
+ *
+ *
+ * Relocation types.
+ *
+ * 7 6 5 4 3 2 1 0
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+#define R_WORD 0x00 /* 16 bit */
+#define R_BYTE 0x01 /* 8 bit */
+
+#define R_AREA 0x00 /* Base type */
+#define R_SYM 0x02
+
+#define R_NORM 0x00 /* PC adjust */
+#define R_PCR 0x04
+
+#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */
+#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */
+
+#define R_SGND 0x00 /* Signed value */
+#define R_USGN 0x10 /* Unsigned value */
+
+#define R_NOPAG 0x00 /* Page Mode */
+#define R_PAG0 0x20 /* Page '0' */
+#define R_PAG 0x40 /* Page 'nnn' */
+
+/*
+ * Valid for R_BYT2:
+ */
+#define R_LSB 0x00 /* output low byte */
+#define R_MSB 0x80 /* output high byte */
+
+/*
+ * Global symbol types.
+ */
+#define S_REF 1 /* referenced */
+#define S_DEF 2 /* defined */
+
+/*
+ * Area types
+ */
+#define A_CON 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 */
+
+/*
+ * File types
+ */
+#define F_INV 0 /* invalid */
+#define F_STD 1 /* stdin */
+#define F_LNK 2 /* File.lnk */
+#define F_REL 3 /* File.rel */
+#ifdef SDK
+#define F_CMD 4 /* Command line */
+#endif /* SDK */
+
+#ifdef GAMEBOY
+/*
+ * Multiple banks support
+ */
+extern int nb_rom_banks;
+extern int nb_ram_banks;
+extern int current_rom_bank;
+extern int mbc_type;
+extern char cart_name[];
+/*
+ * ROM patching support
+ */
+typedef struct _patch {
+ unsigned int addr;
+ unsigned char value;
+ struct _patch *next;
+} patch;
+extern patch* patches;
+#endif /* GAMEBOY */
+/*
+ * General assembler address type
+ */
+typedef unsigned int Addr_T;
+
+/*
+ * The structures of head, area, areax, and sym are created
+ * as the REL files are read during the first pass of the
+ * linker. The struct head is created upon encountering a
+ * H directive in the REL file. The structure contains a
+ * link to a link file structure (struct lfile) which describes
+ * the file containing the H directive, the number of data/code
+ * areas contained in this header segment, the number of
+ * symbols referenced/defined in this header segment, a pointer
+ * to an array of pointers to areax structures (struct areax)
+ * created as each A directive is read, and a pointer to an
+ * array of pointers to symbol structures (struct sym) for
+ * all referenced/defined symbols. As H directives are read
+ * from the REL files a linked list of head structures is
+ * created by placing a link to the new head structure
+ * in the previous head structure.
+ */
+struct head
+{
+ struct head *h_hp; /* Header link */
+ struct lfile *h_lfile;/* Associated file */
+ int h_narea; /* # of areas */
+ struct areax **a_list; /* Area list */
+ int h_nglob; /* # of global symbols */
+ struct sym **s_list; /* Globle symbol list */
+ char m_id[NCPS]; /* Module name */
+};
+
+/*
+ * A structure area is created for each 'unique' data/code
+ * area definition found as the REL files are read. The
+ * struct area contains the name of the area, a flag byte
+ * which contains the area attributes (REL/CON/OVR/ABS),
+ * an area subtype (not used in this assembler), and the
+ * area base address and total size which will be filled
+ * in at the end of the first pass through the REL files.
+ * As A directives are read from the REL files a linked
+ * list of unique area structures is created by placing a
+ * link to the new area structure in the previous area structure.
+ */
+struct area
+{
+ struct area *a_ap; /* Area link */
+ struct areax *a_axp; /* Area extension link */
+ Addr_T a_addr; /* Beginning address of area */
+ Addr_T a_size; /* Total size of the area */
+ char a_type; /* Area subtype */
+ char a_flag; /* Flag byte */
+ char a_id[NCPS]; /* Name */
+};
+
+/*
+ * An areax structure is created for every A directive found
+ * while reading the REL files. The struct areax contains a
+ * link to the 'unique' area structure referenced by the A
+ * directive and to the head structure this area segment is
+ * a part of. The size of this area segment as read from the
+ * A directive is placed in the areax structure. The beginning
+ * address of this segment will be filled in at the end of the
+ * first pass through the REL files. As A directives are read
+ * from the REL files a linked list of areax structures is
+ * created for each unique area. The final areax linked
+ * list has at its head the 'unique' area structure linked
+ * to the linked areax structures (one areax structure for
+ * each A directive for this area).
+ */
+struct areax
+{
+ struct areax *a_axp; /* Area extension link */
+ struct area *a_bap; /* Base area link */
+ struct head *a_bhp; /* Base header link */
+ Addr_T a_addr; /* Beginning address of section */
+ Addr_T a_size; /* Size of the area in section */
+};
+
+/*
+ * A sym structure is created for every unique symbol
+ * referenced/defined while reading the REL files. The
+ * struct sym contains the symbol's name, a flag value
+ * (not used in this linker), a symbol type denoting
+ * referenced/defined, and an address which is loaded
+ * with the relative address within the area in which
+ * the symbol was defined. The sym structure also
+ * contains a link to the area where the symbol was defined.
+ * The sym structures are linked into linked lists using
+ * the symbol link element.
+ */
+struct sym
+{
+ struct sym *s_sp; /* Symbol link */
+ struct areax *s_axp; /* Symbol area link */
+ char s_type; /* Symbol subtype */
+ char s_flag; /* Flag byte */
+ Addr_T s_addr; /* Address */
+ char s_id[NCPS]; /* Name */
+};
+
+/*
+ * The structure lfile contains a pointer to a
+ * file specification string, the file type, and
+ * a link to the next lfile structure.
+ */
+struct lfile
+{
+ struct lfile *f_flp; /* lfile link */
+ int f_type; /* File type */
+ char *f_idp; /* Pointer to file spec */
+};
+
+/*
+ * The struct base contains a pointer to a
+ * base definition string and a link to the next
+ * base structure.
+ */
+struct base
+{
+ struct base *b_base; /* Base link */
+ char *b_strp; /* String pointer */
+};
+
+/*
+ * The struct globl contains a pointer to a
+ * global definition string and a link to the next
+ * global structure.
+ */
+struct globl
+{
+ struct globl *g_globl; /* Global link */
+ char *g_strp; /* String pointer */
+};
+
+/*
+ * A structure sdp is created for each 'unique' paged
+ * area definition found as the REL files are read.
+ * As P directives are read from the REL files a linked
+ * list of unique sdp structures is created by placing a
+ * link to the new sdp structure in the previous area structure.
+ */
+struct sdp
+{
+ struct area *s_area; /* Paged Area link */
+ struct areax *s_areax; /* Paged Area Extension Link */
+ Addr_T s_addr; /* Page address offset */
+};
+
+/*
+ * The structure rerr is loaded with the information
+ * required to report an error during the linking
+ * process. The structure contains an index value
+ * which selects the areax structure from the header
+ * areax structure list, a mode value which selects
+ * symbol or area relocation, the base address in the
+ * area section, an area/symbol list index value, and
+ * an area/symbol offset value.
+ */
+struct rerr
+{
+ int aindex; /* Linking area */
+ int mode; /* Relocation mode */
+ Addr_T rtbase; /* Base address in section */
+ int rindex; /* Area/Symbol reloaction index */
+ Addr_T rval; /* Area/Symbol offset value */
+};
+
+/*
+ * The structure lbpath is created for each library
+ * path specification input by the -k option. The
+ * lbpath structures are linked into a list using
+ * the next link element.
+ */
+struct lbpath {
+ struct lbpath *next;
+ char *path;
+};
+
+/*
+ * The structure lbname is created for all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file. The element path points to
+ * the path string, element libfil points to the library
+ * file string, and the element libspc is the concatenation
+ * of the valid path and libfil strings.
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ *
+ * Each library file contains a list of object files
+ * that are contained in the particular library. e.g.:
+ *
+ * \iolib\termio
+ * \inilib\termio
+ *
+ * Only one specification per line is allowed.
+ */
+struct lbname {
+ struct lbname *next;
+ char *path;
+ char *libfil;
+ char *libspc;
+};
+
+/*
+ * The function fndsym() searches through all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file for a symbol definition.
+ *
+ * The structure lbfile is created for the first library
+ * object file which contains the definition for the
+ * specified undefined symbol.
+ *
+ * The element libspc points to the library file path specification
+ * and element relfil points to the object file specification string.
+ * The element filspc is the complete path/file specification for
+ * the library file to be imported into the linker. The
+ * file specicifation may be formed in one of two ways:
+ *
+ * (1) If the library file contained an absolute
+ * path/file specification then this becomes filspc.
+ * (i.e. C:\...)
+ *
+ * (2) If the library file contains a relative path/file
+ * specification then the concatenation of the path
+ * and this file specification becomes filspc.
+ * (i.e. \...)
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ */
+struct lbfile {
+ struct lbfile *next;
+ char *libspc;
+ char *relfil;
+ char *filspc;
+ 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 lk_getline() to read
+ * asmlnk commands from
+ * (1) the standard input or
+ * (2) or a command file
+ * and to read the REL files
+ * sequentially as defined by the
+ * asmlnk input commands.
+ *
+ * The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ */
+extern struct lfile *cfp; /* The pointer *cfp points to the
+ * current lfile structure
+ */
+extern struct lfile *startp;/* asmlnk startup file structure
+ */
+extern struct lfile *linkp; /* pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ */
+extern struct lfile *lfp; /* pointer to current lfile structure
+ * being processed by parse()
+ */
+extern struct head *headp; /* The pointer to the first
+ * head structure of a linked list
+ */
+extern struct head *hp; /* Pointer to the current
+ * head structure
+ */
+extern struct area *areap; /* The pointer to the first
+ * area structure of a linked list
+ */
+extern struct area *ap; /* Pointer to the current
+ * area structure
+ */
+extern struct areax *axp; /* Pointer to the current
+ * areax structure
+ */
+extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
+ * linked symbol lists
+ */
+extern struct base *basep; /* The pointer to the first
+ * base structure
+ */
+extern struct base *bsp; /* Pointer to the current
+ * base structure
+ */
+extern struct globl *globlp;/* The pointer to the first
+ * globl structure
+ */
+extern struct globl *gsp; /* Pointer to the current
+ * globl structure
+ */
+extern struct sdp sdp; /* Base Paged structure
+ */
+extern struct rerr rerr; /* Structure containing the
+ * linker error information
+ */
+extern FILE *ofp; /* Linker Output file handle
+ */
+extern FILE *mfp; /* Map output file handle
+ */
+extern FILE *rfp; /* File handle for output
+ * address relocated ASxxxx
+ * listing file
+ */
+extern FILE *sfp; /* The file handle sfp points to the
+ * currently open file
+ */
+extern FILE *tfp; /* File handle for input
+ * ASxxxx listing file
+ */
+extern int oflag; /* Output file type flag
+ */
+extern int mflag; /* Map output flag
+ */
+#ifdef SDK
+extern int symflag; /* no$gmb .sym output flag
+ */
+#endif
+extern int xflag; /* Map file radix type flag
+ */
+extern int pflag; /* print linker command file flag
+ */
+extern int uflag; /* Listing relocation flag
+ */
+extern int radix; /* current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ */
+extern int line; /* current line number
+ */
+extern int page; /* current page number
+ */
+extern int lop; /* current line number on page
+ */
+extern int pass; /* linker pass number
+ */
+extern int rtcnt; /* count of elements in the
+ * rtval[] and rtflg[] arrays
+ */
+extern Addr_T rtval[]; /* data associated with relocation
+ */
+extern int rtflg[]; /* indicates if rtval[] value is
+ * to be sent to the output file.
+ * (always set in this linker)
+ */
+extern int hilo; /* REL file byte ordering
+ */
+extern int gline; /* LST file relocation active
+ * for current line
+ */
+extern int gcntr; /* LST file relocation active
+ * counter
+ */
+extern struct lbpath *lbphead; /* pointer to the first
+ * library path structure
+ */
+extern struct lbname *lbnhead; /* pointer to the first
+ * library name structure
+ */
+extern struct lbfile *lbfhead; /* pointer to the first
+ * library file structure
+ */
+
+/* C Library function definitions */
+/* for reference only
+extern VOID exit();
+extern int fclose();
+extern char * fgets();
+extern FILE * fopen();
+extern int fprintf();
+extern VOID free();
+extern VOID * malloc();
+extern char putc();
+extern char * strcpy();
+extern int strlen();
+extern char * strncpy();
+*/
+
+/* Program function definitions */
+
+/* lkmain.c */
+extern FILE * afile();
+extern VOID bassav();
+extern VOID gblsav();
+extern VOID link();
+extern VOID lkexit();
+extern int main();
+extern VOID map();
+#ifdef SDK
+extern VOID sym();
+#endif
+extern int parse();
+extern VOID setbas();
+extern VOID setgbl();
+extern VOID usage();
+
+/* lklex.c */
+extern char endline();
+extern char get();
+extern VOID getfid();
+extern VOID getid();
+extern int lk_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 adw_w();
+extern Addr_T adw_hi();
+extern Addr_T adw_lo();
+extern Addr_T evword();
+extern VOID rele();
+extern VOID reloc();
+extern VOID relt();
+extern VOID relr();
+extern VOID relp();
+extern VOID relerr();
+extern char * errmsg[];
+extern VOID errdmp();
+extern VOID relerp();
+extern VOID erpdmp();
+extern VOID prntval();
+
+/* lklibr.c */
+extern 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();
+
+/* lkgb.h */
+VOID gb(int in);
+VOID gg(int in);
+
--- /dev/null
+# Deleting all files created by building the program
+# --------------------------------------------------
+include $(top_builddir)Makefile.common
+
+clean:
+ rm -f *core *[%~] *.[oa]
+ rm -f .[a-z]*~
+ rm -f $(top_builddir)bin/link-z80$(EXEEXT) link-z80$(EXEEXT) \
+ $(top_builddir)bin/link-gbz80$(EXEEXT) link-gbz80$(EXEEXT)
+ rm -f *.dep
+ rm -rf obj
+
+# Deleting all files created by configuring or building the program
+# -----------------------------------------------------------------
+distclean: clean
+ rm -f Makefile
+
+# 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
+# Deleting all files created by building the program
+# --------------------------------------------------
+clean:
+ rm -f *core *[%~] *.[oa]
+ rm -f .[a-z]*~
+ rm -f $(top_builddir)bin/link-z80 link-z80
+
+
+# Deleting all files created by configuring or building the program
+# -----------------------------------------------------------------
+distclean: clean
+ rm -f Makefile *.dep
+
+
+# Like clean but some files may still exist
+# -----------------------------------------
+mostlyclean: clean
+
+
+# Deleting everything that can reconstructed by this Makefile. It deletes
+# everything deleted by distclean plus files created by bison, etc.
+# -----------------------------------------------------------------------
+realclean: distclean
--- /dev/null
+# Microsoft Developer Studio Project File - Name="linkgbz80" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=linkgbz80 - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "linkgbz80.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "linkgbz80.mak" CFG="linkgbz80 - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "linkgbz80 - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "linkgbz80 - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF "$(CFG)" == "linkgbz80 - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release_gbz80"\r
+# PROP BASE Intermediate_Dir "Release_gbz80"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release_gbz80"\r
+# PROP Intermediate_Dir "Release_gbz80"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\link-gbz80.exe"\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF "$(CFG)" == "linkgbz80 - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug_gbz80"\r
+# PROP BASE Intermediate_Dir "Debug_gbz80"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug_gbz80"\r
+# PROP Intermediate_Dir "Debug_gbz80"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\link-gbz80.exe" /pdbtype:sept\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "linkgbz80 - Win32 Release"\r
+# Name "linkgbz80 - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\lkarea.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkdata.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkeval.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkgb.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkgg.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkhead.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkihx.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklex.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklibr.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklist.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkmain.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkrloc.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lks19.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lksym.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\aslink.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
--- /dev/null
+# Microsoft Developer Studio Project File - Name="linkz80" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=linkz80 - Win32 Debug\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "linkz80.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "linkz80.mak" CFG="linkz80 - Win32 Debug"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "linkz80 - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "linkz80 - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF "$(CFG)" == "linkz80 - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release_z80"\r
+# PROP BASE Intermediate_Dir "Release_z80"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "Release_z80"\r
+# PROP Intermediate_Dir "Release_z80"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\link-z80.exe"\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF "$(CFG)" == "linkz80 - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "Debug_z80"\r
+# PROP BASE Intermediate_Dir "Debug_z80"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "Debug_z80"\r
+# PROP Intermediate_Dir "Debug_z80"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\link-z80.exe" /pdbtype:sept\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "linkz80 - Win32 Release"\r
+# Name "linkz80 - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\lkarea.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkdata.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkeval.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkgb.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkgg.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkhead.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkihx.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklex.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklibr.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lklist.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkmain.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lkrloc.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lks19.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\lksym.c\r
+# ADD CPP /D "SDK" /D "INDEXLIB"\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\aslink.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# End Group\r
+# End Target\r
+# End Project\r
--- /dev/null
+/* lkarea.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "aslink.h"
+
+/*)Module lkarea.c
+ *
+ * The module lkarea.c contains the functions which
+ * create and link together all area definitions read
+ * from the .rel file(s).
+ *
+ * lkarea.c contains the following functions:
+ * VOID lnkarea()
+ * VOID lnksect()
+ * VOID lkparea()
+ * VOID newarea()
+ *
+ * lkarea.c contains no global variables.
+ */
+
+/*)Function VOID newarea()
+ *
+ * The function newarea() creates and/or modifies area
+ * and areax structures for each A directive read from
+ * the .rel file(s). The function lkparea() is called
+ * to find tha area structure associated with this name.
+ * If the area does not yet exist then a new area
+ * structure is created and linked to any existing
+ * linked area structures. The area flags are copied
+ * into the area flag variable. For each occurence of
+ * an A directive an areax structure is created and
+ * linked to the areax structures associated with this
+ * area. The size of this area section is placed into
+ * the areax structure. The flag value for all subsequent
+ * area definitions for the same area are compared and
+ * flagged as an error if they are not identical.
+ * The areax structure created for every occurence of
+ * an A directive is loaded with a pointer to the base
+ * area structure and a pointer to the associated
+ * head structure. And finally, a pointer to this
+ * areax structure is loaded into the list of areax
+ * structures in the head structure. Refer to lkdata.c
+ * for details of the structures and their linkage.
+ *
+ * local variables:
+ * areax **halp pointer to an array of pointers
+ * int i counter, loop variable, value
+ * char id[] id string
+ * int narea number of areas in this head structure
+ * areax * taxp pointer to an areax structure
+ * to areax structures
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * areax *axp Pointer to the current
+ * areax structure
+ * head *hp Pointer to the current
+ * head structure
+ * int lkerr error flag
+ *
+ * functions called:
+ * Addr_T eval() lkeval.c
+ * VOID exit() c_library
+ * int fprintf() c_library
+ * VOID getid() lklex.c
+ * VOID lkparea() lkarea.c
+ * VOID skip() lklex.c
+ *
+ * side effects:
+ * The area and areax structures are created and
+ * linked with the appropriate head structures.
+ * Failure to allocate area or areax structure
+ * space will terminate the linker. Other internal
+ * errors most likely caused by corrupted .rel
+ * files will also terminate the linker.
+ */
+
+/*
+ * Create an area entry.
+ *
+ * A xxxxxx size nnnn flags mm
+ * | | |
+ * | | `-- ap->a_flag
+ * | `------------- axp->a_size
+ * `------------------------- ap->a_id
+ *
+ */
+VOID
+newarea()
+{
+ register int i, narea;
+ struct areax *taxp;
+ struct areax **halp;
+ char id[NCPS];
+
+ /*
+ * Create Area entry
+ */
+ getid(id, -1);
+ lkparea(id);
+ /*
+ * Evaluate area size
+ */
+ skip(-1);
+ axp->a_size = eval();
+ /*
+ * Evaluate flags
+ */
+ skip(-1);
+ i = 0;
+ taxp = ap->a_axp;
+ while (taxp->a_axp) {
+ ++i;
+ taxp = taxp->a_axp;
+ }
+ if (i == 0) {
+ ap->a_flag = eval();
+ } else {
+ i = eval();
+ if (i && (ap->a_flag != i)) {
+ fprintf(stderr, "Conflicting flags in area %.8s\n", id);
+ lkerr++;
+ }
+ }
+ /*
+ * Place pointer in header area list
+ */
+ if (headp == NULL) {
+ fprintf(stderr, "No header defined\n");
+ lkexit(1);
+ }
+ narea = hp->h_narea;
+ halp = hp->a_list;
+ for (i=0; i < narea ;++i) {
+ if (halp[i] == NULL) {
+ halp[i] = taxp;
+ return;
+ }
+ }
+ fprintf(stderr, "Header area list overflow\n");
+ lkexit(1);
+}
+
+/*)Function VOID lkparea(id)
+ *
+ * char * id pointer to the area name string
+ *
+ * The function lkparea() searches the linked area structures
+ * for a name match. If the name is not found then an area
+ * structure is created. An areax structure is created and
+ * appended to the areax structures linked to the area structure.
+ * The associated base area and head structure pointers are
+ * loaded into the areax structure.
+ *
+ * local variables:
+ * area * tap pointer to an area structure
+ * areax * taxp pointer to an areax structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ * areax *axp Pointer to the current
+ * areax structure
+ *
+ * functions called:
+ * VOID * new() lksym()
+ * char * strcpy() c_library
+ * int symeq() lksym.c
+ *
+ * side effects:
+ * Area and/or areax structures are created.
+ * Failure to allocate space for created structures
+ * will terminate the linker.
+ */
+
+VOID
+lkparea(id)
+char *id;
+{
+ register struct area *tap;
+ register struct areax *taxp;
+
+ ap = areap;
+ axp = (struct areax *) new (sizeof(struct areax));
+ while (ap) {
+ if (symeq(id, ap->a_id)) {
+ taxp = ap->a_axp;
+ while (taxp->a_axp)
+ taxp = taxp->a_axp;
+ taxp->a_axp = axp;
+ axp->a_bap = ap;
+ axp->a_bhp = hp;
+ return;
+ }
+ ap = ap->a_ap;
+ }
+ ap = (struct area *) new (sizeof(struct area));
+ if (areap == NULL) {
+ areap = ap;
+ } else {
+ tap = areap;
+ while (tap->a_ap)
+ tap = tap->a_ap;
+ tap->a_ap = ap;
+ }
+ ap->a_axp = axp;
+ axp->a_bap = ap;
+ axp->a_bhp = hp;
+ strncpy(ap->a_id, id, NCPS);
+}
+
+/*)Function VOID lnkarea()
+ *
+ * The function lnkarea() resolves all area addresses.
+ * The function evaluates each area structure (and all
+ * the associated areax structures) in sequence. The
+ * linking process supports four (4) possible area types:
+ *
+ * ABS/OVR - All sections (each individual areax
+ * section) starts at the identical base
+ * area address overlaying all other
+ * areax sections for this area. The
+ * size of the area is largest of the area
+ * sections.
+ *
+ * ABS/CON - All sections (each individual areax
+ * section) are concatenated with the
+ * first section starting at the base
+ * area address. The size of the area
+ * is the sum of the section sizes.
+ *
+ * NOTE: Multiple absolute (ABS) areas are
+ * never concatenated with each other,
+ * thus absolute area A and absolute area
+ * B will overlay each other if they begin
+ * at the same location (the default is
+ * always address 0 for absolute areas).
+ *
+ * REL/OVR - All sections (each individual areax
+ * section) starts at the identical base
+ * area address overlaying all other
+ * areax sections for this area. The
+ * size of the area is largest of the area
+ * sections.
+ *
+ * REL/CON - All sections (each individual areax
+ * section) are concatenated with the
+ * first section starting at the base
+ * area address. The size of the area
+ * is the sum of the section sizes.
+ *
+ * NOTE: Relocatable (REL) areas ae always concatenated
+ * with each other, thus relocatable area B
+ * (defined after area A) will follow
+ * relocatable area A independent of the
+ * starting address of area A. Within a
+ * specific area each areax section may be
+ * overlayed or concatenated with other
+ * areax sections.
+ *
+ *
+ * If a base address for an area is specified then the
+ * area will start at that address. Any relocatable
+ * areas defined subsequently will be concatenated to the
+ * previous relocatable area if it does not have a base
+ * address specified.
+ *
+ * The names s_<areaname> and l_<areaname> are created to
+ * define the starting address and length of each area.
+ *
+ * local variables:
+ * Addr_T rloc ;current relocation address
+ * char temp[] ;temporary string
+ * struct symbol *sp ;symbol structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID lnksect() lkarea.c
+ * symbol *lkpsym() lksysm.c
+ * char * strncpy() c_library
+ * int symeq() lksysm.c
+ *
+ * side effects:
+ * All area and areax addresses and sizes are
+ * determined and saved in their respective
+ * structures.
+ */
+
+/*
+ * Resolve all area addresses.
+ */
+VOID
+lnkarea()
+{
+ register int rloc;
+ char temp[NCPS];
+ struct sym *sp;
+
+ rloc = 0;
+ ap = areap;
+ while (ap) {
+ if (ap->a_flag&A_ABS) {
+ /*
+ * Absolute sections
+ */
+ lnksect(ap);
+ } else {
+ /*
+ * Relocatable sections
+ */
+ if (ap->a_addr == 0)
+ ap->a_addr = rloc;
+ lnksect(ap);
+ rloc = ap->a_addr + ap->a_size;
+ }
+
+ /*
+ * Create symbols called:
+ * s_<areaname> the start address of the area
+ * l_<areaname> the length of the area
+ */
+
+ if (! symeq(ap->a_id, _abs_)) {
+ strncpy(temp+2,ap->a_id,NCPS-2);
+ *(temp+1) = '_';
+
+ *temp = 's';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_addr;
+ sp->s_axp = NULL;
+ sp->s_type |= S_DEF;
+
+ *temp = 'l';
+ sp = lkpsym(temp, 1);
+ sp->s_addr = ap->a_size;
+ sp->s_axp = NULL;
+ sp->s_type |= S_DEF;
+ }
+ ap = ap->a_ap;
+ }
+}
+
+/*)Function VOID lnksect()
+ *
+ * area * tap pointer to an area structure
+ *
+ * The function lnksect() is the function called by
+ * lnkarea() to resolve the areax addresses. Refer
+ * to the function lnkarea() for more detail. Pageing
+ * boundary and length errors will be reported by this
+ * function.
+ *
+ * local variables:
+ * Addr_T size size of area
+ * Addr_T addr address of area
+ * areax * taxp pointer to an areax structure
+ *
+ * global variables:
+ * int lkerr error flag
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * All area and areax addresses and sizes area determined
+ * and linked into the structures.
+ */
+
+VOID
+lnksect(tap)
+register struct area *tap;
+{
+ register Addr_T size, addr;
+ register struct areax *taxp;
+
+ size = 0;
+ addr = tap->a_addr;
+ if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
+ lkerr++;
+ }
+ taxp = tap->a_axp;
+ if (tap->a_flag&A_OVR) {
+ /*
+ * Overlayed sections
+ */
+ while (taxp) {
+ taxp->a_addr = addr;
+ if (taxp->a_size > size)
+ size = taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ } else {
+ /*
+ * Concatenated sections
+ */
+ while (taxp) {
+ taxp->a_addr = addr;
+ addr += taxp->a_size;
+ size += taxp->a_size;
+ taxp = taxp->a_axp;
+ }
+ }
+ tap->a_size = size;
+ if ((tap->a_flag&A_PAG) && (size > 256)) {
+ fprintf(stderr,
+ "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
+ lkerr++;
+ }
+}
--- /dev/null
+/* lkdata.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+//#include <alloc.h>
+#include "aslink.h"
+
+/*)Module lkdata.c
+ *
+ * The module lkdata contains the global variables
+ * and structures used in the linker aslink.
+ */
+
+/*
+ * Definitions for all Global Variables
+ */
+
+char *_abs_ = { ". .ABS." };
+
+int lkerr; /* Linker error flag
+ */
+char *ip; /* Pointer into the REL file text line in ib[]
+ */
+char ib[NINPUT]; /* REL file text line
+ */
+char *rp; /* pointer into the LST file
+ * text line in rb[]
+ */
+char rb[NINPUT]; /* LST file text line being
+ * address relocated
+ */
+
+char sdccopt[NINPUT]="";
+char sdccopt_module[NINPUT]="";
+char curr_module[NINPUT]="";
+
+int oflag; /* Output file type flag
+ */
+int mflag; /* Map output flag
+ */
+#ifdef SDK
+int symflag; /* no$gmb .sym output flag
+ */
+#endif
+int xflag; /* Map file radix type flag
+ */
+int pflag; /* print linker command file flag
+ */
+int uflag; /* Listing relocation flag
+ */
+int radix; /* current number conversion radix:
+ * 2 (binary), 8 (octal), 10 (decimal),
+ * 16 (hexadecimal)
+ */
+int line; /* current line number
+ */
+int page; /* current page number
+ */
+int lop; /* current line number on page
+ */
+int pass; /* linker pass number
+ */
+int rtcnt; /* count of elements in the
+ * rtval[] and rtflg[] arrays
+ */
+Addr_T rtval[NTXT]; /* data associated with relocation
+ */
+int rtflg[NTXT]; /* indicates if rtval[] value is
+ * to be sent to the output file.
+ * (always set in this linker)
+ */
+int hilo; /* REL file byte ordering
+ */
+int gline; /* LST file relocation active
+ * for current line
+ */
+int gcntr; /* LST file relocation active
+ * counter
+ */
+
+/*
+ * The structure lfile contains a pointer to a
+ * file specification string, the file type, and
+ * a link to the next lfile structure.
+ *
+ * struct lfile
+ * {
+ * struct lfile *f_flp; lfile link
+ * int f_type; File type
+ * char *f_idp; Pointer to file spec
+ * };
+ */
+struct lfile *filep; /* The pointers (lfile *) filep,
+ * (lfile *) cfp, and (FILE *) sfp
+ * are used in conjunction with
+ * the routine lk_getline() to read
+ * asmlnk commands from
+ * (1) the standard input or
+ * (2) or a command file
+ * and to read the REL files
+ * sequentially as defined by the
+ * asmlnk input commands.
+ *
+ * The pointer *filep points to the
+ * beginning of a linked list of
+ * lfile structures.
+ */
+struct lfile *cfp; /* The pointer *cfp points to the
+ * current lfile structure
+ */
+struct lfile *startp;/* asmlnk startup file structure
+ */
+struct lfile *linkp; /* pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ */
+struct lfile *lfp; /* pointer to current lfile structure
+ * being processed by parse()
+ */
+FILE *ofp; /* Output file handle
+ * for word formats
+ */
+FILE *mfp; /* Map output file handle
+ */
+FILE *rfp; /* File handle for output
+ * address relocated ASxxxx
+ * listing file
+ */
+FILE *sfp; /* The file handle sfp points to the
+ * currently open file
+ */
+FILE *tfp; /* File handle for input
+ * ASxxxx listing file
+ */
+
+/*
+ * The structures of head, area, areax, and sym are created
+ * as the REL files are read during the first pass of the
+ * linker. The struct head is created upon encountering a
+ * H directive in the REL file. The structure contains a
+ * link to a link file structure (struct lfile) which describes
+ * the file containing the H directive, the number of data/code
+ * areas contained in this header segment, the number of
+ * symbols referenced/defined in this header segment, a pointer
+ * to an array of pointers to areax structures (struct areax)
+ * created as each A directive is read, and a pointer to an
+ * array of pointers to symbol structures (struct sym) for
+ * all referenced/defined symbols. As H directives are read
+ * from the REL files a linked list of head structures is
+ * created by placing a link to the new head structure
+ * in the previous head structure.
+ *
+ * struct head
+ * {
+ * struct head *h_hp; Header link
+ * struct lfile *h_lfile; Associated file
+ * int h_narea; # of areas
+ * struct areax **a_list; Area list
+ * int h_nglob; # of global symbols
+ * struct sym **s_list; Global symbol list
+ * char m_id[NCPS]; Module name
+ * };
+ */
+struct head *headp; /* The pointer to the first
+ * head structure of a linked list
+ */
+struct head *hp; /* Pointer to the current
+ * head structure
+ */
+
+/*
+ * A structure area is created for each 'unique' data/code
+ * area definition found as the REL files are read. The
+ * struct area contains the name of the area, a flag byte
+ * which contains the area attributes (REL/CON/OVR/ABS),
+ * an area subtype (not used in this assembler), and the
+ * area base address and total size which will be filled
+ * in at the end of the first pass through the REL files.
+ * As A directives are read from the REL files a linked
+ * list of unique area structures is created by placing a
+ * link to the new area structure in the previous area structure.
+ *
+ * struct area
+ * {
+ * struct area *a_ap; Area link
+ * struct areax *a_axp; Area extension link
+ * Addr_T a_addr; Beginning address of area
+ * Addr_T a_size; Total size of the area
+ * char a_type; Area subtype
+ * char a_flag; Flag byte
+ * char a_id[NCPS]; Name
+ * };
+ */
+struct area *areap; /* The pointer to the first
+ * area structure of a linked list
+ */
+struct area *ap; /* Pointer to the current
+ * area structure
+ */
+
+/*
+ * An areax structure is created for every A directive found
+ * while reading the REL files. The struct areax contains a
+ * link to the 'unique' area structure referenced by the A
+ * directive and to the head structure this area segment is
+ * a part of. The size of this area segment as read from the
+ * A directive is placed in the areax structure. The beginning
+ * address of this segment will be filled in at the end of the
+ * first pass through the REL files. As A directives are read
+ * from the REL files a linked list of areax structures is
+ * created for each unique area. The final areax linked
+ * list has at its head the 'unique' area structure linked
+ * to the linked areax structures (one areax structure for
+ * each A directive for this area).
+ *
+ * struct areax
+ * {
+ * struct areax *a_axp; Area extension link
+ * struct area *a_bap; Base area link
+ * struct head *a_bhp; Base header link
+ * Addr_T a_addr; Beginning address of section
+ * Addr_T a_size; Size of the area in section
+ * };
+ */
+struct areax *axp; /* Pointer to the current
+ * areax structure
+ */
+
+/*
+ * A sym structure is created for every unique symbol
+ * referenced/defined while reading the REL files. The
+ * struct sym contains the symbol's name, a flag value
+ * (not used in this linker), a symbol type denoting
+ * referenced/defined, and an address which is loaded
+ * with the relative address within the area in which
+ * the symbol was defined. The sym structure also
+ * contains a link to the area where the symbol was defined.
+ * The sym structures are linked into linked lists using
+ * the symbol link element.
+ *
+ * struct sym
+ * {
+ * struct sym *s_sp; Symbol link
+ * struct areax *s_axp; Symbol area link
+ * char s_type; Symbol subtype
+ * char s_flag; Flag byte
+ * Addr_T s_addr; Address
+ * char s_id[NCPS]; Name
+ * };
+ */
+struct sym *symhash[NHASH]; /* array of pointers to NHASH
+ * linked symbol lists
+ */
+/*
+ * The struct base contains a pointer to a
+ * base definition string and a link to the next
+ * base structure.
+ *
+ * struct base
+ * {
+ * struct base *b_base; Base link
+ * char *b_strp; String pointer
+ * };
+ */
+struct base *basep; /* The pointer to the first
+ * base structure
+ */
+struct base *bsp; /* Pointer to the current
+ * base structure
+ */
+
+/*
+ * The struct globl contains a pointer to a
+ * global definition string and a link to the next
+ * global structure.
+ *
+ * struct globl
+ * {
+ * struct globl *g_globl; Global link
+ * char *g_strp; String pointer
+ * };
+ */
+struct globl *globlp;/* The pointer to the first
+ * globl structure
+ */
+struct globl *gsp; /* Pointer to the current
+ * globl structure
+ */
+
+/*
+ * A structure sdp is created for each 'unique' paged
+ * area definition found as the REL files are read.
+ * As P directives are read from the REL files a linked
+ * list of unique sdp structures is created by placing a
+ * link to the new sdp structure in the previous area structure.
+ *
+ * struct sdp
+ * {
+ * struct area *s_area; Paged Area link
+ * struct areax *s_areax; Paged Area Extension Link
+ * Addr_T s_addr; Page address offset
+ * };
+ */
+struct sdp sdp; /* Base Page Structure */
+
+/*
+ * The structure rerr is loaded with the information
+ * required to report an error during the linking
+ * process. The structure contains an index value
+ * which selects the areax structure from the header
+ * areax structure list, a mode value which selects
+ * symbol or area relocation, the base address in the
+ * area section, an area/symbol list index value, and
+ * an area/symbol offset value.
+ *
+ * struct rerr
+ * {
+ * int aindex; Linking area
+ * int mode; Relocation mode
+ * Addr_T rtbase; Base address in section
+ * int rindex; Area/Symbol reloaction index
+ * Addr_T rval; Area/Symbol offset value
+ * };
+ */
+struct rerr rerr; /* Structure containing the
+ * linker error information
+ */
+
+/*
+ * The structure lbpath is created for each library
+ * path specification input by the -k option. The
+ * lbpath structures are linked into a list using
+ * the next link element.
+ *
+ * struct lbpath {
+ * struct lbpath *next;
+ * char *path;
+ * };
+ */
+struct lbpath *lbphead; /* pointer to the first
+ * library path structure
+ */
+
+/*
+ * The structure lbname is created for all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file. The element path points to
+ * the path string, element libfil points to the library
+ * file string, and the element libspc is the concatenation
+ * of the valid path and libfil strings.
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ *
+ * Each library file contains a list of object files
+ * that are contained in the particular library. e.g.:
+ *
+ * \iolib\termio
+ * \inilib\termio
+ *
+ * Only one specification per line is allowed.
+ *
+ * struct lbname {
+ * struct lbname *next;
+ * char *path;
+ * char *libfil;
+ * char *libspc;
+ * };
+ */
+struct lbname *lbnhead; /* pointer to the first
+ * library name structure
+ */
+
+/*
+ * The function fndsym() searches through all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file for a symbol definition.
+ *
+ * The structure lbfile is created for the first library
+ * object file which contains the definition for the
+ * specified undefined symbol.
+ *
+ * The element libspc points to the library file path specification
+ * and element relfil points to the object file specification string.
+ * The element filspc is the complete path/file specification for
+ * the library file to be imported into the linker. The
+ * file specicifation may be formed in one of two ways:
+ *
+ * (1) If the library file contained an absolute
+ * path/file specification then this becomes filspc.
+ * (i.e. C:\...)
+ *
+ * (2) If the library file contains a relative path/file
+ * specification then the concatenation of the path
+ * and this file specification becomes filspc.
+ * (i.e. \...)
+ *
+ * The lbpath structures are linked into a list
+ * using the next link element.
+ *
+ * struct lbfile {
+ * struct lbfile *next;
+ * char *libspc;
+ * char *relfil;
+ * char *filspc;
+ * };
+ */
+struct lbfile *lbfhead; /* pointer to the first
+ * library file structure
+ */
+
+/*
+ * array of character types, one per
+ * ASCII character
+ */
+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 <alloc.h>
+#include "aslink.h"
+
+/*)Module lkeval.c
+ *
+ * The module lkeval.c contains the routines to evaluate
+ * arithmetic/numerical expressions. The functions in
+ * lkeval.c perform a recursive evaluation of the arithmetic
+ * expression read from the input text line.
+ * The expression may include binary/unary operators, brackets,
+ * symbols, labels, and constants in hexadecimal, decimal, octal
+ * and binary. Arithmetic operations are prioritized and
+ * evaluated by normal arithmetic conventions.
+ *
+ * lkeval.c contains the following functions:
+ * int digit()
+ * Addr_T eval()
+ * Addr_T expr()
+ * int oprio()
+ * Addr_T term()
+ *
+ * lkeval.c contains no local/static variables
+ */
+
+/*)Function Addr_T eval()
+ *
+ * The function eval() evaluates a character string to a
+ * numerical value.
+ *
+ * local variables:
+ * int c character from input string
+ * int v value of character in current radix
+ * Addr_T n evaluation value
+ *
+ * global variables:
+ * int radix current number conversion radix
+ *
+ * functions called:
+ * int digit() lkeval.c
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * Input test is scanned and evaluated to a
+ * numerical value.
+ */
+
+Addr_T
+eval()
+{
+ register int c, v;
+ register Addr_T n;
+
+ c = getnb();
+ n = 0;
+ while ((v = digit(c, radix)) >= 0) {
+ n = n*radix + v;
+ c = get();
+ }
+ unget(c);
+ return(n);
+}
+
+/*)Function Addr_T expr(n)
+ *
+ * int n a firewall priority; all top
+ * level calls (from the user)
+ * should be made with n set to 0.
+ *
+ * The function expr() evaluates an expression and
+ * returns the value.
+ *
+ * local variables:
+ * int c current input text character
+ * int p current operator priority
+ * Addr_T v value returned by term()
+ * Addr_T ve value returned by a
+ * recursive call to expr()
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * int lkerr error flag
+ * FILE * stderr c_library
+ *
+ * functions called:
+ * VOID expr() lkeval.c
+ * int fprintf() c_library
+ * int getnb() lklex.c
+ * int oprio() lkeval.c
+ * VOID term() lkeval.c
+ * VOID unget() lklex.c
+ *
+ *
+ * side effects:
+ * An expression is evaluated by scanning the input
+ * text string.
+ */
+
+Addr_T
+expr (n)
+{
+ register int c, p;
+ register Addr_T v, ve;
+
+ v = term();
+ while (ctype[c = getnb()] & BINOP) {
+ if ((p = oprio(c)) <= n)
+ break;
+ if ((c == '>' || c == '<') && c != get()) {
+ fprintf(stderr, "Invalid expression");
+ lkerr++;
+ return(v);
+ }
+ ve = expr(p);
+ if (c == '+') {
+ v += ve;
+ } else
+ if (c == '-') {
+ v -= ve;
+ } else {
+ switch (c) {
+
+ case '*':
+ v *= ve;
+ break;
+
+ case '/':
+ v /= ve;
+ break;
+
+ case '&':
+ v &= ve;
+ break;
+
+ case '|':
+ v |= ve;
+ break;
+
+ case '%':
+ v %= ve;
+ break;
+
+ case '^':
+ v ^= ve;
+ break;
+
+ case '<':
+ v <<= ve;
+ break;
+
+ case '>':
+ v >>= ve;
+ break;
+ }
+ }
+ }
+ unget(c);
+ return(v);
+}
+
+/*)Function Addr_T term()
+ *
+ * The function term() evaluates a single constant
+ * or symbol value prefaced by any unary operator
+ * ( +, -, ~, ', ", >, or < ).
+ *
+ * local variables:
+ * int c current character
+ * char id[] symbol name
+ * int n value of digit in current radix
+ * int r current evaluation radix
+ * sym * sp pointer to a sym structure
+ * Addr_T v evaluation value
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * int lkerr error flag
+ *
+ * functions called:
+ * int digit() lkeval.c
+ * VOID expr() lkeval.c
+ * int fprintf() c_library
+ * int get() lklex.c
+ * VOID getid() lklex.c
+ * int getmap() lklex.c
+ * int getnb() lklex.c
+ * sym * lkpsym() lksym.c
+ * Addr_T symval() lksym.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * An arithmetic term is evaluated by scanning input text.
+ */
+
+Addr_T
+term()
+{
+ register int c, r, n;
+ register Addr_T v;
+ struct sym *sp;
+ char id[NCPS];
+
+ c = getnb();
+ if (c == '#') { c = getnb(); }
+ if (c == '(') {
+ v = expr(0);
+ if (getnb() != ')') {
+ fprintf(stderr, "Missing delimiter");
+ lkerr++;
+ }
+ return(v);
+ }
+ if (c == '-') {
+ return(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));
+ }
+ }
+ /* Shouldn't get here. */
+ return 0;
+}
+
+/*)Function int digit(c, r)
+ *
+ * int c digit character
+ * int r current radix
+ *
+ * The function digit() returns the value of c
+ * in the current radix r. If the c value is not
+ * a number of the current radix then a -1 is returned.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+digit(c, r)
+register int c, r;
+{
+ if (r == 16) {
+ if (ctype[c] & RAD16) {
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ return (c - '0');
+ }
+ } else
+ if (r == 10) {
+ if (ctype[c] & RAD10)
+ return (c - '0');
+ } else
+ if (r == 8) {
+ if (ctype[c] & RAD8)
+ return (c - '0');
+ } else
+ if (r == 2) {
+ if (ctype[c] & RAD2)
+ return (c - '0');
+ }
+ return (-1);
+}
+
+/*)Function int oprio(c)
+ *
+ * int c operator character
+ *
+ * The function oprio() returns a relative priority
+ * for all valid unary and binary operators.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+int
+oprio(c)
+register int c;
+{
+ if (c == '*' || c == '/' || c == '%')
+ return (10);
+ if (c == '+' || c == '-')
+ return (7);
+ if (c == '<' || c == '>')
+ return (5);
+ if (c == '^')
+ return (4);
+ if (c == '&')
+ return (3);
+ if (c == '|')
+ return (1);
+ return (0);
+}
--- /dev/null
+/* lkgb.c */
+
+/*
+ * P. Felber
+ */
+
+#ifdef GAMEBOY
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "aslink.h"
+
+/* Value used to fill the unused portions of the image */
+/* FFh puts less stress on a EPROM/Flash */
+#define FILLVALUE 0xFF
+
+#define CARTSIZE ((unsigned long)nb_rom_banks*16UL*1024UL)
+#define NBSEG 8UL
+#define SEGSIZE (CARTSIZE/NBSEG)
+
+#define ROMSIZE 0x8000UL
+#define BANKSTART 0x4000UL
+#define BANKSIZE 0x4000UL
+
+unsigned char *cart[NBSEG];
+
+int nb_rom_banks;
+int nb_ram_banks;
+int current_rom_bank;
+int mbc_type;
+char cart_name[16] = "";
+
+patch* patches = NULL;
+
+VOID gb(int in)
+{
+ static int first = 1;
+ unsigned long pos, chk;
+ int i;
+ patch *p;
+
+ if(first) {
+ for(i = 0; i < NBSEG; i++) {
+ if((cart[i] = malloc(SEGSIZE)) == NULL) {
+ fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
+ exit(EXIT_FAILURE);
+ }
+ memset(cart[i], FILLVALUE, SEGSIZE);
+ }
+ first = 0;
+ }
+ if(in) {
+ if(rtcnt > 2) {
+ if(hilo == 0)
+ pos = rtval[0] | (rtval[1]<<8);
+ else
+ pos = rtval[1] | (rtval[0]<<8);
+
+ /* Perform some validity checks */
+ if(pos >= ROMSIZE) {
+ fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
+ exit(EXIT_FAILURE);
+ }
+ if(current_rom_bank >= nb_rom_banks) {
+ fprintf(stderr, "ERROR: bank overflow (addr %x > %x)\n", current_rom_bank, nb_rom_banks);
+ exit(EXIT_FAILURE);
+ }
+ if(current_rom_bank > 0 && pos < BANKSTART) {
+ fprintf(stderr, "ERROR: address underflow (addr %lx < %lx)\n", pos, BANKSTART);
+ exit(EXIT_FAILURE);
+ }
+ if(nb_rom_banks == 2 && current_rom_bank > 0) {
+ fprintf(stderr, "ERROR: only 1 32kB segment with 2 bank\n");
+ exit(EXIT_FAILURE);
+ }
+ if(current_rom_bank > 1)
+ pos += (current_rom_bank-1)*BANKSIZE;
+ for(i = 2; i < rtcnt; i++) {
+ if(rtflg[i]) {
+ if(pos < CARTSIZE) {
+ if(cart[pos/SEGSIZE][pos%SEGSIZE] != FILLVALUE)
+ fprintf(stderr, "WARNING: possibly wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
+ cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
+ } else {
+ fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
+ exit(EXIT_FAILURE);
+ }
+ pos++;
+ }
+ }
+ }
+ } else {
+ /* EOF */
+ if(cart_name[0] == 0 && linkp->f_idp != NULL) {
+ for(i = strlen(linkp->f_idp);
+ i > 0 && (isalnum((unsigned char)linkp->f_idp[i-1]) || linkp->f_idp[i-1] == '.');
+ i--)
+ ;
+ for(pos = 0; pos < 16 && linkp->f_idp[i] != '.'; pos++, i++)
+ cart_name[pos] = toupper((unsigned char)linkp->f_idp[i]);
+ if(pos < 16)
+ cart_name[pos] = 0;
+ }
+ for(pos = 0x0134, i = 0;
+ pos < 0x0144 && cart_name[i];
+ pos++, i++)
+ cart[pos/SEGSIZE][pos%SEGSIZE] = cart_name[i];
+ for(; pos < 0x0144; pos++)
+ cart[pos/SEGSIZE][pos%SEGSIZE] = 0;
+ cart[0x147/SEGSIZE][0x147%SEGSIZE] = mbc_type;
+ switch(nb_rom_banks) {
+ case 2:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
+ break;
+ case 4:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 1;
+ break;
+ case 8:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 2;
+ break;
+ case 16:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 3;
+ break;
+ case 32:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 4;
+ break;
+ case 64:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 5;
+ break;
+ case 128:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 6;
+ break;
+ case 256:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 7;
+ break;
+ case 512:
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 8;
+ break;
+ default:
+ fprintf(stderr, "WARNING: unsupported number of ROM banks (%d)\n", nb_rom_banks);
+ cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
+ break;
+ }
+ switch(nb_ram_banks) {
+ case 0:
+ cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
+ break;
+ case 1:
+ cart[0x149/SEGSIZE][0x149%SEGSIZE] = 2;
+ break;
+ case 4:
+ cart[0x149/SEGSIZE][0x149%SEGSIZE] = 3;
+ break;
+ case 16:
+ cart[0x149/SEGSIZE][0x149%SEGSIZE] = 4;
+ break;
+ default:
+ fprintf(stderr, "WARNING: unsupported number of RAM banks (%d)\n", nb_ram_banks);
+ cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
+ break;
+ }
+
+ /* Patch before calculating the checksum */
+ if(patches)
+ for(p = patches; p; p = p->next)
+ cart[p->addr/SEGSIZE][p->addr%SEGSIZE] = p->value;
+
+ /* Update complement checksum */
+ chk = 0;
+ for(pos = 0x0134; pos < 0x014D; pos++)
+ chk += cart[pos/SEGSIZE][pos%SEGSIZE];
+ cart[0x014D/SEGSIZE][0x014D%SEGSIZE] = (unsigned char)(0xE7 - (chk&0xFF));
+ /* Update checksum */
+ chk = 0;
+ cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = 0;
+ cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = 0;
+ for(i = 0; i < NBSEG; i++)
+ for(pos = 0; pos < SEGSIZE; pos++)
+ chk += cart[i][pos];
+ cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = (unsigned char)((chk>>8)&0xFF);
+ cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = (unsigned char)(chk&0xFF);
+
+ for(i = 0; i < NBSEG; i++)
+ fwrite(cart[i], 1, SEGSIZE, ofp);
+ }
+}
+
+#endif /* GAMEBOY */
--- /dev/null
+/* lkgg.c */
+
+/*
+ * P. Felber
+ */
+
+#ifdef GAMEGEAR
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include "aslink.h"
+
+#define CARTSIZE ((unsigned long)4*16UL*1024UL)
+#define NBSEG 8UL
+#define SEGSIZE (CARTSIZE/NBSEG)
+
+unsigned char *cart[NBSEG];
+
+#define ROMSIZE 0x10000UL
+#define BANKSIZE 0x4000UL
+
+int current_rom_bank;
+
+VOID gg(int in)
+{
+ static int first = 1;
+ unsigned long pos;
+ int i;
+
+ if(first) {
+ for(i = 0; i < NBSEG; i++) {
+ if((cart[i] = malloc(SEGSIZE)) == NULL) {
+ fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
+ exit(EXIT_FAILURE);
+ }
+ memset(cart[i], 0, SEGSIZE);
+ }
+ first = 0;
+ }
+ if(in) {
+ if(rtcnt > 2) {
+ if(hilo == 0)
+ pos = rtval[0] | (rtval[1]<<8);
+ else
+ pos = rtval[1] | (rtval[0]<<8);
+
+ /* Perform some validity checks */
+ if(pos >= ROMSIZE) {
+ fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
+ exit(EXIT_FAILURE);
+ }
+ if(current_rom_bank > 1)
+ pos += (current_rom_bank-1)*BANKSIZE;
+ for(i = 2; i < rtcnt; i++) {
+ if(rtflg[i]) {
+ if(pos < CARTSIZE) {
+ if(cart[pos/SEGSIZE][pos%SEGSIZE] != 0)
+ fprintf(stderr, "WARNING: wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
+ cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
+ } else {
+ fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
+ exit(EXIT_FAILURE);
+ }
+ pos++;
+ }
+ }
+ }
+ } else {
+ /* EOF */
+ /* Patch before calculating the checksum */
+ for(i = 0; i < NBSEG; i++)
+ fwrite(cart[i], 1, SEGSIZE, ofp);
+ }
+}
+
+#endif /* GAMEGEAR */
--- /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 <alloc.h>
+#include "aslink.h"
+
+/*Module lkhead.c
+ *
+ * The module lkhead.c contains the function newhead() which
+ * creates a head structure and the function module() which
+ * loads the module name into the current head structure.
+ *
+ * lkhead.c contains the following functions:
+ * VOID newhead()
+ * VOID module()
+ *
+ * lkhead.c contains no local variables.
+ */
+
+/*)Function VOID newhead()
+ *
+ * The function newhead() creates a head structure. All head
+ * structures are linked to form a linked list of head structures
+ * with the current head structure at the tail of the list.
+ *
+ * local variables:
+ * int i evaluation value
+ * head * thp temporary pointer
+ * to a header structure
+ *
+ * global variables:
+ * area *ap Pointer to the current
+ * area structure
+ * lfile *cfp The pointer *cfp points to the
+ * current lfile structure
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * head *hp Pointer to the current
+ * head structure
+ *
+ * functions called:
+ * Addr_T expr() lkeval.c
+ * VOID * new() lksym.c
+ * VOID lkparea() lkarea.c
+ *
+ * side effects:
+ * A new head structure is created and linked to any
+ * existing linked head structure. The head structure
+ * parameters of file handle, number of areas, and number
+ * of global symbols are loaded into the structure.
+ * The default area "_abs_" is created when the first
+ * head structure is created and an areax structure is
+ * created for every head structure called.
+ */
+
+/*
+ * Create a new header entry.
+ *
+ * H n areas n global symbols
+ * | |
+ * | `---- hp->h_nglob
+ * `------------ hp->h_narea
+ *
+ */
+VOID
+newhead()
+{
+ register int i;
+ struct head *thp;
+
+ hp = (struct head *) new (sizeof(struct head));
+ if (headp == NULL) {
+ headp = hp;
+ } else {
+ thp = headp;
+ while (thp->h_hp)
+ thp = thp->h_hp;
+ thp->h_hp = hp;
+ }
+ /*
+ * Set file pointer
+ */
+ hp->h_lfile = cfp;
+ /*
+ * Evaluate and build Area pointer list
+ */
+ i = hp->h_narea = eval();
+ if (i)
+ hp->a_list = (struct areax **) new (i*sizeof(struct areax *));
+ /*
+ * Evaluate and build Global symbol pointer list
+ */
+ skip(-1);
+ i = hp->h_nglob = eval();
+ if (i)
+ hp->s_list = (struct sym **) new (i*sizeof(struct sym *));
+ /*
+ * Setup Absolute DEF linkage.
+ */
+ lkparea(_abs_);
+ ap->a_flag = A_ABS|A_OVR;
+}
+
+/*)Function VOID module()
+ *
+ * The function module() copies the module name into
+ * the current head structure.
+ *
+ * local variables:
+ * char id[] module id string
+ *
+ * global variables:
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * head *hp Pointer to the current
+ * head structure
+ * int lkerr error flag
+ * FILE * stderr c_library
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID getid() lklex.c
+ * char * strncpy() c_library
+ *
+ * side effects:
+ * The module name is copied into the head structure.
+ */
+
+/*
+ * Module Name
+ */
+VOID
+module()
+{
+ char id[NCPS];
+
+ if (headp) {
+ getid(id, -1);
+ strncpy(hp->m_id, id, NCPS);
+ } else {
+ fprintf(stderr, "No header defined\n");
+ lkerr++;
+ }
+}
--- /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 <alloc.h>
+#include "aslink.h"
+
+/*)Module lkihx.c
+ *
+ * The module lkihx.c contains the function to
+ * output the relocated object code in the
+ * Intel Hex format.
+ *
+ * lkihx.c contains the following function:
+ * VOID ihx(i)
+ *
+ * lkihx.c contains no local variables.
+ */
+
+/*Intel Hex Format
+ * Record Mark Field - This field signifies the start of a
+ * record, and consists of an ascii colon
+ * (:).
+ *
+ * Record Length Field - This field consists of two ascii
+ * characters which indicate the number of
+ * data bytes in this record. The
+ * characters are the result of converting
+ * the number of bytes in binary to two
+ * ascii characters, high digit first. An
+ * End of File record contains two ascii
+ * zeros in this field.
+ *
+ * Load Address Field - This field consists of the four ascii
+ * characters which result from converting
+ * the the binary value of the address in
+ * which to begin loading this record. The
+ * order is as follows:
+ *
+ * High digit of high byte of address.
+ * Low digit of high byte of address.
+ * High digit of low byte of address.
+ * Low digit of low byte of address.
+ *
+ * In an End of File record this field con-
+ * sists of either four ascii zeros or the
+ * program entry address. Currently the
+ * entry address option is not supported.
+ *
+ * Record Type Field - This field identifies the record type,
+ * which is either 0 for data records or 1
+ * for an End of File record. It consists
+ * of two ascii characters, with the high
+ * digit of the record type first, followed
+ * by the low digit of the record type.
+ *
+ * Data Field - This field consists of the actual data,
+ * converted to two ascii characters, high
+ * digit first. There are no data bytes in
+ * the End of File record.
+ *
+ * Checksum Field - The checksum field is the 8 bit binary
+ * sum of the record length field, the load
+ * address field, the record type field,
+ * and the data field. This sum is then
+ * negated (2's complement) and converted
+ * to two ascii characters, high digit
+ * first.
+ */
+
+/*)Function ihx(i)
+ *
+ * int i 0 - process data
+ * 1 - end of data
+ *
+ * The function ihx() outputs the relocated data
+ * in the standard Intel Hex format.
+ *
+ * local variables:
+ * Addr_T chksum byte checksum
+ *
+ * global variables:
+ * int hilo byte order
+ * FILE * ofp output file handle
+ * int rtcnt count of data words
+ * int rtflg[] output the data flag
+ * Addr_T rtval[] relocated data
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * The data is output to the file defined by ofp.
+ */
+
+VOID
+ihx(i)
+{
+ register Addr_T chksum;
+
+ if (i) {
+ if (hilo == 0) {
+ chksum = rtval[0];
+ rtval[0] = rtval[1];
+ rtval[1] = chksum;
+ }
+ for (i = 0, chksum = -2; i < rtcnt; i++) {
+ if (rtflg[i])
+ chksum++;
+ }
+ fprintf(ofp, ":%02X", chksum);
+ for (i = 0; i < rtcnt ; i++) {
+ if (rtflg[i]) {
+ fprintf(ofp, "%02X", rtval[i]);
+ chksum += rtval[i];
+ }
+ if (i == 1) {
+ fprintf(ofp, "00");
+ }
+ }
+ fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
+ } else {
+ fprintf(ofp, ":00000001FF\n");
+ }
+}
--- /dev/null
+/* lklex.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+/*
+ * Extensions: P. Felber, M. Hope
+ */
+
+#include <stdio.h>
+#include <string.h>
+//#include <alloc.h>
+#include "aslink.h"
+
+/*)Module lklex.c
+ *
+ * The module lklex.c contains the general lexical analysis
+ * functions used to scan the text lines from the .rel files.
+ *
+ * lklex.c contains the fllowing functions:
+ * char endline()
+ * char get()
+ * VOID getfid()
+ * VOID getid()
+ * int lk_getline()
+ * int getmap()
+ * char getnb()
+ * int more()
+ * VOID skip()
+ * VOID unget()
+ *
+ * lklex.c contains no local variables.
+ */
+
+/*)Function VOID getid(id,c)
+ *
+ * char * id a pointer to a string of
+ * maximum length NCPS
+ * int c mode flag
+ * >=0 this is first character to
+ * copy to the string buffer
+ * <0 skip white space
+ *
+ * The function getid() scans the current input text line
+ * from the current position copying the next LETTER | DIGIT string
+ * into the external string buffer (id). The string ends when a non
+ * LETTER or DIGIT character is found. The maximum number of
+ * characters copied is NCPS. If the input string is larger than
+ * NCPS characters then the string is truncated, if the input string
+ * is shorter than NCPS characters then the string is NULL filled.
+ * If the mode argument (c) is >=0 then (c) is the first character
+ * copied to the string buffer, if (c) is <0 then intervening white
+ * space (SPACES and TABS) are skipped.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of getnb(), get(), and unget() updates the
+ * global pointer ip the position in the current
+ * input text line.
+ */
+
+VOID
+getid(id, c)
+register int c;
+char *id;
+{
+ register char *p;
+
+ if (c < 0) {
+ c = getnb();
+ }
+ p = id;
+ do {
+ if (p < &id[NCPS])
+ *p++ = c;
+ } while (ctype[c=get()] & (LETTER|DIGIT));
+ unget(c);
+ while (p < &id[NCPS])
+ *p++ = 0;
+}
+
+/*)Function VOID getfid(fid,c)
+ *
+ * char * str a pointer to a string of
+ * maximum length FILSPC
+ * int c this is first character to
+ * copy to the string buffer
+ *
+ * The function getfid() scans the current input text line
+ * from the current position copying the next string
+ * into the external string buffer (str). The string ends when a
+ * non SPACE type character is found. The maximum number of
+ * characters copied is FILSPC. If the input string is larger than
+ * FILSPC characters then the string is truncated, if the input string
+ * is shorter than FILSPC characters then the string is NULL filled.
+ *
+ * local variables:
+ * char * p pointer to external string buffer
+ * int c current character value
+ *
+ * global variables:
+ * char ctype[] a character array which defines the
+ * type of character being processed.
+ * This index is the character
+ * being processed.
+ *
+ * called functions:
+ * char get() lklex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip
+ * the position in the current input text line.
+ */
+
+VOID
+getfid(str, c)
+register int c;
+char *str;
+{
+ register char *p;
+
+ p = str;
+ do {
+ if (p < &str[FILSPC-1])
+ *p++ = c;
+ c = get();
+ if (c == ';')
+ while (c)
+ c = get();
+#ifdef SDK
+ } while (c);
+#else /* SDK */
+ } while (c && (ctype[c] != SPACE));
+#endif /* SDK */
+ while (p < &str[FILSPC])
+ *p++ = 0;
+}
+
+/*)Function char getnb()
+ *
+ * The function getnb() scans the current input text
+ * line returning the first character not a SPACE or TAB.
+ *
+ * local variables:
+ * int c current character from input
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char get() lklex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip, the position
+ * in the current input text line
+ */
+
+char
+getnb()
+{
+ register int c;
+
+ while ((c=get())==' ' || c=='\t')
+ ;
+ return (c);
+}
+
+/*)Function VOID skip()
+ *
+ * The function skip() scans the input text skipping all
+ * letters and digits.
+ *
+ * local variables:
+ * none
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ *
+ * functions called:
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * Input letters and digits are skipped.
+ */
+
+VOID
+skip(c)
+register int c;
+{
+ if (c < 0)
+ c = getnb();
+ while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
+ unget(c);
+}
+
+/*)Function char get()
+ *
+ * The function get() returns the next character in the
+ * input text line, at the end of the line a
+ * NULL character is returned.
+ *
+ * local variables:
+ * int c current character from
+ * input text line
+ *
+ * global variables:
+ * char * ip pointer into the current
+ * input text line
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * updates ip to the next character position in the
+ * input text line. If ip is at the end of the
+ * line, ip is not updated.
+ */
+
+char
+get()
+{
+ register int c;
+
+ if ((c = *ip) != 0)
+ ++ip;
+ return (c);
+}
+
+/*)Function VOID unget(c)
+ *
+ * int c value of last character
+ * read from input text line
+ *
+ * If (c) is not a NULL character then the global pointer ip
+ * is updated to point to the preceeding character in the
+ * input text line.
+ *
+ * NOTE: This function does not push the character (c)
+ * back into the input text line, only
+ * the pointer ip is changed.
+ *
+ * local variables:
+ * int c last character read
+ * from input text line
+ *
+ * global variables:
+ * char * ip position into the current
+ * input text line
+ *
+ * called functions:
+ * none
+ *
+ * side effects:
+ * ip decremented by 1 character position
+ */
+
+VOID
+unget(c)
+{
+ if (c != 0)
+ --ip;
+}
+
+/*)Function int getmap(d)
+ *
+ * int d value to compare with the
+ * input text line character
+ *
+ * The function getmap() converts the 'C' style characters \b, \f,
+ * \n, \r, and \t to their equivalent ascii values and also
+ * converts 'C' style octal constants '\123' to their equivalent
+ * numeric values. If the first character is equivalent to (d) then
+ * a (-1) is returned, if the end of the line is detected then
+ * a 'q' error terminates the parse for this line, or if the first
+ * character is not a \ then the character value is returned.
+ *
+ * local variables:
+ * int c value of character
+ * from input text line
+ * int n looping counter
+ * int v current value of numeric conversion
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char get() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of get() updates the global pointer ip the position
+ * in the current input text line
+ */
+
+int
+getmap(d)
+{
+ register int c, n, v;
+
+ if ((c = get()) == '\0')
+ return (-1);
+ if (c == d)
+ return (-1);
+ if (c == '\\') {
+ c = get();
+ switch (c) {
+
+ case 'b':
+ c = '\b';
+ break;
+
+ case 'f':
+ c = '\f';
+ break;
+
+ case 'n':
+ c = '\n';
+ break;
+
+ case 'r':
+ c = '\r';
+ break;
+
+ case 't':
+ c = '\t';
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ n = 0;
+ v = 0;
+ while (++n<=3 && c>='0' && c<='7') {
+ v = (v<<3) + c - '0';
+ c = get();
+ }
+ unget(c);
+ c = v;
+ break;
+ }
+ }
+ return (c);
+}
+
+/*)Function int lk_getline()
+ *
+ * The function lk_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
+ * lk_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
+lk_getline()
+{
+ register int i, ftype;
+ register char *fid;
+
+loop: if (pflag && cfp && cfp->f_type == F_STD)
+ fprintf(stdout, "ASlink >> ");
+
+#ifdef SDK
+ if(cfp == NULL && filep != NULL && filep->f_type == F_CMD) {
+ char **argv = (char **)filep->f_idp;
+ if(argv[0] != NULL && strlen(argv[0]) < sizeof ib) {
+ strcpy(ib, argv[0]);
+ filep->f_idp = (char *)&argv[1];
+ } else {
+ filep = NULL;
+ return(0);
+ }
+ } else
+#endif /* SDK */
+ if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
+ if (sfp) {
+ fclose(sfp);
+#ifdef SDK
+ sfp = NULL;
+#endif /* SDK */
+ lkulist(0);
+ }
+ if (cfp == NULL) {
+ cfp = filep;
+ } else {
+ cfp = cfp->f_flp;
+ }
+ if (cfp) {
+ ftype = cfp->f_type;
+ fid = cfp->f_idp;
+ if (ftype == F_STD) {
+ sfp = stdin;
+ } else
+ if (ftype == F_LNK) {
+#ifdef SDK
+ sfp = afile(fid, "lnk", 0);
+#else /* SDK */
+ sfp = afile(fid, "LNK", 0);
+#endif /* SDK */
+ } else
+ if (ftype == F_REL) {
+#ifdef SDK
+ sfp = afile(fid, "", 0);
+ if (uflag && pass != 0) {
+ if ((tfp = afile(fid, "lst", 0)) != NULL) {
+ if ((rfp = afile(fid, "rst", 1)) == NULL) {
+#else /* SDK */
+ sfp = afile(fid, "REL", 0);
+ if (uflag && pass != 0) {
+ if ((tfp = afile(fid, "LST", 0)) != NULL) {
+ if ((rfp = afile(fid, "RST", 1)) == NULL) {
+#endif /* SDK */
+ fclose(tfp);
+ tfp = NULL;
+ }
+ }
+ }
+ gline = 1;
+ } else {
+ fprintf(stderr, "Invalid file type\n");
+ lkexit(1);
+ }
+ if (sfp == NULL) {
+ lkexit(1);
+ }
+ goto loop;
+ } else {
+ filep = NULL;
+ return(0);
+ }
+ }
+ i = strlen(ib) - 1;
+ if (ib[i] == '\n')
+ ib[i] = 0;
+ return (1);
+}
+
+/*)Function int more()
+ *
+ * The function more() scans the input text line
+ * skipping white space (SPACES and TABS) and returns a (0)
+ * if the end of the line or a comment delimeter (;) is found,
+ * or a (1) if their are additional characters in the line.
+ *
+ * local variables:
+ * int c next character from
+ * the input text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * use of getnb() and unget() updates the global pointer ip
+ * the position in the current input text line
+ */
+
+int
+more()
+{
+ register int c;
+
+ c = getnb();
+ unget(c);
+ return( (c == '\0' || c == ';') ? 0 : 1 );
+}
+
+/*)Function char endline()
+ *
+ * The function endline() scans the input text line
+ * skipping white space (SPACES and TABS) and returns the next
+ * character or a (0) if the end of the line is found or a
+ * comment delimiter (;) is found.
+ *
+ * local variables:
+ * int c next character from
+ * the input text line
+ *
+ * global variables:
+ * none
+ *
+ * called functions:
+ * char getnb() lklex.c
+ *
+ * side effects:
+ * Use of getnb() updates the global pointer ip the
+ * position in the current input text line.
+ */
+
+char
+endline()
+{
+ register int c;
+
+ c = getnb();
+ return( (c == '\0' || c == ';') ? 0 : c );
+}
+
+/*)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
+ *
+ */
+
+/*
+ * Extensions: P. Felber
+ */
+
+#define EQ(A,B) !strcmp((A),(B))
+#define MAXLINE 254 /*when using fgets*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "aslink.h"
+
+#ifdef OTHERSYSTEM
+#ifdef SDK
+#ifdef UNIX
+ #define LKDIRSEP '/'
+ #define LKDIRSEPSTR "/"
+#else /* UNIX */
+ #define LKDIRSEP '\\'
+ #define LKDIRSEPSTR "\\"
+#endif /* UNIX */
+#else /* SDK */
+ #define LKDIRSEP '\\'
+ #define LKDIRSEPSTR "\\"
+#endif /* SDK */
+#endif
+
+#ifdef SDK
+ #define LKOBJEXT "o"
+#else /* SDK */
+ #define LKOBJEXT "rel"
+#endif /* SDK */
+
+/*)Module lklibr.c
+ *
+ * The module lklibr.c contains the functions which
+ * (1) specify the path(s) to library files [.LIB]
+ * (2) specify the library file(s) [.LIB] to search
+ * (3) search the library files for specific symbols
+ * and link the module containing this symbol
+ *
+ * lklibr.c contains the following functions:
+ * VOID addpath()
+ * VOID addlib()
+ * VOID addfile()
+ * VOID search()
+ * VOID fndsym()
+ * VOID library()
+ * VOID loadfile()
+ *
+ */
+
+#ifdef INDEXLIB
+typedef struct slibrarysymbol mlibrarysymbol;
+typedef struct slibrarysymbol *pmlibrarysymbol;
+
+struct slibrarysymbol {
+ char * name; /*Warning: allocate memory before using*/
+ pmlibrarysymbol next;
+};
+
+typedef struct slibraryfile mlibraryfile;
+typedef struct slibraryfile *pmlibraryfile;
+
+struct slibraryfile {
+ int loaded;
+ char * libspc;
+ char * relfil; /*Warning: allocate memory before using*/
+ char * filename; /*Warning: allocate memory before using*/
+ long offset; //if > 0, the embedded file offset in the library file libspc
+ pmlibrarysymbol symbols;
+ pmlibraryfile next;
+};
+
+/* First entry in the library object symbol cache */
+pmlibraryfile libr=NULL;
+
+int buildlibraryindex();
+void freelibraryindex (void);
+#endif /* INDEXLIB */
+
+/*)Function VOID addpath()
+ *
+ * The function addpath() creates a linked structure containing
+ * the paths to various object module library files.
+ *
+ * local variables:
+ * lbpath *lbph pointer to new path structure
+ * lbpath *lbp temporary pointer
+ *
+ * global variables:
+ * lbpath *lbphead The pointer to the first
+ * path structure
+ *
+ * functions called:
+ * char getnb() lklex.c
+ * VOID * new() lksym.c
+ * int strlen() c_library
+ * char * strcpy() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * An lbpath structure may be created.
+ */
+
+VOID
+addpath()
+{
+ struct lbpath *lbph, *lbp;
+
+ lbph = (struct lbpath *) new (sizeof(struct lbpath));
+ if (lbphead == NULL) {
+ lbphead = lbph;
+ } else {
+ lbp = lbphead;
+ while (lbp->next)
+ lbp = lbp->next;
+ lbp->next = lbph;
+ }
+ unget(getnb());
+ lbph->path = (char *) new (strlen(ip)+1);
+ strcpy(lbph->path, ip);
+}
+
+/*)Function VOID addlib()
+ *
+ * The function addlib() tests for the existance of a
+ * library path structure to determine the method of
+ * adding this library file to the library search structure.
+ *
+ * This function calls the function addfile() to actually
+ * add the library file to the search list.
+ *
+ * local variables:
+ * lbpath *lbph pointer to path structure
+ *
+ * global variables:
+ * lbpath *lbphead The pointer to the first
+ * path structure
+ * ip a pointer to the library name
+ *
+ * functions called:
+ * VOID addfile() lklibr.c
+ * char getnb() lklex.c
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * The function addfile() may add the file to
+ * the library search list.
+ */
+
+VOID
+addlib()
+{
+ struct lbpath *lbph;
+ int foundcount=0;
+
+ unget(getnb());
+
+ if (lbphead == NULL)
+ {
+ foundcount=addfile(NULL, ip);
+ }
+ else
+ {
+ for (lbph=lbphead; lbph; lbph=lbph->next)
+ {
+ foundcount+=addfile(lbph->path, ip);
+ }
+ }
+ if(foundcount == 0)
+ {
+ fprintf(stderr, "\n?ASlink-Warning-Couldn't find library '%s'", 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;
+ int libfilinc=0;
+
+ if (path != NULL)
+ {
+ str = (char *) new (strlen(path) + strlen(libfil) + 6);
+ strcpy(str, path);
+
+ if (str[strlen(str)-1] != LKDIRSEP)
+ {
+ strcat(str, LKDIRSEPSTR);
+ }
+ }
+ else
+ {
+ str = (char *) new (strlen(libfil) + 5);
+ }
+
+ if (libfil[0] == LKDIRSEP)
+ {
+ libfil++;
+ libfilinc=1;
+ }
+
+ 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*/
+ if(libfilinc) libfil--;
+ 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 '.o' 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(char * libfname, FILE * libfp, char * ModName)
+{
+ char str[NINPUT+2];
+ int state=0;
+
+ while (fgets(str, NINPUT, libfp) != NULL)
+ {
+ str[NINPUT+1] = '\0';
+ chop_crlf(str);
+ switch(state)
+ {
+ case 0:
+ if(EQ(str, "<FILE>"))
+ {
+ fgets(str, NINPUT, libfp);
+ str[NINPUT+1] = '\0';
+ chop_crlf(str);
+ if(EQ(str, ModName)) state=1;
+ else
+ {
+ fprintf(stderr, "?Aslink-Error-Bad offset in library file %s(%s)\n",
+ libfname, ModName);
+ lkexit(1);
+ }
+ }
+ break;
+ case 1:
+ if(EQ(str, "<REL>")) state=2;
+ break;
+ case 2:
+ if(EQ(str, "</REL>")) return;
+ ip = str;
+ link();
+ break;
+ }
+ }
+}
+
+/*)Function VOID fndsym(name)
+ *
+ * char *name symbol name to find
+ *
+ * The function fndsym() searches through all combinations of the
+ * library path specifications (input by the -k option) and the
+ * library file specifications (input by the -l option) that
+ * lead to an existing file.
+ *
+ * The file specicifation may be formed in one of two ways:
+ *
+ * (1) If the library file contained an absolute
+ * path/file specification then this becomes filspc.
+ * (i.e. C:\...)
+ *
+ * (2) If the library file contains a relative path/file
+ * specification then the concatenation of the path
+ * and this file specification becomes filspc.
+ * (i.e. \...)
+ *
+ * The structure lbfile is created for the first library
+ * object file which contains the definition for the
+ * specified undefined symbol.
+ *
+ * If the library file [.LIB] contains file specifications for
+ * non existant files, no errors are returned.
+ *
+ * local variables:
+ * char buf[] [.REL] file input line
+ * char c [.REL] file input character
+ * FILE *fp file handle for object file
+ * lbfile *lbf temporary pointer
+ * lbfile *lbfh pointer to lbfile structure
+ * FILE *libfp file handle for library file
+ * lbname *lbnh pointer to lbname structure
+ * char *path file specification path
+ * char relfil[] [.REL] file specification
+ * char *str combined path and file specification
+ * char symname[] [.REL] file symbol string
+ *
+ * global variables:
+ * lbname *lbnhead The pointer to the first
+ * name structure
+ * lbfile *lbfhead The pointer to the first
+ * file structure
+ *
+ * functions called:
+ * int fclose() c_library
+ * int fgets() c_library
+ * FILE *fopen() c_library
+ * VOID free() c_library
+ * char getnb() lklex.c
+ * VOID lkexit() lkmain.c
+ * VOID loadfile() lklibr.c
+ * VOID * new() lksym.c
+ * char * sprintf() c_library
+ * int sscanf() c_library
+ * char * strcat() c_library
+ * char * strchr() c_library
+ * char * strcpy() c_library
+ * int strlen() c_library
+ * int strncmp() c_library
+ * VOID unget() lklex.c
+ *
+ * side effects:
+ * If the symbol is found then a new lbfile structure
+ * is created and added to the linked list of lbfile
+ * structures. The file containing the found symbol
+ * is linked.
+ */
+
+#ifdef INDEXLIB
+
+int fndsym( char *name )
+{
+ struct lbfile *lbfh, *lbf;
+ pmlibraryfile ThisLibr;
+ pmlibrarysymbol ThisSym = NULL;
+
+ pmlibraryfile FirstFound;
+ int numfound=0;
+
+ /* Build the index if this is the first call to fndsym */
+ if (libr==NULL) buildlibraryindex();
+
+ /* Iterate through all library object files */
+ ThisLibr = libr;
+ FirstFound = libr; /*So gcc stops whining*/
+ while (ThisLibr)
+ {
+ /* Iterate through all symbols in an object file */
+ ThisSym = ThisLibr->symbols;
+
+ while (ThisSym)
+ {
+ //printf("ThisSym->name=%s\n", ThisSym->name);
+ if (!strcmp(ThisSym->name, name))
+ {
+ if ((!ThisLibr->loaded) && (numfound==0))
+ {
+ /* Object file is not loaded - add it to the list */
+ lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+ if (lbfhead == NULL)
+ {
+ lbfhead = lbfh;
+ }
+ else
+ {
+ lbf = lbfhead;
+ while (lbf->next)
+ lbf = lbf->next;
+ lbf->next = lbfh;
+ }
+ lbfh->libspc = ThisLibr->libspc;
+ lbfh->filspc = ThisLibr->filename;
+ lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
+ strcpy(lbfh->relfil,ThisLibr->relfil);
+ lbfh->offset = ThisLibr->offset;
+ if(lbfh->offset>0)
+ { /*For an embedded object file in a library*/
+ void loadfile_SdccLib(char * libspc, char * module, long offset);
+ loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+ }
+ else
+ { /*For a stand alone object file*/
+ loadfile(lbfh->filspc);
+ }
+ ThisLibr->loaded=1;
+ }
+
+ if(numfound==0)
+ {
+ numfound++;
+ FirstFound=ThisLibr;
+ }
+ else
+ {
+ char absPath1[PATH_MAX];
+ char absPath2[PATH_MAX];
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
+ int j;
+
+ _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
+ _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
+ for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
+ for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
+#else
+ realpath(FirstFound->libspc, absPath1);
+ realpath(ThisLibr->libspc, absPath2);
+#endif
+ if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
+ {
+ if(numfound==1)
+ {
+ fprintf(stderr, "?Aslink-Warning-Definition of public symbol '%s'"
+ " found more than once:\n", name);
+ fprintf(stderr, " Library: '%s', Module: '%s'\n",
+ FirstFound->libspc, FirstFound->relfil);
+ }
+ fprintf(stderr, " Library: '%s', Module: '%s'\n",
+ ThisLibr->libspc, ThisLibr->relfil);
+ numfound++;
+ }
+ }
+ }
+ ThisSym=ThisSym->next; /* Next sym in library */
+ }
+ ThisLibr=ThisLibr->next; /* Next library in list */
+ }
+ return numfound;
+}
+
+pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
+{
+ char ModName[NCPS]="";
+ char FLine[MAXLINE+1];
+ char buff[PATH_MAX];
+ int state=0;
+ long IndexOffset=0, FileOffset;
+ pmlibrarysymbol ThisSym = NULL;
+
+ while(!feof(libfp))
+ {
+ FLine[0]=0;
+ fgets(FLine, MAXLINE, libfp);
+ chop_crlf(FLine);
+
+ switch(state)
+ {
+ case 0:
+ if(EQ(FLine, "<INDEX>"))
+ {
+ /*The next line has the size of the index*/
+ FLine[0]=0;
+ fgets(FLine, MAXLINE, libfp);
+ chop_crlf(FLine);
+ IndexOffset=atol(FLine);
+ state=1;
+ }
+ break;
+ case 1:
+ if(EQ(FLine, "<MODULE>"))
+ {
+ /*The next line has the name of the module and the offset
+ of the corresponding embedded file in the library*/
+ FLine[0]=0;
+ fgets(FLine, MAXLINE, libfp);
+ chop_crlf(FLine);
+ sscanf(FLine, "%s %ld", ModName, &FileOffset);
+ state=2;
+
+ /*Create a new libraryfile object for this module*/
+ if(libr==NULL)
+ {
+ libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ }
+ else
+ {
+ This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ This=This->next;
+ }
+ This->next = NULL;
+ This->loaded=-1;
+ This->offset=FileOffset+IndexOffset;
+ This->libspc=PathLib;
+
+ This->relfil=(char *)new(strlen(ModName)+1);
+ strcpy(This->relfil, ModName);
+
+ sprintf(buff, "%s%s%c%s", DirLib, ModName, FSEPX, LKOBJEXT);
+ This->filename=(char *)new(strlen(buff)+1);
+ strcpy(This->filename, buff);
+
+ This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
+ }
+ else if(EQ(FLine, "</INDEX>"))
+ {
+ return This; /*Finish, get out of here*/
+ }
+ break;
+ case 2:
+ if(EQ(FLine, "</MODULE>"))
+ {
+ This->loaded=0;
+ /*Create the index for the next module*/
+ state=1;
+ }
+ else
+ {
+ /*Add the symbols*/
+ if(ThisSym==NULL) /*First symbol of the current module*/
+ {
+ ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ }
+ else
+ {
+ ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ ThisSym=ThisSym->next;
+ }
+ ThisSym->next=NULL;
+ ThisSym->name=(char *)new(strlen(FLine)+1);
+ strcpy(ThisSym->name, FLine);
+ }
+ break;
+
+ default:
+ return This; /*State machine should never reach this point, but just in case...*/
+ break;
+ }
+ }
+
+ return This; /*State machine should never reach this point, but just in case...*/
+}
+
+
+/* buildlibraryindex - build an in-memory cache of the symbols contained in
+ * the libraries
+ */
+int buildlibraryindex(void)
+{
+ FILE *libfp, *fp;
+ struct lbname *lbnh;
+ char relfil[NINPUT+2], str[PATH_MAX], *path;
+ char buf[NINPUT+2], c;
+ char symname[NINPUT+2];
+ pmlibraryfile This=NULL;
+ pmlibrarysymbol ThisSym;
+
+ /* Iterate through all library files */
+ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
+ {
+ if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
+ {
+ fprintf(stderr, "?Aslink-Error-Cannot open library file %s\n",
+ lbnh->libspc);
+ lkexit(1);
+ }
+
+ path=lbnh->path;
+
+ /*
+ * Read in a line from the library file.
+ * This is the relative file specification
+ * for a .REL file in this library.
+ */
+
+ while (fgets(relfil, NINPUT, libfp) != NULL)
+ {
+ relfil[NINPUT+1] = '\0';
+ chop_crlf(relfil);
+ if (path != NULL)
+ {
+ strcpy(str, path);
+#ifdef OTHERSYSTEM
+ if (str[strlen(str)-1] != LKDIRSEP)
+ {
+ strcat(str, LKDIRSEPSTR);
+ }
+#endif
+ }
+ else
+ {
+ strcpy(str, "");
+ }
+
+ if(strcmp(relfil, "<SDCCLIB>")==0)
+ {
+ /*Get the built in index of a library*/
+ This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
+ break; /*get the index for next library*/
+ }
+
+ /*From here down, build the index for the original library format*/
+
+ if (relfil[0] == LKDIRSEP)
+ {
+ strcat(str, relfil+1);
+ }
+ else
+ {
+ strcat(str, relfil);
+ }
+
+ if(strchr(relfil, FSEPX) == NULL)
+ {
+ sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
+ }
+
+ if ((fp = fopen(str, "r")) != NULL)
+ {
+ /* Opened OK - create a new libraryfile object for it */
+ if(libr==NULL)
+ {
+ libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ }
+ else
+ {
+ This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
+ This=This->next;
+ }
+
+ This->next = NULL;
+ This->loaded=-1;
+ This->offset=-1; /*There should be a rel file*/
+ This->libspc = lbnh->libspc;
+ This->relfil=(char *)new(strlen(relfil)+1);
+ strcpy(This->relfil, relfil);
+ This->filename=(char *)new(strlen(str)+1);
+ strcpy(This->filename, str);
+
+ ThisSym = This->symbols = NULL;
+
+ /*
+ * Read in the object file. Look for lines that
+ * begin with "S" and end with "D". These are
+ * symbol table definitions. If we find one, see
+ * if it is our symbol. Make sure we only read in
+ * our object file and don't go into the next one.
+ */
+
+ while (fgets(buf, NINPUT, fp) != NULL)
+ {
+ buf[NINPUT+1] = '\0';
+ buf[strlen(buf) - 1] = '\0';
+
+ /*
+ * Skip everything that's not a symbol record.
+ */
+ if (buf[0] != 'S') continue;
+
+ /*
+ * When a 'T line' is found terminate file scan.
+ * All 'S line's preceed 'T line's in .REL files.
+ */
+ if (buf[0] == 'T') break;
+
+ sscanf(buf, "S %s %c", symname, &c);
+
+ /* If it's an actual symbol, record it */
+ if (c == 'D')
+ {
+ if(ThisSym==NULL)
+ {
+ ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ }
+ else
+ {
+ ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
+ ThisSym=ThisSym->next;
+ }
+ This->loaded=0;
+ ThisSym->next=NULL;
+ ThisSym->name=(char *)new(strlen(symname)+1);
+ strcpy(ThisSym->name, symname);
+ }
+ } /* Closes while - read object file */
+ fclose(fp);
+ } /* Closes if object file opened OK */
+ } /* Ends while - processing all in libr */
+ fclose(libfp);
+ } /* Ends good open of libr file */
+ return 0;
+}
+
+/*Release all memory allocated for the in-memory library index*/
+void freelibraryindex (void)
+{
+ pmlibraryfile ThisLibr, ThisLibr2Free;
+ pmlibrarysymbol ThisSym, ThisSym2Free;
+
+ ThisLibr = libr;
+
+ while (ThisLibr)
+ {
+ ThisSym = ThisLibr->symbols;
+
+ while (ThisSym)
+ {
+ free(ThisSym->name);
+ ThisSym2Free=ThisSym;
+ ThisSym=ThisSym->next;
+ free(ThisSym2Free);
+ }
+ free(ThisLibr->filename);
+ free(ThisLibr->relfil);
+ ThisLibr2Free=ThisLibr;
+ ThisLibr=ThisLibr->next;
+ free(ThisLibr2Free);
+ }
+
+ libr=NULL;
+}
+
+#else /* INDEXLIB */
+
+
+/*Check for a symbol in a SDCC library. If found, add the embedded .rel.
+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)], "%c%s", FSEPX, LKOBJEXT);
+
+ /*If this module has been loaded already don't load it again.*/
+ lbf = lbfhead;
+ while (lbf)
+ {
+ if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
+ lbf=lbf->next;
+ }
+
+ /*Add the embedded file to the list of files to be loaded in
+ the second pass. That is performed latter by the function
+ library() below.*/
+ lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+ if (lbfhead == NULL)
+ {
+ lbfhead = lbfh;
+ }
+ else
+ {
+ lbf = lbfhead;
+ while (lbf->next)
+ lbf = lbf->next;
+ lbf->next = lbfh;
+ }
+
+ lbfh->libspc = PathLib;
+ lbfh->filspc = DirLib;
+ lbfh->relfil = (char *) new (strlen(ModName) + 1);
+ strcpy(lbfh->relfil, ModName);
+ /*Library embedded file, so lbfh->offset must be >=0*/
+ lbfh->offset = IndexOffset+FileOffset;
+
+ /*Jump to where the .rel begins and load it.*/
+ fseek(libfp, lbfh->offset, SEEK_SET);
+ LoadRel(PathLib, libfp, ModName);
+
+ 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*/
+}
+
+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".
+ */
+
+/*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
+ if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
+ fprintf(stderr, "Cannot open library file %s\n",
+ lbnh->libspc);
+ lkexit(1);
+ }
+ path = lbnh->path;
+
+ /*
+ * Read in a line from the library file.
+ * This is the relative file specification
+ * for a .REL file in this library.
+ */
+
+/*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
+ relfil[NINPUT+1] = '\0';
+ chop_crlf(relfil);
+ if (path != NULL) {
+ str = (char *) new (strlen(path)+strlen(relfil)+6);
+ strcpy(str,path);
+#ifdef OTHERSYSTEM
+#ifdef SDK
+#ifdef UNIX
+ if (str[strlen(str)-1] != '/') {
+ strcat(str,"/");
+#else /* UNIX */
+ if (str[strlen(str)-1] != '\\') {
+ strcat(str,"\\");
+#endif /* UNIX */
+#else /* SDK */
+ if (str[strlen(str)-1] != '\\') {
+ strcat(str,"\\");
+#endif /* SDK */
+ }
+#endif
+ } else {
+ str = (char *) new (strlen(relfil) + 5);
+ }
+
+ /*See if this is a library with embedded files*/
+ if(strcmp(relfil, "<SDCCLIB>")==0)
+ {
+ result=SdccLib(lbnh->libspc, libfp, str, name);
+ if(result) return(1); /*Found the symbol*/
+ free(str);
+ /*The symbol is not in the current library,
+ check the next library in the list*/
+ break;
+ }
+
+ /*From here down is the support for libraries in the original format*/
+#ifdef SDK
+#ifdef UNIX
+ if (relfil[0] == '/') {
+#else /* UNIX */
+ if (relfil[0] == '\\') {
+#endif /* UNIX */
+#else /* SDK */
+ if (relfil[0] == '\\') {
+#endif /* SDK */
+ strcat(str,relfil+1);
+ } else {
+ strcat(str,relfil);
+ }
+ if(strchr(relfil, FSEPX) == NULL)
+ {
+ sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
+ }
+
+/*3*/ if ((fp = fopen(str, "r")) != NULL) {
+
+ /*
+ * Read in the object file. Look for lines that
+ * begin with "S" and end with "D". These are
+ * symbol table definitions. If we find one, see
+ * if it is our symbol. Make sure we only read in
+ * our object file and don't go into the next one.
+ */
+
+/*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
+
+ buf[NINPUT+1] = '\0';
+ buf[strlen(buf) - 1] = '\0';
+
+ /*
+ * Skip everything that's not a symbol record.
+ */
+ if (buf[0] != 'S')
+ continue;
+
+ /*
+ * When a 'T line' is found terminate file scan.
+ * All 'S line's preceed 'T line's in .REL files.
+ */
+ if (buf[0] == 'T')
+ break;
+
+ sscanf(buf, "S %s %c", symname, &c);
+
+ /*
+ * If we find a symbol definition for the
+ * symbol we're looking for, load in the
+ * file and add it to lbfhead so it gets
+ * loaded on pass number 2.
+ */
+/*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
+
+ lbfh = (struct lbfile *) new (sizeof(struct lbfile));
+ if (lbfhead == NULL) {
+ lbfhead = lbfh;
+ } else {
+ lbf = lbfhead;
+ while (lbf->next)
+ lbf = lbf->next;
+ lbf->next = lbfh;
+ }
+ lbfh->libspc = lbnh->libspc;
+ lbfh->filspc = str;
+ lbfh->relfil = (char *) new (strlen(relfil) + 1);
+ lbfh->offset = -1; /*Stand alone rel file*/
+ strcpy(lbfh->relfil,relfil);
+ fclose(fp);
+ fclose(libfp);
+ loadfile(str);
+ return (1);
+
+/*5*/ }
+
+/*4*/ }
+ fclose(fp);
+/*3*/ }
+
+ free(str);
+/*2*/ }
+ fclose(libfp);
+/*1*/ }
+ return(0);
+}
+#endif /* INDEXLIB */
+
+void loadfile_SdccLib(char * libspc, char * module, long offset)
+{
+ FILE *fp;
+
+#ifdef __CYGWIN__
+ char posix_path[PATH_MAX];
+ void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
+ cygwin_conv_to_full_posix_path(libspc, posix_path);
+ fp = fopen(posix_path, "r");
+#else
+ fp = fopen(libspc,"r");
+#endif
+
+ if (fp != NULL)
+ {
+ fseek(fp, offset, SEEK_SET);
+ LoadRel(libspc, fp, module);
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "?Aslink-Error-Opening library '%s'\n", libspc);
+ lkexit(1);
+ }
+}
+
+/*)Function VOID library()
+ *
+ * The function library() links all the library object files
+ * contained in the lbfile structures.
+ *
+ * local variables:
+ * lbfile *lbfh pointer to lbfile structure
+ *
+ * global variables:
+ * lbfile *lbfhead pointer to first lbfile structure
+ *
+ * functions called:
+ * VOID loadfile lklibr.c
+ *
+ * side effects:
+ * Links all files contained in the lbfile structures.
+ */
+
+VOID
+library()
+{
+ struct lbfile *lbfh;
+
+ for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
+ {
+ if(lbfh->offset<0)
+ {
+ /*Stand alone rel file (original lib format)*/
+ loadfile(lbfh->filspc);
+ }
+ else
+ {
+ /*rel file embedded in lib (new lib format)*/
+ loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
+ }
+ }
+#ifdef INDEXLIB
+ freelibraryindex();
+#endif
+}
+
+/*)Function VOID loadfile(filspc)
+ *
+ * char *filspc library object file specification
+ *
+ * The function loadfile() links the library object module.
+ *
+ * local variables:
+ * FILE *fp file handle
+ * int i input line length
+ * char str[] file input line
+ *
+ * global variables:
+ * char *ip pointer to linker input string
+ *
+ * functions called:
+ * int fclose() c_library
+ * int fgets() c_library
+ * FILE * fopen() c_library
+ * VOID link() lkmain.c
+ * int strlen() c_library
+ *
+ * side effects:
+ * If file exists it is linked.
+ */
+
+VOID
+loadfile(filspc)
+char *filspc;
+{
+ FILE *fp;
+ char str[NINPUT+2];
+ int i;
+
+#ifdef __CYGWIN__
+ char posix_path[PATH_MAX];
+ void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
+ cygwin_conv_to_full_posix_path(filspc, posix_path);
+ fp = fopen(posix_path, "r");
+#else
+ fp = fopen(filspc,"r");
+#endif
+
+ if (fp != NULL)
+ {
+ while (fgets(str, NINPUT, fp) != NULL)
+ {
+ str[NINPUT+1] = '\0';
+ i = strlen(str) - 1;
+ if (str[i] == '\n')
+ str[i] = '\0';
+ ip = str;
+ link();
+ }
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "?Aslink-Error-Opening library '%s'\n", filspc);
+ lkexit(1);
+ }
+}
--- /dev/null
+/* lklist.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+/*)Module 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, "Hexidecimal\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;
+}
+
+#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.
+ */
+
+#ifndef MLH_MAP
+VOID
+lstarea(xp)
+struct area *xp;
+{
+// register struct area *op;
+ register struct areax *oxp;
+ register c, i, j;
+ register char *ptr;
+ int nmsym;
+ Addr_T a0, ai, aj;
+ struct sym *sp;
+ struct sym **p;
+
+ putc('\n', mfp);
+ if (xflag == 0) {
+ fprintf(mfp, "Hexidecimal\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 Bytes (Attributes)\n");
+ fprintf(mfp, "-------------------------------- ");
+ fprintf(mfp, "---- ---- ------- ----- ------------\n");
+ /*
+ * 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");
+ }
+ 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;
+ }
+
+ /*
+ * 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;
+ }
+ }
+
+ /*
+ * Symbol Table Output
+ */
+ i = 0;
+ fprintf(mfp, "\n\n");
+ fprintf(mfp, " Value Global\n");
+ fprintf(mfp, " ----- --------------------------------");
+ while (i < nmsym) {
+ fprintf(mfp, "\n");
+ 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];
+ while (ptr < &sp->s_id[NCPS]) {
+ if ((c = *ptr++) != 0) {
+ putc(c, mfp);
+ } else {
+ putc(' ', mfp);
+ }
+ }
+ i++;
+ }
+ putc('\n', mfp);
+ free(p);
+}
+#else
+VOID lstarea(struct area *xp)
+{
+ register struct areax *oxp;
+ register int i, j;
+ int nmsym;
+ Addr_T a0, ai = 0, aj = 0;
+ struct sym *sp;
+ struct sym **p;
+
+ /*
+ * 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;
+ }
+
+ /*
+ * Symbol Table Output
+ */
+ if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
+ fprintf(mfp, "AREA %s\n", xp->a_id );
+ switch (xflag) {
+ case 1:
+ fprintf(mfp, "\tRADIX OCTAL\n" );
+ break;
+ case 2:
+ fprintf(mfp, "\tRADIX DEC\n" );
+ break;
+ default:
+ fprintf(mfp, "\tRADIX HEX\n" );
+ break;
+ }
+ fprintf( mfp, "\tBASE %04X\n"
+ "\tSIZE %04X\n"
+ "\tATTRIB "
+ , xp->a_addr, xp->a_size );
+ 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");
+ }
+ 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"); }
+ }
+
+ fprintf( mfp,"\n");
+ if (nmsym>0) {
+ /*
+ * 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;
+ }
+
+ /*
+ * 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;
+ }
+ }
+
+ fprintf( mfp, "\tGLOBALS\n");
+ i = 0;
+ while (i < nmsym) {
+ fprintf(mfp, "\t\t%s\t%04X\n", p[i]->s_id, p[i]->s_addr + p[i]->s_axp->a_addr );
+ i++;
+ }
+ free(p);
+ }
+ }
+}
+#endif /* MLH_MAP */
+#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;
+
+ 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");
+ }
+ 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;
+ }
+
+ /*
+ * 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;
+ }
+ }
+
+ /*
+ * Symbol Table Output
+ */
+ i = 0;
+ while (i < nmsym) {
+ if (i % 4 == 0) {
+ 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];
+ while (ptr < &sp->s_id[NCPS]) {
+ if ((c = *ptr++) != 0) {
+ putc(c, mfp);
+ } else {
+ putc(' ', mfp);
+ }
+ }
+ if (++i < nmsym)
+ if (i % 4 != 0)
+ fprintf(mfp, " | ");
+ }
+ putc('\n', mfp);
+ free(p);
+ slew(mfp);
+}
+#endif
+
+#ifdef SDK
+VOID lstareatosym(struct area *xp)
+{
+ /* Output the current area symbols to a NO$GMB .sym file */
+ register struct areax *oxp;
+ register int i, j;
+ int nmsym;
+ Addr_T a0, ai;
+ struct sym *sp;
+ struct sym **p;
+
+ /*
+ * 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;
+ }
+
+ /*
+ * Symbol Table Output
+ */
+ if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
+ /* Dont worry about any area information */
+ fprintf(mfp, "; Area: %s\n", xp->a_id );
+ if (nmsym>0) {
+ /*
+ * 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;
+ }
+
+ /*
+ * 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;
+ }
+ }
+ i = 0;
+ while (i < nmsym) {
+ /* no$gmb requires the symbol names to be less than 32 chars long. Truncate. */
+ char name[32];
+ strncpy(name, p[i]->s_id, 31);
+ name[31] = '\0';
+ if ((strncmp("l__", name, 3)!=0)&&(strchr(name,' ')==NULL)) {
+ a0=p[i]->s_addr + p[i]->s_axp->a_addr;
+ if (a0>0x7FFFU) {
+ /* Not inside the ROM, so treat as being in bank zero */
+ fprintf(mfp, "00:%04X %s\n", a0, name);
+ }
+ else {
+ fprintf(mfp, "%02X:%04X %s\n", a0/16384, a0, name);
+ }
+ }
+ i++;
+ }
+ free(p);
+ }
+ }
+}
+#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, rb);
+
+ while (fgets(rb, sizeof(rb), tfp) != 0) {
+ fprintf(rfp, 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, 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, rb);
+ goto loop;
+ }
+
+ /*
+ * Must have an address in the expected radix
+ */
+ if (radix == 16) {
+ if (!dgt(RAD16, &rb[3], 4)) {
+ fprintf(rfp, rb);
+ goto loop;
+ }
+ sprintf(str, "%04X", pc);
+ strncpy(&rb[3], str, 4);
+ } else
+ if (radix == 10) {
+ if (!dgt(RAD10, &rb[3], 5)) {
+ fprintf(rfp, rb);
+ goto loop;
+ }
+ sprintf(str, "%05d", pc);
+ strncpy(&rb[3], str, 5);
+ } else
+ if (radix == 8) {
+ if (!dgt(RAD8, &rb[3], 6)) {
+ fprintf(rfp, rb);
+ goto loop;
+ }
+ sprintf(str, "%06o", pc);
+ strncpy(&rb[3], str, 6);
+ }
+
+ /*
+ * Copy updated LST text line to RST
+ */
+ fprintf(rfp, 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, 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, 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, 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, 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, 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, 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, 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[(unsigned char)(*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
+ */
+
+/*
+ * Extensions: P. Felber
+ */
+
+#include <stdio.h>
+#include <string.h>
+//#include <alloc.h>
+#include "aslink.h"
+#include <stdlib.h>
+
+#ifndef SDK_VERSION_STRING
+#define SDK_VERSION_STRING "3.0.0"
+#endif
+#ifndef TARGET_STRING
+#define TARGET_STRING "gbz80"
+#endif
+
+#ifdef WIN32T
+#include <time.h>
+
+void Timer(int action, char * message)
+{
+ static double start, end, total=0.0;
+ static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+
+ if(action==0) start=clock()*secs_per_tick;
+ else if(action==1)
+ {
+ end=clock() * secs_per_tick;
+ printf("%s \t%f seconds.\n", message, (end-start));
+ total+=end-start;
+ }
+ else
+ {
+ printf("Total time: \t%f seconds.\n", total);
+ total=0.0;
+ }
+}
+#endif
+
+/*)Module lkmain.c
+ *
+ * The module lkmain.c contains the functions which
+ * (1) input the linker options, parameters, and specifications
+ * (2) perform a two pass link
+ * (3) produce the appropriate linked data output and/or
+ * link map file and/or relocated listing files.
+ *
+ * lkmain.c contains the following functions:
+ * FILE * afile(fn,ft,wf)
+ * VOID bassav()
+ * VOID gblsav()
+ * VOID link()
+ * 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
+ *
+ */
+
+/*)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 lk_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 lk_getline() lklex.c
+ * VOID library() lklibr.c
+ * VOID link() 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).
+ */
+
+#ifdef SDK
+int binary = 0;
+#endif /* SDK */
+#ifdef GAMEBOY
+char *default_basep[] = {
+ "_CODE=0x0200",
+ "_DATA=0xC0A0",
+ NULL
+};
+
+char *default_globlp[] = {
+ /* DMA transfer must start at multiples of 0x100 */
+ ".OAM=0xC000",
+ ".STACK=0xE000",
+ ".refresh_OAM=0xFF80",
+
+ ".init=0x0000",
+
+ NULL
+};
+#endif /* GAMEBOY */
+
+int
+main(argc, argv)
+char *argv[];
+{
+ register char *p;
+ register int c, i;
+
+#ifdef WIN32T
+ Timer(0, "");
+#endif
+
+#ifdef GAMEBOY
+ nb_rom_banks = 2;
+ nb_ram_banks = 0;
+ mbc_type = 0;
+ symflag=0;
+
+ for(i = 0; default_basep[i] != NULL; i++) {
+ 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;
+ }
+ bsp->b_strp = default_basep[i];
+ }
+ for(i = 0; default_globlp[i] != NULL; i++) {
+ 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;
+ }
+ gsp->g_strp = default_globlp[i];
+ }
+#endif /* GAMEBOY */
+#ifndef SDK
+ fprintf(stdout, "\n");
+#endif /* SDK */
+
+ 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();
+ }
+ }
+
+#ifdef SDK
+ if(c == '-') {
+ startp->f_type = F_CMD;
+ startp->f_idp = (char *)&argv[i+1];
+ break;
+ }
+#endif /* SDK */
+
+ } else {
+ if (startp->f_type == F_LNK) {
+ startp->f_idp = p;
+ }
+ }
+ }
+ if (startp->f_type == F_INV)
+ usage();
+ if (startp->f_type == F_LNK && startp->f_idp == NULL)
+ usage();
+#ifdef SDK
+ if (startp->f_type == F_CMD && startp->f_idp == NULL)
+ usage();
+#endif /* SDK */
+
+ cfp = NULL;
+ sfp = NULL;
+ filep = startp;
+ while (1) {
+ ip = ib;
+ if (lk_getline() == 0)
+ break;
+ if (pflag && sfp != stdin)
+ fprintf(stdout, "%s\n", ip);
+ if (*ip == '\0' || parse())
+ break;
+ }
+ if (sfp)
+ fclose(sfp);
+ if (linkp == NULL)
+ usage();
+#ifdef SDK
+ if (linkp->f_flp == NULL)
+ usage();
+#endif /* SDK */
+
+#ifdef GAMEBOY
+ for(i = 1; i < nb_rom_banks; i++) {
+ bsp->b_base = (struct base *)new(sizeof(struct base));
+ bsp = bsp->b_base;
+ bsp->b_strp = (char *)malloc(18);
+ sprintf(bsp->b_strp, "_CODE_%d=0x4000", i);
+ }
+ for(i = 0; i < nb_ram_banks; i++) {
+ bsp->b_base = (struct base *)new(sizeof(struct base));
+ bsp = bsp->b_base;
+ bsp->b_strp = (char *)malloc(18);
+ sprintf(bsp->b_strp, "_DATA_%d=0xA000", i);
+ }
+#endif /* GAMEBOY */
+
+ syminit();
+ for (pass=0; pass<2; ++pass) {
+ cfp = NULL;
+ sfp = NULL;
+#ifdef SDK
+ filep = linkp->f_flp;
+#else /* SDK */
+ filep = linkp;
+#endif /* SDK */
+ hp = NULL;
+ radix = 10;
+
+ while (lk_getline()) {
+ ip = ib;
+ link();
+ }
+ 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);
+#ifdef SDK
+ if (symflag)
+ sym();
+#endif
+ /*
+ * Output Link Map.
+ */
+ if (mflag)
+ map();
+ /*
+ * Open output file
+ */
+ if (oflag == 1) {
+#ifdef SDK
+ ofp = afile(linkp->f_idp, "ihx", 1);
+#else /* SDK */
+ ofp = afile(linkp->f_idp, "IHX", 1);
+#endif /* SDK */
+ if (ofp == NULL) {
+ lkexit(1);
+ }
+ } else
+ if (oflag == 2) {
+#ifdef SDK
+ ofp = afile(linkp->f_idp, "s19", 1);
+#else /* SDK */
+ ofp = afile(linkp->f_idp, "S19", 1);
+#endif /* SDK */
+ if (ofp == NULL) {
+ lkexit(1);
+ }
+#ifdef SDK
+ } else
+ if (oflag == 3) {
+ binary = 1;
+ ofp = afile(linkp->f_idp, "", 1);
+ binary = 0;
+ if (ofp == NULL) {
+ lkexit(1);
+ }
+#endif /* SDK */
+ }
+ } else {
+ /*
+ * Link in library files
+ */
+ library();
+ reloc('E');
+ }
+ }
+#ifdef WIN32T
+ Timer(1, "Linker time");
+#endif
+ lkexit(lkerr);
+
+ /* Never get here. */
+ 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 (ofp != NULL) fclose(ofp);
+ if (rfp != NULL) fclose(rfp);
+ if (sfp != NULL) fclose(sfp);
+ if (tfp != NULL) fclose(tfp);
+ exit(i);
+}
+
+/*)Function link()
+ *
+ * The function link() 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()
+{
+ 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.
+ */
+
+#ifndef MLH_MAP
+VOID
+map()
+{
+ register i;
+ register struct head *hdp;
+ register struct lbfile *lbfh;
+
+ /*
+ * Open Map File
+ */
+#ifdef SDK
+ mfp = afile(linkp->f_idp, "map", 1);
+#else /* SDK */
+ mfp = afile(linkp->f_idp, "MAP", 1);
+#endif /* SDK */
+ 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;
+#ifdef SDK
+ filep = linkp->f_flp;
+#else /* SDK */
+ filep = linkp;
+#endif /* SDK */
+ 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);
+}
+#else
+VOID map()
+{
+ register struct head *hdp;
+ register struct lbfile *lbfh;
+
+ /*
+ * Open Map File
+ */
+#ifdef SDK
+ mfp = afile(linkp->f_idp, "map", 1);
+#else /* SDK */
+ mfp = afile(linkp->f_idp, "MAP", 1);
+#endif /* SDK */
+ 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
+ */
+ hdp = headp;
+#ifdef SDK
+ filep = linkp->f_flp;
+#else /* SDK */
+ filep = linkp;
+#endif /* SDK */
+ if (filep) {
+ fprintf( mfp, "MODULES\n");
+ }
+ while (filep) {
+ fprintf(mfp, "\tFILE %s\n", filep->f_idp);
+ while ((hdp != NULL) && (hdp->h_lfile == filep)) {
+ if (strlen(hdp->m_id)>0)
+ fprintf(mfp, "\t\tNAME %s\n", hdp->m_id);
+ hdp = hdp->h_hp;
+ }
+ filep = filep->f_flp;
+ }
+ /*
+ * List Linked Libraries
+ */
+ if (lbfhead != NULL) {
+ fprintf(mfp, "LIBRARIES\n");
+ for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
+ fprintf(mfp, "\tLIBRARY %s\n"
+ "\t\tMODULE %s\n",
+ lbfh->libspc, lbfh->relfil);
+ }
+ }
+ /*
+ * List Base Address Definitions
+ */
+ if (basep) {
+ fprintf(mfp, "USERBASEDEF\n");
+ bsp = basep;
+ while (bsp) {
+ fprintf(mfp, "\t%s\n", bsp->b_strp);
+ bsp = bsp->b_base;
+ }
+ }
+ /*
+ * List Global Definitions
+ */
+ if (globlp) {
+ fprintf(mfp, "USERGLOBALDEF\n");
+ gsp = globlp;
+ while (gsp) {
+ fprintf(mfp, "\t%s\n", gsp->g_strp);
+ gsp = gsp->g_globl;
+ }
+ }
+ symdef(mfp);
+#ifdef SDK
+ if (mfp!=NULL) {
+ fclose(mfp);
+ mfp = NULL;
+ }
+#endif
+}
+#endif /* MLH_MAP */
+
+#ifdef SDK
+/* PENDING */
+VOID lstareatosym(struct area *xp);
+
+VOID sym()
+{
+ /*
+ * Open sym File
+ */
+ mfp = afile(linkp->f_idp, "sym", 1);
+ if (mfp == NULL) {
+ lkexit(1);
+ }
+ fprintf( mfp, "; no$gmb format .sym file\n"
+ "; Generated automagically by ASxxxx linker %s (SDK " SDK_VERSION_STRING ")\n"
+ , VERSION );
+ /*
+ * Output sym Area Lists
+ */
+ page = 0;
+ lop = NLPP;
+ ap = areap;
+ while (ap) {
+ lstareatosym(ap);
+ ap = ap->a_ap;
+ }
+ if (mfp!=NULL) {
+ fclose(mfp);
+ mfp = NULL;
+ }
+}
+#endif /* SDK */
+
+/*)Function int parse()
+ *
+ * The function parse() evaluates all command line or file input
+ * linker directives and updates the appropriate variables.
+ *
+ * local variables:
+ * int c character value
+ * char fid[] file id string
+ *
+ * global variables:
+ * char ctype[] array of character types, one per
+ * ASCII character
+ * lfile *lfp pointer to current lfile structure
+ * being processed by parse()
+ * lfile *linkp pointer to first lfile structure
+ * containing an input REL file
+ * specification
+ * int mflag Map output flag
+ * int oflag Output file type flag
+ * int pflag print linker command file flag
+ * FILE * stderr c_library
+ * int uflag Relocated listing flag
+ * int xflag Map file radix type flag
+ *
+ * Functions called:
+ * VOID addlib() lklibr.c
+ * VOID addpath() lklibr.c
+ * VOID bassav() lkmain.c
+ * int fprintf() c_library
+ * VOID gblsav() lkmain.c
+ * VOID getfid() lklex.c
+ * char getnb() lklex.c
+ * VOID lkexit() lkmain.c
+ * char * strcpy() c_library
+ * int strlen() c_library
+ *
+ * side effects:
+ * Various linker flags are updated and the linked
+ * structure lfile is created.
+ */
+
+int
+parse()
+{
+ register int c;
+ char fid[NINPUT];
+
+ while ((c = getnb()) != 0) {
+ if (c == ';')
+ return(0);
+ if ( c == '-') {
+ while (ctype[c=get()] & LETTER) {
+ switch(c) {
+
+ case 'i':
+ case 'I':
+ oflag = 1;
+ break;
+
+ case 's':
+ case 'S':
+ oflag = 2;
+ break;
+#ifdef GAMEBOY
+ case 'y':
+ case 'Y':
+ c = get();
+ if(c == 'O' || c == 'o')
+ nb_rom_banks = expr(0);
+ else if(c == 'A' || c == 'a')
+ nb_ram_banks = expr(0);
+ else if(c == 'T' || c == 't')
+ mbc_type = expr(0);
+ else if(c == 'N' || c == 'n') {
+ int i = 0;
+ if(getnb() != '=' || getnb() != '"') {
+ fprintf(stderr, "Syntax error in -YN=\"name\" flag\n");
+ lkexit(1);
+ }
+ while((c = get()) != '"' && i < 16) {
+ cart_name[i++] = c;
+ }
+ if(i < 16)
+ cart_name[i] = 0;
+ else
+ while(get() != '"')
+ ;
+ } else if(c == 'P' || c == 'p') {
+ patch *p = patches;
+
+ patches = (patch *)malloc(sizeof(patch));
+ patches->next = p;
+ patches->addr = expr(0);
+ if(getnb() != '=') {
+ fprintf(stderr, "Syntax error in -YHaddr=val flag\n");
+ lkexit(1);
+ }
+ patches->value = expr(0);
+ } else {
+ fprintf(stderr, "Invalid option\n");
+ lkexit(1);
+ }
+ break;
+
+#endif /* GAMEBOY */
+#ifdef SDK
+ case 'j':
+ case 'J':
+ ++symflag;
+ break;
+ case 'z':
+ case 'Z':
+ oflag = 3;
+ break;
+#endif /* SDK */
+ case 'm':
+ case 'M':
+ ++mflag;
+ break;
+
+ case 'u':
+ case 'U':
+ uflag = 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);
+
+ default:
+ fprintf(stderr, "Invalid option\n");
+ lkexit(1);
+ }
+ }
+ if (c == ';')
+ return(0);
+ } else
+ if (ctype[c] != ILL) {
+ 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;
+ } else {
+ fprintf(stderr, "Invalid input");
+ lkexit(1);
+ }
+ }
+ 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) {
+#ifndef SDK
+ fprintf(stderr,
+ "No definition of area %s\n", id);
+ lkerr++;
+#endif /* SDK */
+ } else {
+ ap->a_addr = v;
+ }
+ } else {
+ fprintf(stderr, "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) {
+#ifndef SDK
+ fprintf(stderr,
+ "No definition of symbol %s\n", id);
+ lkerr++;
+#endif /* SDK */
+ } else {
+#ifndef SDK
+ if (sp->s_flag & S_DEF) {
+ fprintf(stderr,
+ "Redefinition of symbol %s\n", id);
+ lkerr++;
+ sp->s_axp = NULL;
+ }
+#endif /* SDK */
+ 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:
+ * int c character value
+ * char fb[] constructed file specification string
+ * 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:
+ * 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;
+{
+#if 0
+ register char *p1, *p2, *p3;
+ register int c;
+#else
+ int i;
+#endif
+ FILE *fp;
+ char fb[FILSPC];
+
+#if 0
+ p1 = fn;
+ p2 = fb;
+ p3 = ft;
+ while ((c = *p1++) != 0 && c != FSEPX) {
+ if (p2 < &fb[FILSPC-4])
+ *p2++ = c;
+ }
+ *p2++ = FSEPX;
+ if (*p3 == 0) {
+ if (c == FSEPX) {
+ p3 = p1;
+ } else {
+#ifdef SDK
+ p3 = "rel";
+#else /* SDK */
+ p3 = "REL";
+#endif /* SDK */
+ }
+ }
+ while ((c = *p3++) != 0) {
+ if (p2 < &fb[FILSPC-1])
+ *p2++ = c;
+ }
+ *p2++ = 0;
+#else
+ /*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]=='.') && *ft && strcmp(ft, "lnk") )
+ {
+ strncpy(fb, fn, i);
+ fb[i]=0;
+ }
+ else
+ {
+ strcpy(fb, fn);
+ }
+
+ /*Add the extension*/
+ if (fb[i] != '.')
+ {
+ strcat(fb, ".");
+#ifdef SDK
+ strcat(fb, strlen(ft)?ft:"rel");
+#else
+ strcat(fb, strlen(ft)?ft:"REL");
+#endif
+ }
+#endif
+
+#ifdef SDK
+ if ((fp = fopen(fb, wf?(binary?"wb":"w"):(binary?"rb":"r"))) == NULL) {
+#else /* SDK */
+ if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
+#endif /* SDK */
+ fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
+ lkerr++;
+ }
+ return (fp);
+}
+
+char *usetxt[] = {
+#ifdef SDK
+ "Distributed with SDK " SDK_VERSION_STRING ", built on " __DATE__ " " __TIME__,
+ "Compile options: SDK Target " TARGET_STRING
+#ifdef INDEXLIB
+ " INDEXLIB"
+#endif
+ "\n",
+#endif
+ "Startup:",
+#ifdef SDK
+ " -- [Commands] Non-interactive command line input",
+#endif /* SDK */
+ " -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",
+#ifdef SDK
+ "Usage: [-Options] outfile file [file ...]",
+#else /* SDK */
+ "Usage: [-Options] file [file ...]",
+#endif /* SDK */
+ "Librarys:",
+ " -k Library path specification, one per -k",
+ " -l Library file specification, one per -l",
+ "Relocation:",
+ " -b area base address = expression",
+ " -g global symbol = expression",
+#ifdef GAMEBOY
+ " -yo Number of rom banks (default: 2)",
+ " -ya Number of ram banks (default: 0)",
+ " -yt MBC type (default: no MBC)",
+ " -yn Name of program (default: name of output file)",
+ " -yp# Patch one byte in the output GB file (# is: addr=byte)",
+#endif /* GAMEBOY */
+ "Map format:",
+ " -m Map output generated as file[MAP]",
+#ifdef SDK
+ " -j no$gmb symbol file generated as file[SYM]",
+#endif /* SDK */
+ " -x Hexidecimal (default)",
+ " -d Decimal",
+ " -q Octal",
+ "Output:",
+ " -i Intel Hex as file[IHX]",
+ " -s Motorola S19 as file[S19]",
+#ifdef SDK
+#ifdef GAMEGEAR
+ " -z Gamegear image as file[GG]",
+#else
+ " -z Gameboy image as file[GB]",
+#endif /* GAMEGEAR */
+#endif /* SDK */
+ "List:",
+ " -u Update listing file(s) with link data as file(s)[.RST]",
+ "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);
+}
--- /dev/null
+/* lkrloc.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+/*
+ * Extensions: P. Felber
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+//#include <alloc.h>
+#include <ctype.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[].
+ *
+ */
+
+/*)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 = 0, pags = 0, 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);
+
+#ifdef GAMEBOY
+ {
+ char *s = strrchr(a[aindex]->a_bap->a_id, '_');
+ if(s != NULL && isdigit((unsigned char)s[1]))
+ current_rom_bank = atoi(s+1);
+ else
+ current_rom_bank = 0;
+ }
+#endif /* GAMEBOY */
+ /*
+ * Do remaining relocations
+ */
+ while (more()) {
+ error = 0;
+ mode = eval();
+ 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_BYT2) {
+ if (mode & R_MSB) {
+ relv = adb_hi(reli, rtp);
+ } else {
+ relv = adb_lo(reli, rtp);
+ }
+ } else {
+ relv = adb_b(reli, rtp);
+ }
+ } else {
+ /*
+ * R_WORD with the R_BYT2 mode is flagged
+ * as an 'r' error by the assembler,
+ * but it is processed here anyway.
+ */
+ if (mode & R_BYT2) {
+ if (mode & R_MSB) {
+ relv = adw_hi(reli, rtp);
+ } else {
+ relv = adw_lo(reli, rtp);
+ }
+ } else {
+ 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);
+ }
+ if (oflag == 1) {
+ ihx(1);
+ } else
+ if (oflag == 2) {
+ s19(1);
+#ifdef SDK
+ } else
+ if (oflag == 3) {
+#ifdef GAMEGEAR
+ gg(1);
+#endif /* GAMEGEAR */
+#ifdef GAMEBOY
+ gb(1);
+#endif /* GAMEBOY */
+#endif /* SDK */
+ }
+}
+
+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);
+#ifdef SDK
+ } else
+ if (oflag == 3) {
+#ifdef GAMEGEAR
+ gg(0);
+#endif /* GAMEGEAR */
+#ifdef GAMEBOY
+ gb(0);
+#endif /* GAMEBOY */
+#endif /* SDK */
+ }
+}
+
+/*)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 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_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",
+ NCPS, &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 <alloc.h>
+#include "aslink.h"
+
+/*)Module lks19.c
+ *
+ * The module lks19.c contains the function to
+ * output the relocated object code in the
+ * Motorola S19 format.
+ *
+ * lks19.c contains the following function:
+ * VOID s19(i)
+ *
+ * lks19.c contains no local variables.
+ */
+
+/*)S19 Format
+ * Record Type Field - This field signifies the start of a
+ * record and identifies the the record
+ * type as follows:
+ *
+ * Ascii S1 - Data Record
+ * Ascii S9 - End of File Record
+ *
+ * Record Length Field - This field specifies the record length
+ * which includes the address, data, and
+ * checksum fields. The 8 bit record
+ * length value is converted to two ascii
+ * characters, high digit first.
+ *
+ * Load Address Field - This field consists of the four ascii
+ * characters which result from converting
+ * the the binary value of the address in
+ * which to begin loading this record. The
+ * order is as follows:
+ *
+ * High digit of high byte of address.
+ * Low digit of high byte of address.
+ * High digit of low byte of address.
+ * Low digit of low byte of address.
+ *
+ * In an End of File record this field con-
+ * sists of either four ascii zeros or the
+ * program entry address. Currently the
+ * entry address option is not supported.
+ *
+ * Data Field - This field consists of the actual data,
+ * converted to two ascii characters, high
+ * digit first. There are no data bytes in
+ * the End of File record.
+ *
+ * Checksum Field - The checksum field is the 8 bit binary
+ * sum of the record length field, the load
+ * address field, and the data field. This
+ * sum is then complemented (1's comple-
+ * ment) and converted to two ascii
+ * characters, high digit first.
+ */
+
+/*)Function s19(i)
+ *
+ * int i 0 - process data
+ * 1 - end of data
+ *
+ * The function s19() outputs the relocated data
+ * in the standard Motorola S19 format.
+ *
+ * local variables:
+ * Addr_T chksum byte checksum
+ *
+ * global variables:
+ * int hilo byte order
+ * FILE * ofp output file handle
+ * int rtcnt count of data words
+ * int rtflg[] output the data flag
+ * Addr_T rtval[] relocated data
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * The data is output to the file defined by ofp.
+ */
+
+VOID
+s19(i)
+{
+ register Addr_T chksum;
+
+ if (i) {
+ if (hilo == 0) {
+ chksum = rtval[0];
+ rtval[0] = rtval[1];
+ rtval[1] = chksum;
+ }
+ for (i = 0, chksum = 1; i < rtcnt; i++) {
+ if (rtflg[i])
+ chksum++;
+ }
+ fprintf(ofp, "S1%02X", chksum);
+ for (i = 0; i < rtcnt ; i++) {
+ if (rtflg[i]) {
+ fprintf(ofp, "%02X", rtval[i]);
+ chksum += rtval[i];
+ }
+ }
+ fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff);
+ } else {
+ fprintf(ofp, "S9030000FC\n");
+ }
+}
--- /dev/null
+/* lksym.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "aslink.h"
+
+/*)Module lksym.c
+ *
+ * The module lksym.c contains the functions that operate
+ * on the symbol structures.
+ *
+ * lksym.c contains the following functions:
+ * int hash()
+ * sym * lkpsym()
+ * VOID * new()
+ * sym * newsym()
+ * VOID symdef()
+ * int symeq()
+ * VOID syminit()
+ * VOID symmod()
+ * Addr_T symval()
+ *
+ * lksym.c contains no local/static variables.
+ */
+
+/*)Function VOID syminit()
+ *
+ * The function syminit() is called to clear the hashtable.
+ *
+ * local variables:
+ * int h computed hash value
+ * sym ** spp pointer to an array of
+ * sym structure pointers
+ *
+ * global variables:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * (1) The symbol hash tables are cleared
+ */
+
+VOID
+syminit()
+{
+ struct sym **spp;
+
+ spp = &symhash[0];
+ while (spp < &symhash[NHASH])
+ *spp++ = NULL;
+}
+
+/*)Function sym * newsym()
+ *
+ * The function newsym() is called to evaluate the symbol
+ * definition/reference directive from the .rel file(s).
+ * If the symbol is not found in the symbol table a new
+ * symbol structure is created. Evaluation of the
+ * directive determines if this is a reference or a definition.
+ * Multiple definitions of the same variable will be flagged
+ * as an error if the values are not identical. A symbol
+ * definition places the symbol value and area extension
+ * into the symbols data structure. And finally, a pointer
+ * to the symbol structure is placed into the head structure
+ * symbol list. Refer to the description of the header, symbol,
+ * area, and areax structures in lkdata.c for structure and
+ * linkage details.
+ *
+ * local variables:
+ * int c character from input text
+ * int i evaluation value
+ * char id[] symbol name
+ * int nglob number of symbols in this header
+ * sym * tsp pointer to symbol structure
+ * sym ** s list of pointers to symbol structures
+ *
+ * global variables:
+ * areax *axp Pointer to the current
+ * areax structure
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * int lkerr error flag
+ *
+ * functions called:
+ * Addr_T eval() lkeval.c
+ * VOID exit() c_library
+ * int fprintf() c_library
+ * char get() lklex.c
+ * char getnb() lklex.c
+ * sym * lkpsym() lksym.c
+ *
+ * side effects:
+ * A symbol structure is created and/or modified.
+ * If structure space allocation fails linker will abort.
+ * Several severe errors (these are internal errors
+ * indicating a corrupted .rel file or corrupted
+ * assembler or linker) will terminated the linker.
+ */
+
+/*
+ * Find/Create a global symbol entry.
+ *
+ * S xxxxxx Defnnnn
+ * | | |
+ * | | `-- sp->s_addr
+ * | `----- sp->s_type
+ * `------------ sp->s_id
+ *
+ */
+struct sym *
+newsym()
+{
+ register unsigned i ;
+ register unsigned nglob ;
+ register int c ;
+ struct sym *tsp;
+ struct sym **s;
+ char id[NCPS];
+
+ getid(id, -1);
+ tsp = lkpsym(id, 1);
+ c = getnb();get();get();
+ if (c == 'R') {
+ tsp->s_type |= S_REF;
+ if (eval()) {
+ fprintf(stderr, "Non zero S_REF\n");
+ lkerr++;
+ }
+ } else
+ if (c == 'D') {
+ i = eval();
+ if (tsp->s_type & S_DEF && tsp->s_addr != i) {
+#ifdef SDK
+ fprintf(stderr, "Multiple definition of %s\n", id);
+#else
+ fprintf(stderr, "Multiple definition of %.8s\n", id);
+#endif
+ lkerr++;
+ }
+ tsp->s_type |= S_DEF;
+ /*
+ * Set value and area extension link.
+ */
+ tsp->s_addr = i;
+ tsp->s_axp = axp;
+ } else {
+ fprintf(stderr, "Invalid symbol type %c for %.8s\n", c, id);
+ lkexit(1);
+ }
+ /*
+ * Place pointer in header symbol list
+ */
+ if (headp == NULL) {
+ fprintf(stderr, "No header defined\n");
+ lkexit(1);
+ }
+ nglob = hp->h_nglob;
+ s = hp->s_list;
+ for (i=0; i < nglob ;++i) {
+ if (s[i] == NULL) {
+ s[i] = tsp;
+ return(tsp);
+ }
+ }
+ fprintf(stderr, "Header symbol list overflow\n");
+ lkexit(1);
+
+ /* Never reached */
+ return 0;
+}
+
+/*)Function sym * lkpsym(id,f)
+ *
+ * char * id symbol name string
+ * int f f == 0, lookup only
+ * f != 0, create if not found
+ *
+ * The function lookup() searches the symbol hash tables for
+ * a symbol name match returning a pointer to the sym structure.
+ * If the symbol is not found then a sym structure is created,
+ * initialized, and linked to the appropriate hash table if f != 0.
+ * A pointer to this new sym structure is returned or a NULL
+ * pointer is returned if f == 0.
+ *
+ * local variables:
+ * int h computed hash value
+ * sym * sp pointer to a sym structure
+ *
+ * global varaibles:
+ * sym * symhash[] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * int hash() lksym.c
+ * VOID * new() lksym.c
+ * int symeq() lksym.c
+ *
+ * side effects:
+ * If the function new() fails to allocate space
+ * for the new sym structure the linker terminates.
+ */
+
+struct sym *
+lkpsym(id, f)
+char *id;
+{
+ register struct sym *sp;
+ register int h;
+
+ h = hash(id);
+ sp = symhash[h];
+ while (sp != NULL) {
+ if (symeq(id, sp->s_id))
+ return (sp);
+ sp = sp->s_sp;
+ }
+ if (f == 0)
+ return (NULL);
+ sp = (struct sym *) new (sizeof(struct sym));
+ sp->s_sp = symhash[h];
+ symhash[h] = sp;
+ strncpy(sp->s_id, id, NCPS);
+ return (sp);
+}
+
+/*)Function Addr_T symval(tsp)
+ *
+ * sym * tsp pointer to a symbol structure
+ *
+ * The function symval() returns the value of the
+ * relocated symbol by adding the variable definition
+ * value to the areax base address.
+ *
+ * local variables:
+ * Addr_T val relocated address value
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ */
+
+Addr_T
+symval(tsp)
+register struct sym *tsp;
+{
+ register Addr_T val;
+
+ val = tsp->s_addr;
+ if (tsp->s_axp) {
+ val += tsp->s_axp->a_addr;
+ }
+ return(val);
+}
+
+/*)Function VOID symdef(fp)
+ *
+ * FILE * fp file handle for output
+ *
+ * The function symdef() scans the hashed symbol table
+ * searching for variables referenced but not defined.
+ * Undefined variables are linked to the default
+ * area "_CODE" and reported as referenced by the
+ * appropriate module.
+ *
+ * local variables:
+ * int i hash table index loop variable
+ * sym * sp pointer to linked symbol structure
+ *
+ * global variables:
+ * area *areap The pointer to the first
+ * area structure of a linked list
+ * sym *symhash[NHASH] array of pointers to NHASH
+ * linked symbol lists
+ *
+ * functions called:
+ * symmod() lksym.c
+ *
+ * side effects:
+ * Undefined variables have their areas set to "_CODE".
+ */
+
+VOID
+symdef(fp)
+FILE *fp;
+{
+ register struct sym *sp;
+ register int i;
+
+ for (i=0; i<NHASH; ++i) {
+ sp = symhash[i];
+ while (sp) {
+ if (sp->s_axp == NULL)
+ sp->s_axp = areap->a_axp;
+ if ((sp->s_type & S_DEF) == 0)
+ symmod(fp, sp);
+ sp = sp->s_sp;
+ }
+ }
+}
+
+/*)Function VOID symmod(fp,tsp)
+ *
+ * FILE * fp output file handle
+ * sym * tsp pointer to a symbol structure
+ *
+ * The function symmod() scans the header structures
+ * searching for a reference to the symbol structure
+ * pointer to by tsp. The function then generates an error
+ * message whichs names the module having referenced the
+ * undefined variable.
+ *
+ * local variables:
+ * int i loop counter
+ * sym ** p pointer to a list of pointers
+ * to symbol structures
+ *
+ * global variables:
+ * head *headp The pointer to the first
+ * head structure of a linked list
+ * head *hp Pointer to the current
+ * head structure
+ * int lkerr error flag
+ *
+ * functions called:
+ * int fprintf() c_library
+ *
+ * side effects:
+ * Error output generated.
+ */
+
+VOID
+symmod(fp, tsp)
+FILE *fp;
+struct sym *tsp;
+{
+ register int i;
+ struct sym **p;
+
+ if ((hp = headp) != NULL) {
+ while(hp) {
+ p = hp->s_list;
+ for (i=0; i<hp->h_nglob; ++i) {
+ if (p[i] == tsp) {
+ fprintf(fp, "\n?ASlink-Warning-Undefined Global %s ", tsp->s_id);
+ fprintf(fp, "referenced by module %s\n", hp->m_id);
+ lkerr++;
+ }
+ }
+ hp = hp->h_hp;
+ }
+ }
+}
+
+/*)Function int symeq(p1, p2)
+ *
+ * char * p1 name string
+ * char * p2 name string
+ *
+ * The function symeq() compares the two name strings for a match.
+ * The return value is 1 for a match and 0 for no match.
+ *
+ * local variables:
+ * int h loop counter
+ *
+ * global variables:
+ * char ccase[] an array of characters which
+ * perform the case translation function
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ *
+ */
+
+int
+symeq(p1, p2)
+register char *p1, *p2;
+{
+ register int n;
+
+ n = NCPS;
+ do {
+
+#if CASE_SENSITIVE
+ if (*p1++ != *p2++)
+ return (0);
+#else
+ if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
+ return (0);
+#endif
+
+ } while (--n);
+ return (1);
+}
+
+/*)Function int hash(p)
+ *
+ * char * p pointer to string to hash
+ *
+ * The function hash() computes a hash code using the sum
+ * of all characters mod table size algorithm.
+ *
+ * local variables:
+ * int h accumulated character sum
+ * int n loop counter
+ *
+ * global variables:
+ * char ccase[] an array of characters which
+ * perform the case translation function
+ *
+ * functions called:
+ * none
+ *
+ * side effects:
+ * none
+ *
+ */
+
+int
+hash(p)
+register char *p;
+{
+ register int h, n;
+
+ h = 0;
+ n = NCPS;
+ do {
+
+#if CASE_SENSITIVE
+ h += *p++;
+#else
+ h += ccase[(unsigned char)(*p++)];
+#endif
+
+ } while (--n);
+ return (h&HMASK);
+}
+
+/*)Function VOID * new(n)
+ *
+ * unsigned int n allocation size in bytes
+ *
+ * The function new() allocates n bytes of space and returns
+ * a pointer to this memory. If no space is available the
+ * linker is terminated.
+ *
+ * local variables:
+ * char * p a general pointer
+ * char * q a general pointer
+ *
+ * global variables:
+ * none
+ *
+ * functions called:
+ * int fprintf() c_library
+ * VOID * malloc() c_library
+ *
+ * side effects:
+ * Memory is allocated, if allocation fails
+ * the linker is terminated.
+ */
+
+VOID *
+new(n)
+unsigned int n;
+{
+ register char *p,*q;
+ register unsigned int i;
+
+ if ((p = (char *) malloc(n)) == NULL) {
+ fprintf(stderr, "Out of space!\n");
+ lkexit(1);
+ }
+ for (i=0,q=p; i<n; i++) {
+ *q++ = 0;
+ }
+ return (p);
+}
if test $OPT_DISABLE_Z80 = 0; then
- ac_config_files="$ac_config_files src/z80/Makefile as/Makefile as/z80/Makefile link/Makefile link/z80/Makefile"
+ ac_config_files="$ac_config_files src/z80/Makefile as/Makefile as/z80/Makefile as/link/Makefile as/link/z80/Makefile"
test $OPT_DISABLE_DEVICE_LIB = 0 && ac_config_files="$ac_config_files device/lib/z80/Makefile device/lib/gbz80/Makefile"
+++ /dev/null
-VPATH = @srcdir@
-srcdir = @srcdir@
-top_builddir = @top_builddir@
-
-include $(top_builddir)Makefile.common
-
-PORTS = z80 gbz80
-
-all:
- $(MAKE) -C z80 _link-z80 _link-gbz80 E=$(E) BUILDDIR=../../bin/
-
-install: all
- $(INSTALL) $(top_builddir)bin/link-z80$(EXEEXT) `echo $(DESTDIR)$(bindir)/link-z80$(EXEEXT)|sed '$(transform)'`
- $(STRIP) `echo $(DESTDIR)$(bindir)/link-z80$(EXEEXT)|sed '$(transform)'`
- $(INSTALL) $(top_builddir)bin/link-gbz80$(EXEEXT) `echo $(DESTDIR)$(bindir)/link-gbz80$(EXEEXT)|sed '$(transform)'`
- $(STRIP) `echo $(DESTDIR)$(bindir)/link-gbz80$(EXEEXT)|sed '$(transform)'`
-
-uninstall:
- cd $(DESTDIR)$(bindir); rm -f link-z80$(EXEEXT) link-gbz80$(EXEEXT)
-
-include $(srcdir)/clean.mk
+++ /dev/null
-sdcc/link
----------
-
-In gbdk the linker and assembler were split into seperate packages.
-
-For now I'm keeping that split, and leaving the mcs51 version as is.
-
--- Michael
+++ /dev/null
-clean:
- $(MAKE) -C z80 clean
-
-distclean: clean
- $(MAKE) -C z80 distclean
- rm -f Makefile
+++ /dev/null
-VPATH = @srcdir@
-srcdir = @srcdir@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-include $(top_builddir)Makefile.common
-
-OBJDIR = obj/$(EXT)
-
-SLIBSRC = NewAlloc.c
-
-SRC = lkarea.c lkdata.c lkeval.c lkhead.c lkihx.c lklex.c \
- lklibr.c lklist.c lkmain.c lkrloc.c lks19.c lksym.c \
- lkgb.c lkgg.c
-
-OBJS = $(SRC:%.c=$(OBJDIR)/%.o)
-SLIBOBJS = $(SLIBSRC:%.c=$(OBJDIR)/%.o)
-
-BINS = $(BUILDDIR)link$(EXT)$(EXEEXT)
-
-CFLAGS += $(CPPFLAGS) $(OPTS) -DINDEXLIB -DMLH_MAP -DUNIX -DSDK
-CFLAGS += -funsigned-char -DUNIX
-CFLAGS += -I$(top_builddir)as/$(PORT) -I$(SLIB)
-
-LDFLAGS += -lm $(EXTRALIBS)
-
-all: $(BINS)
-
-$(BINS): $(OBJDIR) $(OBJS) $(SLIBOBJS)
- $(CC) -g -o $(BINS) $(OBJS) $(SLIBOBJS) $(LDFLAGS)
-
-$(OBJDIR):
- mkdir -p $(OBJDIR)
-
-$(OBJDIR)/%.o: %.c
- $(CC) -c $(CFLAGS) -o $@ $<
-
-$(OBJDIR)/%.o: $(SLIB)/%.c
- $(CC) -c $(CFLAGS) -o $@ $<
-
-_link-z80:
- $(MAKE) EXT=-z80$(E) PORT=z80
-
-_link-gbz80:
- $(MAKE) EXT=-gbz80$(E) OPTS=-DGAMEBOY PORT=z80
-
-include $(srcdir)/clean.mk
+++ /dev/null
-/* aslink.h */
-
-/*
- * (C) Copyright 1989-1996
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-/*
- * Extensions: P. Felber
- */
-#define VERSION "V01.75"
-
-/*
- * Case Sensitivity Flag
- */
-#define CASE_SENSITIVE 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.
- */
-
-#ifdef SDK
-#define NCPS 80 /* characters per symbol. Used to be 32... */
-#else /* SDK */
-#define NCPS 8 /* characters per symbol */
-#endif /* SDK */
-/* #define NCPS 32 */ /* characters per symbol */
-#define NDATA 16 /* actual data */
-#define NINPUT PATH_MAX /* Input buffer size */
-#define NHASH 64 /* Buckets in hash table */
-#define HMASK 077 /* Hash mask */
-#define NLPP 60 /* Lines per page */
-#define NTXT 16 /* T values */
-#define FILSPC PATH_MAX /* File spec length */
-
-/*
- * The "R_" relocation constants define values used in
- * generating the assembler relocation output data for
- * areas, symbols, and code.
- *
- *
- * Relocation types.
- *
- * 7 6 5 4 3 2 1 0
- * +-----+-----+-----+-----+-----+-----+-----+-----+
- * | MSB | PAGn| PAG0| USGN| BYT2| PCR | SYM | BYT |
- * +-----+-----+-----+-----+-----+-----+-----+-----+
- */
-
-#define R_WORD 0x00 /* 16 bit */
-#define R_BYTE 0x01 /* 8 bit */
-
-#define R_AREA 0x00 /* Base type */
-#define R_SYM 0x02
-
-#define R_NORM 0x00 /* PC adjust */
-#define R_PCR 0x04
-
-#define R_BYT1 0x00 /* Byte count for R_BYTE = 1 */
-#define R_BYT2 0x08 /* Byte count for R_BYTE = 2 */
-
-#define R_SGND 0x00 /* Signed value */
-#define R_USGN 0x10 /* Unsigned value */
-
-#define R_NOPAG 0x00 /* Page Mode */
-#define R_PAG0 0x20 /* Page '0' */
-#define R_PAG 0x40 /* Page 'nnn' */
-
-/*
- * Valid for R_BYT2:
- */
-#define R_LSB 0x00 /* output low byte */
-#define R_MSB 0x80 /* output high byte */
-
-/*
- * Global symbol types.
- */
-#define S_REF 1 /* referenced */
-#define S_DEF 2 /* defined */
-
-/*
- * Area types
- */
-#define A_CON 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 */
-
-/*
- * File types
- */
-#define F_INV 0 /* invalid */
-#define F_STD 1 /* stdin */
-#define F_LNK 2 /* File.lnk */
-#define F_REL 3 /* File.rel */
-#ifdef SDK
-#define F_CMD 4 /* Command line */
-#endif /* SDK */
-
-#ifdef GAMEBOY
-/*
- * Multiple banks support
- */
-extern int nb_rom_banks;
-extern int nb_ram_banks;
-extern int current_rom_bank;
-extern int mbc_type;
-extern char cart_name[];
-/*
- * ROM patching support
- */
-typedef struct _patch {
- unsigned int addr;
- unsigned char value;
- struct _patch *next;
-} patch;
-extern patch* patches;
-#endif /* GAMEBOY */
-/*
- * General assembler address type
- */
-typedef unsigned int Addr_T;
-
-/*
- * The structures of head, area, areax, and sym are created
- * as the REL files are read during the first pass of the
- * linker. The struct head is created upon encountering a
- * H directive in the REL file. The structure contains a
- * link to a link file structure (struct lfile) which describes
- * the file containing the H directive, the number of data/code
- * areas contained in this header segment, the number of
- * symbols referenced/defined in this header segment, a pointer
- * to an array of pointers to areax structures (struct areax)
- * created as each A directive is read, and a pointer to an
- * array of pointers to symbol structures (struct sym) for
- * all referenced/defined symbols. As H directives are read
- * from the REL files a linked list of head structures is
- * created by placing a link to the new head structure
- * in the previous head structure.
- */
-struct head
-{
- struct head *h_hp; /* Header link */
- struct lfile *h_lfile;/* Associated file */
- int h_narea; /* # of areas */
- struct areax **a_list; /* Area list */
- int h_nglob; /* # of global symbols */
- struct sym **s_list; /* Globle symbol list */
- char m_id[NCPS]; /* Module name */
-};
-
-/*
- * A structure area is created for each 'unique' data/code
- * area definition found as the REL files are read. The
- * struct area contains the name of the area, a flag byte
- * which contains the area attributes (REL/CON/OVR/ABS),
- * an area subtype (not used in this assembler), and the
- * area base address and total size which will be filled
- * in at the end of the first pass through the REL files.
- * As A directives are read from the REL files a linked
- * list of unique area structures is created by placing a
- * link to the new area structure in the previous area structure.
- */
-struct area
-{
- struct area *a_ap; /* Area link */
- struct areax *a_axp; /* Area extension link */
- Addr_T a_addr; /* Beginning address of area */
- Addr_T a_size; /* Total size of the area */
- char a_type; /* Area subtype */
- char a_flag; /* Flag byte */
- char a_id[NCPS]; /* Name */
-};
-
-/*
- * An areax structure is created for every A directive found
- * while reading the REL files. The struct areax contains a
- * link to the 'unique' area structure referenced by the A
- * directive and to the head structure this area segment is
- * a part of. The size of this area segment as read from the
- * A directive is placed in the areax structure. The beginning
- * address of this segment will be filled in at the end of the
- * first pass through the REL files. As A directives are read
- * from the REL files a linked list of areax structures is
- * created for each unique area. The final areax linked
- * list has at its head the 'unique' area structure linked
- * to the linked areax structures (one areax structure for
- * each A directive for this area).
- */
-struct areax
-{
- struct areax *a_axp; /* Area extension link */
- struct area *a_bap; /* Base area link */
- struct head *a_bhp; /* Base header link */
- Addr_T a_addr; /* Beginning address of section */
- Addr_T a_size; /* Size of the area in section */
-};
-
-/*
- * A sym structure is created for every unique symbol
- * referenced/defined while reading the REL files. The
- * struct sym contains the symbol's name, a flag value
- * (not used in this linker), a symbol type denoting
- * referenced/defined, and an address which is loaded
- * with the relative address within the area in which
- * the symbol was defined. The sym structure also
- * contains a link to the area where the symbol was defined.
- * The sym structures are linked into linked lists using
- * the symbol link element.
- */
-struct sym
-{
- struct sym *s_sp; /* Symbol link */
- struct areax *s_axp; /* Symbol area link */
- char s_type; /* Symbol subtype */
- char s_flag; /* Flag byte */
- Addr_T s_addr; /* Address */
- char s_id[NCPS]; /* Name */
-};
-
-/*
- * The structure lfile contains a pointer to a
- * file specification string, the file type, and
- * a link to the next lfile structure.
- */
-struct lfile
-{
- struct lfile *f_flp; /* lfile link */
- int f_type; /* File type */
- char *f_idp; /* Pointer to file spec */
-};
-
-/*
- * The struct base contains a pointer to a
- * base definition string and a link to the next
- * base structure.
- */
-struct base
-{
- struct base *b_base; /* Base link */
- char *b_strp; /* String pointer */
-};
-
-/*
- * The struct globl contains a pointer to a
- * global definition string and a link to the next
- * global structure.
- */
-struct globl
-{
- struct globl *g_globl; /* Global link */
- char *g_strp; /* String pointer */
-};
-
-/*
- * A structure sdp is created for each 'unique' paged
- * area definition found as the REL files are read.
- * As P directives are read from the REL files a linked
- * list of unique sdp structures is created by placing a
- * link to the new sdp structure in the previous area structure.
- */
-struct sdp
-{
- struct area *s_area; /* Paged Area link */
- struct areax *s_areax; /* Paged Area Extension Link */
- Addr_T s_addr; /* Page address offset */
-};
-
-/*
- * The structure rerr is loaded with the information
- * required to report an error during the linking
- * process. The structure contains an index value
- * which selects the areax structure from the header
- * areax structure list, a mode value which selects
- * symbol or area relocation, the base address in the
- * area section, an area/symbol list index value, and
- * an area/symbol offset value.
- */
-struct rerr
-{
- int aindex; /* Linking area */
- int mode; /* Relocation mode */
- Addr_T rtbase; /* Base address in section */
- int rindex; /* Area/Symbol reloaction index */
- Addr_T rval; /* Area/Symbol offset value */
-};
-
-/*
- * The structure lbpath is created for each library
- * path specification input by the -k option. The
- * lbpath structures are linked into a list using
- * the next link element.
- */
-struct lbpath {
- struct lbpath *next;
- char *path;
-};
-
-/*
- * The structure lbname is created for all combinations of the
- * library path specifications (input by the -k option) and the
- * library file specifications (input by the -l option) that
- * lead to an existing file. The element path points to
- * the path string, element libfil points to the library
- * file string, and the element libspc is the concatenation
- * of the valid path and libfil strings.
- *
- * The lbpath structures are linked into a list
- * using the next link element.
- *
- * Each library file contains a list of object files
- * that are contained in the particular library. e.g.:
- *
- * \iolib\termio
- * \inilib\termio
- *
- * Only one specification per line is allowed.
- */
-struct lbname {
- struct lbname *next;
- char *path;
- char *libfil;
- char *libspc;
-};
-
-/*
- * The function fndsym() searches through all combinations of the
- * library path specifications (input by the -k option) and the
- * library file specifications (input by the -l option) that
- * lead to an existing file for a symbol definition.
- *
- * The structure lbfile is created for the first library
- * object file which contains the definition for the
- * specified undefined symbol.
- *
- * The element libspc points to the library file path specification
- * and element relfil points to the object file specification string.
- * The element filspc is the complete path/file specification for
- * the library file to be imported into the linker. The
- * file specicifation may be formed in one of two ways:
- *
- * (1) If the library file contained an absolute
- * path/file specification then this becomes filspc.
- * (i.e. C:\...)
- *
- * (2) If the library file contains a relative path/file
- * specification then the concatenation of the path
- * and this file specification becomes filspc.
- * (i.e. \...)
- *
- * The lbpath structures are linked into a list
- * using the next link element.
- */
-struct lbfile {
- struct lbfile *next;
- char *libspc;
- char *relfil;
- char *filspc;
- 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 lk_getline() to read
- * asmlnk commands from
- * (1) the standard input or
- * (2) or a command file
- * and to read the REL files
- * sequentially as defined by the
- * asmlnk input commands.
- *
- * The pointer *filep points to the
- * beginning of a linked list of
- * lfile structures.
- */
-extern struct lfile *cfp; /* The pointer *cfp points to the
- * current lfile structure
- */
-extern struct lfile *startp;/* asmlnk startup file structure
- */
-extern struct lfile *linkp; /* pointer to first lfile structure
- * containing an input REL file
- * specification
- */
-extern struct lfile *lfp; /* pointer to current lfile structure
- * being processed by parse()
- */
-extern struct head *headp; /* The pointer to the first
- * head structure of a linked list
- */
-extern struct head *hp; /* Pointer to the current
- * head structure
- */
-extern struct area *areap; /* The pointer to the first
- * area structure of a linked list
- */
-extern struct area *ap; /* Pointer to the current
- * area structure
- */
-extern struct areax *axp; /* Pointer to the current
- * areax structure
- */
-extern struct sym *symhash[NHASH]; /* array of pointers to NHASH
- * linked symbol lists
- */
-extern struct base *basep; /* The pointer to the first
- * base structure
- */
-extern struct base *bsp; /* Pointer to the current
- * base structure
- */
-extern struct globl *globlp;/* The pointer to the first
- * globl structure
- */
-extern struct globl *gsp; /* Pointer to the current
- * globl structure
- */
-extern struct sdp sdp; /* Base Paged structure
- */
-extern struct rerr rerr; /* Structure containing the
- * linker error information
- */
-extern FILE *ofp; /* Linker Output file handle
- */
-extern FILE *mfp; /* Map output file handle
- */
-extern FILE *rfp; /* File handle for output
- * address relocated ASxxxx
- * listing file
- */
-extern FILE *sfp; /* The file handle sfp points to the
- * currently open file
- */
-extern FILE *tfp; /* File handle for input
- * ASxxxx listing file
- */
-extern int oflag; /* Output file type flag
- */
-extern int mflag; /* Map output flag
- */
-#ifdef SDK
-extern int symflag; /* no$gmb .sym output flag
- */
-#endif
-extern int xflag; /* Map file radix type flag
- */
-extern int pflag; /* print linker command file flag
- */
-extern int uflag; /* Listing relocation flag
- */
-extern int radix; /* current number conversion radix:
- * 2 (binary), 8 (octal), 10 (decimal),
- * 16 (hexadecimal)
- */
-extern int line; /* current line number
- */
-extern int page; /* current page number
- */
-extern int lop; /* current line number on page
- */
-extern int pass; /* linker pass number
- */
-extern int rtcnt; /* count of elements in the
- * rtval[] and rtflg[] arrays
- */
-extern Addr_T rtval[]; /* data associated with relocation
- */
-extern int rtflg[]; /* indicates if rtval[] value is
- * to be sent to the output file.
- * (always set in this linker)
- */
-extern int hilo; /* REL file byte ordering
- */
-extern int gline; /* LST file relocation active
- * for current line
- */
-extern int gcntr; /* LST file relocation active
- * counter
- */
-extern struct lbpath *lbphead; /* pointer to the first
- * library path structure
- */
-extern struct lbname *lbnhead; /* pointer to the first
- * library name structure
- */
-extern struct lbfile *lbfhead; /* pointer to the first
- * library file structure
- */
-
-/* C Library function definitions */
-/* for reference only
-extern VOID exit();
-extern int fclose();
-extern char * fgets();
-extern FILE * fopen();
-extern int fprintf();
-extern VOID free();
-extern VOID * malloc();
-extern char putc();
-extern char * strcpy();
-extern int strlen();
-extern char * strncpy();
-*/
-
-/* Program function definitions */
-
-/* lkmain.c */
-extern FILE * afile();
-extern VOID bassav();
-extern VOID gblsav();
-extern VOID link();
-extern VOID lkexit();
-extern int main();
-extern VOID map();
-#ifdef SDK
-extern VOID sym();
-#endif
-extern int parse();
-extern VOID setbas();
-extern VOID setgbl();
-extern VOID usage();
-
-/* lklex.c */
-extern char endline();
-extern char get();
-extern VOID getfid();
-extern VOID getid();
-extern int lk_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 adw_w();
-extern Addr_T adw_hi();
-extern Addr_T adw_lo();
-extern Addr_T evword();
-extern VOID rele();
-extern VOID reloc();
-extern VOID relt();
-extern VOID relr();
-extern VOID relp();
-extern VOID relerr();
-extern char * errmsg[];
-extern VOID errdmp();
-extern VOID relerp();
-extern VOID erpdmp();
-extern VOID prntval();
-
-/* lklibr.c */
-extern 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();
-
-/* lkgb.h */
-VOID gb(int in);
-VOID gg(int in);
-
+++ /dev/null
-# Deleting all files created by building the program
-# --------------------------------------------------
-include $(top_builddir)Makefile.common
-
-clean:
- rm -f *core *[%~] *.[oa]
- rm -f .[a-z]*~
- rm -f $(top_builddir)bin/link-z80$(EXEEXT) link-z80$(EXEEXT) \
- $(top_builddir)bin/link-gbz80$(EXEEXT) link-gbz80$(EXEEXT)
- rm -f *.dep
- rm -rf obj
-
-# Deleting all files created by configuring or building the program
-# -----------------------------------------------------------------
-distclean: clean
- rm -f Makefile
-
-# 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
-# Deleting all files created by building the program
-# --------------------------------------------------
-clean:
- rm -f *core *[%~] *.[oa]
- rm -f .[a-z]*~
- rm -f $(top_builddir)bin/link-z80 link-z80
-
-
-# Deleting all files created by configuring or building the program
-# -----------------------------------------------------------------
-distclean: clean
- rm -f Makefile *.dep
-
-
-# Like clean but some files may still exist
-# -----------------------------------------
-mostlyclean: clean
-
-
-# Deleting everything that can reconstructed by this Makefile. It deletes
-# everything deleted by distclean plus files created by bison, etc.
-# -----------------------------------------------------------------------
-realclean: distclean
+++ /dev/null
-# Microsoft Developer Studio Project File - Name="linkgbz80" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
-\r
-CFG=linkgbz80 - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "linkgbz80.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "linkgbz80.mak" CFG="linkgbz80 - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "linkgbz80 - Win32 Release" (based on "Win32 (x86) Console Application")\r
-!MESSAGE "linkgbz80 - Win32 Debug" (based on "Win32 (x86) Console Application")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF "$(CFG)" == "linkgbz80 - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release_gbz80"\r
-# PROP BASE Intermediate_Dir "Release_gbz80"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release_gbz80"\r
-# PROP Intermediate_Dir "Release_gbz80"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# ADD RSC /l 0x409 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\bin_vc\link-gbz80.exe"\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ELSEIF "$(CFG)" == "linkgbz80 - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug_gbz80"\r
-# PROP BASE Intermediate_Dir "Debug_gbz80"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug_gbz80"\r
-# PROP Intermediate_Dir "Debug_gbz80"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\bin_vc\link-gbz80.exe" /pdbtype:sept\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "linkgbz80 - Win32 Release"\r
-# Name "linkgbz80 - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\lkarea.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkdata.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkeval.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkgb.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkgg.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkhead.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkihx.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lklex.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lklibr.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lklist.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkmain.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkrloc.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lks19.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lksym.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY"\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\aslink.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
+++ /dev/null
-# Microsoft Developer Studio Project File - Name="linkz80" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
-\r
-CFG=linkz80 - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "linkz80.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "linkz80.mak" CFG="linkz80 - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "linkz80 - Win32 Release" (based on "Win32 (x86) Console Application")\r
-!MESSAGE "linkz80 - Win32 Debug" (based on "Win32 (x86) Console Application")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF "$(CFG)" == "linkz80 - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release_z80"\r
-# PROP BASE Intermediate_Dir "Release_z80"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release_z80"\r
-# PROP Intermediate_Dir "Release_z80"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# ADD RSC /l 0x409 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
-# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\bin_vc\link-z80.exe"\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ELSEIF "$(CFG)" == "linkz80 - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug_z80"\r
-# PROP BASE Intermediate_Dir "Debug_z80"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug_z80"\r
-# PROP Intermediate_Dir "Debug_z80"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\bin_vc\link-z80.exe" /pdbtype:sept\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "linkz80 - Win32 Release"\r
-# Name "linkz80 - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\lkarea.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkdata.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkeval.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkgb.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkgg.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkhead.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkihx.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lklex.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lklibr.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lklist.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkmain.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lkrloc.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lks19.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\lksym.c\r
-# ADD CPP /D "SDK" /D "INDEXLIB"\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\aslink.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
+++ /dev/null
-/* lkarea.c */
-
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "aslink.h"
-
-/*)Module lkarea.c
- *
- * The module lkarea.c contains the functions which
- * create and link together all area definitions read
- * from the .rel file(s).
- *
- * lkarea.c contains the following functions:
- * VOID lnkarea()
- * VOID lnksect()
- * VOID lkparea()
- * VOID newarea()
- *
- * lkarea.c contains no global variables.
- */
-
-/*)Function VOID newarea()
- *
- * The function newarea() creates and/or modifies area
- * and areax structures for each A directive read from
- * the .rel file(s). The function lkparea() is called
- * to find tha area structure associated with this name.
- * If the area does not yet exist then a new area
- * structure is created and linked to any existing
- * linked area structures. The area flags are copied
- * into the area flag variable. For each occurence of
- * an A directive an areax structure is created and
- * linked to the areax structures associated with this
- * area. The size of this area section is placed into
- * the areax structure. The flag value for all subsequent
- * area definitions for the same area are compared and
- * flagged as an error if they are not identical.
- * The areax structure created for every occurence of
- * an A directive is loaded with a pointer to the base
- * area structure and a pointer to the associated
- * head structure. And finally, a pointer to this
- * areax structure is loaded into the list of areax
- * structures in the head structure. Refer to lkdata.c
- * for details of the structures and their linkage.
- *
- * local variables:
- * areax **halp pointer to an array of pointers
- * int i counter, loop variable, value
- * char id[] id string
- * int narea number of areas in this head structure
- * areax * taxp pointer to an areax structure
- * to areax structures
- *
- * global variables:
- * area *ap Pointer to the current
- * area structure
- * areax *axp Pointer to the current
- * areax structure
- * head *hp Pointer to the current
- * head structure
- * int lkerr error flag
- *
- * functions called:
- * Addr_T eval() lkeval.c
- * VOID exit() c_library
- * int fprintf() c_library
- * VOID getid() lklex.c
- * VOID lkparea() lkarea.c
- * VOID skip() lklex.c
- *
- * side effects:
- * The area and areax structures are created and
- * linked with the appropriate head structures.
- * Failure to allocate area or areax structure
- * space will terminate the linker. Other internal
- * errors most likely caused by corrupted .rel
- * files will also terminate the linker.
- */
-
-/*
- * Create an area entry.
- *
- * A xxxxxx size nnnn flags mm
- * | | |
- * | | `-- ap->a_flag
- * | `------------- axp->a_size
- * `------------------------- ap->a_id
- *
- */
-VOID
-newarea()
-{
- register int i, narea;
- struct areax *taxp;
- struct areax **halp;
- char id[NCPS];
-
- /*
- * Create Area entry
- */
- getid(id, -1);
- lkparea(id);
- /*
- * Evaluate area size
- */
- skip(-1);
- axp->a_size = eval();
- /*
- * Evaluate flags
- */
- skip(-1);
- i = 0;
- taxp = ap->a_axp;
- while (taxp->a_axp) {
- ++i;
- taxp = taxp->a_axp;
- }
- if (i == 0) {
- ap->a_flag = eval();
- } else {
- i = eval();
- if (i && (ap->a_flag != i)) {
- fprintf(stderr, "Conflicting flags in area %.8s\n", id);
- lkerr++;
- }
- }
- /*
- * Place pointer in header area list
- */
- if (headp == NULL) {
- fprintf(stderr, "No header defined\n");
- lkexit(1);
- }
- narea = hp->h_narea;
- halp = hp->a_list;
- for (i=0; i < narea ;++i) {
- if (halp[i] == NULL) {
- halp[i] = taxp;
- return;
- }
- }
- fprintf(stderr, "Header area list overflow\n");
- lkexit(1);
-}
-
-/*)Function VOID lkparea(id)
- *
- * char * id pointer to the area name string
- *
- * The function lkparea() searches the linked area structures
- * for a name match. If the name is not found then an area
- * structure is created. An areax structure is created and
- * appended to the areax structures linked to the area structure.
- * The associated base area and head structure pointers are
- * loaded into the areax structure.
- *
- * local variables:
- * area * tap pointer to an area structure
- * areax * taxp pointer to an areax structure
- *
- * global variables:
- * area *ap Pointer to the current
- * area structure
- * area *areap The pointer to the first
- * area structure of a linked list
- * areax *axp Pointer to the current
- * areax structure
- *
- * functions called:
- * VOID * new() lksym()
- * char * strcpy() c_library
- * int symeq() lksym.c
- *
- * side effects:
- * Area and/or areax structures are created.
- * Failure to allocate space for created structures
- * will terminate the linker.
- */
-
-VOID
-lkparea(id)
-char *id;
-{
- register struct area *tap;
- register struct areax *taxp;
-
- ap = areap;
- axp = (struct areax *) new (sizeof(struct areax));
- while (ap) {
- if (symeq(id, ap->a_id)) {
- taxp = ap->a_axp;
- while (taxp->a_axp)
- taxp = taxp->a_axp;
- taxp->a_axp = axp;
- axp->a_bap = ap;
- axp->a_bhp = hp;
- return;
- }
- ap = ap->a_ap;
- }
- ap = (struct area *) new (sizeof(struct area));
- if (areap == NULL) {
- areap = ap;
- } else {
- tap = areap;
- while (tap->a_ap)
- tap = tap->a_ap;
- tap->a_ap = ap;
- }
- ap->a_axp = axp;
- axp->a_bap = ap;
- axp->a_bhp = hp;
- strncpy(ap->a_id, id, NCPS);
-}
-
-/*)Function VOID lnkarea()
- *
- * The function lnkarea() resolves all area addresses.
- * The function evaluates each area structure (and all
- * the associated areax structures) in sequence. The
- * linking process supports four (4) possible area types:
- *
- * ABS/OVR - All sections (each individual areax
- * section) starts at the identical base
- * area address overlaying all other
- * areax sections for this area. The
- * size of the area is largest of the area
- * sections.
- *
- * ABS/CON - All sections (each individual areax
- * section) are concatenated with the
- * first section starting at the base
- * area address. The size of the area
- * is the sum of the section sizes.
- *
- * NOTE: Multiple absolute (ABS) areas are
- * never concatenated with each other,
- * thus absolute area A and absolute area
- * B will overlay each other if they begin
- * at the same location (the default is
- * always address 0 for absolute areas).
- *
- * REL/OVR - All sections (each individual areax
- * section) starts at the identical base
- * area address overlaying all other
- * areax sections for this area. The
- * size of the area is largest of the area
- * sections.
- *
- * REL/CON - All sections (each individual areax
- * section) are concatenated with the
- * first section starting at the base
- * area address. The size of the area
- * is the sum of the section sizes.
- *
- * NOTE: Relocatable (REL) areas ae always concatenated
- * with each other, thus relocatable area B
- * (defined after area A) will follow
- * relocatable area A independent of the
- * starting address of area A. Within a
- * specific area each areax section may be
- * overlayed or concatenated with other
- * areax sections.
- *
- *
- * If a base address for an area is specified then the
- * area will start at that address. Any relocatable
- * areas defined subsequently will be concatenated to the
- * previous relocatable area if it does not have a base
- * address specified.
- *
- * The names s_<areaname> and l_<areaname> are created to
- * define the starting address and length of each area.
- *
- * local variables:
- * Addr_T rloc ;current relocation address
- * char temp[] ;temporary string
- * struct symbol *sp ;symbol structure
- *
- * global variables:
- * area *ap Pointer to the current
- * area structure
- * area *areap The pointer to the first
- * area structure of a linked list
- *
- * functions called:
- * int fprintf() c_library
- * VOID lnksect() lkarea.c
- * symbol *lkpsym() lksysm.c
- * char * strncpy() c_library
- * int symeq() lksysm.c
- *
- * side effects:
- * All area and areax addresses and sizes are
- * determined and saved in their respective
- * structures.
- */
-
-/*
- * Resolve all area addresses.
- */
-VOID
-lnkarea()
-{
- register int rloc;
- char temp[NCPS];
- struct sym *sp;
-
- rloc = 0;
- ap = areap;
- while (ap) {
- if (ap->a_flag&A_ABS) {
- /*
- * Absolute sections
- */
- lnksect(ap);
- } else {
- /*
- * Relocatable sections
- */
- if (ap->a_addr == 0)
- ap->a_addr = rloc;
- lnksect(ap);
- rloc = ap->a_addr + ap->a_size;
- }
-
- /*
- * Create symbols called:
- * s_<areaname> the start address of the area
- * l_<areaname> the length of the area
- */
-
- if (! symeq(ap->a_id, _abs_)) {
- strncpy(temp+2,ap->a_id,NCPS-2);
- *(temp+1) = '_';
-
- *temp = 's';
- sp = lkpsym(temp, 1);
- sp->s_addr = ap->a_addr;
- sp->s_axp = NULL;
- sp->s_type |= S_DEF;
-
- *temp = 'l';
- sp = lkpsym(temp, 1);
- sp->s_addr = ap->a_size;
- sp->s_axp = NULL;
- sp->s_type |= S_DEF;
- }
- ap = ap->a_ap;
- }
-}
-
-/*)Function VOID lnksect()
- *
- * area * tap pointer to an area structure
- *
- * The function lnksect() is the function called by
- * lnkarea() to resolve the areax addresses. Refer
- * to the function lnkarea() for more detail. Pageing
- * boundary and length errors will be reported by this
- * function.
- *
- * local variables:
- * Addr_T size size of area
- * Addr_T addr address of area
- * areax * taxp pointer to an areax structure
- *
- * global variables:
- * int lkerr error flag
- *
- * functions called:
- * none
- *
- * side effects:
- * All area and areax addresses and sizes area determined
- * and linked into the structures.
- */
-
-VOID
-lnksect(tap)
-register struct area *tap;
-{
- register Addr_T size, addr;
- register struct areax *taxp;
-
- size = 0;
- addr = tap->a_addr;
- if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
- fprintf(stderr,
- "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
- lkerr++;
- }
- taxp = tap->a_axp;
- if (tap->a_flag&A_OVR) {
- /*
- * Overlayed sections
- */
- while (taxp) {
- taxp->a_addr = addr;
- if (taxp->a_size > size)
- size = taxp->a_size;
- taxp = taxp->a_axp;
- }
- } else {
- /*
- * Concatenated sections
- */
- while (taxp) {
- taxp->a_addr = addr;
- addr += taxp->a_size;
- size += taxp->a_size;
- taxp = taxp->a_axp;
- }
- }
- tap->a_size = size;
- if ((tap->a_flag&A_PAG) && (size > 256)) {
- fprintf(stderr,
- "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);
- lkerr++;
- }
-}
+++ /dev/null
-/* lkdata.c */
-
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-#include <stdio.h>
-#include <string.h>
-//#include <alloc.h>
-#include "aslink.h"
-
-/*)Module lkdata.c
- *
- * The module lkdata contains the global variables
- * and structures used in the linker aslink.
- */
-
-/*
- * Definitions for all Global Variables
- */
-
-char *_abs_ = { ". .ABS." };
-
-int lkerr; /* Linker error flag
- */
-char *ip; /* Pointer into the REL file text line in ib[]
- */
-char ib[NINPUT]; /* REL file text line
- */
-char *rp; /* pointer into the LST file
- * text line in rb[]
- */
-char rb[NINPUT]; /* LST file text line being
- * address relocated
- */
-
-char sdccopt[NINPUT]="";
-char sdccopt_module[NINPUT]="";
-char curr_module[NINPUT]="";
-
-int oflag; /* Output file type flag
- */
-int mflag; /* Map output flag
- */
-#ifdef SDK
-int symflag; /* no$gmb .sym output flag
- */
-#endif
-int xflag; /* Map file radix type flag
- */
-int pflag; /* print linker command file flag
- */
-int uflag; /* Listing relocation flag
- */
-int radix; /* current number conversion radix:
- * 2 (binary), 8 (octal), 10 (decimal),
- * 16 (hexadecimal)
- */
-int line; /* current line number
- */
-int page; /* current page number
- */
-int lop; /* current line number on page
- */
-int pass; /* linker pass number
- */
-int rtcnt; /* count of elements in the
- * rtval[] and rtflg[] arrays
- */
-Addr_T rtval[NTXT]; /* data associated with relocation
- */
-int rtflg[NTXT]; /* indicates if rtval[] value is
- * to be sent to the output file.
- * (always set in this linker)
- */
-int hilo; /* REL file byte ordering
- */
-int gline; /* LST file relocation active
- * for current line
- */
-int gcntr; /* LST file relocation active
- * counter
- */
-
-/*
- * The structure lfile contains a pointer to a
- * file specification string, the file type, and
- * a link to the next lfile structure.
- *
- * struct lfile
- * {
- * struct lfile *f_flp; lfile link
- * int f_type; File type
- * char *f_idp; Pointer to file spec
- * };
- */
-struct lfile *filep; /* The pointers (lfile *) filep,
- * (lfile *) cfp, and (FILE *) sfp
- * are used in conjunction with
- * the routine lk_getline() to read
- * asmlnk commands from
- * (1) the standard input or
- * (2) or a command file
- * and to read the REL files
- * sequentially as defined by the
- * asmlnk input commands.
- *
- * The pointer *filep points to the
- * beginning of a linked list of
- * lfile structures.
- */
-struct lfile *cfp; /* The pointer *cfp points to the
- * current lfile structure
- */
-struct lfile *startp;/* asmlnk startup file structure
- */
-struct lfile *linkp; /* pointer to first lfile structure
- * containing an input REL file
- * specification
- */
-struct lfile *lfp; /* pointer to current lfile structure
- * being processed by parse()
- */
-FILE *ofp; /* Output file handle
- * for word formats
- */
-FILE *mfp; /* Map output file handle
- */
-FILE *rfp; /* File handle for output
- * address relocated ASxxxx
- * listing file
- */
-FILE *sfp; /* The file handle sfp points to the
- * currently open file
- */
-FILE *tfp; /* File handle for input
- * ASxxxx listing file
- */
-
-/*
- * The structures of head, area, areax, and sym are created
- * as the REL files are read during the first pass of the
- * linker. The struct head is created upon encountering a
- * H directive in the REL file. The structure contains a
- * link to a link file structure (struct lfile) which describes
- * the file containing the H directive, the number of data/code
- * areas contained in this header segment, the number of
- * symbols referenced/defined in this header segment, a pointer
- * to an array of pointers to areax structures (struct areax)
- * created as each A directive is read, and a pointer to an
- * array of pointers to symbol structures (struct sym) for
- * all referenced/defined symbols. As H directives are read
- * from the REL files a linked list of head structures is
- * created by placing a link to the new head structure
- * in the previous head structure.
- *
- * struct head
- * {
- * struct head *h_hp; Header link
- * struct lfile *h_lfile; Associated file
- * int h_narea; # of areas
- * struct areax **a_list; Area list
- * int h_nglob; # of global symbols
- * struct sym **s_list; Global symbol list
- * char m_id[NCPS]; Module name
- * };
- */
-struct head *headp; /* The pointer to the first
- * head structure of a linked list
- */
-struct head *hp; /* Pointer to the current
- * head structure
- */
-
-/*
- * A structure area is created for each 'unique' data/code
- * area definition found as the REL files are read. The
- * struct area contains the name of the area, a flag byte
- * which contains the area attributes (REL/CON/OVR/ABS),
- * an area subtype (not used in this assembler), and the
- * area base address and total size which will be filled
- * in at the end of the first pass through the REL files.
- * As A directives are read from the REL files a linked
- * list of unique area structures is created by placing a
- * link to the new area structure in the previous area structure.
- *
- * struct area
- * {
- * struct area *a_ap; Area link
- * struct areax *a_axp; Area extension link
- * Addr_T a_addr; Beginning address of area
- * Addr_T a_size; Total size of the area
- * char a_type; Area subtype
- * char a_flag; Flag byte
- * char a_id[NCPS]; Name
- * };
- */
-struct area *areap; /* The pointer to the first
- * area structure of a linked list
- */
-struct area *ap; /* Pointer to the current
- * area structure
- */
-
-/*
- * An areax structure is created for every A directive found
- * while reading the REL files. The struct areax contains a
- * link to the 'unique' area structure referenced by the A
- * directive and to the head structure this area segment is
- * a part of. The size of this area segment as read from the
- * A directive is placed in the areax structure. The beginning
- * address of this segment will be filled in at the end of the
- * first pass through the REL files. As A directives are read
- * from the REL files a linked list of areax structures is
- * created for each unique area. The final areax linked
- * list has at its head the 'unique' area structure linked
- * to the linked areax structures (one areax structure for
- * each A directive for this area).
- *
- * struct areax
- * {
- * struct areax *a_axp; Area extension link
- * struct area *a_bap; Base area link
- * struct head *a_bhp; Base header link
- * Addr_T a_addr; Beginning address of section
- * Addr_T a_size; Size of the area in section
- * };
- */
-struct areax *axp; /* Pointer to the current
- * areax structure
- */
-
-/*
- * A sym structure is created for every unique symbol
- * referenced/defined while reading the REL files. The
- * struct sym contains the symbol's name, a flag value
- * (not used in this linker), a symbol type denoting
- * referenced/defined, and an address which is loaded
- * with the relative address within the area in which
- * the symbol was defined. The sym structure also
- * contains a link to the area where the symbol was defined.
- * The sym structures are linked into linked lists using
- * the symbol link element.
- *
- * struct sym
- * {
- * struct sym *s_sp; Symbol link
- * struct areax *s_axp; Symbol area link
- * char s_type; Symbol subtype
- * char s_flag; Flag byte
- * Addr_T s_addr; Address
- * char s_id[NCPS]; Name
- * };
- */
-struct sym *symhash[NHASH]; /* array of pointers to NHASH
- * linked symbol lists
- */
-/*
- * The struct base contains a pointer to a
- * base definition string and a link to the next
- * base structure.
- *
- * struct base
- * {
- * struct base *b_base; Base link
- * char *b_strp; String pointer
- * };
- */
-struct base *basep; /* The pointer to the first
- * base structure
- */
-struct base *bsp; /* Pointer to the current
- * base structure
- */
-
-/*
- * The struct globl contains a pointer to a
- * global definition string and a link to the next
- * global structure.
- *
- * struct globl
- * {
- * struct globl *g_globl; Global link
- * char *g_strp; String pointer
- * };
- */
-struct globl *globlp;/* The pointer to the first
- * globl structure
- */
-struct globl *gsp; /* Pointer to the current
- * globl structure
- */
-
-/*
- * A structure sdp is created for each 'unique' paged
- * area definition found as the REL files are read.
- * As P directives are read from the REL files a linked
- * list of unique sdp structures is created by placing a
- * link to the new sdp structure in the previous area structure.
- *
- * struct sdp
- * {
- * struct area *s_area; Paged Area link
- * struct areax *s_areax; Paged Area Extension Link
- * Addr_T s_addr; Page address offset
- * };
- */
-struct sdp sdp; /* Base Page Structure */
-
-/*
- * The structure rerr is loaded with the information
- * required to report an error during the linking
- * process. The structure contains an index value
- * which selects the areax structure from the header
- * areax structure list, a mode value which selects
- * symbol or area relocation, the base address in the
- * area section, an area/symbol list index value, and
- * an area/symbol offset value.
- *
- * struct rerr
- * {
- * int aindex; Linking area
- * int mode; Relocation mode
- * Addr_T rtbase; Base address in section
- * int rindex; Area/Symbol reloaction index
- * Addr_T rval; Area/Symbol offset value
- * };
- */
-struct rerr rerr; /* Structure containing the
- * linker error information
- */
-
-/*
- * The structure lbpath is created for each library
- * path specification input by the -k option. The
- * lbpath structures are linked into a list using
- * the next link element.
- *
- * struct lbpath {
- * struct lbpath *next;
- * char *path;
- * };
- */
-struct lbpath *lbphead; /* pointer to the first
- * library path structure
- */
-
-/*
- * The structure lbname is created for all combinations of the
- * library path specifications (input by the -k option) and the
- * library file specifications (input by the -l option) that
- * lead to an existing file. The element path points to
- * the path string, element libfil points to the library
- * file string, and the element libspc is the concatenation
- * of the valid path and libfil strings.
- *
- * The lbpath structures are linked into a list
- * using the next link element.
- *
- * Each library file contains a list of object files
- * that are contained in the particular library. e.g.:
- *
- * \iolib\termio
- * \inilib\termio
- *
- * Only one specification per line is allowed.
- *
- * struct lbname {
- * struct lbname *next;
- * char *path;
- * char *libfil;
- * char *libspc;
- * };
- */
-struct lbname *lbnhead; /* pointer to the first
- * library name structure
- */
-
-/*
- * The function fndsym() searches through all combinations of the
- * library path specifications (input by the -k option) and the
- * library file specifications (input by the -l option) that
- * lead to an existing file for a symbol definition.
- *
- * The structure lbfile is created for the first library
- * object file which contains the definition for the
- * specified undefined symbol.
- *
- * The element libspc points to the library file path specification
- * and element relfil points to the object file specification string.
- * The element filspc is the complete path/file specification for
- * the library file to be imported into the linker. The
- * file specicifation may be formed in one of two ways:
- *
- * (1) If the library file contained an absolute
- * path/file specification then this becomes filspc.
- * (i.e. C:\...)
- *
- * (2) If the library file contains a relative path/file
- * specification then the concatenation of the path
- * and this file specification becomes filspc.
- * (i.e. \...)
- *
- * The lbpath structures are linked into a list
- * using the next link element.
- *
- * struct lbfile {
- * struct lbfile *next;
- * char *libspc;
- * char *relfil;
- * char *filspc;
- * };
- */
-struct lbfile *lbfhead; /* pointer to the first
- * library file structure
- */
-
-/*
- * array of character types, one per
- * ASCII character
- */
-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 <alloc.h>
-#include "aslink.h"
-
-/*)Module lkeval.c
- *
- * The module lkeval.c contains the routines to evaluate
- * arithmetic/numerical expressions. The functions in
- * lkeval.c perform a recursive evaluation of the arithmetic
- * expression read from the input text line.
- * The expression may include binary/unary operators, brackets,
- * symbols, labels, and constants in hexadecimal, decimal, octal
- * and binary. Arithmetic operations are prioritized and
- * evaluated by normal arithmetic conventions.
- *
- * lkeval.c contains the following functions:
- * int digit()
- * Addr_T eval()
- * Addr_T expr()
- * int oprio()
- * Addr_T term()
- *
- * lkeval.c contains no local/static variables
- */
-
-/*)Function Addr_T eval()
- *
- * The function eval() evaluates a character string to a
- * numerical value.
- *
- * local variables:
- * int c character from input string
- * int v value of character in current radix
- * Addr_T n evaluation value
- *
- * global variables:
- * int radix current number conversion radix
- *
- * functions called:
- * int digit() lkeval.c
- * char get() lklex.c
- * char getnb() lklex.c
- * VOID unget() lklex.c
- *
- * side effects:
- * Input test is scanned and evaluated to a
- * numerical value.
- */
-
-Addr_T
-eval()
-{
- register int c, v;
- register Addr_T n;
-
- c = getnb();
- n = 0;
- while ((v = digit(c, radix)) >= 0) {
- n = n*radix + v;
- c = get();
- }
- unget(c);
- return(n);
-}
-
-/*)Function Addr_T expr(n)
- *
- * int n a firewall priority; all top
- * level calls (from the user)
- * should be made with n set to 0.
- *
- * The function expr() evaluates an expression and
- * returns the value.
- *
- * local variables:
- * int c current input text character
- * int p current operator priority
- * Addr_T v value returned by term()
- * Addr_T ve value returned by a
- * recursive call to expr()
- *
- * global variables:
- * char ctype[] array of character types, one per
- * ASCII character
- * int lkerr error flag
- * FILE * stderr c_library
- *
- * functions called:
- * VOID expr() lkeval.c
- * int fprintf() c_library
- * int getnb() lklex.c
- * int oprio() lkeval.c
- * VOID term() lkeval.c
- * VOID unget() lklex.c
- *
- *
- * side effects:
- * An expression is evaluated by scanning the input
- * text string.
- */
-
-Addr_T
-expr (n)
-{
- register int c, p;
- register Addr_T v, ve;
-
- v = term();
- while (ctype[c = getnb()] & BINOP) {
- if ((p = oprio(c)) <= n)
- break;
- if ((c == '>' || c == '<') && c != get()) {
- fprintf(stderr, "Invalid expression");
- lkerr++;
- return(v);
- }
- ve = expr(p);
- if (c == '+') {
- v += ve;
- } else
- if (c == '-') {
- v -= ve;
- } else {
- switch (c) {
-
- case '*':
- v *= ve;
- break;
-
- case '/':
- v /= ve;
- break;
-
- case '&':
- v &= ve;
- break;
-
- case '|':
- v |= ve;
- break;
-
- case '%':
- v %= ve;
- break;
-
- case '^':
- v ^= ve;
- break;
-
- case '<':
- v <<= ve;
- break;
-
- case '>':
- v >>= ve;
- break;
- }
- }
- }
- unget(c);
- return(v);
-}
-
-/*)Function Addr_T term()
- *
- * The function term() evaluates a single constant
- * or symbol value prefaced by any unary operator
- * ( +, -, ~, ', ", >, or < ).
- *
- * local variables:
- * int c current character
- * char id[] symbol name
- * int n value of digit in current radix
- * int r current evaluation radix
- * sym * sp pointer to a sym structure
- * Addr_T v evaluation value
- *
- * global variables:
- * char ctype[] array of character types, one per
- * ASCII character
- * int lkerr error flag
- *
- * functions called:
- * int digit() lkeval.c
- * VOID expr() lkeval.c
- * int fprintf() c_library
- * int get() lklex.c
- * VOID getid() lklex.c
- * int getmap() lklex.c
- * int getnb() lklex.c
- * sym * lkpsym() lksym.c
- * Addr_T symval() lksym.c
- * VOID unget() lklex.c
- *
- * side effects:
- * An arithmetic term is evaluated by scanning input text.
- */
-
-Addr_T
-term()
-{
- register int c, r, n;
- register Addr_T v;
- struct sym *sp;
- char id[NCPS];
-
- c = getnb();
- if (c == '#') { c = getnb(); }
- if (c == '(') {
- v = expr(0);
- if (getnb() != ')') {
- fprintf(stderr, "Missing delimiter");
- lkerr++;
- }
- return(v);
- }
- if (c == '-') {
- return(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));
- }
- }
- /* Shouldn't get here. */
- return 0;
-}
-
-/*)Function int digit(c, r)
- *
- * int c digit character
- * int r current radix
- *
- * The function digit() returns the value of c
- * in the current radix r. If the c value is not
- * a number of the current radix then a -1 is returned.
- *
- * local variables:
- * none
- *
- * global variables:
- * char ctype[] array of character types, one per
- * ASCII character
- *
- * functions called:
- * none
- *
- * side effects:
- * none
- */
-
-int
-digit(c, r)
-register int c, r;
-{
- if (r == 16) {
- if (ctype[c] & RAD16) {
- if (c >= 'A' && c <= 'F')
- return (c - 'A' + 10);
- if (c >= 'a' && c <= 'f')
- return (c - 'a' + 10);
- return (c - '0');
- }
- } else
- if (r == 10) {
- if (ctype[c] & RAD10)
- return (c - '0');
- } else
- if (r == 8) {
- if (ctype[c] & RAD8)
- return (c - '0');
- } else
- if (r == 2) {
- if (ctype[c] & RAD2)
- return (c - '0');
- }
- return (-1);
-}
-
-/*)Function int oprio(c)
- *
- * int c operator character
- *
- * The function oprio() returns a relative priority
- * for all valid unary and binary operators.
- *
- * local variables:
- * none
- *
- * global variables:
- * none
- *
- * functions called:
- * none
- *
- * side effects:
- * none
- */
-
-int
-oprio(c)
-register int c;
-{
- if (c == '*' || c == '/' || c == '%')
- return (10);
- if (c == '+' || c == '-')
- return (7);
- if (c == '<' || c == '>')
- return (5);
- if (c == '^')
- return (4);
- if (c == '&')
- return (3);
- if (c == '|')
- return (1);
- return (0);
-}
+++ /dev/null
-/* lkgb.c */
-
-/*
- * P. Felber
- */
-
-#ifdef GAMEBOY
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "aslink.h"
-
-/* Value used to fill the unused portions of the image */
-/* FFh puts less stress on a EPROM/Flash */
-#define FILLVALUE 0xFF
-
-#define CARTSIZE ((unsigned long)nb_rom_banks*16UL*1024UL)
-#define NBSEG 8UL
-#define SEGSIZE (CARTSIZE/NBSEG)
-
-#define ROMSIZE 0x8000UL
-#define BANKSTART 0x4000UL
-#define BANKSIZE 0x4000UL
-
-unsigned char *cart[NBSEG];
-
-int nb_rom_banks;
-int nb_ram_banks;
-int current_rom_bank;
-int mbc_type;
-char cart_name[16] = "";
-
-patch* patches = NULL;
-
-VOID gb(int in)
-{
- static int first = 1;
- unsigned long pos, chk;
- int i;
- patch *p;
-
- if(first) {
- for(i = 0; i < NBSEG; i++) {
- if((cart[i] = malloc(SEGSIZE)) == NULL) {
- fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
- exit(EXIT_FAILURE);
- }
- memset(cart[i], FILLVALUE, SEGSIZE);
- }
- first = 0;
- }
- if(in) {
- if(rtcnt > 2) {
- if(hilo == 0)
- pos = rtval[0] | (rtval[1]<<8);
- else
- pos = rtval[1] | (rtval[0]<<8);
-
- /* Perform some validity checks */
- if(pos >= ROMSIZE) {
- fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
- exit(EXIT_FAILURE);
- }
- if(current_rom_bank >= nb_rom_banks) {
- fprintf(stderr, "ERROR: bank overflow (addr %x > %x)\n", current_rom_bank, nb_rom_banks);
- exit(EXIT_FAILURE);
- }
- if(current_rom_bank > 0 && pos < BANKSTART) {
- fprintf(stderr, "ERROR: address underflow (addr %lx < %lx)\n", pos, BANKSTART);
- exit(EXIT_FAILURE);
- }
- if(nb_rom_banks == 2 && current_rom_bank > 0) {
- fprintf(stderr, "ERROR: only 1 32kB segment with 2 bank\n");
- exit(EXIT_FAILURE);
- }
- if(current_rom_bank > 1)
- pos += (current_rom_bank-1)*BANKSIZE;
- for(i = 2; i < rtcnt; i++) {
- if(rtflg[i]) {
- if(pos < CARTSIZE) {
- if(cart[pos/SEGSIZE][pos%SEGSIZE] != FILLVALUE)
- fprintf(stderr, "WARNING: possibly wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
- cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
- } else {
- fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
- exit(EXIT_FAILURE);
- }
- pos++;
- }
- }
- }
- } else {
- /* EOF */
- if(cart_name[0] == 0 && linkp->f_idp != NULL) {
- for(i = strlen(linkp->f_idp);
- i > 0 && (isalnum((unsigned char)linkp->f_idp[i-1]) || linkp->f_idp[i-1] == '.');
- i--)
- ;
- for(pos = 0; pos < 16 && linkp->f_idp[i] != '.'; pos++, i++)
- cart_name[pos] = toupper((unsigned char)linkp->f_idp[i]);
- if(pos < 16)
- cart_name[pos] = 0;
- }
- for(pos = 0x0134, i = 0;
- pos < 0x0144 && cart_name[i];
- pos++, i++)
- cart[pos/SEGSIZE][pos%SEGSIZE] = cart_name[i];
- for(; pos < 0x0144; pos++)
- cart[pos/SEGSIZE][pos%SEGSIZE] = 0;
- cart[0x147/SEGSIZE][0x147%SEGSIZE] = mbc_type;
- switch(nb_rom_banks) {
- case 2:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
- break;
- case 4:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 1;
- break;
- case 8:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 2;
- break;
- case 16:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 3;
- break;
- case 32:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 4;
- break;
- case 64:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 5;
- break;
- case 128:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 6;
- break;
- case 256:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 7;
- break;
- case 512:
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 8;
- break;
- default:
- fprintf(stderr, "WARNING: unsupported number of ROM banks (%d)\n", nb_rom_banks);
- cart[0x148/SEGSIZE][0x148%SEGSIZE] = 0;
- break;
- }
- switch(nb_ram_banks) {
- case 0:
- cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
- break;
- case 1:
- cart[0x149/SEGSIZE][0x149%SEGSIZE] = 2;
- break;
- case 4:
- cart[0x149/SEGSIZE][0x149%SEGSIZE] = 3;
- break;
- case 16:
- cart[0x149/SEGSIZE][0x149%SEGSIZE] = 4;
- break;
- default:
- fprintf(stderr, "WARNING: unsupported number of RAM banks (%d)\n", nb_ram_banks);
- cart[0x149/SEGSIZE][0x149%SEGSIZE] = 0;
- break;
- }
-
- /* Patch before calculating the checksum */
- if(patches)
- for(p = patches; p; p = p->next)
- cart[p->addr/SEGSIZE][p->addr%SEGSIZE] = p->value;
-
- /* Update complement checksum */
- chk = 0;
- for(pos = 0x0134; pos < 0x014D; pos++)
- chk += cart[pos/SEGSIZE][pos%SEGSIZE];
- cart[0x014D/SEGSIZE][0x014D%SEGSIZE] = (unsigned char)(0xE7 - (chk&0xFF));
- /* Update checksum */
- chk = 0;
- cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = 0;
- cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = 0;
- for(i = 0; i < NBSEG; i++)
- for(pos = 0; pos < SEGSIZE; pos++)
- chk += cart[i][pos];
- cart[0x014E/SEGSIZE][0x014E%SEGSIZE] = (unsigned char)((chk>>8)&0xFF);
- cart[0x014F/SEGSIZE][0x014F%SEGSIZE] = (unsigned char)(chk&0xFF);
-
- for(i = 0; i < NBSEG; i++)
- fwrite(cart[i], 1, SEGSIZE, ofp);
- }
-}
-
-#endif /* GAMEBOY */
+++ /dev/null
-/* lkgg.c */
-
-/*
- * P. Felber
- */
-
-#ifdef GAMEGEAR
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <string.h>
-#include "aslink.h"
-
-#define CARTSIZE ((unsigned long)4*16UL*1024UL)
-#define NBSEG 8UL
-#define SEGSIZE (CARTSIZE/NBSEG)
-
-unsigned char *cart[NBSEG];
-
-#define ROMSIZE 0x10000UL
-#define BANKSIZE 0x4000UL
-
-int current_rom_bank;
-
-VOID gg(int in)
-{
- static int first = 1;
- unsigned long pos;
- int i;
-
- if(first) {
- for(i = 0; i < NBSEG; i++) {
- if((cart[i] = malloc(SEGSIZE)) == NULL) {
- fprintf(stderr, "ERROR: can't allocate %dth segment of memory (%d bytes)\n", i, (int)SEGSIZE);
- exit(EXIT_FAILURE);
- }
- memset(cart[i], 0, SEGSIZE);
- }
- first = 0;
- }
- if(in) {
- if(rtcnt > 2) {
- if(hilo == 0)
- pos = rtval[0] | (rtval[1]<<8);
- else
- pos = rtval[1] | (rtval[0]<<8);
-
- /* Perform some validity checks */
- if(pos >= ROMSIZE) {
- fprintf(stderr, "ERROR: address overflow (addr %lx >= %lx)\n", pos, ROMSIZE);
- exit(EXIT_FAILURE);
- }
- if(current_rom_bank > 1)
- pos += (current_rom_bank-1)*BANKSIZE;
- for(i = 2; i < rtcnt; i++) {
- if(rtflg[i]) {
- if(pos < CARTSIZE) {
- if(cart[pos/SEGSIZE][pos%SEGSIZE] != 0)
- fprintf(stderr, "WARNING: wrote twice at addr %lx (%02X->%02X)\n", pos, rtval[i], cart[pos/SEGSIZE][pos%SEGSIZE]);
- cart[pos/SEGSIZE][pos%SEGSIZE] = rtval[i];
- } else {
- fprintf(stderr, "ERROR: cartridge size overflow (addr %lx >= %lx)\n", pos, CARTSIZE);
- exit(EXIT_FAILURE);
- }
- pos++;
- }
- }
- }
- } else {
- /* EOF */
- /* Patch before calculating the checksum */
- for(i = 0; i < NBSEG; i++)
- fwrite(cart[i], 1, SEGSIZE, ofp);
- }
-}
-
-#endif /* GAMEGEAR */
+++ /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 <alloc.h>
-#include "aslink.h"
-
-/*Module lkhead.c
- *
- * The module lkhead.c contains the function newhead() which
- * creates a head structure and the function module() which
- * loads the module name into the current head structure.
- *
- * lkhead.c contains the following functions:
- * VOID newhead()
- * VOID module()
- *
- * lkhead.c contains no local variables.
- */
-
-/*)Function VOID newhead()
- *
- * The function newhead() creates a head structure. All head
- * structures are linked to form a linked list of head structures
- * with the current head structure at the tail of the list.
- *
- * local variables:
- * int i evaluation value
- * head * thp temporary pointer
- * to a header structure
- *
- * global variables:
- * area *ap Pointer to the current
- * area structure
- * lfile *cfp The pointer *cfp points to the
- * current lfile structure
- * head *headp The pointer to the first
- * head structure of a linked list
- * head *hp Pointer to the current
- * head structure
- *
- * functions called:
- * Addr_T expr() lkeval.c
- * VOID * new() lksym.c
- * VOID lkparea() lkarea.c
- *
- * side effects:
- * A new head structure is created and linked to any
- * existing linked head structure. The head structure
- * parameters of file handle, number of areas, and number
- * of global symbols are loaded into the structure.
- * The default area "_abs_" is created when the first
- * head structure is created and an areax structure is
- * created for every head structure called.
- */
-
-/*
- * Create a new header entry.
- *
- * H n areas n global symbols
- * | |
- * | `---- hp->h_nglob
- * `------------ hp->h_narea
- *
- */
-VOID
-newhead()
-{
- register int i;
- struct head *thp;
-
- hp = (struct head *) new (sizeof(struct head));
- if (headp == NULL) {
- headp = hp;
- } else {
- thp = headp;
- while (thp->h_hp)
- thp = thp->h_hp;
- thp->h_hp = hp;
- }
- /*
- * Set file pointer
- */
- hp->h_lfile = cfp;
- /*
- * Evaluate and build Area pointer list
- */
- i = hp->h_narea = eval();
- if (i)
- hp->a_list = (struct areax **) new (i*sizeof(struct areax *));
- /*
- * Evaluate and build Global symbol pointer list
- */
- skip(-1);
- i = hp->h_nglob = eval();
- if (i)
- hp->s_list = (struct sym **) new (i*sizeof(struct sym *));
- /*
- * Setup Absolute DEF linkage.
- */
- lkparea(_abs_);
- ap->a_flag = A_ABS|A_OVR;
-}
-
-/*)Function VOID module()
- *
- * The function module() copies the module name into
- * the current head structure.
- *
- * local variables:
- * char id[] module id string
- *
- * global variables:
- * head *headp The pointer to the first
- * head structure of a linked list
- * head *hp Pointer to the current
- * head structure
- * int lkerr error flag
- * FILE * stderr c_library
- *
- * functions called:
- * int fprintf() c_library
- * VOID getid() lklex.c
- * char * strncpy() c_library
- *
- * side effects:
- * The module name is copied into the head structure.
- */
-
-/*
- * Module Name
- */
-VOID
-module()
-{
- char id[NCPS];
-
- if (headp) {
- getid(id, -1);
- strncpy(hp->m_id, id, NCPS);
- } else {
- fprintf(stderr, "No header defined\n");
- lkerr++;
- }
-}
+++ /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 <alloc.h>
-#include "aslink.h"
-
-/*)Module lkihx.c
- *
- * The module lkihx.c contains the function to
- * output the relocated object code in the
- * Intel Hex format.
- *
- * lkihx.c contains the following function:
- * VOID ihx(i)
- *
- * lkihx.c contains no local variables.
- */
-
-/*Intel Hex Format
- * Record Mark Field - This field signifies the start of a
- * record, and consists of an ascii colon
- * (:).
- *
- * Record Length Field - This field consists of two ascii
- * characters which indicate the number of
- * data bytes in this record. The
- * characters are the result of converting
- * the number of bytes in binary to two
- * ascii characters, high digit first. An
- * End of File record contains two ascii
- * zeros in this field.
- *
- * Load Address Field - This field consists of the four ascii
- * characters which result from converting
- * the the binary value of the address in
- * which to begin loading this record. The
- * order is as follows:
- *
- * High digit of high byte of address.
- * Low digit of high byte of address.
- * High digit of low byte of address.
- * Low digit of low byte of address.
- *
- * In an End of File record this field con-
- * sists of either four ascii zeros or the
- * program entry address. Currently the
- * entry address option is not supported.
- *
- * Record Type Field - This field identifies the record type,
- * which is either 0 for data records or 1
- * for an End of File record. It consists
- * of two ascii characters, with the high
- * digit of the record type first, followed
- * by the low digit of the record type.
- *
- * Data Field - This field consists of the actual data,
- * converted to two ascii characters, high
- * digit first. There are no data bytes in
- * the End of File record.
- *
- * Checksum Field - The checksum field is the 8 bit binary
- * sum of the record length field, the load
- * address field, the record type field,
- * and the data field. This sum is then
- * negated (2's complement) and converted
- * to two ascii characters, high digit
- * first.
- */
-
-/*)Function ihx(i)
- *
- * int i 0 - process data
- * 1 - end of data
- *
- * The function ihx() outputs the relocated data
- * in the standard Intel Hex format.
- *
- * local variables:
- * Addr_T chksum byte checksum
- *
- * global variables:
- * int hilo byte order
- * FILE * ofp output file handle
- * int rtcnt count of data words
- * int rtflg[] output the data flag
- * Addr_T rtval[] relocated data
- *
- * functions called:
- * int fprintf() c_library
- *
- * side effects:
- * The data is output to the file defined by ofp.
- */
-
-VOID
-ihx(i)
-{
- register Addr_T chksum;
-
- if (i) {
- if (hilo == 0) {
- chksum = rtval[0];
- rtval[0] = rtval[1];
- rtval[1] = chksum;
- }
- for (i = 0, chksum = -2; i < rtcnt; i++) {
- if (rtflg[i])
- chksum++;
- }
- fprintf(ofp, ":%02X", chksum);
- for (i = 0; i < rtcnt ; i++) {
- if (rtflg[i]) {
- fprintf(ofp, "%02X", rtval[i]);
- chksum += rtval[i];
- }
- if (i == 1) {
- fprintf(ofp, "00");
- }
- }
- fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
- } else {
- fprintf(ofp, ":00000001FF\n");
- }
-}
+++ /dev/null
-/* lklex.c */
-
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-/*
- * Extensions: P. Felber, M. Hope
- */
-
-#include <stdio.h>
-#include <string.h>
-//#include <alloc.h>
-#include "aslink.h"
-
-/*)Module lklex.c
- *
- * The module lklex.c contains the general lexical analysis
- * functions used to scan the text lines from the .rel files.
- *
- * lklex.c contains the fllowing functions:
- * char endline()
- * char get()
- * VOID getfid()
- * VOID getid()
- * int lk_getline()
- * int getmap()
- * char getnb()
- * int more()
- * VOID skip()
- * VOID unget()
- *
- * lklex.c contains no local variables.
- */
-
-/*)Function VOID getid(id,c)
- *
- * char * id a pointer to a string of
- * maximum length NCPS
- * int c mode flag
- * >=0 this is first character to
- * copy to the string buffer
- * <0 skip white space
- *
- * The function getid() scans the current input text line
- * from the current position copying the next LETTER | DIGIT string
- * into the external string buffer (id). The string ends when a non
- * LETTER or DIGIT character is found. The maximum number of
- * characters copied is NCPS. If the input string is larger than
- * NCPS characters then the string is truncated, if the input string
- * is shorter than NCPS characters then the string is NULL filled.
- * If the mode argument (c) is >=0 then (c) is the first character
- * copied to the string buffer, if (c) is <0 then intervening white
- * space (SPACES and TABS) are skipped.
- *
- * local variables:
- * char * p pointer to external string buffer
- * int c current character value
- *
- * global variables:
- * char ctype[] a character array which defines the
- * type of character being processed.
- * This index is the character
- * being processed.
- *
- * called functions:
- * char get() lklex.c
- * char getnb() lklex.c
- * VOID unget() lklex.c
- *
- * side effects:
- * use of getnb(), get(), and unget() updates the
- * global pointer ip the position in the current
- * input text line.
- */
-
-VOID
-getid(id, c)
-register int c;
-char *id;
-{
- register char *p;
-
- if (c < 0) {
- c = getnb();
- }
- p = id;
- do {
- if (p < &id[NCPS])
- *p++ = c;
- } while (ctype[c=get()] & (LETTER|DIGIT));
- unget(c);
- while (p < &id[NCPS])
- *p++ = 0;
-}
-
-/*)Function VOID getfid(fid,c)
- *
- * char * str a pointer to a string of
- * maximum length FILSPC
- * int c this is first character to
- * copy to the string buffer
- *
- * The function getfid() scans the current input text line
- * from the current position copying the next string
- * into the external string buffer (str). The string ends when a
- * non SPACE type character is found. The maximum number of
- * characters copied is FILSPC. If the input string is larger than
- * FILSPC characters then the string is truncated, if the input string
- * is shorter than FILSPC characters then the string is NULL filled.
- *
- * local variables:
- * char * p pointer to external string buffer
- * int c current character value
- *
- * global variables:
- * char ctype[] a character array which defines the
- * type of character being processed.
- * This index is the character
- * being processed.
- *
- * called functions:
- * char get() lklex.c
- *
- * side effects:
- * use of get() updates the global pointer ip
- * the position in the current input text line.
- */
-
-VOID
-getfid(str, c)
-register int c;
-char *str;
-{
- register char *p;
-
- p = str;
- do {
- if (p < &str[FILSPC-1])
- *p++ = c;
- c = get();
- if (c == ';')
- while (c)
- c = get();
-#ifdef SDK
- } while (c);
-#else /* SDK */
- } while (c && (ctype[c] != SPACE));
-#endif /* SDK */
- while (p < &str[FILSPC])
- *p++ = 0;
-}
-
-/*)Function char getnb()
- *
- * The function getnb() scans the current input text
- * line returning the first character not a SPACE or TAB.
- *
- * local variables:
- * int c current character from input
- *
- * global variables:
- * none
- *
- * called functions:
- * char get() lklex.c
- *
- * side effects:
- * use of get() updates the global pointer ip, the position
- * in the current input text line
- */
-
-char
-getnb()
-{
- register int c;
-
- while ((c=get())==' ' || c=='\t')
- ;
- return (c);
-}
-
-/*)Function VOID skip()
- *
- * The function skip() scans the input text skipping all
- * letters and digits.
- *
- * local variables:
- * none
- *
- * global variables:
- * char ctype[] array of character types, one per
- * ASCII character
- *
- * functions called:
- * char get() lklex.c
- * char getnb() lklex.c
- * VOID unget() lklex.c
- *
- * side effects:
- * Input letters and digits are skipped.
- */
-
-VOID
-skip(c)
-register int c;
-{
- if (c < 0)
- c = getnb();
- while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
- unget(c);
-}
-
-/*)Function char get()
- *
- * The function get() returns the next character in the
- * input text line, at the end of the line a
- * NULL character is returned.
- *
- * local variables:
- * int c current character from
- * input text line
- *
- * global variables:
- * char * ip pointer into the current
- * input text line
- *
- * called functions:
- * none
- *
- * side effects:
- * updates ip to the next character position in the
- * input text line. If ip is at the end of the
- * line, ip is not updated.
- */
-
-char
-get()
-{
- register int c;
-
- if ((c = *ip) != 0)
- ++ip;
- return (c);
-}
-
-/*)Function VOID unget(c)
- *
- * int c value of last character
- * read from input text line
- *
- * If (c) is not a NULL character then the global pointer ip
- * is updated to point to the preceeding character in the
- * input text line.
- *
- * NOTE: This function does not push the character (c)
- * back into the input text line, only
- * the pointer ip is changed.
- *
- * local variables:
- * int c last character read
- * from input text line
- *
- * global variables:
- * char * ip position into the current
- * input text line
- *
- * called functions:
- * none
- *
- * side effects:
- * ip decremented by 1 character position
- */
-
-VOID
-unget(c)
-{
- if (c != 0)
- --ip;
-}
-
-/*)Function int getmap(d)
- *
- * int d value to compare with the
- * input text line character
- *
- * The function getmap() converts the 'C' style characters \b, \f,
- * \n, \r, and \t to their equivalent ascii values and also
- * converts 'C' style octal constants '\123' to their equivalent
- * numeric values. If the first character is equivalent to (d) then
- * a (-1) is returned, if the end of the line is detected then
- * a 'q' error terminates the parse for this line, or if the first
- * character is not a \ then the character value is returned.
- *
- * local variables:
- * int c value of character
- * from input text line
- * int n looping counter
- * int v current value of numeric conversion
- *
- * global variables:
- * none
- *
- * called functions:
- * char get() lklex.c
- * VOID unget() lklex.c
- *
- * side effects:
- * use of get() updates the global pointer ip the position
- * in the current input text line
- */
-
-int
-getmap(d)
-{
- register int c, n, v;
-
- if ((c = get()) == '\0')
- return (-1);
- if (c == d)
- return (-1);
- if (c == '\\') {
- c = get();
- switch (c) {
-
- case 'b':
- c = '\b';
- break;
-
- case 'f':
- c = '\f';
- break;
-
- case 'n':
- c = '\n';
- break;
-
- case 'r':
- c = '\r';
- break;
-
- case 't':
- c = '\t';
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- n = 0;
- v = 0;
- while (++n<=3 && c>='0' && c<='7') {
- v = (v<<3) + c - '0';
- c = get();
- }
- unget(c);
- c = v;
- break;
- }
- }
- return (c);
-}
-
-/*)Function int lk_getline()
- *
- * The function lk_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
- * lk_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
-lk_getline()
-{
- register int i, ftype;
- register char *fid;
-
-loop: if (pflag && cfp && cfp->f_type == F_STD)
- fprintf(stdout, "ASlink >> ");
-
-#ifdef SDK
- if(cfp == NULL && filep != NULL && filep->f_type == F_CMD) {
- char **argv = (char **)filep->f_idp;
- if(argv[0] != NULL && strlen(argv[0]) < sizeof ib) {
- strcpy(ib, argv[0]);
- filep->f_idp = (char *)&argv[1];
- } else {
- filep = NULL;
- return(0);
- }
- } else
-#endif /* SDK */
- if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
- if (sfp) {
- fclose(sfp);
-#ifdef SDK
- sfp = NULL;
-#endif /* SDK */
- lkulist(0);
- }
- if (cfp == NULL) {
- cfp = filep;
- } else {
- cfp = cfp->f_flp;
- }
- if (cfp) {
- ftype = cfp->f_type;
- fid = cfp->f_idp;
- if (ftype == F_STD) {
- sfp = stdin;
- } else
- if (ftype == F_LNK) {
-#ifdef SDK
- sfp = afile(fid, "lnk", 0);
-#else /* SDK */
- sfp = afile(fid, "LNK", 0);
-#endif /* SDK */
- } else
- if (ftype == F_REL) {
-#ifdef SDK
- sfp = afile(fid, "", 0);
- if (uflag && pass != 0) {
- if ((tfp = afile(fid, "lst", 0)) != NULL) {
- if ((rfp = afile(fid, "rst", 1)) == NULL) {
-#else /* SDK */
- sfp = afile(fid, "REL", 0);
- if (uflag && pass != 0) {
- if ((tfp = afile(fid, "LST", 0)) != NULL) {
- if ((rfp = afile(fid, "RST", 1)) == NULL) {
-#endif /* SDK */
- fclose(tfp);
- tfp = NULL;
- }
- }
- }
- gline = 1;
- } else {
- fprintf(stderr, "Invalid file type\n");
- lkexit(1);
- }
- if (sfp == NULL) {
- lkexit(1);
- }
- goto loop;
- } else {
- filep = NULL;
- return(0);
- }
- }
- i = strlen(ib) - 1;
- if (ib[i] == '\n')
- ib[i] = 0;
- return (1);
-}
-
-/*)Function int more()
- *
- * The function more() scans the input text line
- * skipping white space (SPACES and TABS) and returns a (0)
- * if the end of the line or a comment delimeter (;) is found,
- * or a (1) if their are additional characters in the line.
- *
- * local variables:
- * int c next character from
- * the input text line
- *
- * global variables:
- * none
- *
- * called functions:
- * char getnb() lklex.c
- * VOID unget() lklex.c
- *
- * side effects:
- * use of getnb() and unget() updates the global pointer ip
- * the position in the current input text line
- */
-
-int
-more()
-{
- register int c;
-
- c = getnb();
- unget(c);
- return( (c == '\0' || c == ';') ? 0 : 1 );
-}
-
-/*)Function char endline()
- *
- * The function endline() scans the input text line
- * skipping white space (SPACES and TABS) and returns the next
- * character or a (0) if the end of the line is found or a
- * comment delimiter (;) is found.
- *
- * local variables:
- * int c next character from
- * the input text line
- *
- * global variables:
- * none
- *
- * called functions:
- * char getnb() lklex.c
- *
- * side effects:
- * Use of getnb() updates the global pointer ip the
- * position in the current input text line.
- */
-
-char
-endline()
-{
- register int c;
-
- c = getnb();
- return( (c == '\0' || c == ';') ? 0 : c );
-}
-
-/*)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
- *
- */
-
-/*
- * Extensions: P. Felber
- */
-
-#define EQ(A,B) !strcmp((A),(B))
-#define MAXLINE 254 /*when using fgets*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include "aslink.h"
-
-#ifdef OTHERSYSTEM
-#ifdef SDK
-#ifdef UNIX
- #define LKDIRSEP '/'
- #define LKDIRSEPSTR "/"
-#else /* UNIX */
- #define LKDIRSEP '\\'
- #define LKDIRSEPSTR "\\"
-#endif /* UNIX */
-#else /* SDK */
- #define LKDIRSEP '\\'
- #define LKDIRSEPSTR "\\"
-#endif /* SDK */
-#endif
-
-#ifdef SDK
- #define LKOBJEXT "o"
-#else /* SDK */
- #define LKOBJEXT "rel"
-#endif /* SDK */
-
-/*)Module lklibr.c
- *
- * The module lklibr.c contains the functions which
- * (1) specify the path(s) to library files [.LIB]
- * (2) specify the library file(s) [.LIB] to search
- * (3) search the library files for specific symbols
- * and link the module containing this symbol
- *
- * lklibr.c contains the following functions:
- * VOID addpath()
- * VOID addlib()
- * VOID addfile()
- * VOID search()
- * VOID fndsym()
- * VOID library()
- * VOID loadfile()
- *
- */
-
-#ifdef INDEXLIB
-typedef struct slibrarysymbol mlibrarysymbol;
-typedef struct slibrarysymbol *pmlibrarysymbol;
-
-struct slibrarysymbol {
- char * name; /*Warning: allocate memory before using*/
- pmlibrarysymbol next;
-};
-
-typedef struct slibraryfile mlibraryfile;
-typedef struct slibraryfile *pmlibraryfile;
-
-struct slibraryfile {
- int loaded;
- char * libspc;
- char * relfil; /*Warning: allocate memory before using*/
- char * filename; /*Warning: allocate memory before using*/
- long offset; //if > 0, the embedded file offset in the library file libspc
- pmlibrarysymbol symbols;
- pmlibraryfile next;
-};
-
-/* First entry in the library object symbol cache */
-pmlibraryfile libr=NULL;
-
-int buildlibraryindex();
-void freelibraryindex (void);
-#endif /* INDEXLIB */
-
-/*)Function VOID addpath()
- *
- * The function addpath() creates a linked structure containing
- * the paths to various object module library files.
- *
- * local variables:
- * lbpath *lbph pointer to new path structure
- * lbpath *lbp temporary pointer
- *
- * global variables:
- * lbpath *lbphead The pointer to the first
- * path structure
- *
- * functions called:
- * char getnb() lklex.c
- * VOID * new() lksym.c
- * int strlen() c_library
- * char * strcpy() c_library
- * VOID unget() lklex.c
- *
- * side effects:
- * An lbpath structure may be created.
- */
-
-VOID
-addpath()
-{
- struct lbpath *lbph, *lbp;
-
- lbph = (struct lbpath *) new (sizeof(struct lbpath));
- if (lbphead == NULL) {
- lbphead = lbph;
- } else {
- lbp = lbphead;
- while (lbp->next)
- lbp = lbp->next;
- lbp->next = lbph;
- }
- unget(getnb());
- lbph->path = (char *) new (strlen(ip)+1);
- strcpy(lbph->path, ip);
-}
-
-/*)Function VOID addlib()
- *
- * The function addlib() tests for the existance of a
- * library path structure to determine the method of
- * adding this library file to the library search structure.
- *
- * This function calls the function addfile() to actually
- * add the library file to the search list.
- *
- * local variables:
- * lbpath *lbph pointer to path structure
- *
- * global variables:
- * lbpath *lbphead The pointer to the first
- * path structure
- * ip a pointer to the library name
- *
- * functions called:
- * VOID addfile() lklibr.c
- * char getnb() lklex.c
- * VOID unget() lklex.c
- *
- * side effects:
- * The function addfile() may add the file to
- * the library search list.
- */
-
-VOID
-addlib()
-{
- struct lbpath *lbph;
- int foundcount=0;
-
- unget(getnb());
-
- if (lbphead == NULL)
- {
- foundcount=addfile(NULL, ip);
- }
- else
- {
- for (lbph=lbphead; lbph; lbph=lbph->next)
- {
- foundcount+=addfile(lbph->path, ip);
- }
- }
- if(foundcount == 0)
- {
- fprintf(stderr, "\n?ASlink-Warning-Couldn't find library '%s'", 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;
- int libfilinc=0;
-
- if (path != NULL)
- {
- str = (char *) new (strlen(path) + strlen(libfil) + 6);
- strcpy(str, path);
-
- if (str[strlen(str)-1] != LKDIRSEP)
- {
- strcat(str, LKDIRSEPSTR);
- }
- }
- else
- {
- str = (char *) new (strlen(libfil) + 5);
- }
-
- if (libfil[0] == LKDIRSEP)
- {
- libfil++;
- libfilinc=1;
- }
-
- 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*/
- if(libfilinc) libfil--;
- 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 '.o' 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(char * libfname, FILE * libfp, char * ModName)
-{
- char str[NINPUT+2];
- int state=0;
-
- while (fgets(str, NINPUT, libfp) != NULL)
- {
- str[NINPUT+1] = '\0';
- chop_crlf(str);
- switch(state)
- {
- case 0:
- if(EQ(str, "<FILE>"))
- {
- fgets(str, NINPUT, libfp);
- str[NINPUT+1] = '\0';
- chop_crlf(str);
- if(EQ(str, ModName)) state=1;
- else
- {
- fprintf(stderr, "?Aslink-Error-Bad offset in library file %s(%s)\n",
- libfname, ModName);
- lkexit(1);
- }
- }
- break;
- case 1:
- if(EQ(str, "<REL>")) state=2;
- break;
- case 2:
- if(EQ(str, "</REL>")) return;
- ip = str;
- link();
- break;
- }
- }
-}
-
-/*)Function VOID fndsym(name)
- *
- * char *name symbol name to find
- *
- * The function fndsym() searches through all combinations of the
- * library path specifications (input by the -k option) and the
- * library file specifications (input by the -l option) that
- * lead to an existing file.
- *
- * The file specicifation may be formed in one of two ways:
- *
- * (1) If the library file contained an absolute
- * path/file specification then this becomes filspc.
- * (i.e. C:\...)
- *
- * (2) If the library file contains a relative path/file
- * specification then the concatenation of the path
- * and this file specification becomes filspc.
- * (i.e. \...)
- *
- * The structure lbfile is created for the first library
- * object file which contains the definition for the
- * specified undefined symbol.
- *
- * If the library file [.LIB] contains file specifications for
- * non existant files, no errors are returned.
- *
- * local variables:
- * char buf[] [.REL] file input line
- * char c [.REL] file input character
- * FILE *fp file handle for object file
- * lbfile *lbf temporary pointer
- * lbfile *lbfh pointer to lbfile structure
- * FILE *libfp file handle for library file
- * lbname *lbnh pointer to lbname structure
- * char *path file specification path
- * char relfil[] [.REL] file specification
- * char *str combined path and file specification
- * char symname[] [.REL] file symbol string
- *
- * global variables:
- * lbname *lbnhead The pointer to the first
- * name structure
- * lbfile *lbfhead The pointer to the first
- * file structure
- *
- * functions called:
- * int fclose() c_library
- * int fgets() c_library
- * FILE *fopen() c_library
- * VOID free() c_library
- * char getnb() lklex.c
- * VOID lkexit() lkmain.c
- * VOID loadfile() lklibr.c
- * VOID * new() lksym.c
- * char * sprintf() c_library
- * int sscanf() c_library
- * char * strcat() c_library
- * char * strchr() c_library
- * char * strcpy() c_library
- * int strlen() c_library
- * int strncmp() c_library
- * VOID unget() lklex.c
- *
- * side effects:
- * If the symbol is found then a new lbfile structure
- * is created and added to the linked list of lbfile
- * structures. The file containing the found symbol
- * is linked.
- */
-
-#ifdef INDEXLIB
-
-int fndsym( char *name )
-{
- struct lbfile *lbfh, *lbf;
- pmlibraryfile ThisLibr;
- pmlibrarysymbol ThisSym = NULL;
-
- pmlibraryfile FirstFound;
- int numfound=0;
-
- /* Build the index if this is the first call to fndsym */
- if (libr==NULL) buildlibraryindex();
-
- /* Iterate through all library object files */
- ThisLibr = libr;
- FirstFound = libr; /*So gcc stops whining*/
- while (ThisLibr)
- {
- /* Iterate through all symbols in an object file */
- ThisSym = ThisLibr->symbols;
-
- while (ThisSym)
- {
- //printf("ThisSym->name=%s\n", ThisSym->name);
- if (!strcmp(ThisSym->name, name))
- {
- if ((!ThisLibr->loaded) && (numfound==0))
- {
- /* Object file is not loaded - add it to the list */
- lbfh = (struct lbfile *) new (sizeof(struct lbfile));
- if (lbfhead == NULL)
- {
- lbfhead = lbfh;
- }
- else
- {
- lbf = lbfhead;
- while (lbf->next)
- lbf = lbf->next;
- lbf->next = lbfh;
- }
- lbfh->libspc = ThisLibr->libspc;
- lbfh->filspc = ThisLibr->filename;
- lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
- strcpy(lbfh->relfil,ThisLibr->relfil);
- lbfh->offset = ThisLibr->offset;
- if(lbfh->offset>0)
- { /*For an embedded object file in a library*/
- void loadfile_SdccLib(char * libspc, char * module, long offset);
- loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
- }
- else
- { /*For a stand alone object file*/
- loadfile(lbfh->filspc);
- }
- ThisLibr->loaded=1;
- }
-
- if(numfound==0)
- {
- numfound++;
- FirstFound=ThisLibr;
- }
- else
- {
- char absPath1[PATH_MAX];
- char absPath2[PATH_MAX];
-#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
- int j;
-
- _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
- _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
- for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
- for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
-#else
- realpath(FirstFound->libspc, absPath1);
- realpath(ThisLibr->libspc, absPath2);
-#endif
- if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
- {
- if(numfound==1)
- {
- fprintf(stderr, "?Aslink-Warning-Definition of public symbol '%s'"
- " found more than once:\n", name);
- fprintf(stderr, " Library: '%s', Module: '%s'\n",
- FirstFound->libspc, FirstFound->relfil);
- }
- fprintf(stderr, " Library: '%s', Module: '%s'\n",
- ThisLibr->libspc, ThisLibr->relfil);
- numfound++;
- }
- }
- }
- ThisSym=ThisSym->next; /* Next sym in library */
- }
- ThisLibr=ThisLibr->next; /* Next library in list */
- }
- return numfound;
-}
-
-pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
-{
- char ModName[NCPS]="";
- char FLine[MAXLINE+1];
- char buff[PATH_MAX];
- int state=0;
- long IndexOffset=0, FileOffset;
- pmlibrarysymbol ThisSym = NULL;
-
- while(!feof(libfp))
- {
- FLine[0]=0;
- fgets(FLine, MAXLINE, libfp);
- chop_crlf(FLine);
-
- switch(state)
- {
- case 0:
- if(EQ(FLine, "<INDEX>"))
- {
- /*The next line has the size of the index*/
- FLine[0]=0;
- fgets(FLine, MAXLINE, libfp);
- chop_crlf(FLine);
- IndexOffset=atol(FLine);
- state=1;
- }
- break;
- case 1:
- if(EQ(FLine, "<MODULE>"))
- {
- /*The next line has the name of the module and the offset
- of the corresponding embedded file in the library*/
- FLine[0]=0;
- fgets(FLine, MAXLINE, libfp);
- chop_crlf(FLine);
- sscanf(FLine, "%s %ld", ModName, &FileOffset);
- state=2;
-
- /*Create a new libraryfile object for this module*/
- if(libr==NULL)
- {
- libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
- }
- else
- {
- This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
- This=This->next;
- }
- This->next = NULL;
- This->loaded=-1;
- This->offset=FileOffset+IndexOffset;
- This->libspc=PathLib;
-
- This->relfil=(char *)new(strlen(ModName)+1);
- strcpy(This->relfil, ModName);
-
- sprintf(buff, "%s%s%c%s", DirLib, ModName, FSEPX, LKOBJEXT);
- This->filename=(char *)new(strlen(buff)+1);
- strcpy(This->filename, buff);
-
- This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
- }
- else if(EQ(FLine, "</INDEX>"))
- {
- return This; /*Finish, get out of here*/
- }
- break;
- case 2:
- if(EQ(FLine, "</MODULE>"))
- {
- This->loaded=0;
- /*Create the index for the next module*/
- state=1;
- }
- else
- {
- /*Add the symbols*/
- if(ThisSym==NULL) /*First symbol of the current module*/
- {
- ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- }
- else
- {
- ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- ThisSym=ThisSym->next;
- }
- ThisSym->next=NULL;
- ThisSym->name=(char *)new(strlen(FLine)+1);
- strcpy(ThisSym->name, FLine);
- }
- break;
-
- default:
- return This; /*State machine should never reach this point, but just in case...*/
- break;
- }
- }
-
- return This; /*State machine should never reach this point, but just in case...*/
-}
-
-
-/* buildlibraryindex - build an in-memory cache of the symbols contained in
- * the libraries
- */
-int buildlibraryindex(void)
-{
- FILE *libfp, *fp;
- struct lbname *lbnh;
- char relfil[NINPUT+2], str[PATH_MAX], *path;
- char buf[NINPUT+2], c;
- char symname[NINPUT+2];
- pmlibraryfile This=NULL;
- pmlibrarysymbol ThisSym;
-
- /* Iterate through all library files */
- for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
- {
- if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
- {
- fprintf(stderr, "?Aslink-Error-Cannot open library file %s\n",
- lbnh->libspc);
- lkexit(1);
- }
-
- path=lbnh->path;
-
- /*
- * Read in a line from the library file.
- * This is the relative file specification
- * for a .REL file in this library.
- */
-
- while (fgets(relfil, NINPUT, libfp) != NULL)
- {
- relfil[NINPUT+1] = '\0';
- chop_crlf(relfil);
- if (path != NULL)
- {
- strcpy(str, path);
-#ifdef OTHERSYSTEM
- if (str[strlen(str)-1] != LKDIRSEP)
- {
- strcat(str, LKDIRSEPSTR);
- }
-#endif
- }
- else
- {
- strcpy(str, "");
- }
-
- if(strcmp(relfil, "<SDCCLIB>")==0)
- {
- /*Get the built in index of a library*/
- This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
- break; /*get the index for next library*/
- }
-
- /*From here down, build the index for the original library format*/
-
- if (relfil[0] == LKDIRSEP)
- {
- strcat(str, relfil+1);
- }
- else
- {
- strcat(str, relfil);
- }
-
- if(strchr(relfil, FSEPX) == NULL)
- {
- sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
- }
-
- if ((fp = fopen(str, "r")) != NULL)
- {
- /* Opened OK - create a new libraryfile object for it */
- if(libr==NULL)
- {
- libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
- }
- else
- {
- This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
- This=This->next;
- }
-
- This->next = NULL;
- This->loaded=-1;
- This->offset=-1; /*There should be a rel file*/
- This->libspc = lbnh->libspc;
- This->relfil=(char *)new(strlen(relfil)+1);
- strcpy(This->relfil, relfil);
- This->filename=(char *)new(strlen(str)+1);
- strcpy(This->filename, str);
-
- ThisSym = This->symbols = NULL;
-
- /*
- * Read in the object file. Look for lines that
- * begin with "S" and end with "D". These are
- * symbol table definitions. If we find one, see
- * if it is our symbol. Make sure we only read in
- * our object file and don't go into the next one.
- */
-
- while (fgets(buf, NINPUT, fp) != NULL)
- {
- buf[NINPUT+1] = '\0';
- buf[strlen(buf) - 1] = '\0';
-
- /*
- * Skip everything that's not a symbol record.
- */
- if (buf[0] != 'S') continue;
-
- /*
- * When a 'T line' is found terminate file scan.
- * All 'S line's preceed 'T line's in .REL files.
- */
- if (buf[0] == 'T') break;
-
- sscanf(buf, "S %s %c", symname, &c);
-
- /* If it's an actual symbol, record it */
- if (c == 'D')
- {
- if(ThisSym==NULL)
- {
- ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- }
- else
- {
- ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
- ThisSym=ThisSym->next;
- }
- This->loaded=0;
- ThisSym->next=NULL;
- ThisSym->name=(char *)new(strlen(symname)+1);
- strcpy(ThisSym->name, symname);
- }
- } /* Closes while - read object file */
- fclose(fp);
- } /* Closes if object file opened OK */
- } /* Ends while - processing all in libr */
- fclose(libfp);
- } /* Ends good open of libr file */
- return 0;
-}
-
-/*Release all memory allocated for the in-memory library index*/
-void freelibraryindex (void)
-{
- pmlibraryfile ThisLibr, ThisLibr2Free;
- pmlibrarysymbol ThisSym, ThisSym2Free;
-
- ThisLibr = libr;
-
- while (ThisLibr)
- {
- ThisSym = ThisLibr->symbols;
-
- while (ThisSym)
- {
- free(ThisSym->name);
- ThisSym2Free=ThisSym;
- ThisSym=ThisSym->next;
- free(ThisSym2Free);
- }
- free(ThisLibr->filename);
- free(ThisLibr->relfil);
- ThisLibr2Free=ThisLibr;
- ThisLibr=ThisLibr->next;
- free(ThisLibr2Free);
- }
-
- libr=NULL;
-}
-
-#else /* INDEXLIB */
-
-
-/*Check for a symbol in a SDCC library. If found, add the embedded .rel.
-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)], "%c%s", FSEPX, LKOBJEXT);
-
- /*If this module has been loaded already don't load it again.*/
- lbf = lbfhead;
- while (lbf)
- {
- if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
- lbf=lbf->next;
- }
-
- /*Add the embedded file to the list of files to be loaded in
- the second pass. That is performed latter by the function
- library() below.*/
- lbfh = (struct lbfile *) new (sizeof(struct lbfile));
- if (lbfhead == NULL)
- {
- lbfhead = lbfh;
- }
- else
- {
- lbf = lbfhead;
- while (lbf->next)
- lbf = lbf->next;
- lbf->next = lbfh;
- }
-
- lbfh->libspc = PathLib;
- lbfh->filspc = DirLib;
- lbfh->relfil = (char *) new (strlen(ModName) + 1);
- strcpy(lbfh->relfil, ModName);
- /*Library embedded file, so lbfh->offset must be >=0*/
- lbfh->offset = IndexOffset+FileOffset;
-
- /*Jump to where the .rel begins and load it.*/
- fseek(libfp, lbfh->offset, SEEK_SET);
- LoadRel(PathLib, libfp, ModName);
-
- 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*/
-}
-
-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".
- */
-
-/*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
- if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
- fprintf(stderr, "Cannot open library file %s\n",
- lbnh->libspc);
- lkexit(1);
- }
- path = lbnh->path;
-
- /*
- * Read in a line from the library file.
- * This is the relative file specification
- * for a .REL file in this library.
- */
-
-/*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
- relfil[NINPUT+1] = '\0';
- chop_crlf(relfil);
- if (path != NULL) {
- str = (char *) new (strlen(path)+strlen(relfil)+6);
- strcpy(str,path);
-#ifdef OTHERSYSTEM
-#ifdef SDK
-#ifdef UNIX
- if (str[strlen(str)-1] != '/') {
- strcat(str,"/");
-#else /* UNIX */
- if (str[strlen(str)-1] != '\\') {
- strcat(str,"\\");
-#endif /* UNIX */
-#else /* SDK */
- if (str[strlen(str)-1] != '\\') {
- strcat(str,"\\");
-#endif /* SDK */
- }
-#endif
- } else {
- str = (char *) new (strlen(relfil) + 5);
- }
-
- /*See if this is a library with embedded files*/
- if(strcmp(relfil, "<SDCCLIB>")==0)
- {
- result=SdccLib(lbnh->libspc, libfp, str, name);
- if(result) return(1); /*Found the symbol*/
- free(str);
- /*The symbol is not in the current library,
- check the next library in the list*/
- break;
- }
-
- /*From here down is the support for libraries in the original format*/
-#ifdef SDK
-#ifdef UNIX
- if (relfil[0] == '/') {
-#else /* UNIX */
- if (relfil[0] == '\\') {
-#endif /* UNIX */
-#else /* SDK */
- if (relfil[0] == '\\') {
-#endif /* SDK */
- strcat(str,relfil+1);
- } else {
- strcat(str,relfil);
- }
- if(strchr(relfil, FSEPX) == NULL)
- {
- sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
- }
-
-/*3*/ if ((fp = fopen(str, "r")) != NULL) {
-
- /*
- * Read in the object file. Look for lines that
- * begin with "S" and end with "D". These are
- * symbol table definitions. If we find one, see
- * if it is our symbol. Make sure we only read in
- * our object file and don't go into the next one.
- */
-
-/*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
-
- buf[NINPUT+1] = '\0';
- buf[strlen(buf) - 1] = '\0';
-
- /*
- * Skip everything that's not a symbol record.
- */
- if (buf[0] != 'S')
- continue;
-
- /*
- * When a 'T line' is found terminate file scan.
- * All 'S line's preceed 'T line's in .REL files.
- */
- if (buf[0] == 'T')
- break;
-
- sscanf(buf, "S %s %c", symname, &c);
-
- /*
- * If we find a symbol definition for the
- * symbol we're looking for, load in the
- * file and add it to lbfhead so it gets
- * loaded on pass number 2.
- */
-/*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
-
- lbfh = (struct lbfile *) new (sizeof(struct lbfile));
- if (lbfhead == NULL) {
- lbfhead = lbfh;
- } else {
- lbf = lbfhead;
- while (lbf->next)
- lbf = lbf->next;
- lbf->next = lbfh;
- }
- lbfh->libspc = lbnh->libspc;
- lbfh->filspc = str;
- lbfh->relfil = (char *) new (strlen(relfil) + 1);
- lbfh->offset = -1; /*Stand alone rel file*/
- strcpy(lbfh->relfil,relfil);
- fclose(fp);
- fclose(libfp);
- loadfile(str);
- return (1);
-
-/*5*/ }
-
-/*4*/ }
- fclose(fp);
-/*3*/ }
-
- free(str);
-/*2*/ }
- fclose(libfp);
-/*1*/ }
- return(0);
-}
-#endif /* INDEXLIB */
-
-void loadfile_SdccLib(char * libspc, char * module, long offset)
-{
- FILE *fp;
-
-#ifdef __CYGWIN__
- char posix_path[PATH_MAX];
- void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
- cygwin_conv_to_full_posix_path(libspc, posix_path);
- fp = fopen(posix_path, "r");
-#else
- fp = fopen(libspc,"r");
-#endif
-
- if (fp != NULL)
- {
- fseek(fp, offset, SEEK_SET);
- LoadRel(libspc, fp, module);
- fclose(fp);
- }
- else
- {
- fprintf(stderr, "?Aslink-Error-Opening library '%s'\n", libspc);
- lkexit(1);
- }
-}
-
-/*)Function VOID library()
- *
- * The function library() links all the library object files
- * contained in the lbfile structures.
- *
- * local variables:
- * lbfile *lbfh pointer to lbfile structure
- *
- * global variables:
- * lbfile *lbfhead pointer to first lbfile structure
- *
- * functions called:
- * VOID loadfile lklibr.c
- *
- * side effects:
- * Links all files contained in the lbfile structures.
- */
-
-VOID
-library()
-{
- struct lbfile *lbfh;
-
- for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
- {
- if(lbfh->offset<0)
- {
- /*Stand alone rel file (original lib format)*/
- loadfile(lbfh->filspc);
- }
- else
- {
- /*rel file embedded in lib (new lib format)*/
- loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
- }
- }
-#ifdef INDEXLIB
- freelibraryindex();
-#endif
-}
-
-/*)Function VOID loadfile(filspc)
- *
- * char *filspc library object file specification
- *
- * The function loadfile() links the library object module.
- *
- * local variables:
- * FILE *fp file handle
- * int i input line length
- * char str[] file input line
- *
- * global variables:
- * char *ip pointer to linker input string
- *
- * functions called:
- * int fclose() c_library
- * int fgets() c_library
- * FILE * fopen() c_library
- * VOID link() lkmain.c
- * int strlen() c_library
- *
- * side effects:
- * If file exists it is linked.
- */
-
-VOID
-loadfile(filspc)
-char *filspc;
-{
- FILE *fp;
- char str[NINPUT+2];
- int i;
-
-#ifdef __CYGWIN__
- char posix_path[PATH_MAX];
- void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
- cygwin_conv_to_full_posix_path(filspc, posix_path);
- fp = fopen(posix_path, "r");
-#else
- fp = fopen(filspc,"r");
-#endif
-
- if (fp != NULL)
- {
- while (fgets(str, NINPUT, fp) != NULL)
- {
- str[NINPUT+1] = '\0';
- i = strlen(str) - 1;
- if (str[i] == '\n')
- str[i] = '\0';
- ip = str;
- link();
- }
- fclose(fp);
- }
- else
- {
- fprintf(stderr, "?Aslink-Error-Opening library '%s'\n", filspc);
- lkexit(1);
- }
-}
+++ /dev/null
-/* lklist.c */
-
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "aslink.h"
-
-/*)Module 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, "Hexidecimal\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;
-}
-
-#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.
- */
-
-#ifndef MLH_MAP
-VOID
-lstarea(xp)
-struct area *xp;
-{
-// register struct area *op;
- register struct areax *oxp;
- register c, i, j;
- register char *ptr;
- int nmsym;
- Addr_T a0, ai, aj;
- struct sym *sp;
- struct sym **p;
-
- putc('\n', mfp);
- if (xflag == 0) {
- fprintf(mfp, "Hexidecimal\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 Bytes (Attributes)\n");
- fprintf(mfp, "-------------------------------- ");
- fprintf(mfp, "---- ---- ------- ----- ------------\n");
- /*
- * 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");
- }
- 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;
- }
-
- /*
- * 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;
- }
- }
-
- /*
- * Symbol Table Output
- */
- i = 0;
- fprintf(mfp, "\n\n");
- fprintf(mfp, " Value Global\n");
- fprintf(mfp, " ----- --------------------------------");
- while (i < nmsym) {
- fprintf(mfp, "\n");
- 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];
- while (ptr < &sp->s_id[NCPS]) {
- if ((c = *ptr++) != 0) {
- putc(c, mfp);
- } else {
- putc(' ', mfp);
- }
- }
- i++;
- }
- putc('\n', mfp);
- free(p);
-}
-#else
-VOID lstarea(struct area *xp)
-{
- register struct areax *oxp;
- register int i, j;
- int nmsym;
- Addr_T a0, ai = 0, aj = 0;
- struct sym *sp;
- struct sym **p;
-
- /*
- * 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;
- }
-
- /*
- * Symbol Table Output
- */
- if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
- fprintf(mfp, "AREA %s\n", xp->a_id );
- switch (xflag) {
- case 1:
- fprintf(mfp, "\tRADIX OCTAL\n" );
- break;
- case 2:
- fprintf(mfp, "\tRADIX DEC\n" );
- break;
- default:
- fprintf(mfp, "\tRADIX HEX\n" );
- break;
- }
- fprintf( mfp, "\tBASE %04X\n"
- "\tSIZE %04X\n"
- "\tATTRIB "
- , xp->a_addr, xp->a_size );
- 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");
- }
- 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"); }
- }
-
- fprintf( mfp,"\n");
- if (nmsym>0) {
- /*
- * 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;
- }
-
- /*
- * 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;
- }
- }
-
- fprintf( mfp, "\tGLOBALS\n");
- i = 0;
- while (i < nmsym) {
- fprintf(mfp, "\t\t%s\t%04X\n", p[i]->s_id, p[i]->s_addr + p[i]->s_axp->a_addr );
- i++;
- }
- free(p);
- }
- }
-}
-#endif /* MLH_MAP */
-#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;
-
- 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");
- }
- 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;
- }
-
- /*
- * 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;
- }
- }
-
- /*
- * Symbol Table Output
- */
- i = 0;
- while (i < nmsym) {
- if (i % 4 == 0) {
- 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];
- while (ptr < &sp->s_id[NCPS]) {
- if ((c = *ptr++) != 0) {
- putc(c, mfp);
- } else {
- putc(' ', mfp);
- }
- }
- if (++i < nmsym)
- if (i % 4 != 0)
- fprintf(mfp, " | ");
- }
- putc('\n', mfp);
- free(p);
- slew(mfp);
-}
-#endif
-
-#ifdef SDK
-VOID lstareatosym(struct area *xp)
-{
- /* Output the current area symbols to a NO$GMB .sym file */
- register struct areax *oxp;
- register int i, j;
- int nmsym;
- Addr_T a0, ai;
- struct sym *sp;
- struct sym **p;
-
- /*
- * 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;
- }
-
- /*
- * Symbol Table Output
- */
- if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
- /* Dont worry about any area information */
- fprintf(mfp, "; Area: %s\n", xp->a_id );
- if (nmsym>0) {
- /*
- * 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;
- }
-
- /*
- * 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;
- }
- }
- i = 0;
- while (i < nmsym) {
- /* no$gmb requires the symbol names to be less than 32 chars long. Truncate. */
- char name[32];
- strncpy(name, p[i]->s_id, 31);
- name[31] = '\0';
- if ((strncmp("l__", name, 3)!=0)&&(strchr(name,' ')==NULL)) {
- a0=p[i]->s_addr + p[i]->s_axp->a_addr;
- if (a0>0x7FFFU) {
- /* Not inside the ROM, so treat as being in bank zero */
- fprintf(mfp, "00:%04X %s\n", a0, name);
- }
- else {
- fprintf(mfp, "%02X:%04X %s\n", a0/16384, a0, name);
- }
- }
- i++;
- }
- free(p);
- }
- }
-}
-#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, rb);
-
- while (fgets(rb, sizeof(rb), tfp) != 0) {
- fprintf(rfp, 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, 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, rb);
- goto loop;
- }
-
- /*
- * Must have an address in the expected radix
- */
- if (radix == 16) {
- if (!dgt(RAD16, &rb[3], 4)) {
- fprintf(rfp, rb);
- goto loop;
- }
- sprintf(str, "%04X", pc);
- strncpy(&rb[3], str, 4);
- } else
- if (radix == 10) {
- if (!dgt(RAD10, &rb[3], 5)) {
- fprintf(rfp, rb);
- goto loop;
- }
- sprintf(str, "%05d", pc);
- strncpy(&rb[3], str, 5);
- } else
- if (radix == 8) {
- if (!dgt(RAD8, &rb[3], 6)) {
- fprintf(rfp, rb);
- goto loop;
- }
- sprintf(str, "%06o", pc);
- strncpy(&rb[3], str, 6);
- }
-
- /*
- * Copy updated LST text line to RST
- */
- fprintf(rfp, 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, 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, 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, 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, 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, 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, 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, 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[(unsigned char)(*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
- */
-
-/*
- * Extensions: P. Felber
- */
-
-#include <stdio.h>
-#include <string.h>
-//#include <alloc.h>
-#include "aslink.h"
-#include <stdlib.h>
-
-#ifndef SDK_VERSION_STRING
-#define SDK_VERSION_STRING "3.0.0"
-#endif
-#ifndef TARGET_STRING
-#define TARGET_STRING "gbz80"
-#endif
-
-#ifdef WIN32T
-#include <time.h>
-
-void Timer(int action, char * message)
-{
- static double start, end, total=0.0;
- static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
-
- if(action==0) start=clock()*secs_per_tick;
- else if(action==1)
- {
- end=clock() * secs_per_tick;
- printf("%s \t%f seconds.\n", message, (end-start));
- total+=end-start;
- }
- else
- {
- printf("Total time: \t%f seconds.\n", total);
- total=0.0;
- }
-}
-#endif
-
-/*)Module lkmain.c
- *
- * The module lkmain.c contains the functions which
- * (1) input the linker options, parameters, and specifications
- * (2) perform a two pass link
- * (3) produce the appropriate linked data output and/or
- * link map file and/or relocated listing files.
- *
- * lkmain.c contains the following functions:
- * FILE * afile(fn,ft,wf)
- * VOID bassav()
- * VOID gblsav()
- * VOID link()
- * 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
- *
- */
-
-/*)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 lk_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 lk_getline() lklex.c
- * VOID library() lklibr.c
- * VOID link() 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).
- */
-
-#ifdef SDK
-int binary = 0;
-#endif /* SDK */
-#ifdef GAMEBOY
-char *default_basep[] = {
- "_CODE=0x0200",
- "_DATA=0xC0A0",
- NULL
-};
-
-char *default_globlp[] = {
- /* DMA transfer must start at multiples of 0x100 */
- ".OAM=0xC000",
- ".STACK=0xE000",
- ".refresh_OAM=0xFF80",
-
- ".init=0x0000",
-
- NULL
-};
-#endif /* GAMEBOY */
-
-int
-main(argc, argv)
-char *argv[];
-{
- register char *p;
- register int c, i;
-
-#ifdef WIN32T
- Timer(0, "");
-#endif
-
-#ifdef GAMEBOY
- nb_rom_banks = 2;
- nb_ram_banks = 0;
- mbc_type = 0;
- symflag=0;
-
- for(i = 0; default_basep[i] != NULL; i++) {
- 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;
- }
- bsp->b_strp = default_basep[i];
- }
- for(i = 0; default_globlp[i] != NULL; i++) {
- 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;
- }
- gsp->g_strp = default_globlp[i];
- }
-#endif /* GAMEBOY */
-#ifndef SDK
- fprintf(stdout, "\n");
-#endif /* SDK */
-
- 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();
- }
- }
-
-#ifdef SDK
- if(c == '-') {
- startp->f_type = F_CMD;
- startp->f_idp = (char *)&argv[i+1];
- break;
- }
-#endif /* SDK */
-
- } else {
- if (startp->f_type == F_LNK) {
- startp->f_idp = p;
- }
- }
- }
- if (startp->f_type == F_INV)
- usage();
- if (startp->f_type == F_LNK && startp->f_idp == NULL)
- usage();
-#ifdef SDK
- if (startp->f_type == F_CMD && startp->f_idp == NULL)
- usage();
-#endif /* SDK */
-
- cfp = NULL;
- sfp = NULL;
- filep = startp;
- while (1) {
- ip = ib;
- if (lk_getline() == 0)
- break;
- if (pflag && sfp != stdin)
- fprintf(stdout, "%s\n", ip);
- if (*ip == '\0' || parse())
- break;
- }
- if (sfp)
- fclose(sfp);
- if (linkp == NULL)
- usage();
-#ifdef SDK
- if (linkp->f_flp == NULL)
- usage();
-#endif /* SDK */
-
-#ifdef GAMEBOY
- for(i = 1; i < nb_rom_banks; i++) {
- bsp->b_base = (struct base *)new(sizeof(struct base));
- bsp = bsp->b_base;
- bsp->b_strp = (char *)malloc(18);
- sprintf(bsp->b_strp, "_CODE_%d=0x4000", i);
- }
- for(i = 0; i < nb_ram_banks; i++) {
- bsp->b_base = (struct base *)new(sizeof(struct base));
- bsp = bsp->b_base;
- bsp->b_strp = (char *)malloc(18);
- sprintf(bsp->b_strp, "_DATA_%d=0xA000", i);
- }
-#endif /* GAMEBOY */
-
- syminit();
- for (pass=0; pass<2; ++pass) {
- cfp = NULL;
- sfp = NULL;
-#ifdef SDK
- filep = linkp->f_flp;
-#else /* SDK */
- filep = linkp;
-#endif /* SDK */
- hp = NULL;
- radix = 10;
-
- while (lk_getline()) {
- ip = ib;
- link();
- }
- 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);
-#ifdef SDK
- if (symflag)
- sym();
-#endif
- /*
- * Output Link Map.
- */
- if (mflag)
- map();
- /*
- * Open output file
- */
- if (oflag == 1) {
-#ifdef SDK
- ofp = afile(linkp->f_idp, "ihx", 1);
-#else /* SDK */
- ofp = afile(linkp->f_idp, "IHX", 1);
-#endif /* SDK */
- if (ofp == NULL) {
- lkexit(1);
- }
- } else
- if (oflag == 2) {
-#ifdef SDK
- ofp = afile(linkp->f_idp, "s19", 1);
-#else /* SDK */
- ofp = afile(linkp->f_idp, "S19", 1);
-#endif /* SDK */
- if (ofp == NULL) {
- lkexit(1);
- }
-#ifdef SDK
- } else
- if (oflag == 3) {
- binary = 1;
- ofp = afile(linkp->f_idp, "", 1);
- binary = 0;
- if (ofp == NULL) {
- lkexit(1);
- }
-#endif /* SDK */
- }
- } else {
- /*
- * Link in library files
- */
- library();
- reloc('E');
- }
- }
-#ifdef WIN32T
- Timer(1, "Linker time");
-#endif
- lkexit(lkerr);
-
- /* Never get here. */
- 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 (ofp != NULL) fclose(ofp);
- if (rfp != NULL) fclose(rfp);
- if (sfp != NULL) fclose(sfp);
- if (tfp != NULL) fclose(tfp);
- exit(i);
-}
-
-/*)Function link()
- *
- * The function link() 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()
-{
- 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.
- */
-
-#ifndef MLH_MAP
-VOID
-map()
-{
- register i;
- register struct head *hdp;
- register struct lbfile *lbfh;
-
- /*
- * Open Map File
- */
-#ifdef SDK
- mfp = afile(linkp->f_idp, "map", 1);
-#else /* SDK */
- mfp = afile(linkp->f_idp, "MAP", 1);
-#endif /* SDK */
- 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;
-#ifdef SDK
- filep = linkp->f_flp;
-#else /* SDK */
- filep = linkp;
-#endif /* SDK */
- 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);
-}
-#else
-VOID map()
-{
- register struct head *hdp;
- register struct lbfile *lbfh;
-
- /*
- * Open Map File
- */
-#ifdef SDK
- mfp = afile(linkp->f_idp, "map", 1);
-#else /* SDK */
- mfp = afile(linkp->f_idp, "MAP", 1);
-#endif /* SDK */
- 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
- */
- hdp = headp;
-#ifdef SDK
- filep = linkp->f_flp;
-#else /* SDK */
- filep = linkp;
-#endif /* SDK */
- if (filep) {
- fprintf( mfp, "MODULES\n");
- }
- while (filep) {
- fprintf(mfp, "\tFILE %s\n", filep->f_idp);
- while ((hdp != NULL) && (hdp->h_lfile == filep)) {
- if (strlen(hdp->m_id)>0)
- fprintf(mfp, "\t\tNAME %s\n", hdp->m_id);
- hdp = hdp->h_hp;
- }
- filep = filep->f_flp;
- }
- /*
- * List Linked Libraries
- */
- if (lbfhead != NULL) {
- fprintf(mfp, "LIBRARIES\n");
- for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
- fprintf(mfp, "\tLIBRARY %s\n"
- "\t\tMODULE %s\n",
- lbfh->libspc, lbfh->relfil);
- }
- }
- /*
- * List Base Address Definitions
- */
- if (basep) {
- fprintf(mfp, "USERBASEDEF\n");
- bsp = basep;
- while (bsp) {
- fprintf(mfp, "\t%s\n", bsp->b_strp);
- bsp = bsp->b_base;
- }
- }
- /*
- * List Global Definitions
- */
- if (globlp) {
- fprintf(mfp, "USERGLOBALDEF\n");
- gsp = globlp;
- while (gsp) {
- fprintf(mfp, "\t%s\n", gsp->g_strp);
- gsp = gsp->g_globl;
- }
- }
- symdef(mfp);
-#ifdef SDK
- if (mfp!=NULL) {
- fclose(mfp);
- mfp = NULL;
- }
-#endif
-}
-#endif /* MLH_MAP */
-
-#ifdef SDK
-/* PENDING */
-VOID lstareatosym(struct area *xp);
-
-VOID sym()
-{
- /*
- * Open sym File
- */
- mfp = afile(linkp->f_idp, "sym", 1);
- if (mfp == NULL) {
- lkexit(1);
- }
- fprintf( mfp, "; no$gmb format .sym file\n"
- "; Generated automagically by ASxxxx linker %s (SDK " SDK_VERSION_STRING ")\n"
- , VERSION );
- /*
- * Output sym Area Lists
- */
- page = 0;
- lop = NLPP;
- ap = areap;
- while (ap) {
- lstareatosym(ap);
- ap = ap->a_ap;
- }
- if (mfp!=NULL) {
- fclose(mfp);
- mfp = NULL;
- }
-}
-#endif /* SDK */
-
-/*)Function int parse()
- *
- * The function parse() evaluates all command line or file input
- * linker directives and updates the appropriate variables.
- *
- * local variables:
- * int c character value
- * char fid[] file id string
- *
- * global variables:
- * char ctype[] array of character types, one per
- * ASCII character
- * lfile *lfp pointer to current lfile structure
- * being processed by parse()
- * lfile *linkp pointer to first lfile structure
- * containing an input REL file
- * specification
- * int mflag Map output flag
- * int oflag Output file type flag
- * int pflag print linker command file flag
- * FILE * stderr c_library
- * int uflag Relocated listing flag
- * int xflag Map file radix type flag
- *
- * Functions called:
- * VOID addlib() lklibr.c
- * VOID addpath() lklibr.c
- * VOID bassav() lkmain.c
- * int fprintf() c_library
- * VOID gblsav() lkmain.c
- * VOID getfid() lklex.c
- * char getnb() lklex.c
- * VOID lkexit() lkmain.c
- * char * strcpy() c_library
- * int strlen() c_library
- *
- * side effects:
- * Various linker flags are updated and the linked
- * structure lfile is created.
- */
-
-int
-parse()
-{
- register int c;
- char fid[NINPUT];
-
- while ((c = getnb()) != 0) {
- if (c == ';')
- return(0);
- if ( c == '-') {
- while (ctype[c=get()] & LETTER) {
- switch(c) {
-
- case 'i':
- case 'I':
- oflag = 1;
- break;
-
- case 's':
- case 'S':
- oflag = 2;
- break;
-#ifdef GAMEBOY
- case 'y':
- case 'Y':
- c = get();
- if(c == 'O' || c == 'o')
- nb_rom_banks = expr(0);
- else if(c == 'A' || c == 'a')
- nb_ram_banks = expr(0);
- else if(c == 'T' || c == 't')
- mbc_type = expr(0);
- else if(c == 'N' || c == 'n') {
- int i = 0;
- if(getnb() != '=' || getnb() != '"') {
- fprintf(stderr, "Syntax error in -YN=\"name\" flag\n");
- lkexit(1);
- }
- while((c = get()) != '"' && i < 16) {
- cart_name[i++] = c;
- }
- if(i < 16)
- cart_name[i] = 0;
- else
- while(get() != '"')
- ;
- } else if(c == 'P' || c == 'p') {
- patch *p = patches;
-
- patches = (patch *)malloc(sizeof(patch));
- patches->next = p;
- patches->addr = expr(0);
- if(getnb() != '=') {
- fprintf(stderr, "Syntax error in -YHaddr=val flag\n");
- lkexit(1);
- }
- patches->value = expr(0);
- } else {
- fprintf(stderr, "Invalid option\n");
- lkexit(1);
- }
- break;
-
-#endif /* GAMEBOY */
-#ifdef SDK
- case 'j':
- case 'J':
- ++symflag;
- break;
- case 'z':
- case 'Z':
- oflag = 3;
- break;
-#endif /* SDK */
- case 'm':
- case 'M':
- ++mflag;
- break;
-
- case 'u':
- case 'U':
- uflag = 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);
-
- default:
- fprintf(stderr, "Invalid option\n");
- lkexit(1);
- }
- }
- if (c == ';')
- return(0);
- } else
- if (ctype[c] != ILL) {
- 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;
- } else {
- fprintf(stderr, "Invalid input");
- lkexit(1);
- }
- }
- 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) {
-#ifndef SDK
- fprintf(stderr,
- "No definition of area %s\n", id);
- lkerr++;
-#endif /* SDK */
- } else {
- ap->a_addr = v;
- }
- } else {
- fprintf(stderr, "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) {
-#ifndef SDK
- fprintf(stderr,
- "No definition of symbol %s\n", id);
- lkerr++;
-#endif /* SDK */
- } else {
-#ifndef SDK
- if (sp->s_flag & S_DEF) {
- fprintf(stderr,
- "Redefinition of symbol %s\n", id);
- lkerr++;
- sp->s_axp = NULL;
- }
-#endif /* SDK */
- 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:
- * int c character value
- * char fb[] constructed file specification string
- * 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:
- * 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;
-{
-#if 0
- register char *p1, *p2, *p3;
- register int c;
-#else
- int i;
-#endif
- FILE *fp;
- char fb[FILSPC];
-
-#if 0
- p1 = fn;
- p2 = fb;
- p3 = ft;
- while ((c = *p1++) != 0 && c != FSEPX) {
- if (p2 < &fb[FILSPC-4])
- *p2++ = c;
- }
- *p2++ = FSEPX;
- if (*p3 == 0) {
- if (c == FSEPX) {
- p3 = p1;
- } else {
-#ifdef SDK
- p3 = "rel";
-#else /* SDK */
- p3 = "REL";
-#endif /* SDK */
- }
- }
- while ((c = *p3++) != 0) {
- if (p2 < &fb[FILSPC-1])
- *p2++ = c;
- }
- *p2++ = 0;
-#else
- /*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]=='.') && *ft && strcmp(ft, "lnk") )
- {
- strncpy(fb, fn, i);
- fb[i]=0;
- }
- else
- {
- strcpy(fb, fn);
- }
-
- /*Add the extension*/
- if (fb[i] != '.')
- {
- strcat(fb, ".");
-#ifdef SDK
- strcat(fb, strlen(ft)?ft:"rel");
-#else
- strcat(fb, strlen(ft)?ft:"REL");
-#endif
- }
-#endif
-
-#ifdef SDK
- if ((fp = fopen(fb, wf?(binary?"wb":"w"):(binary?"rb":"r"))) == NULL) {
-#else /* SDK */
- if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
-#endif /* SDK */
- fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
- lkerr++;
- }
- return (fp);
-}
-
-char *usetxt[] = {
-#ifdef SDK
- "Distributed with SDK " SDK_VERSION_STRING ", built on " __DATE__ " " __TIME__,
- "Compile options: SDK Target " TARGET_STRING
-#ifdef INDEXLIB
- " INDEXLIB"
-#endif
- "\n",
-#endif
- "Startup:",
-#ifdef SDK
- " -- [Commands] Non-interactive command line input",
-#endif /* SDK */
- " -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",
-#ifdef SDK
- "Usage: [-Options] outfile file [file ...]",
-#else /* SDK */
- "Usage: [-Options] file [file ...]",
-#endif /* SDK */
- "Librarys:",
- " -k Library path specification, one per -k",
- " -l Library file specification, one per -l",
- "Relocation:",
- " -b area base address = expression",
- " -g global symbol = expression",
-#ifdef GAMEBOY
- " -yo Number of rom banks (default: 2)",
- " -ya Number of ram banks (default: 0)",
- " -yt MBC type (default: no MBC)",
- " -yn Name of program (default: name of output file)",
- " -yp# Patch one byte in the output GB file (# is: addr=byte)",
-#endif /* GAMEBOY */
- "Map format:",
- " -m Map output generated as file[MAP]",
-#ifdef SDK
- " -j no$gmb symbol file generated as file[SYM]",
-#endif /* SDK */
- " -x Hexidecimal (default)",
- " -d Decimal",
- " -q Octal",
- "Output:",
- " -i Intel Hex as file[IHX]",
- " -s Motorola S19 as file[S19]",
-#ifdef SDK
-#ifdef GAMEGEAR
- " -z Gamegear image as file[GG]",
-#else
- " -z Gameboy image as file[GB]",
-#endif /* GAMEGEAR */
-#endif /* SDK */
- "List:",
- " -u Update listing file(s) with link data as file(s)[.RST]",
- "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);
-}
+++ /dev/null
-/* lkrloc.c */
-
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-/*
- * Extensions: P. Felber
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-//#include <alloc.h>
-#include <ctype.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[].
- *
- */
-
-/*)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 = 0, pags = 0, 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);
-
-#ifdef GAMEBOY
- {
- char *s = strrchr(a[aindex]->a_bap->a_id, '_');
- if(s != NULL && isdigit((unsigned char)s[1]))
- current_rom_bank = atoi(s+1);
- else
- current_rom_bank = 0;
- }
-#endif /* GAMEBOY */
- /*
- * Do remaining relocations
- */
- while (more()) {
- error = 0;
- mode = eval();
- 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_BYT2) {
- if (mode & R_MSB) {
- relv = adb_hi(reli, rtp);
- } else {
- relv = adb_lo(reli, rtp);
- }
- } else {
- relv = adb_b(reli, rtp);
- }
- } else {
- /*
- * R_WORD with the R_BYT2 mode is flagged
- * as an 'r' error by the assembler,
- * but it is processed here anyway.
- */
- if (mode & R_BYT2) {
- if (mode & R_MSB) {
- relv = adw_hi(reli, rtp);
- } else {
- relv = adw_lo(reli, rtp);
- }
- } else {
- 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);
- }
- if (oflag == 1) {
- ihx(1);
- } else
- if (oflag == 2) {
- s19(1);
-#ifdef SDK
- } else
- if (oflag == 3) {
-#ifdef GAMEGEAR
- gg(1);
-#endif /* GAMEGEAR */
-#ifdef GAMEBOY
- gb(1);
-#endif /* GAMEBOY */
-#endif /* SDK */
- }
-}
-
-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);
-#ifdef SDK
- } else
- if (oflag == 3) {
-#ifdef GAMEGEAR
- gg(0);
-#endif /* GAMEGEAR */
-#ifdef GAMEBOY
- gb(0);
-#endif /* GAMEBOY */
-#endif /* SDK */
- }
-}
-
-/*)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 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_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",
- NCPS, &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 <alloc.h>
-#include "aslink.h"
-
-/*)Module lks19.c
- *
- * The module lks19.c contains the function to
- * output the relocated object code in the
- * Motorola S19 format.
- *
- * lks19.c contains the following function:
- * VOID s19(i)
- *
- * lks19.c contains no local variables.
- */
-
-/*)S19 Format
- * Record Type Field - This field signifies the start of a
- * record and identifies the the record
- * type as follows:
- *
- * Ascii S1 - Data Record
- * Ascii S9 - End of File Record
- *
- * Record Length Field - This field specifies the record length
- * which includes the address, data, and
- * checksum fields. The 8 bit record
- * length value is converted to two ascii
- * characters, high digit first.
- *
- * Load Address Field - This field consists of the four ascii
- * characters which result from converting
- * the the binary value of the address in
- * which to begin loading this record. The
- * order is as follows:
- *
- * High digit of high byte of address.
- * Low digit of high byte of address.
- * High digit of low byte of address.
- * Low digit of low byte of address.
- *
- * In an End of File record this field con-
- * sists of either four ascii zeros or the
- * program entry address. Currently the
- * entry address option is not supported.
- *
- * Data Field - This field consists of the actual data,
- * converted to two ascii characters, high
- * digit first. There are no data bytes in
- * the End of File record.
- *
- * Checksum Field - The checksum field is the 8 bit binary
- * sum of the record length field, the load
- * address field, and the data field. This
- * sum is then complemented (1's comple-
- * ment) and converted to two ascii
- * characters, high digit first.
- */
-
-/*)Function s19(i)
- *
- * int i 0 - process data
- * 1 - end of data
- *
- * The function s19() outputs the relocated data
- * in the standard Motorola S19 format.
- *
- * local variables:
- * Addr_T chksum byte checksum
- *
- * global variables:
- * int hilo byte order
- * FILE * ofp output file handle
- * int rtcnt count of data words
- * int rtflg[] output the data flag
- * Addr_T rtval[] relocated data
- *
- * functions called:
- * int fprintf() c_library
- *
- * side effects:
- * The data is output to the file defined by ofp.
- */
-
-VOID
-s19(i)
-{
- register Addr_T chksum;
-
- if (i) {
- if (hilo == 0) {
- chksum = rtval[0];
- rtval[0] = rtval[1];
- rtval[1] = chksum;
- }
- for (i = 0, chksum = 1; i < rtcnt; i++) {
- if (rtflg[i])
- chksum++;
- }
- fprintf(ofp, "S1%02X", chksum);
- for (i = 0; i < rtcnt ; i++) {
- if (rtflg[i]) {
- fprintf(ofp, "%02X", rtval[i]);
- chksum += rtval[i];
- }
- }
- fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff);
- } else {
- fprintf(ofp, "S9030000FC\n");
- }
-}
+++ /dev/null
-/* lksym.c */
-
-/*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio 44240
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include "aslink.h"
-
-/*)Module lksym.c
- *
- * The module lksym.c contains the functions that operate
- * on the symbol structures.
- *
- * lksym.c contains the following functions:
- * int hash()
- * sym * lkpsym()
- * VOID * new()
- * sym * newsym()
- * VOID symdef()
- * int symeq()
- * VOID syminit()
- * VOID symmod()
- * Addr_T symval()
- *
- * lksym.c contains no local/static variables.
- */
-
-/*)Function VOID syminit()
- *
- * The function syminit() is called to clear the hashtable.
- *
- * local variables:
- * int h computed hash value
- * sym ** spp pointer to an array of
- * sym structure pointers
- *
- * global variables:
- * sym * symhash[] array of pointers to NHASH
- * linked symbol lists
- *
- * functions called:
- * none
- *
- * side effects:
- * (1) The symbol hash tables are cleared
- */
-
-VOID
-syminit()
-{
- struct sym **spp;
-
- spp = &symhash[0];
- while (spp < &symhash[NHASH])
- *spp++ = NULL;
-}
-
-/*)Function sym * newsym()
- *
- * The function newsym() is called to evaluate the symbol
- * definition/reference directive from the .rel file(s).
- * If the symbol is not found in the symbol table a new
- * symbol structure is created. Evaluation of the
- * directive determines if this is a reference or a definition.
- * Multiple definitions of the same variable will be flagged
- * as an error if the values are not identical. A symbol
- * definition places the symbol value and area extension
- * into the symbols data structure. And finally, a pointer
- * to the symbol structure is placed into the head structure
- * symbol list. Refer to the description of the header, symbol,
- * area, and areax structures in lkdata.c for structure and
- * linkage details.
- *
- * local variables:
- * int c character from input text
- * int i evaluation value
- * char id[] symbol name
- * int nglob number of symbols in this header
- * sym * tsp pointer to symbol structure
- * sym ** s list of pointers to symbol structures
- *
- * global variables:
- * areax *axp Pointer to the current
- * areax structure
- * head *headp The pointer to the first
- * head structure of a linked list
- * int lkerr error flag
- *
- * functions called:
- * Addr_T eval() lkeval.c
- * VOID exit() c_library
- * int fprintf() c_library
- * char get() lklex.c
- * char getnb() lklex.c
- * sym * lkpsym() lksym.c
- *
- * side effects:
- * A symbol structure is created and/or modified.
- * If structure space allocation fails linker will abort.
- * Several severe errors (these are internal errors
- * indicating a corrupted .rel file or corrupted
- * assembler or linker) will terminated the linker.
- */
-
-/*
- * Find/Create a global symbol entry.
- *
- * S xxxxxx Defnnnn
- * | | |
- * | | `-- sp->s_addr
- * | `----- sp->s_type
- * `------------ sp->s_id
- *
- */
-struct sym *
-newsym()
-{
- register unsigned i ;
- register unsigned nglob ;
- register int c ;
- struct sym *tsp;
- struct sym **s;
- char id[NCPS];
-
- getid(id, -1);
- tsp = lkpsym(id, 1);
- c = getnb();get();get();
- if (c == 'R') {
- tsp->s_type |= S_REF;
- if (eval()) {
- fprintf(stderr, "Non zero S_REF\n");
- lkerr++;
- }
- } else
- if (c == 'D') {
- i = eval();
- if (tsp->s_type & S_DEF && tsp->s_addr != i) {
-#ifdef SDK
- fprintf(stderr, "Multiple definition of %s\n", id);
-#else
- fprintf(stderr, "Multiple definition of %.8s\n", id);
-#endif
- lkerr++;
- }
- tsp->s_type |= S_DEF;
- /*
- * Set value and area extension link.
- */
- tsp->s_addr = i;
- tsp->s_axp = axp;
- } else {
- fprintf(stderr, "Invalid symbol type %c for %.8s\n", c, id);
- lkexit(1);
- }
- /*
- * Place pointer in header symbol list
- */
- if (headp == NULL) {
- fprintf(stderr, "No header defined\n");
- lkexit(1);
- }
- nglob = hp->h_nglob;
- s = hp->s_list;
- for (i=0; i < nglob ;++i) {
- if (s[i] == NULL) {
- s[i] = tsp;
- return(tsp);
- }
- }
- fprintf(stderr, "Header symbol list overflow\n");
- lkexit(1);
-
- /* Never reached */
- return 0;
-}
-
-/*)Function sym * lkpsym(id,f)
- *
- * char * id symbol name string
- * int f f == 0, lookup only
- * f != 0, create if not found
- *
- * The function lookup() searches the symbol hash tables for
- * a symbol name match returning a pointer to the sym structure.
- * If the symbol is not found then a sym structure is created,
- * initialized, and linked to the appropriate hash table if f != 0.
- * A pointer to this new sym structure is returned or a NULL
- * pointer is returned if f == 0.
- *
- * local variables:
- * int h computed hash value
- * sym * sp pointer to a sym structure
- *
- * global varaibles:
- * sym * symhash[] array of pointers to NHASH
- * linked symbol lists
- *
- * functions called:
- * int hash() lksym.c
- * VOID * new() lksym.c
- * int symeq() lksym.c
- *
- * side effects:
- * If the function new() fails to allocate space
- * for the new sym structure the linker terminates.
- */
-
-struct sym *
-lkpsym(id, f)
-char *id;
-{
- register struct sym *sp;
- register int h;
-
- h = hash(id);
- sp = symhash[h];
- while (sp != NULL) {
- if (symeq(id, sp->s_id))
- return (sp);
- sp = sp->s_sp;
- }
- if (f == 0)
- return (NULL);
- sp = (struct sym *) new (sizeof(struct sym));
- sp->s_sp = symhash[h];
- symhash[h] = sp;
- strncpy(sp->s_id, id, NCPS);
- return (sp);
-}
-
-/*)Function Addr_T symval(tsp)
- *
- * sym * tsp pointer to a symbol structure
- *
- * The function symval() returns the value of the
- * relocated symbol by adding the variable definition
- * value to the areax base address.
- *
- * local variables:
- * Addr_T val relocated address value
- *
- * global variables:
- * none
- *
- * functions called:
- * none
- *
- * side effects:
- * none
- */
-
-Addr_T
-symval(tsp)
-register struct sym *tsp;
-{
- register Addr_T val;
-
- val = tsp->s_addr;
- if (tsp->s_axp) {
- val += tsp->s_axp->a_addr;
- }
- return(val);
-}
-
-/*)Function VOID symdef(fp)
- *
- * FILE * fp file handle for output
- *
- * The function symdef() scans the hashed symbol table
- * searching for variables referenced but not defined.
- * Undefined variables are linked to the default
- * area "_CODE" and reported as referenced by the
- * appropriate module.
- *
- * local variables:
- * int i hash table index loop variable
- * sym * sp pointer to linked symbol structure
- *
- * global variables:
- * area *areap The pointer to the first
- * area structure of a linked list
- * sym *symhash[NHASH] array of pointers to NHASH
- * linked symbol lists
- *
- * functions called:
- * symmod() lksym.c
- *
- * side effects:
- * Undefined variables have their areas set to "_CODE".
- */
-
-VOID
-symdef(fp)
-FILE *fp;
-{
- register struct sym *sp;
- register int i;
-
- for (i=0; i<NHASH; ++i) {
- sp = symhash[i];
- while (sp) {
- if (sp->s_axp == NULL)
- sp->s_axp = areap->a_axp;
- if ((sp->s_type & S_DEF) == 0)
- symmod(fp, sp);
- sp = sp->s_sp;
- }
- }
-}
-
-/*)Function VOID symmod(fp,tsp)
- *
- * FILE * fp output file handle
- * sym * tsp pointer to a symbol structure
- *
- * The function symmod() scans the header structures
- * searching for a reference to the symbol structure
- * pointer to by tsp. The function then generates an error
- * message whichs names the module having referenced the
- * undefined variable.
- *
- * local variables:
- * int i loop counter
- * sym ** p pointer to a list of pointers
- * to symbol structures
- *
- * global variables:
- * head *headp The pointer to the first
- * head structure of a linked list
- * head *hp Pointer to the current
- * head structure
- * int lkerr error flag
- *
- * functions called:
- * int fprintf() c_library
- *
- * side effects:
- * Error output generated.
- */
-
-VOID
-symmod(fp, tsp)
-FILE *fp;
-struct sym *tsp;
-{
- register int i;
- struct sym **p;
-
- if ((hp = headp) != NULL) {
- while(hp) {
- p = hp->s_list;
- for (i=0; i<hp->h_nglob; ++i) {
- if (p[i] == tsp) {
- fprintf(fp, "\n?ASlink-Warning-Undefined Global %s ", tsp->s_id);
- fprintf(fp, "referenced by module %s\n", hp->m_id);
- lkerr++;
- }
- }
- hp = hp->h_hp;
- }
- }
-}
-
-/*)Function int symeq(p1, p2)
- *
- * char * p1 name string
- * char * p2 name string
- *
- * The function symeq() compares the two name strings for a match.
- * The return value is 1 for a match and 0 for no match.
- *
- * local variables:
- * int h loop counter
- *
- * global variables:
- * char ccase[] an array of characters which
- * perform the case translation function
- *
- * functions called:
- * none
- *
- * side effects:
- * none
- *
- */
-
-int
-symeq(p1, p2)
-register char *p1, *p2;
-{
- register int n;
-
- n = NCPS;
- do {
-
-#if CASE_SENSITIVE
- if (*p1++ != *p2++)
- return (0);
-#else
- if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
- return (0);
-#endif
-
- } while (--n);
- return (1);
-}
-
-/*)Function int hash(p)
- *
- * char * p pointer to string to hash
- *
- * The function hash() computes a hash code using the sum
- * of all characters mod table size algorithm.
- *
- * local variables:
- * int h accumulated character sum
- * int n loop counter
- *
- * global variables:
- * char ccase[] an array of characters which
- * perform the case translation function
- *
- * functions called:
- * none
- *
- * side effects:
- * none
- *
- */
-
-int
-hash(p)
-register char *p;
-{
- register int h, n;
-
- h = 0;
- n = NCPS;
- do {
-
-#if CASE_SENSITIVE
- h += *p++;
-#else
- h += ccase[(unsigned char)(*p++)];
-#endif
-
- } while (--n);
- return (h&HMASK);
-}
-
-/*)Function VOID * new(n)
- *
- * unsigned int n allocation size in bytes
- *
- * The function new() allocates n bytes of space and returns
- * a pointer to this memory. If no space is available the
- * linker is terminated.
- *
- * local variables:
- * char * p a general pointer
- * char * q a general pointer
- *
- * global variables:
- * none
- *
- * functions called:
- * int fprintf() c_library
- * VOID * malloc() c_library
- *
- * side effects:
- * Memory is allocated, if allocation fails
- * the linker is terminated.
- */
-
-VOID *
-new(n)
-unsigned int n;
-{
- register char *p,*q;
- register unsigned int i;
-
- if ((p = (char *) malloc(n)) == NULL) {
- fprintf(stderr, "Out of space!\n");
- lkexit(1);
- }
- for (i=0,q=p; i<n; i++) {
- *q++ = 0;
- }
- return (p);
-}
###############################################################################
-Project: "linkgbz80"=.\link\z80\linkgbz80.dsp - Package Owner=<4>
+Project: "linkgbz80"=.\as\link\z80\linkgbz80.dsp - Package Owner=<4>
Package=<5>
{{{
###############################################################################
-Project: "linkz80"=.\LINK\Z80\linkz80.dsp - Package Owner=<4>
+Project: "linkz80"=.\as\link\z80\linkz80.dsp - Package Owner=<4>
Package=<5>
{{{