diff --git a/LICENSE b/LICENSE index 4e031993..1ad679d9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -rgbasm, rgblink, and rgblib are derived from Justin Lloyd's RGBDS, which -is released under the following license: +rgbasm and rgblink are derived from Justin Lloyd's RGBDS, which is +released under the following license: DO WHATEVER PUBLIC LICENSE* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION @@ -17,3 +17,9 @@ is released under the following license: rgbfix was rewritten from scratch by Anthony J. Bentley, and is released under the ISC license; see the source file for the text of the license. + +extern/err.c is derived from the Musl C library, http://www.musl-libc.org, +and is released under the MIT license. + +extern/strl.c is derived from the OpenBSD Project, http://www.openbsd.org, +and is released under the BSD license. diff --git a/Makefile b/Makefile index 6aedbcae..f5da5aef 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -CFLAGS += -Wall -Iinclude -Iinclude/asm/gameboy -g -std=c99 +.POSIX: + +REALCFLAGS = ${CFLAGS} -Wall -Iinclude -Iinclude/asm/gameboy -g -std=c99 # User-defined variables PREFIX = /usr/local @@ -13,7 +15,6 @@ yacc_pre := \ src/asm/gameboy/yaccprt4.y rgbasm_obj := \ - src/asm/alloca.o \ src/asm/asmy.o \ src/asm/charmap.o \ src/asm/fstack.o \ @@ -24,11 +25,10 @@ rgbasm_obj := \ src/asm/output.o \ src/asm/rpn.o \ src/asm/symbol.o \ - src/asm/gameboy/locallex.o - -rgblib_obj := \ - src/lib/library.o \ - src/lib/main.o + src/asm/gameboy/locallex.o \ + src/extern/err.o \ + src/extern/strlcpy.o \ + src/extern/strlcat.o rgblink_obj := \ src/link/assign.o \ @@ -38,61 +38,53 @@ rgblink_obj := \ src/link/object.o \ src/link/output.o \ src/link/patch.o \ - src/link/symbol.o + src/link/symbol.o \ + src/extern/err.o rgbfix_obj := \ - src/fix/main.o + src/fix/main.o \ + src/extern/err.o -all: rgbasm rgblib rgblink rgbfix +all: rgbasm rgblink rgbfix clean: - ${Q}rm -rf rgbds.html - ${Q}rm -rf rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.html - ${Q}rm -rf rgblib rgblib.exe ${rgblib_obj} rgblib.html - ${Q}rm -rf rgblink rgblink.exe ${rgblink_obj} rgblink.html - ${Q}rm -rf rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.html - ${Q}rm -rf src/asm/asmy.c src/asm/asmy.h src/asm/asmy.y + $Qrm -rf rgbds.html + $Qrm -rf rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.html + $Qrm -rf rgblink rgblink.exe ${rgblink_obj} rgblink.html + $Qrm -rf rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.html + $Qrm -rf src/asm/asmy.c src/asm/asmy.h src/asm/asmy.y install: all - ${Q}install -s -m 555 rgbasm ${BINPREFIX}/rgbasm - ${Q}install -s -m 555 rgbfix ${BINPREFIX}/rgbfix - ${Q}install -s -m 555 rgblink ${BINPREFIX}/rgblink - ${Q}install -s -m 555 rgblib ${BINPREFIX}/rgblib - ${Q}install -m 444 src/rgbds.7 ${MANPREFIX}/man7/rgbds.7 || \ - (echo Installing manpages to ${MANPREFIX} failed. >&2 && \ - echo Check where your manpages are installed and set the \ - proper directory >&2 && \ - echo with, e.g., make install MANPREFIX=/usr/share/man \ - >&2 ; false) - ${Q}install -m 444 src/asm/rgbasm.1 \ - ${MANPREFIX}/man1/rgbasm.1 - ${Q}install -m 444 src/fix/rgbfix.1 \ - ${MANPREFIX}/man1/rgbfix.1 - ${Q}install -m 444 src/link/rgblink.1 \ - ${MANPREFIX}/man1/rgblink.1 - ${Q}install -m 444 src/lib/rgblib.1 \ - ${MANPREFIX}/man1/rgblib.1 + $Qmkdir -p ${BINPREFIX} + $Qinstall -s -m 555 rgbasm ${BINPREFIX}/rgbasm + $Qinstall -s -m 555 rgbfix ${BINPREFIX}/rgbfix + $Qinstall -s -m 555 rgblink ${BINPREFIX}/rgblink + $Qmkdir -p ${MANPREFIX}/man1 ${MANPREFIX}/man7 + $Qinstall -m 444 src/rgbds.7 ${MANPREFIX}/man7/rgbds.7 + $Qinstall -m 444 src/asm/rgbasm.1 ${MANPREFIX}/man1/rgbasm.1 + $Qinstall -m 444 src/fix/rgbfix.1 ${MANPREFIX}/man1/rgbfix.1 + $Qinstall -m 444 src/link/rgblink.1 ${MANPREFIX}/man1/rgblink.1 rgbasm: ${rgbasm_obj} - ${Q}${CC} ${CFLAGS} -o $@ ${rgbasm_obj} -lm - -rgblib: ${rgblib_obj} - ${Q}${CC} ${CFLAGS} -o $@ ${rgblib_obj} + $Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm rgblink: ${rgblink_obj} - ${Q}${CC} ${CFLAGS} -o $@ ${rgblink_obj} + $Q${CC} ${REALCFLAGS} -o $@ ${rgblink_obj} rgbfix: ${rgbfix_obj} - ${Q}${CC} ${CFLAGS} -o $@ ${rgbfix_obj} + $Q${CC} ${REALCFLAGS} -o $@ ${rgbfix_obj} + +.y.c: + $Q${YACC} -d ${YFLAGS} -o $@ $< .c.o: - ${Q}${CC} ${CFLAGS} -c -o $@ $< + $Q${CC} ${REALCFLAGS} -c -o $@ $< -src/asm/asmy.c: src/asm/asmy.y - ${Q}${YACC} -d -o $@ $< +src/asm/gameboy/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h +src/asm/asmy.h: src/asm/asmy.c src/asm/asmy.y: ${yacc_pre} - ${Q}cat ${yacc_pre} > $@ + $Qcat ${yacc_pre} > $@ # Below is a target for the project maintainer to easily create win32 exes. @@ -100,19 +92,23 @@ src/asm/asmy.y: ${yacc_pre} # If you're building on Windows with Cygwin or Mingw, just follow the Unix # install instructions instead. mingw: - ${Q}env PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin make CC=gcc CFLAGS="-I/usr/local/mingw32/include ${CFLAGS}" - ${Q}mv rgbasm rgbasm.exe - ${Q}mv rgblib rgblib.exe - ${Q}mv rgblink rgblink.exe - ${Q}mv rgbfix rgbfix.exe + $Qenv PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin \ + make CC=gcc CFLAGS="-I/usr/local/mingw32/include \ + -D__progname=\\\"\\\" ${CFLAGS}" + $Qmv rgbasm rgbasm.exe + $Qmv rgblink rgblink.exe + $Qmv rgbfix rgbfix.exe # Below is a target for the project maintainer to easily create web manuals. # It relies on mandoc: http://mdocml.bsd.lv -MANDOC = -Thtml -Oman=/rgbds/manual/%N/ -Ostyle=/rgbds/manual/manual.css -Ios=General +MANDOC = -Thtml -Ios=General -Oman=/rgbds/manual/%N/ \ + -Ostyle=/rgbds/manual/manual.css wwwman: - ${Q}mandoc ${MANDOC} src/rgbds.7 | sed s/OpenBSD/General/ > rgbds.html - ${Q}mandoc ${MANDOC} src/asm/rgbasm.1 | sed s/OpenBSD/General/ > rgbasm.html - ${Q}mandoc ${MANDOC} src/fix/rgbfix.1 | sed s/OpenBSD/General/ > rgbfix.html - ${Q}mandoc ${MANDOC} src/lib/rgblib.1 | sed s/OpenBSD/General/ > rgblib.html - ${Q}mandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > rgblink.html + $Qmandoc ${MANDOC} src/rgbds.7 | sed s/OpenBSD/General/ > rgbds.html + $Qmandoc ${MANDOC} src/asm/rgbasm.1 | sed s/OpenBSD/General/ > \ + rgbasm.html + $Qmandoc ${MANDOC} src/fix/rgbfix.1 | sed s/OpenBSD/General/ > \ + rgbfix.html + $Qmandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > \ + rgblink.html diff --git a/README b/README index 8b08fedd..c5d562ba 100644 --- a/README +++ b/README @@ -7,7 +7,6 @@ for the Game Boy and Game Boy Color. It consists of: - rgbasm (assembler) - rgblink (linker) - - rgblib (library manager) - rgbfix (checksum/header fixer) rgbds-linux is a fork of the original RGBDS which aims to make the programs diff --git a/doc/index.htm b/doc/index.htm index 2896cf88..148e4e34 100644 --- a/doc/index.htm +++ b/doc/index.htm @@ -12,7 +12,6 @@
  • ASMotor General Information
  • xASM Documentation
  • xLink Documentation -
  • xLib Documentation
  • RGBFix Documentation
  • The RGB0-2 ObjectFileFormat diff --git a/doc/lib.htm b/doc/lib.htm deleted file mode 100644 index 559e1e60..00000000 --- a/doc/lib.htm +++ /dev/null @@ -1,47 +0,0 @@ - - - - - xLib - - - -

    xLib Documentation

    -

    Table of Contents

    - -
    -

    History

    - - - - - - - - - - - - - - -
    The history of xLib
    VersionDatedRelease notes
    1.021 Sep. 1997First release
    -

    Usage

    -
        xlib library command [module1 module2 ... modulen]
    -

    The Commands

    -

    The command specified after library on the commandline tells xLib what to do. -

    The following commands are available: -

    -
    -

    Last updated 21 September 1997 by Carsten Sorensen

    - - diff --git a/include/asm/asm.h b/include/asm/asm.h index bde48eb3..548a412e 100644 --- a/include/asm/asm.h +++ b/include/asm/asm.h @@ -17,8 +17,6 @@ #include "localasm.h" -#include "asmotor.h" - extern SLONG nLineNo; extern ULONG nTotalLines; extern ULONG nPC; diff --git a/include/asm/fstack.h b/include/asm/fstack.h index 9978a3e2..c3ca1ef0 100644 --- a/include/asm/fstack.h +++ b/include/asm/fstack.h @@ -9,6 +9,8 @@ #ifndef ASMOTOR_ASM_FSTACK_H #define ASMOTOR_ASM_FSTACK_H +#include + #include "asm/asm.h" #include "asm/types.h" #include "asm/lexer.h" @@ -27,14 +29,17 @@ struct sContext { ULONG nREPTBlockSize; }; -extern ULONG fstk_RunInclude(char *s); +void +fstk_RunInclude(char *); extern void fstk_RunMacroArg(SLONG s); -extern ULONG fstk_Init(char *s); +void +fstk_Init(char *); extern void fstk_Dump(void); extern void fstk_AddIncludePath(char *s); extern ULONG fstk_RunMacro(char *s); extern void fstk_RunRept(ULONG count); -extern void fstk_FindFile(char *s); +FILE * +fstk_FindFile(char *); extern int yywrap(void); diff --git a/include/asm/lexer.h b/include/asm/lexer.h index 27fe475c..5b6db4a2 100644 --- a/include/asm/lexer.h +++ b/include/asm/lexer.h @@ -5,7 +5,8 @@ #include "asm/types.h" -#define LEXHASHSIZE 512 +#define LEXHASHSIZE (1 << 11) +#define MAXSTRLEN 255 struct sLexInitString { char *tzName; @@ -18,7 +19,9 @@ struct sLexFloat { }; struct yy_buffer_state { - char *pBufferStart; + char *pBufferRealStart; // actual starting address + char *pBufferStart; // address where the data is initially written + // after the "safety margin" char *pBuffer; ULONG nBufferSize; ULONG oAtLineStart; diff --git a/include/asm/symbol.h b/include/asm/symbol.h index e63aa196..516a5486 100644 --- a/include/asm/symbol.h +++ b/include/asm/symbol.h @@ -3,7 +3,7 @@ #include "asm/types.h" -#define HASHSIZE 73 +#define HASHSIZE (1 << 16) #define MAXSYMLEN 256 struct sSymbol { @@ -35,6 +35,7 @@ struct sSymbol { #define SYMF_CONST 0x200 /* symbol has a constant value, will * not be changed during linking */ +ULONG calchash(char *s); void sym_PrepPass1(void); void sym_PrepPass2(void); void sym_AddLocalReloc(char *tzSym); diff --git a/include/asmotor.h b/include/asmotor.h deleted file mode 100644 index d9fa856c..00000000 --- a/include/asmotor.h +++ /dev/null @@ -1,21 +0,0 @@ -/* asmotor.h - * - * Contains defines for every program in the ASMotor package - * - * Copyright 1997 Carsten Sorensen - * - */ - -#ifndef ASMOTOR_ASMOTOR_H -#define ASMOTOR_ASMOTOR_H - -#define ASMOTOR - -#define ASMOTOR_VERSION "1.10-linux" - -#define ASM_VERSION "1.08c" -#define LINK_VERSION "1.06c" -#define RGBFIX_VERSION "1.02" -#define LIB_VERSION "1.00" - -#endif diff --git a/include/extern/err.h b/include/extern/err.h new file mode 100644 index 00000000..ffb4f26d --- /dev/null +++ b/include/extern/err.h @@ -0,0 +1,63 @@ +/* + * Copyright © 2005-2013 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef EXTERN_ERR_H +#define EXTERN_ERR_H + +#ifdef ERR_IN_LIBC +#include +#else + +#include + +#define warn rgbds_warn +#define vwarn rgbds_vwarn +#define warnx rgbds_warnx +#define vwarnx rgbds_vwarnx + +#define err rgbds_err +#define verr rgbds_verr +#define errx rgbds_errx +#define verrx rgbds_verrx + +#ifdef __cplusplus +extern "C" { +#endif + +void warn(const char *, ...); +void vwarn(const char *, va_list); +void warnx(const char *, ...); +void vwarnx(const char *, va_list); + +void err(int, const char *, ...); +void verr(int, const char *, va_list); +void errx(int, const char *, ...); +void verrx(int, const char *, va_list); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/include/extern/strl.h b/include/extern/strl.h new file mode 100644 index 00000000..02c9bd43 --- /dev/null +++ b/include/extern/strl.h @@ -0,0 +1,13 @@ +#ifndef STRL_H +#define STRL_H + +#ifdef STRL_IN_LIBC +#include +#else +#define strlcpy rgbds_strlcpy +#define strlcat rgbds_strlcat +size_t strlcpy(char *, const char *, size_t); +size_t strlcat(char *, const char *, size_t); +#endif + +#endif diff --git a/include/lib/library.h b/include/lib/library.h deleted file mode 100644 index 4037c930..00000000 --- a/include/lib/library.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ASMOTOR_LIB_LIBRARY_H -#define ASMOTOR_LIB_LIBRARY_H - -#include "lib/libwrap.h" - -extern sLibrary *lib_Read(char *filename); -extern BBOOL lib_Write(sLibrary * lib, char *filename); -extern sLibrary *lib_AddReplace(sLibrary * lib, char *filename); -extern void lib_Free(sLibrary * lib); -extern sLibrary *lib_DeleteModule(sLibrary * lib, char *filename); -extern sLibrary *lib_Find(sLibrary * lib, char *filename); - -#endif diff --git a/include/lib/libwrap.h b/include/lib/libwrap.h deleted file mode 100644 index d8c81447..00000000 --- a/include/lib/libwrap.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ASMOTOR_LIB_LIBWRAP_H -#define ASMOTOR_LIB_LIBWRAP_H - -#include "lib/types.h" - -#define MAXNAMELENGTH 256 - -struct LibraryWrapper { - char tName[MAXNAMELENGTH]; - UWORD uwTime; - UWORD uwDate; - SLONG nByteLength; - UBYTE *pData; - struct LibraryWrapper *pNext; -}; - -typedef struct LibraryWrapper sLibrary; - -#endif diff --git a/include/lib/types.h b/include/lib/types.h deleted file mode 100644 index 997702c0..00000000 --- a/include/lib/types.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef ASMOTOR_LIB_TYPES_H -#define ASMOTOR_LIB_TYPES_H - -#ifndef _MAX_PATH -#define _MAX_PATH 512 -#endif - -typedef unsigned char UBYTE; -typedef signed char SBYTE; -typedef unsigned short UWORD; -typedef signed short SWORD; -typedef unsigned long ULONG; -typedef signed long SLONG; -typedef signed char BBOOL; - -#endif diff --git a/include/link/object.h b/include/link/object.h index 72cb9f9e..3f514adf 100644 --- a/include/link/object.h +++ b/include/link/object.h @@ -2,6 +2,5 @@ #define ASMOTOR_LINK_OBJECT_H extern void obj_Readfile(char *tzObjectfile); -extern void lib_Readfile(char *tzLibfile); #endif diff --git a/src/asm/alloca.c b/src/asm/alloca.c deleted file mode 100644 index eb6ebd75..00000000 --- a/src/asm/alloca.c +++ /dev/null @@ -1,466 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef emacs -#include "blockinput.h" -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -#ifndef alloca - -#ifdef emacs -#ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -#ifndef STACK_DIRECTION -you lose-- must know STACK_DIRECTION at compile - time -#endif /* STACK_DIRECTION undefined */ -#endif /* static */ -#endif /* emacs */ -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ -#if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc(); -#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -#else -#define ADDRESS_FUNCTION(arg) &(arg) -#endif -#if __STDC__ - typedef void *pointer; -#else - typedef char *pointer; -#endif - -#define NULL 0 - -/* Different portions of Emacs need to call different versions of - malloc. The Emacs executable needs alloca to call xmalloc, because - ordinary malloc isn't protected from input signals. On the other - hand, the utilities in lib-src need alloca to call malloc; some of - them are very simple, and don't have an xmalloc routine. - - Non-Emacs programs expect this to call use xmalloc. - - Callers below should use malloc. */ - -/* Carsten Sorensen 09/09/97 - * Commented out the following, I want malloc! -#ifndef emacs -#define malloc xmalloc -#endif -extern pointer malloc (); - And added the following line: - */ -#include - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -#ifndef STACK_DIRECTION -#define STACK_DIRECTION 0 /* Direction unknown. */ -#endif - -#if STACK_DIRECTION != 0 - -#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -#else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -#define STACK_DIR stack_dir - -static void -find_stack_direction() -{ - static char *addr = NULL; /* Address of first `dummy', once - * known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) { /* Initial entry. */ - addr = ADDRESS_FUNCTION(dummy); - - find_stack_direction(); /* Recurse once. */ - } else { - /* Second entry. */ - if (ADDRESS_FUNCTION(dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} -#endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -#ifndef ALIGN_SIZE -#define ALIGN_SIZE sizeof(double) -#endif - -typedef union hdr { - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct { - union hdr *next;/* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -pointer -alloca(size) - unsigned size; -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION(probe); - -#if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction(); -#endif - - /* Reclaim garbage, defined as all alloca'd storage that was allocated - * from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -#ifdef emacs - BLOCK_INPUT; -#endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) { - register header *np = hp->h.next; - - free((pointer) hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -#ifdef emacs - UNBLOCK_INPUT; -#endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - register pointer new = malloc(sizeof(header) + size); - /* Address of header. */ - - ((header *) new)->h.next = last_alloca_header; - ((header *) new)->h.deep = depth; - - last_alloca_header = (header *) new; - - /* User storage begins just after header. */ - - return (pointer) ((char *) new + sizeof(header)); - } -} -#if defined (CRAY) && defined (CRAY_STACKSEG_END) - -#ifdef DEBUG_I00AFUNC -#include -#endif - -#ifndef CRAY_STACK -#define CRAY_STACK -#ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ -}; -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - * segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - * microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; -}; -#else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would be - * required to satisfy the maximum stack - * demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This number is - * actually corrupted by STKSTAT to include - * the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ -}; -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include this - * trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - * segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; -}; -#endif /* CRAY2 */ -#endif /* not CRAY_STACK */ - -#ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc(long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first step is - * to get the stack status structure. We could do this more quickly - * and more directly, perhaps, by referencing the $LM00 common block, - * but I know that this works. */ - - STKSTAT(&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - 15); - - /* There must be at least one stack segment. Therefore it is a fatal - * error if "trailer" is null. */ - - if (trailer == 0) - abort(); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort(); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes of - * all predecessor segments. */ - - result = address - block; - - if (trailer == 0) { - return result; - } - do { - if (trailer->this_size <= 0) - abort(); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one not in - * any segment), you will get a different number back, formed from - * subtracting the address of the first block. This is probably not - * what you want. */ - - return (result); -} -#else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc(long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the current stack - * segment. If you (as a subprogram) store your registers on the - * stack and find that you are past the contents of B67, you have - * overflowed the segment. - * - * B67 also points to the stack segment linkage control area, which is - * what we are really interested in. */ - - stkl = CRAY_STACKSEG_END(); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, one has the - * address of the first word of the segment. - * - * If this is not the first segment, 'pseg' will be nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused a stack - * overflow. Discard stack segments which do not contain the target - * address. */ - - while (!(this_segment <= address && address <= stkl)) { -#ifdef DEBUG_I00AFUNC - fprintf(stderr, "%011o %011o %011o\n", this_segment, address, - stkl); -#endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, you get the - * address of the previous stack segment's end. This seems a little - * convoluted to me, but I'll bet you save a cycle somewhere. */ - - while (pseg != 0) { -#ifdef DEBUG_I00AFUNC - fprintf(stderr, "%011o %011o\n", pseg, size); -#endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} -#endif /* not CRAY2 */ -#endif /* CRAY */ - -#endif /* no alloca */ -#endif /* not GCC version 2 */ diff --git a/src/asm/fstack.c b/src/asm/fstack.c index 87a0b7b5..da1b10af 100644 --- a/src/asm/fstack.c +++ b/src/asm/fstack.c @@ -5,6 +5,8 @@ * */ +#include +#include #include #include #include @@ -14,6 +16,12 @@ #include "asm/types.h" #include "asm/main.h" #include "asm/lexer.h" +#include "extern/err.h" +#include "extern/strl.h" + +#ifndef PATH_MAX +#define PATH_MAX 256 +#endif /* * RGBAsm - FSTACK.C (FileStack routines) @@ -62,8 +70,7 @@ pushcontext(void) while (*ppFileStack) ppFileStack = &((*ppFileStack)->pNext); - if ((*ppFileStack = - (struct sContext *) malloc(sizeof(struct sContext))) != NULL) { + if ((*ppFileStack = malloc(sizeof(struct sContext))) != NULL) { (*ppFileStack)->FlexHandle = CurrentFlexHandle; (*ppFileStack)->pNext = NULL; strcpy((char *) (*ppFileStack)->tzFileName, @@ -195,28 +202,33 @@ fstk_AddIncludePath(char *s) strcpy(IncludePaths[NextIncPath++], s); } -void -fstk_FindFile(char *s) +FILE * +fstk_FindFile(char *fname) { - char t[_MAX_PATH + 1]; - SLONG i = -1; + char path[PATH_MAX]; + int i; + FILE *f; - strcpy(t, s); + if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) { + return f; + } - while (i < NextIncPath) { - FILE *f; - - if ((f = fopen(t, "rb")) != NULL) { - fclose(f); - strcpy(s, t); - return; + for (i = 0; i < NextIncPath; ++i) { + if (strlcpy(path, IncludePaths[i], sizeof path) >= + sizeof path) { + continue; } - i += 1; - if (i < NextIncPath) { - strcpy(t, IncludePaths[i]); - strcat(t, s); + if (strlcat(path, fname, sizeof path) >= sizeof path) { + continue; + } + + if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) { + return f; } } + + errno = ENOENT; + return NULL; } /* * RGBAsm - FSTACK.C (FileStack routines) @@ -225,33 +237,30 @@ fstk_FindFile(char *s) * */ -ULONG +void fstk_RunInclude(char *tzFileName) { FILE *f; - //printf("INCLUDE: %s\n", s); + f = fstk_FindFile(tzFileName); - fstk_FindFile(tzFileName); - //printf("INCLUDING: %s\n", tzFileName); + if (f == NULL) { + err(1, "Unable to open included file '%s'", + tzFileName); + } - if ((f = fopen(tzFileName, "r")) != NULL) { - pushcontext(); - nLineNo = 1; - nCurrentStatus = STAT_isInclude; - strcpy(tzCurrentFileName, tzFileName); - pCurrentFile = f; - CurrentFlexHandle = yy_create_buffer(pCurrentFile); - yy_switch_to_buffer(CurrentFlexHandle); + pushcontext(); + nLineNo = 1; + nCurrentStatus = STAT_isInclude; + strcpy(tzCurrentFileName, tzFileName); + pCurrentFile = f; + CurrentFlexHandle = yy_create_buffer(pCurrentFile); + yy_switch_to_buffer(CurrentFlexHandle); - //Dirty hack to give the INCLUDE directive a linefeed + //Dirty hack to give the INCLUDE directive a linefeed - yyunput('\n'); - nLineNo -= 1; - - return (1); - } else - return (0); + yyunput('\n'); + nLineNo -= 1; } /* * RGBAsm - FSTACK.C (FileStack routines) @@ -360,7 +369,7 @@ fstk_RunRept(ULONG count) * */ -ULONG +void fstk_Init(char *s) { char tzFileName[_MAX_PATH + 1]; @@ -368,17 +377,16 @@ fstk_Init(char *s) sym_AddString("__FILE__", s); strcpy(tzFileName, s); - fstk_FindFile(tzFileName); - pFileStack = NULL; - if ((pCurrentFile = fopen(tzFileName, "r")) != NULL) { - nMacroCount = 0; - nCurrentStatus = STAT_isInclude; - strcpy(tzCurrentFileName, tzFileName); - CurrentFlexHandle = yy_create_buffer(pCurrentFile); - yy_switch_to_buffer(CurrentFlexHandle); - nLineNo = 1; - return (1); - } else - return (0); + pCurrentFile = fopen(tzFileName, "rb"); + if (pCurrentFile == NULL) { + err(1, "Unable to open file '%s'", tzFileName); + } + + nMacroCount = 0; + nCurrentStatus = STAT_isInclude; + strcpy(tzCurrentFileName, tzFileName); + CurrentFlexHandle = yy_create_buffer(pCurrentFile); + yy_switch_to_buffer(CurrentFlexHandle); + nLineNo = 1; } diff --git a/src/asm/gameboy/yaccprt4.y b/src/asm/gameboy/yaccprt4.y index 9b8bfcba..bc113e70 100644 --- a/src/asm/gameboy/yaccprt4.y +++ b/src/asm/gameboy/yaccprt4.y @@ -290,6 +290,8 @@ z80_ld : z80_ld_mem z80_ld_hl : T_Z80_LD T_MODE_HL comma '[' T_MODE_SP const_8bit ']' { out_AbsByte(0xF8); out_RelByte(&$6); } + | T_Z80_LD T_MODE_HL comma T_MODE_SP const_8bit + { out_AbsByte(0xF8); out_RelByte(&$5); } | T_Z80_LD T_MODE_HL comma const_16bit { out_AbsByte(0x01|(REG_HL<<4)); out_RelWord(&$4); } ; diff --git a/src/asm/globlex.c b/src/asm/globlex.c index 088076bf..0d09ef69 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -208,10 +208,14 @@ PutMacroArg(char *src, ULONG size) char *s; yyskipbytes(size); - if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) { - yyunputstr(s); + if ((size == 2 && src[1] >= '1' && src[1] <= '9')) { + if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) { + yyunputstr(s); + } else { + yyerror("Macro argument not defined"); + } } else { - yyerror("Macro argument not defined"); + yyerror("Invalid macro argument"); } return (0); } @@ -219,9 +223,15 @@ PutMacroArg(char *src, ULONG size) ULONG PutUniqueArg(char *src, ULONG size) { + char *s; + src = src; yyskipbytes(size); - yyunputstr(sym_FindMacroArg(-1)); + if ((s = sym_FindMacroArg(-1)) != NULL) { + yyunputstr(s); + } else { + yyerror("Macro unique label string not defined"); + } return (0); } @@ -388,7 +398,7 @@ setuplex(void) id = lex_FloatAlloc(&tMacroArgToken); lex_FloatAddFirstRange(id, '\\', '\\'); - lex_FloatAddSecondRange(id, '0', '9'); + lex_FloatAddSecondRange(id, '1', '9'); id = lex_FloatAlloc(&tMacroUniqueToken); lex_FloatAddFirstRange(id, '\\', '\\'); lex_FloatAddSecondRange(id, '@', '@'); diff --git a/src/asm/lexer.c b/src/asm/lexer.c index 814da5ba..868f50a5 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -11,6 +11,7 @@ #include "asm/main.h" #include "asm/rpn.h" #include "asm/fstack.h" +#include "extern/err.h" #include "asmy.h" @@ -20,18 +21,18 @@ struct sLexString { ULONG nNameLength; struct sLexString *pNext; }; -#define pLexBuffer (pCurrentBuffer->pBuffer) -#define nLexBufferLeng (pCurrentBuffer->nBufferSize) +#define pLexBufferRealStart (pCurrentBuffer->pBufferRealStart) +#define pLexBuffer (pCurrentBuffer->pBuffer) +#define AtLineStart (pCurrentBuffer->oAtLineStart) #define SAFETYMARGIN 1024 -extern ULONG symvaluetostring(char *dest, char *s); +extern size_t symvaluetostring(char *dest, size_t maxLength, char *sym); struct sLexFloat tLexFloat[32]; struct sLexString *tLexHash[LEXHASHSIZE]; YY_BUFFER_STATE pCurrentBuffer; -ULONG yyleng; -ULONG nLexMaxLeng; +ULONG nLexMaxLength; // max length of all keywords and operators ULONG tFloatingSecondChar[256]; ULONG tFloatingFirstChar[256]; @@ -39,8 +40,6 @@ ULONG tFloatingChars[256]; ULONG nFloating; enum eLexerState lexerstate = LEX_STATE_NORMAL; -#define AtLineStart pCurrentBuffer->oAtLineStart - #ifdef __GNUC__ void strupr(char *s) @@ -75,18 +74,24 @@ yyunputbytes(ULONG count) void yyunput(char c) { + if (pLexBuffer <= pLexBufferRealStart) + fatalerror("Buffer safety margin exceeded"); + *(--pLexBuffer) = c; } void yyunputstr(char *s) { - SLONG i; + int i, len; - i = strlen(s) - 1; + len = strlen(s); - while (i >= 0) - yyunput(s[i--]); + if (pLexBuffer - len < pLexBufferRealStart) + fatalerror("Buffer safety margin exceeded"); + + for (i = len - 1; i >= 0; i--) + *(--pLexBuffer) = s[i]; } void @@ -113,13 +118,11 @@ yy_scan_bytes(char *mem, ULONG size) { YY_BUFFER_STATE pBuffer; - if ((pBuffer = - (YY_BUFFER_STATE) malloc(sizeof(struct yy_buffer_state))) != - NULL) { - if ((pBuffer->pBuffer = pBuffer->pBufferStart = - (char *) malloc(size + 1 + SAFETYMARGIN)) != NULL) { - pBuffer->pBuffer += SAFETYMARGIN; - pBuffer->pBufferStart += SAFETYMARGIN; + if ((pBuffer = malloc(sizeof(struct yy_buffer_state))) != NULL) { + if ((pBuffer->pBufferRealStart = + malloc(size + 1 + SAFETYMARGIN)) != NULL) { + pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN; + pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN; memcpy(pBuffer->pBuffer, mem, size); pBuffer->nBufferSize = size; pBuffer->oAtLineStart = 1; @@ -136,22 +139,20 @@ yy_create_buffer(FILE * f) { YY_BUFFER_STATE pBuffer; - if ((pBuffer = - (YY_BUFFER_STATE) malloc(sizeof(struct yy_buffer_state))) != - NULL) { + if ((pBuffer = malloc(sizeof(struct yy_buffer_state))) != NULL) { ULONG size; fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); - if ((pBuffer->pBuffer = pBuffer->pBufferStart = - (char *) malloc(size + 2 + SAFETYMARGIN)) != NULL) { + if ((pBuffer->pBufferRealStart = + malloc(size + 2 + SAFETYMARGIN)) != NULL) { char *mem; ULONG instring = 0; - pBuffer->pBuffer += SAFETYMARGIN; - pBuffer->pBufferStart += SAFETYMARGIN; + pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN; + pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN; size = fread(pBuffer->pBuffer, sizeof(UBYTE), size, f); @@ -165,28 +166,26 @@ yy_create_buffer(FILE * f) if (*mem == '\"') instring = 1 - instring; - if (instring) { + if (mem[0] == '\\' && + (mem[1] == '\"' || mem[1] == '\\')) { + mem += 2; + } else if (instring) { mem += 1; } else { if ((mem[0] == 10 && mem[1] == 13) - || (mem[0] == 13 && mem[1] == 10)) { + || (mem[0] == 13 && mem[1] == 10)) { mem[0] = ' '; mem[1] = '\n'; mem += 2; } else if (mem[0] == 10 || mem[0] == 13) { mem[0] = '\n'; mem += 1; - } else if (mem[0] == '\n' - && mem[1] == '*') { + } else if (mem[0] == '\n' && mem[1] == '*') { mem += 1; - while (! - (*mem == '\n' - || *mem == '\0')) + while (!(*mem == '\n' || *mem == '\0')) *mem++ = ' '; } else if (*mem == ';') { - while (! - (*mem == '\n' - || *mem == '\0')) + while (!(*mem == '\n' || *mem == '\0')) *mem++ = ' '; } else mem += 1; @@ -201,17 +200,32 @@ yy_create_buffer(FILE * f) return (NULL); } -ULONG -lex_FloatAlloc(struct sLexFloat * tok) +ULONG +lex_FloatAlloc(struct sLexFloat *token) { - tLexFloat[nFloating] = (*tok); + tLexFloat[nFloating] = *token; return (1 << (nFloating++)); } +/* + * Make sure that only non-zero ASCII characters are used. Also, check if the + * start is greater than the end of the range. + */ +void +lex_CheckCharacterRange(UWORD start, UWORD end) +{ + if (start > end || start < 1 || end > 127) { + errx(1, "Invalid character range (start: %u, end: %u)", + start, end); + } +} + void lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end) { + lex_CheckCharacterRange(start, end); + while (start <= end) { tFloatingChars[start] &= ~id; start += 1; @@ -221,6 +235,8 @@ lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end) void lex_FloatAddRange(ULONG id, UWORD start, UWORD end) { + lex_CheckCharacterRange(start, end); + while (start <= end) { tFloatingChars[start] |= id; start += 1; @@ -230,6 +246,8 @@ lex_FloatAddRange(ULONG id, UWORD start, UWORD end) void lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end) { + lex_CheckCharacterRange(start, end); + while (start <= end) { tFloatingFirstChar[start] &= ~id; start += 1; @@ -239,6 +257,8 @@ lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end) void lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end) { + lex_CheckCharacterRange(start, end); + while (start <= end) { tFloatingFirstChar[start] |= id; start += 1; @@ -248,6 +268,8 @@ lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end) void lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end) { + lex_CheckCharacterRange(start, end); + while (start <= end) { tFloatingSecondChar[start] &= ~id; start += 1; @@ -257,6 +279,8 @@ lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end) void lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end) { + lex_CheckCharacterRange(start, end); + while (start <= end) { tFloatingSecondChar[start] |= id; start += 1; @@ -264,32 +288,32 @@ lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end) } struct sLexFloat * -lexgetfloat(ULONG id) +lexgetfloat(ULONG nFloatMask) { - ULONG r = 0, mask = 1; - - if (id == 0) - return (NULL); - - while ((id & mask) == 0) { - mask <<= 1; - r += 1; + if (nFloatMask == 0) { + fatalerror("Internal error in lexgetfloat"); } - return (&tLexFloat[r]); + int i = 0; + + while ((nFloatMask & 1) == 0) { + nFloatMask >>= 1; + i++; + } + + return (&tLexFloat[i]); } ULONG lexcalchash(char *s) { - ULONG r = 0; + ULONG hash = 0; while (*s) { - r = ((r << 1) + (toupper(*s))) % LEXHASHSIZE; - s += 1; + hash = (hash * 283) ^ toupper(*s++); } - return (r); + return (hash % LEXHASHSIZE); } void @@ -297,17 +321,17 @@ lex_Init(void) { ULONG i; - for (i = 0; i < LEXHASHSIZE; i += 1) { + for (i = 0; i < LEXHASHSIZE; i++) { tLexHash[i] = NULL; } - for (i = 0; i < 256; i += 1) { + for (i = 0; i < 256; i++) { tFloatingFirstChar[i] = 0; tFloatingSecondChar[i] = 0; tFloatingChars[i] = 0; } - nLexMaxLeng = 0; + nLexMaxLength = 0; nFloating = 0; } @@ -322,11 +346,7 @@ lex_AddStrings(struct sLexInitString * lex) while (*ppHash) ppHash = &((*ppHash)->pNext); - //printf("%s has hashvalue %d\n", lex->tzName, hash); - - if (((*ppHash) = - (struct sLexString *) malloc(sizeof(struct sLexString))) != - NULL) { + if (((*ppHash) = malloc(sizeof(struct sLexString))) != NULL) { if (((*ppHash)->tzName = (char *) strdup(lex->tzName)) != NULL) { (*ppHash)->nNameLength = strlen(lex->tzName); @@ -335,8 +355,8 @@ lex_AddStrings(struct sLexInitString * lex) strupr((*ppHash)->tzName); - if ((*ppHash)->nNameLength > nLexMaxLeng) - nLexMaxLeng = (*ppHash)->nNameLength; + if ((*ppHash)->nNameLength > nLexMaxLength) + nLexMaxLength = (*ppHash)->nNameLength; } else fatalerror("Out of memory!"); @@ -347,458 +367,390 @@ lex_AddStrings(struct sLexInitString * lex) } } +/* + * Gets the "float" mask and "float" length. + * "Float" refers to the token type of a token that is not a keyword. + * The character classes floatingFirstChar, floatingSecondChar, and + * floatingChars are defined separately for each token type. + * It uses bit masks to match against a set of simple regular expressions + * of the form /[floatingFirstChar]([floatingSecondChar][floatingChars]*)?/. + * The token types with the longest match from the current position in the + * buffer will have their bits set in the float mask. + */ +void +yylex_GetFloatMaskAndFloatLen(ULONG *pnFloatMask, ULONG *pnFloatLen) +{ + // Note that '\0' should always have a bit mask of 0 in the "floating" + // tables, so it doesn't need to be checked for separately. + + char *s = pLexBuffer; + ULONG nOldFloatMask = 0; + ULONG nFloatMask = tFloatingFirstChar[(int)*s]; + + if (nFloatMask != 0) { + s++; + nOldFloatMask = nFloatMask; + nFloatMask &= tFloatingSecondChar[(int)*s]; + + while (nFloatMask != 0) { + s++; + nOldFloatMask = nFloatMask; + nFloatMask &= tFloatingChars[(int)*s]; + } + } + + *pnFloatMask = nOldFloatMask; + *pnFloatLen = (ULONG)(s - pLexBuffer); +} + +/* + * Gets the longest keyword/operator from the current position in the buffer. + */ +struct sLexString * +yylex_GetLongestFixed() +{ + struct sLexString *pLongestFixed = NULL; + char *s = pLexBuffer; + ULONG hash = 0; + ULONG length = 0; + + while (length < nLexMaxLength && *s) { + hash = (hash * 283) ^ toupper(*s); + s++; + length++; + + struct sLexString *lex = tLexHash[hash % LEXHASHSIZE]; + + while (lex) { + if (lex->nNameLength == length + && strncasecmp(pLexBuffer, lex->tzName, length) == 0) { + pLongestFixed = lex; + break; + } + lex = lex->pNext; + } + } + + return pLongestFixed; +} + +size_t +CopyMacroArg(char *dest, size_t maxLength, char c) +{ + int i; + char *s; + int argNum; + + switch (c) { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + argNum = c - '0'; + break; + case '@': + argNum = -1; + break; + default: + return 0; + } + + if ((s = sym_FindMacroArg(argNum)) == NULL) + fatalerror("Macro argument not defined"); + + for (i = 0; s[i] != 0; i++) { + if (i >= maxLength) { + fatalerror("Macro argument too long to fit buffer"); + } + dest[i] = s[i]; + } + + return i; +} + +static inline void +yylex_StringWriteChar(char *s, size_t index, char c) +{ + if (index >= MAXSTRLEN) { + fatalerror("String too long"); + } + + s[index] = c; +} + +static inline void +yylex_SymbolWriteChar(char *s, size_t index, char c) +{ + if (index >= MAXSYMLEN) { + fatalerror("Symbol too long"); + } + + s[index] = c; +} + +/* + * Trims white space at the end of a string. + * The index parameter is the index of the 0 at the end of the string. + */ +void yylex_TrimEnd(char *s, size_t index) +{ + int i; + + for (i = (int)index - 1; i >= 0 && (s[i] == ' ' || s[i] == '\t'); i--) + s[i] = 0; +} + +size_t +yylex_ReadBracketedSymbol(char *dest, size_t index) +{ + char sym[MAXSYMLEN + 1]; + char ch; + size_t i = 0; + size_t length, maxLength; + + for (ch = *pLexBuffer; + ch != '}' && ch != '"' && ch != '\n'; + ch = *(++pLexBuffer)) { + if (ch == '\\') { + ch = *(++pLexBuffer); + maxLength = MAXSYMLEN - i; + length = CopyMacroArg(&sym[i], maxLength, ch); + + if (length != 0) + i += length; + else + fatalerror("Illegal character escape '%c'", ch); + } else + yylex_SymbolWriteChar(sym, i++, ch); + } + + yylex_SymbolWriteChar(sym, i, 0); + + maxLength = MAXSTRLEN - index; // it's assumed we're writing to a T_STRING + length = symvaluetostring(&dest[index], maxLength, sym); + + if (*pLexBuffer == '}') + pLexBuffer++; + else + yyerror("Missing }"); + + return length; +} + +void +yylex_ReadQuotedString() +{ + size_t index = 0; + size_t length, maxLength; + + while (*pLexBuffer != '"' && *pLexBuffer != '\n') { + char ch = *pLexBuffer++; + + if (ch == '\\') { + ch = *pLexBuffer++; + + switch (ch) { + case 'n': + ch = '\n'; + break; + case 't': + ch = '\t'; + break; + case '\\': + ch = '\\'; + break; + case '"': + ch = '"'; + break; + default: + maxLength = MAXSTRLEN - index; + length = CopyMacroArg(&yylval.tzString[index], maxLength, ch); + + if (length != 0) + index += length; + else + fatalerror("Illegal character escape '%c'", ch); + + ch = 0; + break; + } + } else if (ch == '{') { + // Get bracketed symbol within string. + index += yylex_ReadBracketedSymbol(yylval.tzString, index); + ch = 0; + } + + if (ch) + yylex_StringWriteChar(yylval.tzString, index++, ch); + } + + yylex_StringWriteChar(yylval.tzString, index, 0); + + if (*pLexBuffer == '"') + pLexBuffer++; + else + yyerror("Unterminated string"); +} + +ULONG +yylex_NORMAL() +{ + struct sLexString *pLongestFixed = NULL; + ULONG nFloatMask, nFloatLen; + ULONG linestart = AtLineStart; + + AtLineStart = 0; + +scanagain: + while (*pLexBuffer == ' ' || *pLexBuffer == '\t') { + linestart = 0; + pLexBuffer++; + } + + if (*pLexBuffer == 0) { + // Reached the end of a file, macro, or rept. + if (yywrap() == 0) { + linestart = AtLineStart; + AtLineStart = 0; + goto scanagain; + } + } + + // Try to match an identifier, macro argument (e.g. \1), + // or numeric literal. + yylex_GetFloatMaskAndFloatLen(&nFloatMask, &nFloatLen); + + // Try to match a keyword or operator. + pLongestFixed = yylex_GetLongestFixed(); + + if (nFloatLen == 0 && pLongestFixed == NULL) { + // No keyword, identifier, operator, or numerical literal matches. + + if (*pLexBuffer == '"') { + pLexBuffer++; + yylex_ReadQuotedString(); + return T_STRING; + } else if (*pLexBuffer == '{') { + pLexBuffer++; + yylex_ReadBracketedSymbol(yylval.tzString, 0); + return T_STRING; + } else { + // It's not a keyword, operator, identifier, macro argument, + // numeric literal, string, or bracketed symbol, so just return + // the ASCII character. + if (*pLexBuffer == '\n') + AtLineStart = 1; + + return *pLexBuffer++; + } + } + + if (pLongestFixed == NULL || nFloatLen > pLongestFixed->nNameLength) { + // Longest match was an identifier, macro argument, or numeric literal. + struct sLexFloat *token = lexgetfloat(nFloatMask); + + if (token->Callback) { + int done = token->Callback(pLexBuffer, nFloatLen); + if (!done) + goto scanagain; + } + + pLexBuffer += nFloatLen; + + if (token->nToken == T_ID && linestart) { + return T_LABEL; + } else { + return token->nToken; + } + } + + // Longest match was a keyword or operator. + pLexBuffer += pLongestFixed->nNameLength; + return pLongestFixed->nToken; +} + +ULONG +yylex_MACROARGS() +{ + size_t index = 0; + size_t length, maxLength; + + while (*pLexBuffer == ' ' || *pLexBuffer == '\t') { + pLexBuffer++; + } + + while (*pLexBuffer != ',' && (*pLexBuffer != '\n')) { + char ch = *pLexBuffer++; + + if (ch == '\\') { + ch = *pLexBuffer++; + + switch (ch) { + case 'n': + ch = '\n'; + break; + case 't': + ch = '\t'; + break; + case '\\': + ch = '\\'; + break; + default: + maxLength = MAXSTRLEN - index; + length = CopyMacroArg(&yylval.tzString[index], maxLength, ch); + + if (length != 0) + index += length; + else + fatalerror("Illegal character escape '%c'", ch); + + ch = 0; + break; + } + } else if (ch == '{') { + index += yylex_ReadBracketedSymbol(yylval.tzString, index); + ch = 0; + } + if (ch) + yylex_StringWriteChar(yylval.tzString, index++, ch); + } + + if (index) { + yylex_StringWriteChar(yylval.tzString, index, 0); + + // trim trailing white space at the end of the line + if (*pLexBuffer == '\n') + yylex_TrimEnd(yylval.tzString, index); + + return T_STRING; + } else if (*pLexBuffer == '\n') { + pLexBuffer++; + AtLineStart = 1; + return '\n'; + } else if (*pLexBuffer == ',') { + pLexBuffer++; + return ','; + } + + fatalerror("Internal error in yylex_MACROARGS"); + return 0; +} + ULONG yylex(void) { - ULONG hash, maxlen; - char *s; - struct sLexString *pLongestFixed = NULL; - ULONG nFloatMask, nOldFloatMask, nFloatLen; - ULONG linestart = AtLineStart; - switch (lexerstate) { case LEX_STATE_NORMAL: - AtLineStart = 0; - -scanagain: - - while (*pLexBuffer == ' ' || *pLexBuffer == '\t') { - linestart = 0; - pLexBuffer += 1; - } - - if (*pLexBuffer == 0) { - if (yywrap() == 0) { - linestart = AtLineStart; - AtLineStart = 0; - goto scanagain; - } - } - s = pLexBuffer; - nOldFloatMask = nFloatLen = 0; - nFloatMask = tFloatingFirstChar[(int) *s++]; - while (nFloatMask && nFloatLen < nLexBufferLeng) { - nFloatLen += 1; - nOldFloatMask = nFloatMask; - if (nFloatLen == 1) - nFloatMask &= tFloatingSecondChar[(int) *s++]; - else - nFloatMask &= tFloatingChars[(int) *s++]; - } - - maxlen = nLexBufferLeng; - if (nLexMaxLeng < maxlen) - maxlen = nLexMaxLeng; - - yyleng = 0; - hash = 0; - s = pLexBuffer; - while (yyleng < nLexMaxLeng) { - /* XXX: Kludge warning! The dereference of s below - * may go beyond the end of the buffer. We use the - * following test to stop that from happening, - * without really understanding what the rest of - * the code is doing. This may not be the correct - * fix! */ - if (!*s) - break; - - yyleng += 1; - hash = ((hash << 1) + (toupper(*s))) % LEXHASHSIZE; - s += 1; - if (tLexHash[hash]) { - struct sLexString *lex; - - lex = tLexHash[hash]; - while (lex) { - if (lex->nNameLength == yyleng) { - if (strncasecmp - (pLexBuffer, lex->tzName, - yyleng) == 0) { - pLongestFixed = lex; - } - } - lex = lex->pNext; - } - } - } - - if (nFloatLen == 0 && pLongestFixed == NULL) { - if (*pLexBuffer == '"') { - ULONG index = 0; - - pLexBuffer += 1; - while ((*pLexBuffer != '"') - && (*pLexBuffer != '\n')) { - char ch, *marg; - - if ((ch = *pLexBuffer++) == '\\') { - switch (ch = (*pLexBuffer++)) { - case 'n': - ch = '\n'; - break; - case 't': - ch = '\t'; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if ((marg = - sym_FindMacroArg(ch - - - '0')) - != NULL) { - while (*marg) - yylval. - tzString - [index++] - = - *marg++; - ch = 0; - } - break; - case '@': - if ((marg = - sym_FindMacroArg - (-1)) != NULL) { - while (*marg) - yylval. - tzString - [index++] - = - *marg++; - ch = 0; - } - break; - } - } else if (ch == '{') { - char sym[MAXSYMLEN]; - int i = 0; - - while ((*pLexBuffer != '}') - && (*pLexBuffer != '"') - && (*pLexBuffer != - '\n')) { - if ((ch = - *pLexBuffer++) == - '\\') { - switch (ch = - (*pLexBuffer++)) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if ((marg = sym_FindMacroArg(ch - '0')) != NULL) { - while - (*marg) - sym[i++] = *marg++; - ch = 0; - } - break; - case '@': - if ((marg = sym_FindMacroArg(-1)) != NULL) { - while - (*marg) - sym[i++] = *marg++; - ch = 0; - } - break; - } - } else - sym[i++] = ch; - } - - sym[i] = 0; - index += - symvaluetostring(&yylval. - tzString - [index], - sym); - if (*pLexBuffer == '}') - pLexBuffer += 1; - else - yyerror("Missing }"); - ch = 0; - } - if (ch) - yylval.tzString[index++] = ch; - } - - yylval.tzString[index++] = 0; - - if (*pLexBuffer == '\n') - yyerror("Unterminated string"); - else - pLexBuffer += 1; - - return (T_STRING); - } else if (*pLexBuffer == '{') { - char sym[MAXSYMLEN], ch, *marg; - int i = 0; - - pLexBuffer += 1; - - while ((*pLexBuffer != '}') - && (*pLexBuffer != '\n')) { - if ((ch = *pLexBuffer++) == '\\') { - switch (ch = (*pLexBuffer++)) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if ((marg = - sym_FindMacroArg(ch - - - '0')) - != NULL) { - while (*marg) - sym[i++] - = - *marg++; - ch = 0; - } - break; - case '@': - if ((marg = - sym_FindMacroArg - (-1)) != NULL) { - while (*marg) - sym[i++] - = - *marg++; - ch = 0; - } - break; - } - } else - sym[i++] = ch; - } - sym[i] = 0; - symvaluetostring(yylval.tzString, sym); - if (*pLexBuffer == '}') - pLexBuffer += 1; - else - yyerror("Missing }"); - - return (T_STRING); - } else { - if (*pLexBuffer == '\n') - AtLineStart = 1; - - yyleng = 1; - return (*pLexBuffer++); - } - } - if (nFloatLen == 0) { - yyleng = pLongestFixed->nNameLength; - pLexBuffer += yyleng; - return (pLongestFixed->nToken); - } - if (pLongestFixed == NULL) { - struct sLexFloat *tok; - - tok = lexgetfloat(nOldFloatMask); - yyleng = nFloatLen; - if (tok->Callback) { - if (tok->Callback(pLexBuffer, yyleng) == 0) - goto scanagain; - } - if (tok->nToken == T_ID && linestart) { - pLexBuffer += yyleng; - return (T_LABEL); - } else { - pLexBuffer += yyleng; - return (tok->nToken); - } - } - if (nFloatLen > pLongestFixed->nNameLength) { - struct sLexFloat *tok; - - tok = lexgetfloat(nOldFloatMask); - yyleng = nFloatLen; - if (tok->Callback) { - if (tok->Callback(pLexBuffer, yyleng) == 0) - goto scanagain; - } - if (tok->nToken == T_ID && linestart) { - pLexBuffer += yyleng; - return (T_LABEL); - } else { - pLexBuffer += yyleng; - return (tok->nToken); - } - } else { - yyleng = pLongestFixed->nNameLength; - pLexBuffer += yyleng; - return (pLongestFixed->nToken); - } - break; - + return yylex_NORMAL(); case LEX_STATE_MACROARGS: - { - ULONG index = 0; - - while (*pLexBuffer == ' ' || *pLexBuffer == '\t') { - linestart = 0; - pLexBuffer += 1; - } - - while ((*pLexBuffer != ',') - && (*pLexBuffer != '\n')) { - char ch, *marg; - - if ((ch = *pLexBuffer++) == '\\') { - switch (ch = (*pLexBuffer++)) { - case 'n': - ch = '\n'; - break; - case 't': - ch = '\t'; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if ((marg = - sym_FindMacroArg(ch - - '0')) != - NULL) { - while (*marg) - yylval. - tzString - [index++] = - *marg++; - ch = 0; - } - break; - case '@': - if ((marg = - sym_FindMacroArg(-1)) != - NULL) { - while (*marg) - yylval. - tzString - [index++] = - *marg++; - ch = 0; - } - break; - } - } else if (ch == '{') { - char sym[MAXSYMLEN]; - int i = 0; - - while ((*pLexBuffer != '}') - && (*pLexBuffer != '"') - && (*pLexBuffer != '\n')) { - if ((ch = - *pLexBuffer++) == '\\') { - switch (ch = - (*pLexBuffer++)) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if ((marg = - sym_FindMacroArg - (ch - - '0')) != - NULL) { - while - (*marg) - sym[i++] = *marg++; - ch = 0; - } - break; - case '@': - if ((marg = - sym_FindMacroArg - (-1)) != - NULL) { - while - (*marg) - sym[i++] = *marg++; - ch = 0; - } - break; - } - } else - sym[i++] = ch; - } - sym[i] = 0; - index += - symvaluetostring(&yylval. - tzString[index], - sym); - if (*pLexBuffer == '}') - pLexBuffer += 1; - else - yyerror("Missing }"); - ch = 0; - } - if (ch) - yylval.tzString[index++] = ch; - } - - if (index) { - yyleng = index; - yylval.tzString[index] = 0; - if (*pLexBuffer == '\n') { - while (yylval.tzString[--index] == ' ') { - yylval.tzString[index] = 0; - yyleng -= 1; - } - } - return (T_STRING); - } else if (*pLexBuffer == '\n') { - pLexBuffer += 1; - AtLineStart = 1; - yyleng = 1; - return ('\n'); - } else if (*pLexBuffer == ',') { - pLexBuffer += 1; - yyleng = 1; - return (','); - } else { - yyerror("INTERNAL ERROR IN YYLEX"); - return (0); - } - } - - break; + return yylex_MACROARGS(); } - yyerror("INTERNAL ERROR IN YYLEX"); - return (0); + fatalerror("Internal error in yylex"); + return 0; } diff --git a/src/asm/main.c b/src/asm/main.c index 62ed48f6..46ff501d 100644 --- a/src/asm/main.c +++ b/src/asm/main.c @@ -19,6 +19,7 @@ #include "asm/fstack.h" #include "asm/output.h" #include "asm/main.h" +#include "extern/err.h" int yyparse(void); void setuplex(void); @@ -133,9 +134,8 @@ opt_Parse(char *s) newopt.gbgfx[2] = s[3]; newopt.gbgfx[3] = s[4]; } else { - fprintf(stderr, "Must specify exactly 4 characters " - "for option 'g'\n"); - exit(1); + errx(1, "Must specify exactly 4 characters for " + "option 'g'"); } break; case 'b': @@ -143,9 +143,8 @@ opt_Parse(char *s) newopt.binary[0] = s[1]; newopt.binary[1] = s[2]; } else { - fprintf(stderr, "Must specify exactly 2 characters " - "for option 'b'\n"); - exit(1); + errx(1, "Must specify exactly 2 characters for option " + "'b'"); } break; case 'z': @@ -154,12 +153,10 @@ opt_Parse(char *s) result = sscanf(&s[1], "%lx", &newopt.fillchar); if (!((result == EOF) || (result == 1))) { - fprintf(stderr, - "Invalid argument for option 'z'\n"); - exit(1); + errx(1, "Invalid argument for option 'z'"); } } else { - fprintf(stderr, "Invalid argument for option 'z'\n"); + errx(1, "Invalid argument for option 'z'"); exit(1); } break; @@ -176,9 +173,7 @@ opt_Push(void) { struct sOptionStackEntry *pOpt; - if ((pOpt = - (struct sOptionStackEntry *) - malloc(sizeof(struct sOptionStackEntry))) != NULL) { + if ((pOpt = malloc(sizeof(struct sOptionStackEntry))) != NULL) { pOpt->Options = CurrentOptions; pOpt->pNext = pOptionStack; pOptionStack = pOpt; @@ -245,8 +240,6 @@ fatalerror(const char *fmt, ...) void PrintUsage(void) { - printf("RGBAsm v" ASM_VERSION " (part of ASMotor " ASMOTOR_VERSION - ")\n\n"); printf("Usage: rgbasm [-v] [-h] [-b chars] [-g chars] [-i path] [-o outfile] [-p pad_value]\n" " file\n"); exit(1); @@ -295,9 +288,8 @@ main(int argc, char *argv[]) newopt.binary[0] = optarg[1]; newopt.binary[1] = optarg[2]; } else { - fprintf(stderr, "Must specify exactly " - "2 characters for option 'b'\n"); - exit(1); + errx(1, "Must specify exactly 2 characters for " + "option 'b'"); } break; case 'g': @@ -307,9 +299,8 @@ main(int argc, char *argv[]) newopt.gbgfx[2] = optarg[3]; newopt.gbgfx[3] = optarg[4]; } else { - fprintf(stderr, "Must specify exactly " - "4 characters for option 'g'\n"); - exit(1); + errx(1, "Must specify exactly 4 characters for " + "option 'g'"); } break; case 'h': @@ -324,14 +315,11 @@ main(int argc, char *argv[]) case 'p': newopt.fillchar = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, - "Invalid argument for option 'p'\n"); - exit(1); + errx(1, "Invalid argument for option 'p'"); } if (newopt.fillchar < 0 || newopt.fillchar > 0xFF) { - fprintf(stderr, "Argument for option 'p' " - "must be between 0 and 0xFF\n"); - exit(1); + errx(1, "Argument for option 'p' must be " + "between 0 and 0xFF"); } break; case 'v': @@ -348,7 +336,6 @@ main(int argc, char *argv[]) DefaultOptions = CurrentOptions; - /* tzMainfile=argv[argn++]; argc-=1; */ tzMainfile = argv[argc - 1]; setuplex(); @@ -366,75 +353,67 @@ main(int argc, char *argv[]) nPass = 1; nErrors = 0; sym_PrepPass1(); - if (fstk_Init(tzMainfile)) { - if (CurrentOptions.verbose) { - printf("Pass 1...\n"); - } + fstk_Init(tzMainfile); + if (CurrentOptions.verbose) { + printf("Pass 1...\n"); + } - yy_set_state(LEX_STATE_NORMAL); - opt_SetCurrentOptions(&DefaultOptions); + yy_set_state(LEX_STATE_NORMAL); + opt_SetCurrentOptions(&DefaultOptions); - if (yyparse() == 0 && nErrors == 0) { - if (nIFDepth == 0) { - nTotalLines = 0; - nLineNo = 1; - nIFDepth = 0; - nPC = 0; - nPass = 2; - nErrors = 0; - sym_PrepPass2(); - out_PrepPass2(); - fstk_Init(tzMainfile); - yy_set_state(LEX_STATE_NORMAL); - opt_SetCurrentOptions(&DefaultOptions); + if (yyparse() == 0 && nErrors == 0) { + if (nIFDepth == 0) { + nTotalLines = 0; + nLineNo = 1; + nIFDepth = 0; + nPC = 0; + nPass = 2; + nErrors = 0; + sym_PrepPass2(); + out_PrepPass2(); + fstk_Init(tzMainfile); + yy_set_state(LEX_STATE_NORMAL); + opt_SetCurrentOptions(&DefaultOptions); + if (CurrentOptions.verbose) { + printf("Pass 2...\n"); + } + + if (yyparse() == 0 && nErrors == 0) { + double timespent; + + nEndClock = clock(); + timespent = + ((double) (nEndClock - nStartClock)) + / (double) CLOCKS_PER_SEC; if (CurrentOptions.verbose) { - printf("Pass 2...\n"); - } - - if (yyparse() == 0 && nErrors == 0) { - double timespent; - - nEndClock = clock(); - timespent = - ((double) (nEndClock - nStartClock)) - / (double) CLOCKS_PER_SEC; - if (CurrentOptions.verbose) { - printf - ("Success! %ld lines in %d.%02d seconds ", - nTotalLines, (int) timespent, - ((int) (timespent * 100.0)) % 100); - if (timespent == 0) - printf - ("(INFINITY lines/minute)\n"); - else - printf("(%d lines/minute)\n", - (int) (60 / timespent * - nTotalLines)); - } - out_WriteObject(); - } else { printf - ("Assembly aborted in pass 2 (%ld errors)!\n", - nErrors); - //sym_PrintSymbolTable(); - exit(5); + ("Success! %ld lines in %d.%02d seconds ", + nTotalLines, (int) timespent, + ((int) (timespent * 100.0)) % 100); + if (timespent == 0) + printf + ("(INFINITY lines/minute)\n"); + else + printf("(%d lines/minute)\n", + (int) (60 / timespent * + nTotalLines)); } + out_WriteObject(); } else { - fprintf(stderr, - "Unterminated IF construct (%ld levels)!\n", - nIFDepth); - exit(1); + printf + ("Assembly aborted in pass 2 (%ld errors)!\n", + nErrors); + //sym_PrintSymbolTable(); + exit(5); } } else { - fprintf(stderr, - "Assembly aborted in pass 1 (%ld errors)!\n", - nErrors); - exit(1); + errx(1, "Unterminated IF construct (%ld levels)!", + nIFDepth); } } else { - printf("File '%s' not found\n", tzMainfile); - exit(5); + errx(1, "Assembly aborted in pass 1 (%ld errors)!", + nErrors); } - return (0); + return 0; } diff --git a/src/asm/output.c b/src/asm/output.c index 318b5fbc..affd9272 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -18,6 +18,7 @@ #include "asm/main.h" #include "asm/rpn.h" #include "asm/fstack.h" +#include "extern/err.h" #define SECTIONCHUNK 0x4000 @@ -44,6 +45,7 @@ struct PatchSymbol { ULONG ID; struct sSymbol *pSymbol; struct PatchSymbol *pNext; + struct PatchSymbol *pBucketNext; // next symbol in hash table bucket }; struct SectionStackEntry { @@ -57,9 +59,11 @@ struct SectionStackEntry { * */ +struct PatchSymbol *tHashedPatchSymbols[HASHSIZE]; struct Section *pSectionList = NULL, *pCurrentSection = NULL; struct PatchSymbol *pPatchSymbols = NULL; -char tzObjectname[_MAX_PATH]; +struct PatchSymbol **ppPatchSymbolsTail = &pPatchSymbols; +char *tzObjectname; struct SectionStackEntry *pSectionStack = NULL; /* @@ -74,9 +78,7 @@ out_PushSection(void) { struct SectionStackEntry *pSect; - if ((pSect = - (struct SectionStackEntry *) - malloc(sizeof(struct SectionStackEntry))) != NULL) { + if ((pSect = malloc(sizeof(struct SectionStackEntry))) != NULL) { pSect->pSection = pCurrentSection; pSect->pNext = pSectionStack; pSectionStack = pSect; @@ -328,30 +330,30 @@ ULONG addsymbol(struct sSymbol * pSym) { struct PatchSymbol *pPSym, **ppPSym; - ULONG ID = 0; + static ULONG nextID = 0; + ULONG hash; - pPSym = pPatchSymbols; - ppPSym = &(pPatchSymbols); + hash = calchash(pSym->tzName); + ppPSym = &(tHashedPatchSymbols[hash]); - while (pPSym) { - if (pSym == pPSym->pSymbol) - return (pPSym->ID); - ppPSym = &(pPSym->pNext); - pPSym = pPSym->pNext; - ID += 1; + while ((*ppPSym) != NULL) { + if (pSym == (*ppPSym)->pSymbol) + return (*ppPSym)->ID; + ppPSym = &((*ppPSym)->pBucketNext); } - if ((*ppPSym = pPSym = - (struct PatchSymbol *) malloc(sizeof(struct PatchSymbol))) != - NULL) { + if ((*ppPSym = pPSym = malloc(sizeof(struct PatchSymbol))) != NULL) { pPSym->pNext = NULL; + pPSym->pBucketNext = NULL; pPSym->pSymbol = pSym; - pPSym->ID = ID; - return (ID); + pPSym->ID = nextID++; } else fatalerror("No memory for patchsymbol"); - return ((ULONG) - 1); + *ppPatchSymbolsTail = pPSym; + ppPatchSymbolsTail = &(pPSym->pNext); + + return pPSym->ID; } /* * RGBAsm - OUTPUT.C - Outputs an objectfile @@ -386,24 +388,17 @@ addexports(void) struct Patch * allocpatch(void) { - struct Patch *pPatch, **ppPatch; + struct Patch *pPatch; - pPatch = pCurrentSection->pPatches; - ppPatch = &(pCurrentSection->pPatches); - - while (pPatch) { - ppPatch = &(pPatch->pNext); - pPatch = pPatch->pNext; - } - - if ((*ppPatch = pPatch = - (struct Patch *) malloc(sizeof(struct Patch))) != NULL) { - pPatch->pNext = NULL; + if ((pPatch = malloc(sizeof(struct Patch))) != NULL) { + pPatch->pNext = pCurrentSection->pPatches; pPatch->nRPNSize = 0; pPatch->pRPN = NULL; } else fatalerror("No memory for patch"); + pCurrentSection->pPatches = pPatch; + return (pPatch); } /* @@ -473,7 +468,7 @@ createpatch(ULONG type, struct Expression * expr) break; } } - if ((pPatch->pRPN = (UBYTE *) malloc(rpnptr)) != NULL) { + if ((pPatch->pRPN = malloc(rpnptr)) != NULL) { memcpy(pPatch->pRPN, rpnexpr, rpnptr); pPatch->nRPNSize = rpnptr; } @@ -505,9 +500,12 @@ void checkcodesection(SLONG size) { checksection(); - if ((pCurrentSection->nType == SECT_ROM0 - || pCurrentSection->nType == SECT_ROMX) - && (pCurrentSection->nPC + size <= MAXSECTIONSIZE)) { + if (pCurrentSection->nType != SECT_ROM0 && + pCurrentSection->nType != SECT_ROMX) { + errx(1, "Section '%s' cannot contain code or data (not a " + "ROM0 or ROMX)", pCurrentSection->pzName); + } + if (pCurrentSection->nPC + size <= MAXSECTIONSIZE) { if (((pCurrentSection->nPC % SECTIONCHUNK) > ((pCurrentSection->nPC + size) % SECTIONCHUNK)) && (pCurrentSection->nType == SECT_ROM0 @@ -524,8 +522,7 @@ checkcodesection(SLONG size) } return; } else - fatalerror - ("Section can't contain initialized data or section limit exceeded"); + errx(1, "Section '%s' is too big", pCurrentSection->pzName); } /* * RGBAsm - OUTPUT.C - Outputs an objectfile @@ -594,7 +591,7 @@ out_PrepPass2(void) void out_SetFileName(char *s) { - strcpy(tzObjectname, s); + tzObjectname = s; if (CurrentOptions.verbose) { printf("Output filename %s\n", s); } @@ -632,11 +629,8 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, pSect = pSect->pNext; } - if ((*ppSect = - (pSect = - (struct Section *) malloc(sizeof(struct Section)))) != NULL) { - if ((pSect->pzName = - (char *) malloc(strlen(pzName) + 1)) != NULL) { + if ((*ppSect = (pSect = malloc(sizeof(struct Section)))) != NULL) { + if ((pSect->pzName = malloc(strlen(pzName) + 1)) != NULL) { strcpy(pSect->pzName, pzName); pSect->nType = secttype; pSect->nPC = 0; @@ -647,8 +641,7 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, pSect->charmap = NULL; pPatchSymbols = NULL; - if ((pSect->tData = - (UBYTE *) malloc(SECTIONCHUNK)) != NULL) { + if ((pSect->tData = malloc(SECTIONCHUNK)) != NULL) { return (pSect); } else fatalerror("Not enough memory for section"); @@ -918,30 +911,30 @@ out_BinaryFile(char *s) { FILE *f; - fstk_FindFile(s); + f = fstk_FindFile(s); + if (f == NULL) { + err(1, "Unable to open incbin file '%s'", s); + } - if ((f = fopen(s, "rb")) != NULL) { - SLONG fsize; + SLONG fsize; - fseek(f, 0, SEEK_END); - fsize = ftell(f); - fseek(f, 0, SEEK_SET); + fseek(f, 0, SEEK_END); + fsize = ftell(f); + fseek(f, 0, SEEK_SET); - checkcodesection(fsize); + checkcodesection(fsize); - if (nPass == 2) { - SLONG dest = nPC; - SLONG todo = fsize; + if (nPass == 2) { + SLONG dest = nPC; + SLONG todo = fsize; - while (todo--) - pCurrentSection->tData[dest++] = fgetc(f); - } - pCurrentSection->nPC += fsize; - nPC += fsize; - pPCSymbol->nValue += fsize; - fclose(f); - } else - fatalerror("Could not open file '%s': %s", s, strerror(errno)); + while (todo--) + pCurrentSection->tData[dest++] = fgetc(f); + } + pCurrentSection->nPC += fsize; + nPC += fsize; + pPCSymbol->nValue += fsize; + fclose(f); } void @@ -955,36 +948,36 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length) if (length < 0) fatalerror("Number of bytes to read must be greater than zero"); - fstk_FindFile(s); + f = fstk_FindFile(s); + if (f == NULL) { + err(1, "Unable to open included file '%s'", s); + } - if ((f = fopen(s, "rb")) != NULL) { - SLONG fsize; + SLONG fsize; - fseek(f, 0, SEEK_END); - fsize = ftell(f); + fseek(f, 0, SEEK_END); + fsize = ftell(f); - if (start_pos >= fsize) - fatalerror("Specified start position is greater than length of file"); + if (start_pos >= fsize) + fatalerror("Specified start position is greater than length of file"); - if ((start_pos + length) > fsize) - fatalerror("Specified range in INCBIN is out of bounds"); + if ((start_pos + length) > fsize) + fatalerror("Specified range in INCBIN is out of bounds"); - fseek(f, start_pos, SEEK_SET); + fseek(f, start_pos, SEEK_SET); - checkcodesection(length); + checkcodesection(length); - if (nPass == 2) { - SLONG dest = nPC; - SLONG todo = length; + if (nPass == 2) { + SLONG dest = nPC; + SLONG todo = length; - while (todo--) - pCurrentSection->tData[dest++] = fgetc(f); - } - pCurrentSection->nPC += length; - nPC += length; - pPCSymbol->nValue += length; + while (todo--) + pCurrentSection->tData[dest++] = fgetc(f); + } + pCurrentSection->nPC += length; + nPC += length; + pPCSymbol->nValue += length; - fclose(f); - } else - fatalerror("Could not open file '%s': %s", s, strerror(errno)); + fclose(f); } diff --git a/src/asm/rgbasm.1 b/src/asm/rgbasm.1 index 2a7804a0..c31d5507 100644 --- a/src/asm/rgbasm.1 +++ b/src/asm/rgbasm.1 @@ -60,7 +60,6 @@ and .Sh SEE ALSO .Xr rgbds 7 , .Xr rgbfix 1 , -.Xr rgblib 1 , .Xr rgblink 1 , .Xr gbz80 7 .Sh HISTORY diff --git a/src/asm/symbol.c b/src/asm/symbol.c index 82443c85..92adcffa 100644 --- a/src/asm/symbol.c +++ b/src/asm/symbol.c @@ -6,6 +6,7 @@ */ #define _XOPEN_SOURCE 500 +#include #include #include #include @@ -27,7 +28,6 @@ struct sSymbol *tHashedSymbols[HASHSIZE]; struct sSymbol *pScope = NULL; struct sSymbol *pPCSymbol = NULL; struct sSymbol *p_NARGSymbol = NULL; -struct sSymbol *p__LINE__Symbol = NULL; char *currentmacroargs[MAXMACROARGS + 1]; char *newmacroargs[MAXMACROARGS + 1]; char SavedTIME[256]; @@ -45,12 +45,6 @@ Callback_NARG(struct sSymbol * sym) return (i); } -SLONG -Callback__LINE__(struct sSymbol * sym) -{ - sym = sym; - return (nLineNo); -} /* * RGBAsm - SYMBOL.C - Symboltable stuff * @@ -76,10 +70,10 @@ getvaluefield(struct sSymbol * sym) ULONG calchash(char *s) { - ULONG hash = 0; + ULONG hash = 5381; while (*s != 0) - hash += (*s++); + hash = (hash * 33) ^ (*s++); return (hash % HASHSIZE); } @@ -102,8 +96,7 @@ createsymbol(char *s) while ((*ppsym) != NULL) ppsym = &((*ppsym)->pNext); - if (((*ppsym) = - (struct sSymbol *) malloc(sizeof(struct sSymbol))) != NULL) { + if (((*ppsym) = malloc(sizeof(struct sSymbol))) != NULL) { strcpy((*ppsym)->tzName, s); (*ppsym)->nValue = 0; (*ppsym)->nType = 0; @@ -440,6 +433,8 @@ sym_FindMacroArg(SLONG i) if (i == -1) i = MAXMACROARGS + 1; + assert(i-1 >= 0 && + i-1 < sizeof currentmacroargs / sizeof *currentmacroargs); return (currentmacroargs[i - 1]); } @@ -578,8 +573,7 @@ sym_AddString(char *tzSym, char *tzValue) nsym = createsymbol(tzSym); if (nsym) { - if ((nsym->pMacro = - (char *) malloc(strlen(tzValue) + 1)) != NULL) + if ((nsym->pMacro = malloc(strlen(tzValue) + 1)) != NULL) strcpy(nsym->pMacro, tzValue); else fatalerror("No memory for stringequate"); @@ -849,6 +843,10 @@ sym_PrepPass2(void) sym_AddString("__TIME__", SavedTIME); sym_AddString("__DATE__", SavedDATE); sym_AddSet("_RS", 0); + + sym_AddEqu("_NARG", 0); + p_NARGSymbol = findsymbol("_NARG", NULL); + p_NARGSymbol->Callback = Callback_NARG; } /* * RGBAsm - SYMBOL.C - Symboltable stuff @@ -876,11 +874,7 @@ sym_Init(void) sym_AddEqu("_NARG", 0); p_NARGSymbol = findsymbol("_NARG", NULL); p_NARGSymbol->Callback = Callback_NARG; - sym_AddEqu("__LINE__", 0); - p__LINE__Symbol = findsymbol("__LINE__", NULL); - p__LINE__Symbol->Callback = Callback__LINE__; - sym_AddEqu("__ASM__", (SLONG) (atof(ASM_VERSION) * 65536)); sym_AddSet("_RS", 0); if (time(&tod) != -1) { diff --git a/src/asm/yaccprt1.y b/src/asm/yaccprt1.y index 5f008f2f..5f5c4842 100644 --- a/src/asm/yaccprt1.y +++ b/src/asm/yaccprt1.y @@ -24,14 +24,38 @@ extern bool haltnop; char *tzNewMacro; ULONG ulNewMacroSize; -ULONG symvaluetostring( char *dest, char *sym ) +size_t symvaluetostring(char *dest, size_t maxLength, char *sym) { - if( sym_isString(sym) ) - strcpy( dest, sym_GetStringValue(sym) ); - else - sprintf( dest, "$%lX", sym_GetConstantValue(sym) ); + size_t length; - return( strlen(dest) ); + if (sym_isString(sym)) { + char *src = sym_GetStringValue(sym); + size_t i; + + for (i = 0; src[i] != 0; i++) { + if (i >= maxLength) { + fatalerror("Symbol value too long to fit buffer"); + } + dest[i] = src[i]; + } + + length = i; + } else { + ULONG value = sym_GetConstantValue(sym); + int fullLength = snprintf(dest, maxLength + 1, "$%lX", value); + + if (fullLength < 0) { + fatalerror("snprintf encoding error"); + } else { + length = (size_t)fullLength; + + if (length > maxLength) { + fatalerror("Symbol value too long to fit buffer"); + } + } + } + + return length; } ULONG str2int( char *s ) @@ -124,8 +148,7 @@ void copyrept( void ) src=pCurrentBuffer->pBuffer; ulNewMacroSize=len; - if( (tzNewMacro=(char *)malloc(ulNewMacroSize+1))!=NULL ) - { + if ((tzNewMacro = malloc(ulNewMacroSize + 1)) != NULL) { ULONG i; tzNewMacro[ulNewMacroSize]=0; @@ -134,8 +157,7 @@ void copyrept( void ) if( (tzNewMacro[i]=src[i])=='\n' ) nLineNo+=1; } - } - else + } else fatalerror( "No mem for REPT block" ); yyskipbytes( ulNewMacroSize+4 ); @@ -353,8 +375,8 @@ void if_skip_to_endc( void ) %union { - char tzSym[MAXSYMLEN+1]; - char tzString[256]; + char tzSym[MAXSYMLEN + 1]; + char tzString[MAXSTRLEN + 1]; struct Expression sVal; SLONG nConstValue; } diff --git a/src/asm/yaccprt3.y b/src/asm/yaccprt3.y index 90c45070..28ed9d0a 100644 --- a/src/asm/yaccprt3.y +++ b/src/asm/yaccprt3.y @@ -266,10 +266,7 @@ set : T_LABEL T_POP_SET const include : T_POP_INCLUDE string { - if( !fstk_RunInclude($2) ) - { - yyerror("Could not open file '%s' : %s\n", $2, strerror(errno)); - } + fstk_RunInclude($2); } ; diff --git a/src/extern/err.c b/src/extern/err.c new file mode 100644 index 00000000..c6322830 --- /dev/null +++ b/src/extern/err.c @@ -0,0 +1,92 @@ +/* + * Copyright © 2005-2013 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include "extern/err.h" + +#ifndef __MINGW32__ +char *__progname; +#endif + +void rgbds_vwarn(const char *fmt, va_list ap) +{ + fprintf (stderr, "%s: ", __progname); + if (fmt) { + vfprintf(stderr, fmt, ap); + fputs (": ", stderr); + } + perror(0); +} + +void rgbds_vwarnx(const char *fmt, va_list ap) +{ + fprintf (stderr, "%s: ", __progname); + if (fmt) vfprintf(stderr, fmt, ap); + putc('\n', stderr); +} + +void rgbds_verr(int status, const char *fmt, va_list ap) +{ + vwarn(fmt, ap); + exit(status); +} + +void rgbds_verrx(int status, const char *fmt, va_list ap) +{ + vwarnx(fmt, ap); + exit(status); +} + +void rgbds_warn(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} + +void rgbds_warnx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} + +void rgbds_err(int status, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verr(status, fmt, ap); + va_end(ap); +} + +void rgbds_errx(int status, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verrx(status, fmt, ap); + va_end(ap); +} diff --git a/src/extern/strlcat.c b/src/extern/strlcat.c new file mode 100644 index 00000000..ca202404 --- /dev/null +++ b/src/extern/strlcat.c @@ -0,0 +1,55 @@ +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +rgbds_strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/src/extern/strlcpy.c b/src/extern/strlcpy.c new file mode 100644 index 00000000..f20c00c2 --- /dev/null +++ b/src/extern/strlcpy.c @@ -0,0 +1,51 @@ +/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +rgbds_strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} diff --git a/src/fix/main.c b/src/fix/main.c index d1d4a35d..f43f96ba 100644 --- a/src/fix/main.c +++ b/src/fix/main.c @@ -22,6 +22,8 @@ #include #include +#include "extern/err.h" + static void usage(void) { @@ -47,9 +49,7 @@ main(int argc, char *argv[]) usage(); if ((rom = fopen(argv[argc - 1], "rb+")) == NULL) { - fprintf(stderr, "Error opening file %s: \n", argv[argc - 1]); - perror(NULL); - exit(1); + err(1, "Error opening file %s", argv[argc - 1]); } /* @@ -93,9 +93,8 @@ main(int argc, char *argv[]) setid = true; if (strlen(optarg) != 4) { - fprintf(stderr, "Game ID %s must be exactly 4 " - "characters\n", optarg); - exit(1); + errx(1, "Game ID %s must be exactly 4 " + "characters", optarg); } id = optarg; @@ -107,10 +106,8 @@ main(int argc, char *argv[]) setnewlicensee = true; if (strlen(optarg) != 2) { - fprintf(stderr, - "New licensee code %s is not the correct " - "length of 2 characters\n", optarg); - exit(1); + errx(1, "New licensee code %s is not the " + "correct length of 2 characters", optarg); } newlicensee = optarg; @@ -120,15 +117,11 @@ main(int argc, char *argv[]) licensee = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, - "Invalid argument for option 'l'\n"); - exit(1); + errx(1, "Invalid argument for option 'l'"); } if (licensee < 0 || licensee > 0xFF) { - fprintf(stderr, - "Argument for option 'l' must be " - "between 0 and 255\n"); - exit(1); + errx(1, "Argument for option 'l' must be " + "between 0 and 255"); } break; case 'm': @@ -136,15 +129,11 @@ main(int argc, char *argv[]) cartridge = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, - "Invalid argument for option 'm'\n"); - exit(1); + errx(1, "Invalid argument for option 'm'"); } if (cartridge < 0 || cartridge > 0xFF) { - fprintf(stderr, - "Argument for option 'm' must be " - "between 0 and 255\n"); - exit(1); + errx(1, "Argument for option 'm' must be " + "between 0 and 255"); } break; case 'n': @@ -152,15 +141,11 @@ main(int argc, char *argv[]) version = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, - "Invalid argument for option 'n'\n"); - exit(1); + errx(1, "Invalid argument for option 'n'"); } if (version < 0 || version > 0xFF) { - fprintf(stderr, - "Argument for option 'n' must be " - "between 0 and 255\n"); - exit(1); + errx(1, "Argument for option 'n' must be " + "between 0 and 255"); } break; case 'p': @@ -168,15 +153,11 @@ main(int argc, char *argv[]) padvalue = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, - "Invalid argument for option 'p'\n"); - exit(1); + errx(1, "Invalid argument for option 'p'"); } if (padvalue < 0 || padvalue > 0xFF) { - fprintf(stderr, - "Argument for option 'p' must be " - "between 0 and 255\n"); - exit(1); + errx(1, "Argument for option 'p' must be " + "between 0 and 255"); } break; case 'r': @@ -184,14 +165,11 @@ main(int argc, char *argv[]) ramsize = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, - "Invalid argument for option 'r'\n"); + errx(1, "Invalid argument for option 'r'"); } if (ramsize < 0 || ramsize > 0xFF) { - fprintf(stderr, - "Argument for option 'r' must be " - "between 0 and 255\n"); - exit(1); + errx(1, "Argument for option 'r' must be " + "between 0 and 255"); } break; case 's': @@ -201,15 +179,13 @@ main(int argc, char *argv[]) settitle = true; if (strlen(optarg) > 16) { - fprintf(stderr, "Title %s is greater than the " - "maximum of 16 characters\n", optarg); - exit(1); + errx(1, "Title %s is greater than the " + "maximum of 16 characters", optarg); } if (strlen(optarg) == 16) - fprintf(stderr, - "Title %s is 16 chars, it is best " - "to keep it to 15 or fewer\n", optarg); + warnx("Title %s is 16 chars, it is best to " + "keep it to 15 or fewer", optarg); title = optarg; break; @@ -221,8 +197,6 @@ main(int argc, char *argv[]) /* NOTREACHED */ } } - argc -= optind; - argv += optind; /* * Write changes to ROM @@ -315,8 +289,7 @@ main(int argc, char *argv[]) byte |= 1 << 6; if (byte & 0x3F) - fprintf(stderr, - "Color flag conflicts with game title\n"); + warnx("Color flag conflicts with game title"); fseek(rom, 0x143, SEEK_SET); fputc(byte, rom); @@ -353,9 +326,8 @@ main(int argc, char *argv[]) */ if (!setlicensee) - fprintf(stderr, - "You should probably set both '-s' and " - "'-l 0x33'\n"); + warnx("You should probably set both '-s' and " + "'-l 0x33'"); fseek(rom, 0x146, SEEK_SET); fputc(3, rom); @@ -380,6 +352,7 @@ main(int argc, char *argv[]) /* We will pad the ROM to match the size given in the header. */ int romsize, newsize, headbyte; + uint8_t *buf; fseek(rom, 0, SEEK_END); romsize = ftell(rom); newsize = 0x8000; @@ -390,14 +363,17 @@ main(int argc, char *argv[]) headbyte++; } - while (newsize != ftell(rom)) /* ROM needs resizing */ - fputc(padvalue, rom); - if (newsize > 0x800000) /* ROM is bigger than 8MiB */ - fprintf(stderr, "ROM size is bigger than 8MiB\n"); + warnx("ROM size is bigger than 8MiB"); + + buf = malloc(newsize - romsize); + memset(buf, padvalue, newsize - romsize); + fwrite(buf, 1, newsize - romsize, rom); fseek(rom, 0x148, SEEK_SET); fputc(headbyte, rom); + + free(buf); } if (setramsize) { diff --git a/src/fix/rgbfix.1 b/src/fix/rgbfix.1 index 93397993..5db9814c 100644 --- a/src/fix/rgbfix.1 +++ b/src/fix/rgbfix.1 @@ -130,7 +130,6 @@ of the game .Sh SEE ALSO .Xr rgbds 7 , .Xr rgbasm 1 , -.Xr rgblib 1 , .Xr rgblink 1 , .Xr gbz80 7 .Sh HISTORY diff --git a/src/lib/library.c b/src/lib/library.c deleted file mode 100644 index 6f322d9a..00000000 --- a/src/lib/library.c +++ /dev/null @@ -1,306 +0,0 @@ -#include -#include -#include - -#include "lib/types.h" -#include "lib/libwrap.h" - -SLONG -file_Length(FILE * f) -{ - ULONG r, p; - - p = ftell(f); - fseek(f, 0, SEEK_END); - r = ftell(f); - fseek(f, p, SEEK_SET); - - return (r); -} - -SLONG -file_ReadASCIIz(char *b, FILE * f) -{ - SLONG r = 0; - - while ((*b++ = fgetc(f)) != 0) - r += 1; - - return (r + 1); -} - -void -file_WriteASCIIz(char *b, FILE * f) -{ - while (*b) - fputc(*b++, f); - - fputc(0, f); -} - -UWORD -file_ReadWord(FILE * f) -{ - UWORD r; - - r = fgetc(f); - r |= fgetc(f) << 8; - - return (r); -} - -void -file_WriteWord(UWORD w, FILE * f) -{ - fputc(w, f); - fputc(w >> 8, f); -} - -ULONG -file_ReadLong(FILE * f) -{ - ULONG r; - - r = fgetc(f); - r |= fgetc(f) << 8; - r |= fgetc(f) << 16; - r |= fgetc(f) << 24; - - return (r); -} - -void -file_WriteLong(UWORD w, FILE * f) -{ - fputc(w, f); - fputc(w >> 8, f); - fputc(w >> 16, f); - fputc(w >> 24, f); -} - -sLibrary * -lib_ReadLib0(FILE * f, SLONG size) -{ - if (size) { - sLibrary *l = NULL, *first = NULL; - - while (size > 0) { - if (l == NULL) { - l = malloc(sizeof *l); - if (!l) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - - first = l; - } else { - l->pNext = malloc(sizeof *l->pNext); - if (!l->pNext) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - - l = l->pNext; - } - - size -= file_ReadASCIIz(l->tName, f); - l->uwTime = file_ReadWord(f); - size -= 2; - l->uwDate = file_ReadWord(f); - size -= 2; - l->nByteLength = file_ReadLong(f); - size -= 4; - if ((l->pData = malloc(l->nByteLength))) { - fread(l->pData, sizeof(UBYTE), l->nByteLength, - f); - size -= l->nByteLength; - } else { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - - l->pNext = NULL; - } - return (first); - } - return (NULL); -} - -sLibrary * -lib_Read(char *filename) -{ - FILE *f; - - if ((f = fopen(filename, "rb"))) { - SLONG size; - char ID[5]; - - size = file_Length(f); - if (size == 0) { - fclose(f); - return (NULL); - } - fread(ID, sizeof(char), 4, f); - ID[4] = 0; - size -= 4; - - if (strcmp(ID, "XLB0") == 0) { - sLibrary *r; - - r = lib_ReadLib0(f, size); - fclose(f); - printf("Library '%s' opened\n", filename); - return (r); - } else { - fclose(f); - fprintf(stderr, "Not a valid xLib library\n"); - exit(1); - } - } else { - printf - ("Library '%s' not found, it will be created if necessary\n", - filename); - return (NULL); - } -} - -BBOOL -lib_Write(sLibrary * lib, char *filename) -{ - FILE *f; - - if ((f = fopen(filename, "wb"))) { - fwrite("XLB0", sizeof(char), 4, f); - while (lib) { - file_WriteASCIIz(lib->tName, f); - file_WriteWord(lib->uwTime, f); - file_WriteWord(lib->uwDate, f); - file_WriteLong(lib->nByteLength, f); - fwrite(lib->pData, sizeof(UBYTE), lib->nByteLength, f); - lib = lib->pNext; - } - - fclose(f); - printf("Library '%s' closed\n", filename); - return (1); - } - return (0); -} - -sLibrary * -lib_Find(sLibrary * lib, char *filename) -{ - if (strlen(filename) >= MAXNAMELENGTH) { - fprintf(stderr, "Module name too long: %s\n", filename); - exit(1); - } - - while (lib) { - if (strcmp(lib->tName, filename) == 0) - break; - - lib = lib->pNext; - } - - return (lib); -} - -sLibrary * -lib_AddReplace(sLibrary * lib, char *filename) -{ - FILE *f; - - if ((f = fopen(filename, "rb"))) { - sLibrary *module; - - if (strlen(filename) >= MAXNAMELENGTH) { - fprintf(stderr, "Module name too long: %s\n", - filename); - exit(1); - } - - if ((module = lib_Find(lib, filename)) == NULL) { - module = malloc(sizeof *module); - if (!module) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - - module->pNext = lib; - lib = module; - } else { - /* Module already exists */ - free(module->pData); - } - - module->nByteLength = file_Length(f); - strcpy(module->tName, filename); - module->pData = malloc(module->nByteLength); - if (!module->pData) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - - fread(module->pData, sizeof(UBYTE), module->nByteLength, f); - - printf("Added module '%s'\n", filename); - - fclose(f); - } - return (lib); -} - -sLibrary * -lib_DeleteModule(sLibrary * lib, char *filename) -{ - sLibrary **pp, **first; - BBOOL found = 0; - - pp = &lib; - first = pp; - - if (strlen(filename) >= MAXNAMELENGTH) { - fprintf(stderr, "Module name too long: %s\n", filename); - exit(1); - } - - while ((*pp) && (!found)) { - if (strcmp((*pp)->tName, filename) == 0) { - sLibrary *t; - - t = *pp; - - if (t->pData) - free(t->pData); - - *pp = t->pNext; - - free(t); - found = 1; - } - pp = &((*pp)->pNext); - } - - if (!found) { - fprintf(stderr, "Module not found\n"); - exit(1); - } else - printf("Module '%s' deleted from library\n", filename); - - return (*first); -} - -void -lib_Free(sLibrary * lib) -{ - while (lib) { - sLibrary *l; - - if (lib->pData) - free(lib->pData); - - l = lib; - lib = lib->pNext; - free(l); - } -} diff --git a/src/lib/main.c b/src/lib/main.c deleted file mode 100644 index 6c023350..00000000 --- a/src/lib/main.c +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include -#include -#include - -#include "asmotor.h" - -#include "lib/types.h" -#include "lib/library.h" - -/* - * Print the usagescreen - * - */ - -static void -usage(void) -{ - printf("RGBLib v" LIB_VERSION " (part of ASMotor " ASMOTOR_VERSION ")\n\n"); - printf("usage: rgblib file [add | delete | extract | list] [module ...]\n"); - exit(1); -} -/* - * The main routine - * - */ - -int -main(int argc, char *argv[]) -{ - SLONG argn = 0; - char *libname; - - argc -= 1; - argn += 1; - - if (argc >= 2) { - sLibrary *lib; - - lib = lib_Read(libname = argv[argn++]); - argc -= 1; - - if (strcmp(argv[argn], "add") == 0) { - argn += 1; - argc -= 1; - - while (argc) { - lib = lib_AddReplace(lib, argv[argn++]); - argc -= 1; - } - lib_Write(lib, libname); - lib_Free(lib); - } else if (strcmp(argv[argn], "delete") == 0) { - argn += 1; - argc -= 1; - - while (argc) { - lib = - lib_DeleteModule(lib, argv[argn++]); - argc -= 1; - } - lib_Write(lib, libname); - lib_Free(lib); - } else if (strcmp(argv[argn], "extract") == 0) { - argn += 1; - argc -= 1; - - while (argc) { - sLibrary *l; - - l = lib_Find(lib, argv[argn]); - if (l) { - FILE *f; - - if ((f = fopen(argv[argn], "wb"))) { - fwrite(l->pData, - sizeof(UBYTE), - l->nByteLength, - f); - fclose(f); - printf - ("Extracted module '%s'\n", - argv[argn]); - } else { - fprintf(stderr, - "Unable to write module '%s': ", argv[argn]); - perror(NULL); - exit(1); - } - } else { - fprintf(stderr, "Module not found\n"); - exit(1); - } - - argn += 1; - argc -= 1; - } - lib_Free(lib); - } else if (strcmp(argv[argn], "list") == 0) { - argn += 1; - argc -= 1; - - sLibrary *l; - - l = lib; - - while (l) { - printf("%10ld %s\n", - l->nByteLength, - l->tName); - l = l->pNext; - } - } else - usage(); - } else - usage(); - - return (0); -} diff --git a/src/lib/rgblib.1 b/src/lib/rgblib.1 deleted file mode 100644 index 7a53b3d5..00000000 --- a/src/lib/rgblib.1 +++ /dev/null @@ -1,36 +0,0 @@ -.Dd $Mdocdate$ -.Dt RGBLIB 1 -.Os RGBDS Manual -.Sh NAME -.Nm rgblib -.Nd Game Boy library manager -.Sh SYNOPSIS -.Nm rgblib -.Ar library -.Op add | delete | extract | list -.Ar module ... -.Sh DESCRIPTION -The -.Nm -program manages libraries for use with -.Xr rgblink 1 . -.Bl -tag -width Ds -.It add -Add the given modules to the library. -.It delete -Delete the given modules from the library. -.It extract -Extract the given modules from the library. -.It list -List all the modules in the library. -.El -.Sh SEE ALSO -.Xr rgbds 7 , -.Xr rgbasm 1 , -.Xr rgbfix 1 , -.Xr rgblink 1 , -.Xr gbz80 7 -.Sh HISTORY -.Nm -was originally released by Carsten S\(/orensen as part of the ASMotor package, -and was later packaged in RGBDS by Justin Lloyd. diff --git a/src/link/assign.c b/src/link/assign.c index 09b0dc6f..edbefc33 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -1,6 +1,7 @@ #include #include +#include "extern/err.h" #include "link/mylink.h" #include "link/main.h" #include "link/symbol.h" @@ -63,7 +64,6 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) struct sFreeArea *pNewArea; if ((pNewArea = - (struct sFreeArea *) malloc(sizeof(struct sFreeArea))) != NULL) { *pNewArea = *pArea; @@ -77,9 +77,7 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) return (org); } else { - fprintf(stderr, - "Out of memory!\n"); - exit(1); + err(1, NULL); } } } @@ -310,9 +308,7 @@ AssignVRAMSections(void) pSection->oAssigned = 1; DOMAXVBANK(pSection->nBank); } else { - fprintf(stderr, - "Unable to place VRAM section anywhere\n"); - exit(1); + errx(1, "Unable to place VRAM section anywhere"); } } } @@ -331,9 +327,7 @@ AssignSRAMSections(void) pSection->oAssigned = 1; DOMAXSBANK(pSection->nBank); } else { - fprintf(stderr, - "Unable to place SRAM section anywhere\n"); - exit(1); + errx(1, "Unable to place SRAM section anywhere"); } } } @@ -352,9 +346,7 @@ AssignWRAMSections(void) pSection->oAssigned = 1; DOMAXWBANK(pSection->nBank); } else { - fprintf(stderr, - "Unable to place WRAMX section anywhere\n"); - exit(1); + errx(1, "Unable to place WRAMX section anywhere"); } } } @@ -373,9 +365,7 @@ AssignCodeSections(void) pSection->oAssigned = 1; DOMAXBANK(pSection->nBank); } else { - fprintf(stderr, - "Unable to place ROMX section anywhere\n"); - exit(1); + errx(1, "Unable to place ROMX section anywhere"); } } } @@ -397,8 +387,7 @@ AssignSections(void) BankFree[i] = malloc(sizeof *BankFree[i]); if (!BankFree[i]) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } if (i == 0) { @@ -472,10 +461,9 @@ AssignSections(void) if (area_AllocAbs (&BankFree[BANK_WRAM0], pSection->nOrg, pSection->nByteSize) != pSection->nOrg) { - fprintf(stderr, - "Unable to load fixed WRAM0 section " - "at $%lX\n", pSection->nOrg); - exit(1); + errx(1, + "Unable to load fixed WRAM0 " + "section at $%lX", pSection->nOrg); } pSection->oAssigned = 1; pSection->nBank = BANK_WRAM0; @@ -484,10 +472,8 @@ AssignSections(void) if (area_AllocAbs (&BankFree[BANK_HRAM], pSection->nOrg, pSection->nByteSize) != pSection->nOrg) { - fprintf(stderr, "Unable to load fixed " - "HRAM section at $%lX\n", - pSection->nOrg); - exit(1); + errx(1, "Unable to load fixed HRAM " + "section at $%lX", pSection->nOrg); } pSection->oAssigned = 1; pSection->nBank = BANK_HRAM; @@ -530,17 +516,15 @@ AssignSections(void) pSection->nOrg, pSection->nByteSize) != pSection->nOrg) { - fprintf(stderr, -"Unable to load fixed SRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, +"Unable to load fixed SRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } DOMAXVBANK(pSection-> nBank); pSection->oAssigned = 1; } else { - fprintf(stderr, -"Unable to load fixed SRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, +"Unable to load fixed SRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } } } @@ -583,17 +567,15 @@ AssignSections(void) pSection->nOrg, pSection->nByteSize) != pSection->nOrg) { - fprintf(stderr, -"Unable to load fixed WRAMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, +"Unable to load fixed WRAMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } DOMAXWBANK(pSection-> nBank); pSection->oAssigned = 1; } else { - fprintf(stderr, -"Unable to load fixed WRAMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, +"Unable to load fixed WRAMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } } } @@ -636,17 +618,15 @@ AssignSections(void) pSection->nOrg, pSection->nByteSize) != pSection->nOrg) { - fprintf(stderr, -"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, +"Unable to load fixed VRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } DOMAXVBANK(pSection-> nBank); pSection->oAssigned = 1; } else { - fprintf(stderr, -"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, +"Unable to load fixed VRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } } } @@ -655,10 +635,8 @@ AssignSections(void) if (area_AllocAbs (&BankFree[BANK_ROM0], pSection->nOrg, pSection->nByteSize) != pSection->nOrg) { - fprintf(stderr, "Unable to load fixed " - "ROM0 section at $%lX\n", - pSection->nOrg); - exit(1); + errx(1, "Unable to load fixed ROM0 " + "section at $%lX", pSection->nOrg); } pSection->oAssigned = 1; pSection->nBank = BANK_ROM0; @@ -703,15 +681,15 @@ AssignSections(void) pSection-> nByteSize) != pSection->nOrg) { - fprintf(stderr, "Unable to load fixed ROMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, + "Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } DOMAXBANK(pSection-> nBank); pSection->oAssigned = 1; } else { - fprintf(stderr, "Unable to load fixed ROMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); - exit(1); + errx(1, + "Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank); } } @@ -737,14 +715,13 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed ROMX section into bank $%02lX\n", pSection->nBank); - exit(1); + errx(1, + "Unable to load fixed ROMX section into bank $%02lX", pSection->nBank); } pSection->oAssigned = 1; DOMAXBANK(pSection->nBank); } else { - fprintf(stderr, "Unable to load fixed ROMX section into bank $%02lX\n", pSection->nBank); - exit(1); + errx(1, "Unable to load fixed ROMX section into bank $%02lX", pSection->nBank); } } else if (pSection->oAssigned == 0 && pSection->Type == SECT_SRAM @@ -755,14 +732,12 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed SRAM section into bank $%02lX\n", pSection->nBank); - exit(1); + errx(1, "Unable to load fixed SRAM section into bank $%02lX", pSection->nBank); } pSection->oAssigned = 1; DOMAXSBANK(pSection->nBank); } else { - fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank); - exit(1); + errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank); } } else if (pSection->oAssigned == 0 && pSection->Type == SECT_VRAM @@ -773,14 +748,12 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank); - exit(1); + errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank); } pSection->oAssigned = 1; DOMAXVBANK(pSection->nBank); } else { - fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank); - exit(1); + errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank); } } else if (pSection->oAssigned == 0 && pSection->Type == SECT_WRAMX @@ -791,14 +764,12 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed WRAMX section into bank $%02lX\n", pSection->nBank - BANK_WRAMX); - exit(1); + errx(1, "Unable to load fixed WRAMX section into bank $%02lX", pSection->nBank - BANK_WRAMX); } pSection->oAssigned = 1; DOMAXWBANK(pSection->nBank); } else { - fprintf(stderr, "Unable to load fixed WRAMX section into bank $%02lX\n", pSection->nBank - BANK_WRAMX); - exit(1); + errx(1, "Unable to load fixed WRAMX section into bank $%02lX", pSection->nBank - BANK_WRAMX); } } pSection = pSection->pNext; @@ -820,8 +791,7 @@ AssignSections(void) area_AllocAbsROMXAnyBank(pSection->nOrg, pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed ROMX section at $%lX into any bank\n", pSection->nOrg); - exit(1); + errx(1, "Unable to load fixed ROMX section at $%lX into any bank", pSection->nOrg); } pSection->oAssigned = 1; DOMAXBANK(pSection->nBank); @@ -834,8 +804,7 @@ AssignSections(void) area_AllocAbsVRAMAnyBank(pSection->nOrg, pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed VRAM section at $%lX into any bank\n", pSection->nOrg); - exit(1); + errx(1, "Unable to load fixed VRAM section at $%lX into any bank", pSection->nOrg); } pSection->oAssigned = 1; DOMAXVBANK(pSection->nBank); @@ -848,8 +817,7 @@ AssignSections(void) area_AllocAbsSRAMAnyBank(pSection->nOrg, pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed SRAM section at $%lX into any bank\n", pSection->nOrg); - exit(1); + errx(1, "Unable to load fixed SRAM section at $%lX into any bank", pSection->nOrg); } pSection->oAssigned = 1; DOMAXSBANK(pSection->nBank); @@ -862,8 +830,7 @@ AssignSections(void) area_AllocAbsWRAMAnyBank(pSection->nOrg, pSection->nByteSize)) == -1) { - fprintf(stderr, "Unable to load fixed WRAMX section at $%lX into any bank\n", pSection->nOrg); - exit(1); + errx(1, "Unable to load fixed WRAMX section at $%lX into any bank", pSection->nOrg); } pSection->oAssigned = 1; DOMAXWBANK(pSection->nBank); @@ -885,8 +852,7 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[BANK_WRAM0], pSection->nByteSize)) == -1) { - fprintf(stderr, "WRAM0 section too large\n"); - exit(1); + errx(1, "WRAM0 section too large"); } pSection->nBank = BANK_WRAM0; pSection->oAssigned = 1; @@ -895,8 +861,7 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[BANK_HRAM], pSection->nByteSize)) == -1) { - fprintf(stderr, "HRAM section too large\n"); - exit(1); + errx(1, "HRAM section too large"); } pSection->nBank = BANK_HRAM; pSection->oAssigned = 1; @@ -911,8 +876,7 @@ AssignSections(void) if ((pSection->nOrg = area_Alloc(&BankFree[BANK_ROM0], pSection->nByteSize)) == -1) { - fprintf(stderr, "ROM0 section too large\n"); - exit(1); + errx(1, "ROM0 section too large"); } pSection->nBank = BANK_ROM0; pSection->oAssigned = 1; @@ -920,8 +884,7 @@ AssignSections(void) case SECT_ROMX: break; default: - fprintf(stderr, "(INTERNAL) Unknown section type!\n"); - exit(1); + errx(1, "(INTERNAL) Unknown section type!"); break; } } diff --git a/src/link/library.c b/src/link/library.c index 9e847c55..e49d7671 100644 --- a/src/link/library.c +++ b/src/link/library.c @@ -2,6 +2,7 @@ #include #include +#include "extern/err.h" #include "link/types.h" #include "link/mylink.h" #include "link/main.h" @@ -91,9 +92,8 @@ AddNeededModules(void) } if (options & OPT_SMART_C_LINK) { if (!addmodulecontaining(smartlinkstartsymbol)) { - fprintf(stderr, "Can't find start symbol '%s'\n", + errx(1, "Can't find start symbol '%s'", smartlinkstartsymbol); - exit(1); } else printf("Smart linking with symbol '%s'\n", smartlinkstartsymbol); diff --git a/src/link/main.c b/src/link/main.c index a5e54b60..2507bb56 100644 --- a/src/link/main.c +++ b/src/link/main.c @@ -4,8 +4,7 @@ #include #include -#include "asmotor.h" - +#include "extern/err.h" #include "link/object.h" #include "link/output.h" #include "link/assign.h" @@ -34,9 +33,7 @@ char smartlinkstartsymbol[256]; static void usage(void) { - printf("RGBLink v" LINK_VERSION " (part of ASMotor " ASMOTOR_VERSION - ")\n\n"); - printf("usage: rgblink [-t] [-l library] [-m mapfile] [-n symfile] [-o outfile]\n"); + printf("usage: rgblink [-t] [-m mapfile] [-n symfile] [-o outfile]\n"); printf("\t [-s symbol] [-z pad_value] objectfile [...]\n"); exit(1); @@ -58,9 +55,6 @@ main(int argc, char *argv[]) while ((ch = getopt(argc, argv, "l:m:n:o:p:s:t")) != -1) { switch (ch) { - case 'l': - lib_Readfile(optarg); - break; case 'm': SetMapfileName(optarg); break; @@ -73,8 +67,7 @@ main(int argc, char *argv[]) case 'p': fillchar = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { - fprintf(stderr, "Invalid argument for option 'p'\n"); - exit(1); + errx(1, "Invalid argument for option 'p'"); } if (fillchar < 0 || fillchar > 0xFF) { fprintf(stderr, "Argument for option 'p' must be between 0 and 0xFF"); diff --git a/src/link/mapfile.c b/src/link/mapfile.c index f953afe5..1264d7c3 100644 --- a/src/link/mapfile.c +++ b/src/link/mapfile.c @@ -3,8 +3,7 @@ #include #include -#include "asmotor.h" - +#include "extern/err.h" #include "link/main.h" #include "link/mylink.h" #include "link/assign.h" @@ -20,9 +19,7 @@ SetMapfileName(char *name) mf = fopen(name, "w"); if (mf == NULL) { - fprintf(stderr, "Cannot open mapfile '%s': ", name); - perror(NULL); - exit(1); + err(1, "Cannot open mapfile '%s'", name); } } @@ -32,11 +29,10 @@ SetSymfileName(char *name) sf = fopen(name, "w"); if (sf == NULL) { - fprintf(stderr, "Cannot open symfile '%s'\n", name); - exit(1); + err(1, "Cannot open symfile '%s'", name); } - fprintf(sf, ";File generated by xLink v" LINK_VERSION "\n\n"); + fprintf(sf, ";File generated by rgblink\n\n"); } void diff --git a/src/link/object.c b/src/link/object.c index 9a45b74b..d216425d 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -8,6 +8,7 @@ #include #include +#include "extern/err.h" #include "link/mylink.h" #include "link/main.h" @@ -80,8 +81,7 @@ AllocSection(void) *ppSections = malloc(sizeof **ppSections); if (!*ppSections) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } (*ppSections)->tSymbols = tSymbols; (*ppSections)->pNext = NULL; @@ -102,15 +102,13 @@ obj_ReadSymbol(FILE * f) pSym = malloc(sizeof *pSym); if (!pSym) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } readasciiz(s, f); pSym->pzName = malloc(strlen(s) + 1); if (!pSym->pzName) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } strcpy(pSym->pzName, s); @@ -150,7 +148,7 @@ obj_ReadRGB0Section(FILE * f) if (pSection->nByteSize) { pSection->pData = malloc(pSection->nByteSize); if (!pSection->pData) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } SLONG nNumberOfPatches; @@ -169,7 +167,7 @@ obj_ReadRGB0Section(FILE * f) while (nNumberOfPatches--) { pPatch = malloc(sizeof *pPatch); if (!pPatch) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } *ppPatch = pPatch; @@ -177,7 +175,7 @@ obj_ReadRGB0Section(FILE * f) pPatch->pzFilename = malloc(strlen(s) + 1); if (!pPatch->pzFilename) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } strcpy(pPatch->pzFilename, s); @@ -193,8 +191,7 @@ obj_ReadRGB0Section(FILE * f) if ((pPatch->nRPNSize = readlong(f)) > 0) { pPatch->pRPN = malloc(pPatch->nRPNSize); if (!pPatch->pRPN) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } fread(pPatch->pRPN, sizeof(UBYTE), @@ -228,8 +225,7 @@ obj_ReadRGB0(FILE * pObjfile) if (nNumberOfSymbols) { tSymbols = malloc(nNumberOfSymbols * sizeof(struct sSymbol *)); if (!tSymbols) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } for (i = 0; i < nNumberOfSymbols; i += 1) @@ -305,8 +301,7 @@ obj_ReadRGB1Section(FILE * f) if (pSection->nByteSize) { pSection->pData = malloc(pSection->nByteSize); if (!pSection->pData) { - fprintf(stderr, "Out of memory!\n"); - exit(1); + err(1, NULL); } SLONG nNumberOfPatches; @@ -325,14 +320,14 @@ obj_ReadRGB1Section(FILE * f) while (nNumberOfPatches--) { pPatch = malloc(sizeof *pPatch); if (!pPatch) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } *ppPatch = pPatch; readasciiz(s, f); pPatch->pzFilename = malloc(strlen(s) + 1); if (!pPatch->pzFilename) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } strcpy(pPatch->pzFilename, s); @@ -342,7 +337,7 @@ obj_ReadRGB1Section(FILE * f) if ((pPatch->nRPNSize = readlong(f)) > 0) { pPatch->pRPN = malloc(pPatch->nRPNSize); if (!pPatch->pRPN) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } fread(pPatch->pRPN, sizeof(UBYTE), @@ -376,7 +371,7 @@ obj_ReadRGB1(FILE * pObjfile) if (nNumberOfSymbols) { tSymbols = malloc(nNumberOfSymbols * sizeof *tSymbols); if (!tSymbols) { - fprintf(stderr, "Out of memory!\n"); + err(1, NULL); } for (i = 0; i < nNumberOfSymbols; i += 1) @@ -440,14 +435,10 @@ obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile) obj_ReadRGB1(pObjfile); break; default: - fprintf(stderr, "'%s' is an unsupported version", - tzObjectfile); - exit(1); - break; + errx(1, "'%s' is an unsupported version", tzObjectfile); } } else { - fprintf(stderr, "'%s' is not a valid object\n", tzObjectfile); - exit(1); + errx(1, "'%s' is not a valid object", tzObjectfile); } } @@ -463,10 +454,7 @@ obj_Readfile(char *tzObjectfile) pObjfile = fopen(tzObjectfile, "rb"); if (pObjfile == NULL) { - fprintf(stderr, "Unable to open object '%s': ", - tzObjectfile); - perror(NULL); - exit(1); + err(1, "Unable to open object '%s'", tzObjectfile); } obj_ReadOpenFile(pObjfile, tzObjectfile); fclose(pObjfile); @@ -506,34 +494,3 @@ lib_ReadXLB0(FILE * f) obj_ReadOpenFile(f, name); } } - -void -lib_Readfile(char *tzLibfile) -{ - FILE *pObjfile; - - oReadLib = 1; - - pObjfile = fopen(tzLibfile, "rb"); - if (pObjfile == NULL) { - fprintf(stderr, "Unable to open object '%s': ", tzLibfile); - perror(NULL); - exit(1); - } - if (!pObjfile) { - fprintf(stderr, "Unable to open '%s'\n", tzLibfile); - exit(1); - } - char tzHeader[5]; - - fread(tzHeader, sizeof(char), 4, pObjfile); - tzHeader[4] = 0; - if (strcmp(tzHeader, "XLB0") == 0) - lib_ReadXLB0(pObjfile); - else { - fprintf(stderr, "'%s' is an invalid library\n", - tzLibfile); - exit(1); - } - fclose(pObjfile); -} diff --git a/src/link/output.c b/src/link/output.c index f849bb1d..7adfc8f1 100644 --- a/src/link/output.c +++ b/src/link/output.c @@ -7,8 +7,7 @@ #include "link/main.h" #include "link/assign.h" -char tzOutname[_MAX_PATH]; -BBOOL oOutput = 0; +char *tzOutname; void writehome(FILE * f) @@ -71,8 +70,7 @@ writebank(FILE * f, SLONG bank) void out_Setname(char *tzOutputfile) { - strcpy(tzOutname, tzOutputfile); - oOutput = 1; + tzOutname = tzOutputfile; } void diff --git a/src/link/patch.c b/src/link/patch.c index 822a7c24..d9376586 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -2,6 +2,7 @@ #include #include +#include "extern/err.h" #include "link/mylink.h" #include "link/symbol.h" #include "link/main.h" @@ -46,8 +47,7 @@ getsymvalue(SLONG symid) default: break; } - fprintf(stderr, "*INTERNAL* UNKNOWN SYMBOL TYPE\n"); - exit(1); + errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE"); } SLONG @@ -64,8 +64,7 @@ getsymbank(SLONG symid) default: break; } - fprintf(stderr, "*INTERNAL* UNKNOWN SYMBOL TYPE\n"); - exit(1); + errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE"); } SLONG @@ -159,20 +158,18 @@ calcrpn(struct sPatch * pPatch) t = rpnpop(); rpnpush(t & 0xFF); if (t < 0 || (t > 0xFF && t < 0xFF00) || t > 0xFFFF) { - fprintf(stderr, - "%s(%ld) : Value must be in the HRAM area\n", + errx(1, + "%s(%ld) : Value must be in the HRAM area", pPatch->pzFilename, pPatch->nLineNo); - exit(1); } break; case RPN_PCEZP: t = rpnpop(); rpnpush(t & 0xFF); if (t < 0x2000 || t > 0x20FF) { - fprintf(stderr, - "%s(%ld) : Value must be in the ZP area\n", + errx(1, + "%s(%ld) : Value must be in the ZP area", pPatch->pzFilename, pPatch->nLineNo); - exit(1); } break; case RPN_CONST: @@ -217,11 +214,10 @@ calcrpn(struct sPatch * pPatch) high |= (*rpn++) << 24; t = rpnpop(); if (t < low || t > high) { - fprintf(stderr, - "%s(%ld) : Value must be in the range [%ld;%ld]\n", + errx(1, + "%s(%ld) : Value must be in the range [%ld;%ld]", pPatch->pzFilename, pPatch->nLineNo, low, high); - exit(1); } rpnpush(t); size -= 8; @@ -255,11 +251,10 @@ Patch(void) pSect->pData[pPatch->nOffset] = (UBYTE) t; } else { - fprintf(stderr, - "%s(%ld) : Value must be 8-bit\n", + errx(1, + "%s(%ld) : Value must be 8-bit", pPatch->pzFilename, pPatch->nLineNo); - exit(1); } break; case PATCH_WORD_L: @@ -280,11 +275,10 @@ Patch(void) 1] = t & 0xFF; } } else { - fprintf(stderr, - "%s(%ld) : Value must be 16-bit\n", + errx(1, + "%s(%ld) : Value must be 16-bit", pPatch->pzFilename, pPatch->nLineNo); - exit(1); } break; case PATCH_LONG_L: diff --git a/src/link/rgblink.1 b/src/link/rgblink.1 index 8c350450..64eee3d0 100644 --- a/src/link/rgblink.1 +++ b/src/link/rgblink.1 @@ -29,12 +29,6 @@ option to override this. .Pp The arguments are as follows: .Bl -tag -width Ds -.It Fl l Ar library -Include a referenced library module created with -.Xr rgblib 1 . -Note that specified libraries will be included only if needed\(emthat is, if -a SECTION from a library is referenced by an object file. -Only the relevant SECTION will be included, rather than the entire module. .It Fl m Ar mapfile Write a mapfile to the given filename. .It Fl n Ar symfile @@ -70,7 +64,6 @@ to fix these so that the program will actually run in a Game Boy: .Xr rgbds 7 , .Xr rgbasm 1 , .Xr rgbfix 1 , -.Xr rgblib 1 , .Xr gbz80 7 .Sh HISTORY .Nm diff --git a/src/link/symbol.c b/src/link/symbol.c index ee696cc5..6f5cc9cc 100644 --- a/src/link/symbol.c +++ b/src/link/symbol.c @@ -2,6 +2,7 @@ #include #include +#include "extern/err.h" #include "link/main.h" #include "link/patch.h" #include "link/types.h" @@ -53,8 +54,7 @@ sym_GetValue(char *tzName) } } - fprintf(stderr, "Unknown symbol '%s'\n", tzName); - exit(1); + errx(1, "Unknown symbol '%s'", tzName); } } @@ -72,8 +72,7 @@ sym_GetBank(char *tzName) } } - fprintf(stderr, "Unknown symbol '%s'\n", tzName); - exit(1); + errx(1, "Unknown symbol '%s'", tzName); } void @@ -93,10 +92,7 @@ sym_CreateSymbol(char *tzName, SLONG nValue, SBYTE nBank) if (nBank == -1) return; - fprintf(stderr, - "Symbol '%s' defined more than once\n", - tzName); - exit(1); + errx(1, "Symbol '%s' defined more than once", tzName); } } diff --git a/src/rgbds.7 b/src/rgbds.7 index 28dcde59..72ed881c 100644 --- a/src/rgbds.7 +++ b/src/rgbds.7 @@ -13,7 +13,6 @@ To get a working ROM image from a single assembly source file: .Sh SEE ALSO .Xr rgbasm 1 , .Xr rgbfix 1 , -.Xr rgblib 1 , .Xr rgblink 1 , .Xr gbz80 7 .Sh HISTORY