From: MaartenBrock Date: Thu, 14 Sep 2006 18:32:41 +0000 (+0000) Subject: moved link/ to as/link/ X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=0a174b5c835e5487aaa0db4c54e7db84ea1a2e9f;p=fw%2Fsdcc moved link/ to as/link/ git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4377 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index e7a9acde..0e3315f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2006-09-14 Maarten Brock + + * 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 * as/mcs51/i51mch.c (machine): fixed warning diff --git a/Makefile.in b/Makefile.in index 72c60ff6..fd9410ad 100644 --- a/Makefile.in +++ b/Makefile.in @@ -30,7 +30,7 @@ SDCC_MISC += debugger/mcs51 endif ifeq ($(OPT_DISABLE_Z80), 0) -SDCC_ASLINK += as link +SDCC_ASLINK += as as/link endif ifeq ($(OPT_DISABLE_UCSIM), 0) diff --git a/as/link/Makefile.in b/as/link/Makefile.in new file mode 100644 index 00000000..9776ae60 --- /dev/null +++ b/as/link/Makefile.in @@ -0,0 +1,21 @@ +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 diff --git a/as/link/README b/as/link/README new file mode 100644 index 00000000..5aba86d3 --- /dev/null +++ b/as/link/README @@ -0,0 +1,8 @@ +sdcc/link +--------- + +In gbdk the linker and assembler were split into seperate packages. + +For now I'm keeping that split, and leaving the mcs51 version as is. + +-- Michael diff --git a/as/link/clean.mk b/as/link/clean.mk new file mode 100644 index 00000000..e8435817 --- /dev/null +++ b/as/link/clean.mk @@ -0,0 +1,6 @@ +clean: + $(MAKE) -C z80 clean + +distclean: clean + $(MAKE) -C z80 distclean + rm -f Makefile diff --git a/as/link/z80/Makefile.in b/as/link/z80/Makefile.in new file mode 100644 index 00000000..1f67a7f7 --- /dev/null +++ b/as/link/z80/Makefile.in @@ -0,0 +1,47 @@ +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 diff --git a/as/link/z80/aslink.h b/as/link/z80/aslink.h new file mode 100644 index 00000000..e18cd023 --- /dev/null +++ b/as/link/z80/aslink.h @@ -0,0 +1,737 @@ +/* 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 +#ifndef PATH_MAX /* POSIX, but not required */ + #if defined(__BORLANDC__) || defined(_MSC_VER) + #include + #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); + diff --git a/as/link/z80/clean.mk b/as/link/z80/clean.mk new file mode 100644 index 00000000..4e13a896 --- /dev/null +++ b/as/link/z80/clean.mk @@ -0,0 +1,25 @@ +# 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 diff --git a/as/link/z80/conf.mk b/as/link/z80/conf.mk new file mode 100644 index 00000000..3fa379d4 --- /dev/null +++ b/as/link/z80/conf.mk @@ -0,0 +1,23 @@ +# 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 diff --git a/as/link/z80/linkgbz80.dsp b/as/link/z80/linkgbz80.dsp new file mode 100644 index 00000000..db0fa18e --- /dev/null +++ b/as/link/z80/linkgbz80.dsp @@ -0,0 +1,174 @@ +# Microsoft Developer Studio Project File - Name="linkgbz80" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=linkgbz80 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "linkgbz80.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "linkgbz80.mak" CFG="linkgbz80 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "linkgbz80 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "linkgbz80 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "linkgbz80 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_gbz80" +# PROP BASE Intermediate_Dir "Release_gbz80" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_gbz80" +# PROP Intermediate_Dir "Release_gbz80" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\link-gbz80.exe" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "linkgbz80 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_gbz80" +# PROP BASE Intermediate_Dir "Debug_gbz80" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_gbz80" +# PROP Intermediate_Dir "Debug_gbz80" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\link-gbz80.exe" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "linkgbz80 - Win32 Release" +# Name "linkgbz80 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\lkarea.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkdata.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkeval.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkgb.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkgg.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkhead.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkihx.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lklex.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lklibr.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lklist.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkmain.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lkrloc.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lks19.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# Begin Source File + +SOURCE=.\lksym.c +# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\aslink.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/as/link/z80/linkz80.dsp b/as/link/z80/linkz80.dsp new file mode 100644 index 00000000..cc287c78 --- /dev/null +++ b/as/link/z80/linkz80.dsp @@ -0,0 +1,174 @@ +# Microsoft Developer Studio Project File - Name="linkz80" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=linkz80 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "linkz80.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "linkz80.mak" CFG="linkz80 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "linkz80 - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "linkz80 - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "linkz80 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_z80" +# PROP BASE Intermediate_Dir "Release_z80" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_z80" +# PROP Intermediate_Dir "Release_z80" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\..\bin_vc\link-z80.exe" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "linkz80 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_z80" +# PROP BASE Intermediate_Dir "Debug_z80" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_z80" +# PROP Intermediate_Dir "Debug_z80" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\..\bin_vc\link-z80.exe" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "linkz80 - Win32 Release" +# Name "linkz80 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\lkarea.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkdata.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkeval.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkgb.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkgg.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkhead.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkihx.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lklex.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lklibr.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lklist.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkmain.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lkrloc.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lks19.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# Begin Source File + +SOURCE=.\lksym.c +# ADD CPP /D "SDK" /D "INDEXLIB" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\aslink.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/as/link/z80/lkarea.c b/as/link/z80/lkarea.c new file mode 100644 index 00000000..deb61c99 --- /dev/null +++ b/as/link/z80/lkarea.c @@ -0,0 +1,430 @@ +/* lkarea.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#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_ and l_ 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_ the start address of the area + * l_ 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++; + } +} diff --git a/as/link/z80/lkdata.c b/as/link/z80/lkdata.c new file mode 100644 index 00000000..3d075b7d --- /dev/null +++ b/as/link/z80/lkdata.c @@ -0,0 +1,470 @@ +/* lkdata.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +//#include +#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 diff --git a/as/link/z80/lkeval.c b/as/link/z80/lkeval.c new file mode 100644 index 00000000..e4bfe1d5 --- /dev/null +++ b/as/link/z80/lkeval.c @@ -0,0 +1,398 @@ +/* lkeval.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +//#include +#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); +} diff --git a/as/link/z80/lkgb.c b/as/link/z80/lkgb.c new file mode 100644 index 00000000..55ae41ff --- /dev/null +++ b/as/link/z80/lkgb.c @@ -0,0 +1,190 @@ +/* lkgb.c */ + +/* + * P. Felber + */ + +#ifdef GAMEBOY + +#include +#include +#include +#include +#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 */ diff --git a/as/link/z80/lkgg.c b/as/link/z80/lkgg.c new file mode 100644 index 00000000..3e8bb37a --- /dev/null +++ b/as/link/z80/lkgg.c @@ -0,0 +1,78 @@ +/* lkgg.c */ + +/* + * P. Felber + */ + +#ifdef GAMEGEAR + +#include +#include +#include +#include +#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 */ diff --git a/as/link/z80/lkhead.c b/as/link/z80/lkhead.c new file mode 100644 index 00000000..3eb127d9 --- /dev/null +++ b/as/link/z80/lkhead.c @@ -0,0 +1,154 @@ +/* lkhead.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +//#include +#include "aslink.h" + +/*Module lkhead.c + * + * The module lkhead.c contains the function newhead() which + * creates a head structure and the function module() which + * loads the module name into the current head structure. + * + * lkhead.c contains the following functions: + * VOID newhead() + * VOID module() + * + * lkhead.c contains no local variables. + */ + +/*)Function VOID newhead() + * + * The function newhead() creates a head structure. All head + * structures are linked to form a linked list of head structures + * with the current head structure at the tail of the list. + * + * local variables: + * int i evaluation value + * head * thp temporary pointer + * to a header structure + * + * global variables: + * area *ap Pointer to the current + * area structure + * lfile *cfp The pointer *cfp points to the + * current lfile structure + * head *headp The pointer to the first + * head structure of a linked list + * head *hp Pointer to the current + * head structure + * + * functions called: + * Addr_T expr() lkeval.c + * VOID * new() lksym.c + * VOID lkparea() lkarea.c + * + * side effects: + * A new head structure is created and linked to any + * existing linked head structure. The head structure + * parameters of file handle, number of areas, and number + * of global symbols are loaded into the structure. + * The default area "_abs_" is created when the first + * head structure is created and an areax structure is + * created for every head structure called. + */ + +/* + * Create a new header entry. + * + * H n areas n global symbols + * | | + * | `---- hp->h_nglob + * `------------ hp->h_narea + * + */ +VOID +newhead() +{ + register int i; + struct head *thp; + + hp = (struct head *) new (sizeof(struct head)); + if (headp == NULL) { + headp = hp; + } else { + thp = headp; + while (thp->h_hp) + thp = thp->h_hp; + thp->h_hp = hp; + } + /* + * Set file pointer + */ + hp->h_lfile = cfp; + /* + * Evaluate and build Area pointer list + */ + i = hp->h_narea = eval(); + if (i) + hp->a_list = (struct areax **) new (i*sizeof(struct areax *)); + /* + * Evaluate and build Global symbol pointer list + */ + skip(-1); + i = hp->h_nglob = eval(); + if (i) + hp->s_list = (struct sym **) new (i*sizeof(struct sym *)); + /* + * Setup Absolute DEF linkage. + */ + lkparea(_abs_); + ap->a_flag = A_ABS|A_OVR; +} + +/*)Function VOID module() + * + * The function module() copies the module name into + * the current head structure. + * + * local variables: + * char id[] module id string + * + * global variables: + * head *headp The pointer to the first + * head structure of a linked list + * head *hp Pointer to the current + * head structure + * int lkerr error flag + * FILE * stderr c_library + * + * functions called: + * int fprintf() c_library + * VOID getid() lklex.c + * char * strncpy() c_library + * + * side effects: + * The module name is copied into the head structure. + */ + +/* + * Module Name + */ +VOID +module() +{ + char id[NCPS]; + + if (headp) { + getid(id, -1); + strncpy(hp->m_id, id, NCPS); + } else { + fprintf(stderr, "No header defined\n"); + lkerr++; + } +} diff --git a/as/link/z80/lkihx.c b/as/link/z80/lkihx.c new file mode 100644 index 00000000..082a5fc5 --- /dev/null +++ b/as/link/z80/lkihx.c @@ -0,0 +1,134 @@ +/* lkihx.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +//#include +#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"); + } +} diff --git a/as/link/z80/lklex.c b/as/link/z80/lklex.c new file mode 100644 index 00000000..1ccdeea8 --- /dev/null +++ b/as/link/z80/lklex.c @@ -0,0 +1,603 @@ +/* lklex.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +/* + * Extensions: P. Felber, M. Hope + */ + +#include +#include +//#include +#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; +} diff --git a/as/link/z80/lklibr.c b/as/link/z80/lklibr.c new file mode 100644 index 00000000..c3761bbd --- /dev/null +++ b/as/link/z80/lklibr.c @@ -0,0 +1,1297 @@ +/* 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 +#include +#include +#include +#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; is_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, "")) + { + 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, "")) state=2; + break; + case 2: + if(EQ(str, "")) 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, "")) + { + /*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, "")) + { + /*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, "")) + { + return This; /*Finish, get out of here*/ + } + break; + case 2: + if(EQ(FLine, "")) + { + 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, "")==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, "")) + { + /*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, "")) + { + /*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, "")) + { + /*Reached the end of the index. The symbol is not in this library.*/ + return 0; + } + break; + case 2: + if(EQ(FLine, "")) + { + /*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, "")==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); + } +} diff --git a/as/link/z80/lklist.c b/as/link/z80/lklist.c new file mode 100644 index 00000000..827b44c2 --- /dev/null +++ b/as/link/z80/lklist.c @@ -0,0 +1,1270 @@ +/* lklist.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include +#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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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 +#include +//#include +#include "aslink.h" +#include + +#ifndef SDK_VERSION_STRING +#define SDK_VERSION_STRING "3.0.0" +#endif +#ifndef TARGET_STRING +#define TARGET_STRING "gbz80" +#endif + +#ifdef WIN32T +#include + +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; if_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); +} diff --git a/as/link/z80/lkrloc.c b/as/link/z80/lkrloc.c new file mode 100644 index 00000000..e5bdd05a --- /dev/null +++ b/as/link/z80/lkrloc.c @@ -0,0 +1,1171 @@ +/* lkrloc.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +/* + * Extensions: P. Felber + */ + +#include +#include +#include +//#include +#include +#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); +} diff --git a/as/link/z80/lks19.c b/as/link/z80/lks19.c new file mode 100644 index 00000000..bbca7530 --- /dev/null +++ b/as/link/z80/lks19.c @@ -0,0 +1,123 @@ +/* lks19.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +//#include +#include "aslink.h" + +/*)Module lks19.c + * + * The module lks19.c contains the function to + * output the relocated object code in the + * Motorola S19 format. + * + * lks19.c contains the following function: + * VOID s19(i) + * + * lks19.c contains no local variables. + */ + +/*)S19 Format + * Record Type Field - This field signifies the start of a + * record and identifies the the record + * type as follows: + * + * Ascii S1 - Data Record + * Ascii S9 - End of File Record + * + * Record Length Field - This field specifies the record length + * which includes the address, data, and + * checksum fields. The 8 bit record + * length value is converted to two ascii + * characters, high digit first. + * + * Load Address Field - This field consists of the four ascii + * characters which result from converting + * the the binary value of the address in + * which to begin loading this record. The + * order is as follows: + * + * High digit of high byte of address. + * Low digit of high byte of address. + * High digit of low byte of address. + * Low digit of low byte of address. + * + * In an End of File record this field con- + * sists of either four ascii zeros or the + * program entry address. Currently the + * entry address option is not supported. + * + * Data Field - This field consists of the actual data, + * converted to two ascii characters, high + * digit first. There are no data bytes in + * the End of File record. + * + * Checksum Field - The checksum field is the 8 bit binary + * sum of the record length field, the load + * address field, and the data field. This + * sum is then complemented (1's comple- + * ment) and converted to two ascii + * characters, high digit first. + */ + +/*)Function s19(i) + * + * int i 0 - process data + * 1 - end of data + * + * The function s19() outputs the relocated data + * in the standard Motorola S19 format. + * + * local variables: + * Addr_T chksum byte checksum + * + * global variables: + * int hilo byte order + * FILE * ofp output file handle + * int rtcnt count of data words + * int rtflg[] output the data flag + * Addr_T rtval[] relocated data + * + * functions called: + * int fprintf() c_library + * + * side effects: + * The data is output to the file defined by ofp. + */ + +VOID +s19(i) +{ + register Addr_T chksum; + + if (i) { + if (hilo == 0) { + chksum = rtval[0]; + rtval[0] = rtval[1]; + rtval[1] = chksum; + } + for (i = 0, chksum = 1; i < rtcnt; i++) { + if (rtflg[i]) + chksum++; + } + fprintf(ofp, "S1%02X", chksum); + for (i = 0; i < rtcnt ; i++) { + if (rtflg[i]) { + fprintf(ofp, "%02X", rtval[i]); + chksum += rtval[i]; + } + } + fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff); + } else { + fprintf(ofp, "S9030000FC\n"); + } +} diff --git a/as/link/z80/lksym.c b/as/link/z80/lksym.c new file mode 100644 index 00000000..33cc6ffb --- /dev/null +++ b/as/link/z80/lksym.c @@ -0,0 +1,498 @@ +/* lksym.c */ + +/* + * (C) Copyright 1989-1995 + * All Rights Reserved + * + * Alan R. Baldwin + * 721 Berkeley St. + * Kent, Ohio 44240 + */ + +#include +#include +#include +#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; is_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; ih_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 -#ifndef PATH_MAX /* POSIX, but not required */ - #if defined(__BORLANDC__) || defined(_MSC_VER) - #include - #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); - diff --git a/link/z80/clean.mk b/link/z80/clean.mk deleted file mode 100644 index 4e13a896..00000000 --- a/link/z80/clean.mk +++ /dev/null @@ -1,25 +0,0 @@ -# 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 diff --git a/link/z80/conf.mk b/link/z80/conf.mk deleted file mode 100644 index 3fa379d4..00000000 --- a/link/z80/conf.mk +++ /dev/null @@ -1,23 +0,0 @@ -# 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 diff --git a/link/z80/linkgbz80.dsp b/link/z80/linkgbz80.dsp deleted file mode 100644 index 80e1d506..00000000 --- a/link/z80/linkgbz80.dsp +++ /dev/null @@ -1,174 +0,0 @@ -# Microsoft Developer Studio Project File - Name="linkgbz80" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=linkgbz80 - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "linkgbz80.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "linkgbz80.mak" CFG="linkgbz80 - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "linkgbz80 - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "linkgbz80 - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "linkgbz80 - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release_gbz80" -# PROP BASE Intermediate_Dir "Release_gbz80" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release_gbz80" -# PROP Intermediate_Dir "Release_gbz80" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\bin_vc\link-gbz80.exe" -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "linkgbz80 - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug_gbz80" -# PROP BASE Intermediate_Dir "Debug_gbz80" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug_gbz80" -# PROP Intermediate_Dir "Debug_gbz80" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\bin_vc\link-gbz80.exe" /pdbtype:sept -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "linkgbz80 - Win32 Release" -# Name "linkgbz80 - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\lkarea.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkdata.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkeval.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkgb.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkgg.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkhead.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkihx.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lklex.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lklibr.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lklist.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkmain.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lkrloc.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lks19.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# Begin Source File - -SOURCE=.\lksym.c -# ADD CPP /D "SDK" /D "INDEXLIB" /D "GAMEBOY" -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\aslink.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/link/z80/linkz80.dsp b/link/z80/linkz80.dsp deleted file mode 100644 index eb63e0c5..00000000 --- a/link/z80/linkz80.dsp +++ /dev/null @@ -1,174 +0,0 @@ -# Microsoft Developer Studio Project File - Name="linkz80" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=linkz80 - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "linkz80.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "linkz80.mak" CFG="linkz80 - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "linkz80 - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "linkz80 - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "linkz80 - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release_z80" -# PROP BASE Intermediate_Dir "Release_z80" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release_z80" -# PROP Intermediate_Dir "Release_z80" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 /nologo /subsystem:console /machine:I386 /out:"..\..\bin_vc\link-z80.exe" -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "linkz80 - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug_z80" -# PROP BASE Intermediate_Dir "Debug_z80" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug_z80" -# PROP Intermediate_Dir "Debug_z80" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"..\..\bin_vc\link-z80.exe" /pdbtype:sept -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "linkz80 - Win32 Release" -# Name "linkz80 - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\lkarea.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkdata.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkeval.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkgb.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkgg.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkhead.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkihx.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lklex.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lklibr.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lklist.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkmain.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lkrloc.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lks19.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# Begin Source File - -SOURCE=.\lksym.c -# ADD CPP /D "SDK" /D "INDEXLIB" -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\aslink.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/link/z80/lkarea.c b/link/z80/lkarea.c deleted file mode 100644 index deb61c99..00000000 --- a/link/z80/lkarea.c +++ /dev/null @@ -1,430 +0,0 @@ -/* lkarea.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#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_ and l_ 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_ the start address of the area - * l_ 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++; - } -} diff --git a/link/z80/lkdata.c b/link/z80/lkdata.c deleted file mode 100644 index 3d075b7d..00000000 --- a/link/z80/lkdata.c +++ /dev/null @@ -1,470 +0,0 @@ -/* lkdata.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -//#include -#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 diff --git a/link/z80/lkeval.c b/link/z80/lkeval.c deleted file mode 100644 index e4bfe1d5..00000000 --- a/link/z80/lkeval.c +++ /dev/null @@ -1,398 +0,0 @@ -/* lkeval.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -//#include -#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); -} diff --git a/link/z80/lkgb.c b/link/z80/lkgb.c deleted file mode 100644 index 55ae41ff..00000000 --- a/link/z80/lkgb.c +++ /dev/null @@ -1,190 +0,0 @@ -/* lkgb.c */ - -/* - * P. Felber - */ - -#ifdef GAMEBOY - -#include -#include -#include -#include -#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 */ diff --git a/link/z80/lkgg.c b/link/z80/lkgg.c deleted file mode 100644 index 3e8bb37a..00000000 --- a/link/z80/lkgg.c +++ /dev/null @@ -1,78 +0,0 @@ -/* lkgg.c */ - -/* - * P. Felber - */ - -#ifdef GAMEGEAR - -#include -#include -#include -#include -#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 */ diff --git a/link/z80/lkhead.c b/link/z80/lkhead.c deleted file mode 100644 index 3eb127d9..00000000 --- a/link/z80/lkhead.c +++ /dev/null @@ -1,154 +0,0 @@ -/* lkhead.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -//#include -#include "aslink.h" - -/*Module lkhead.c - * - * The module lkhead.c contains the function newhead() which - * creates a head structure and the function module() which - * loads the module name into the current head structure. - * - * lkhead.c contains the following functions: - * VOID newhead() - * VOID module() - * - * lkhead.c contains no local variables. - */ - -/*)Function VOID newhead() - * - * The function newhead() creates a head structure. All head - * structures are linked to form a linked list of head structures - * with the current head structure at the tail of the list. - * - * local variables: - * int i evaluation value - * head * thp temporary pointer - * to a header structure - * - * global variables: - * area *ap Pointer to the current - * area structure - * lfile *cfp The pointer *cfp points to the - * current lfile structure - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * - * functions called: - * Addr_T expr() lkeval.c - * VOID * new() lksym.c - * VOID lkparea() lkarea.c - * - * side effects: - * A new head structure is created and linked to any - * existing linked head structure. The head structure - * parameters of file handle, number of areas, and number - * of global symbols are loaded into the structure. - * The default area "_abs_" is created when the first - * head structure is created and an areax structure is - * created for every head structure called. - */ - -/* - * Create a new header entry. - * - * H n areas n global symbols - * | | - * | `---- hp->h_nglob - * `------------ hp->h_narea - * - */ -VOID -newhead() -{ - register int i; - struct head *thp; - - hp = (struct head *) new (sizeof(struct head)); - if (headp == NULL) { - headp = hp; - } else { - thp = headp; - while (thp->h_hp) - thp = thp->h_hp; - thp->h_hp = hp; - } - /* - * Set file pointer - */ - hp->h_lfile = cfp; - /* - * Evaluate and build Area pointer list - */ - i = hp->h_narea = eval(); - if (i) - hp->a_list = (struct areax **) new (i*sizeof(struct areax *)); - /* - * Evaluate and build Global symbol pointer list - */ - skip(-1); - i = hp->h_nglob = eval(); - if (i) - hp->s_list = (struct sym **) new (i*sizeof(struct sym *)); - /* - * Setup Absolute DEF linkage. - */ - lkparea(_abs_); - ap->a_flag = A_ABS|A_OVR; -} - -/*)Function VOID module() - * - * The function module() copies the module name into - * the current head structure. - * - * local variables: - * char id[] module id string - * - * global variables: - * head *headp The pointer to the first - * head structure of a linked list - * head *hp Pointer to the current - * head structure - * int lkerr error flag - * FILE * stderr c_library - * - * functions called: - * int fprintf() c_library - * VOID getid() lklex.c - * char * strncpy() c_library - * - * side effects: - * The module name is copied into the head structure. - */ - -/* - * Module Name - */ -VOID -module() -{ - char id[NCPS]; - - if (headp) { - getid(id, -1); - strncpy(hp->m_id, id, NCPS); - } else { - fprintf(stderr, "No header defined\n"); - lkerr++; - } -} diff --git a/link/z80/lkihx.c b/link/z80/lkihx.c deleted file mode 100644 index 082a5fc5..00000000 --- a/link/z80/lkihx.c +++ /dev/null @@ -1,134 +0,0 @@ -/* lkihx.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -//#include -#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"); - } -} diff --git a/link/z80/lklex.c b/link/z80/lklex.c deleted file mode 100644 index 1ccdeea8..00000000 --- a/link/z80/lklex.c +++ /dev/null @@ -1,603 +0,0 @@ -/* lklex.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -/* - * Extensions: P. Felber, M. Hope - */ - -#include -#include -//#include -#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; -} diff --git a/link/z80/lklibr.c b/link/z80/lklibr.c deleted file mode 100644 index c3761bbd..00000000 --- a/link/z80/lklibr.c +++ /dev/null @@ -1,1297 +0,0 @@ -/* 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 -#include -#include -#include -#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; is_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, "")) - { - 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, "")) state=2; - break; - case 2: - if(EQ(str, "")) 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, "")) - { - /*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, "")) - { - /*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, "")) - { - return This; /*Finish, get out of here*/ - } - break; - case 2: - if(EQ(FLine, "")) - { - 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, "")==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, "")) - { - /*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, "")) - { - /*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, "")) - { - /*Reached the end of the index. The symbol is not in this library.*/ - return 0; - } - break; - case 2: - if(EQ(FLine, "")) - { - /*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, "")==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); - } -} diff --git a/link/z80/lklist.c b/link/z80/lklist.c deleted file mode 100644 index 827b44c2..00000000 --- a/link/z80/lklist.c +++ /dev/null @@ -1,1270 +0,0 @@ -/* lklist.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include -#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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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; is_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 -#include -//#include -#include "aslink.h" -#include - -#ifndef SDK_VERSION_STRING -#define SDK_VERSION_STRING "3.0.0" -#endif -#ifndef TARGET_STRING -#define TARGET_STRING "gbz80" -#endif - -#ifdef WIN32T -#include - -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; if_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); -} diff --git a/link/z80/lkrloc.c b/link/z80/lkrloc.c deleted file mode 100644 index e5bdd05a..00000000 --- a/link/z80/lkrloc.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* lkrloc.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -/* - * Extensions: P. Felber - */ - -#include -#include -#include -//#include -#include -#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); -} diff --git a/link/z80/lks19.c b/link/z80/lks19.c deleted file mode 100644 index bbca7530..00000000 --- a/link/z80/lks19.c +++ /dev/null @@ -1,123 +0,0 @@ -/* lks19.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -//#include -#include "aslink.h" - -/*)Module lks19.c - * - * The module lks19.c contains the function to - * output the relocated object code in the - * Motorola S19 format. - * - * lks19.c contains the following function: - * VOID s19(i) - * - * lks19.c contains no local variables. - */ - -/*)S19 Format - * Record Type Field - This field signifies the start of a - * record and identifies the the record - * type as follows: - * - * Ascii S1 - Data Record - * Ascii S9 - End of File Record - * - * Record Length Field - This field specifies the record length - * which includes the address, data, and - * checksum fields. The 8 bit record - * length value is converted to two ascii - * characters, high digit first. - * - * Load Address Field - This field consists of the four ascii - * characters which result from converting - * the the binary value of the address in - * which to begin loading this record. The - * order is as follows: - * - * High digit of high byte of address. - * Low digit of high byte of address. - * High digit of low byte of address. - * Low digit of low byte of address. - * - * In an End of File record this field con- - * sists of either four ascii zeros or the - * program entry address. Currently the - * entry address option is not supported. - * - * Data Field - This field consists of the actual data, - * converted to two ascii characters, high - * digit first. There are no data bytes in - * the End of File record. - * - * Checksum Field - The checksum field is the 8 bit binary - * sum of the record length field, the load - * address field, and the data field. This - * sum is then complemented (1's comple- - * ment) and converted to two ascii - * characters, high digit first. - */ - -/*)Function s19(i) - * - * int i 0 - process data - * 1 - end of data - * - * The function s19() outputs the relocated data - * in the standard Motorola S19 format. - * - * local variables: - * Addr_T chksum byte checksum - * - * global variables: - * int hilo byte order - * FILE * ofp output file handle - * int rtcnt count of data words - * int rtflg[] output the data flag - * Addr_T rtval[] relocated data - * - * functions called: - * int fprintf() c_library - * - * side effects: - * The data is output to the file defined by ofp. - */ - -VOID -s19(i) -{ - register Addr_T chksum; - - if (i) { - if (hilo == 0) { - chksum = rtval[0]; - rtval[0] = rtval[1]; - rtval[1] = chksum; - } - for (i = 0, chksum = 1; i < rtcnt; i++) { - if (rtflg[i]) - chksum++; - } - fprintf(ofp, "S1%02X", chksum); - for (i = 0; i < rtcnt ; i++) { - if (rtflg[i]) { - fprintf(ofp, "%02X", rtval[i]); - chksum += rtval[i]; - } - } - fprintf(ofp, "%02X\n", (0-chksum-1) & 0xff); - } else { - fprintf(ofp, "S9030000FC\n"); - } -} diff --git a/link/z80/lksym.c b/link/z80/lksym.c deleted file mode 100644 index 33cc6ffb..00000000 --- a/link/z80/lksym.c +++ /dev/null @@ -1,498 +0,0 @@ -/* lksym.c */ - -/* - * (C) Copyright 1989-1995 - * All Rights Reserved - * - * Alan R. Baldwin - * 721 Berkeley St. - * Kent, Ohio 44240 - */ - -#include -#include -#include -#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; is_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; ih_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 ############################################################################### -Project: "linkgbz80"=.\link\z80\linkgbz80.dsp - Package Owner=<4> +Project: "linkgbz80"=.\as\link\z80\linkgbz80.dsp - Package Owner=<4> Package=<5> {{{ @@ -252,7 +252,7 @@ Package=<4> ############################################################################### -Project: "linkz80"=.\LINK\Z80\linkz80.dsp - Package Owner=<4> +Project: "linkz80"=.\as\link\z80\linkz80.dsp - Package Owner=<4> Package=<5> {{{