summaryrefslogtreecommitdiff
path: root/bcc
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-03-24 17:45:55 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:29:43 +0200
commitfe22c37817ce338fbbc90b239320248c270957fa (patch)
treed9550410c4a20bdd382fcc58d2d3d7c5e04e5245 /bcc
parenta7aba15e8efffb1c5d3097656f1a93955a64f01f (diff)
parent42192453ea219b80d0bf9f41e51e36d3d4d0740b (diff)
downloaddev86-fe22c37817ce338fbbc90b239320248c270957fa.tar.gz
Import Dev86-0.0.4.tar.gzv0.0.4
Diffstat (limited to 'bcc')
-rw-r--r--bcc/6809/const.h52
-rw-r--r--bcc/Makefile43
-rw-r--r--bcc/align.h16
-rw-r--r--bcc/assign.c387
-rw-r--r--bcc/bcc-cc1.c25
-rw-r--r--bcc/bcc.bugs169
-rw-r--r--bcc/bcc.c961
-rw-r--r--bcc/bcc.c.gnu983
-rw-r--r--bcc/bcc.doc177
-rw-r--r--bcc/byteord.h13
-rw-r--r--bcc/codefrag.c1843
-rw-r--r--bcc/condcode.h16
-rw-r--r--bcc/const.h52
-rw-r--r--bcc/debug.c202
-rw-r--r--bcc/declare.c1124
-rw-r--r--bcc/express.c466
-rw-r--r--bcc/exptree.c1087
-rw-r--r--bcc/floatop.c173
-rw-r--r--bcc/function.c413
-rw-r--r--bcc/gencode.c736
-rw-r--r--bcc/gencode.h101
-rw-r--r--bcc/genloads.c1255
-rw-r--r--bcc/glogcode.c560
-rw-r--r--bcc/hardop.c510
-rw-r--r--bcc/input.c771
-rw-r--r--bcc/input.h37
-rw-r--r--bcc/label.c429
-rw-r--r--bcc/label.h24
-rw-r--r--bcc/loadexp.c180
-rw-r--r--bcc/longop.c169
-rw-r--r--bcc/misc/sformat56
-rw-r--r--bcc/misc/test/8queens.pas33
-rw-r--r--bcc/misc/test/8queens.t74
-rw-r--r--bcc/misc/test/atol.t29
-rw-r--r--bcc/misc/test/bigsievec.t29
-rw-r--r--bcc/misc/test/bt.t373
-rw-r--r--bcc/misc/test/cast.t144
-rw-r--r--bcc/misc/test/cast1.t144
-rw-r--r--bcc/misc/test/castest.t74
-rw-r--r--bcc/misc/test/ctype.t38
-rw-r--r--bcc/misc/test/error.t78
-rw-r--r--bcc/misc/test/extern.t236
-rw-r--r--bcc/misc/test/hilbert.t169
-rw-r--r--bcc/misc/test/longtest.c24
-rw-r--r--bcc/misc/test/longtest.dat15
-rwxr-xr-xbcc/misc/test/longtest.mak3
-rwxr-xr-xbcc/misc/test/longtest.sh4
-rw-r--r--bcc/misc/test/miniltest.t72
-rw-r--r--bcc/misc/test/op1.t120
-rw-r--r--bcc/misc/test/opcmp.t106
-rw-r--r--bcc/misc/test/oplong.t264
-rw-r--r--bcc/misc/test/opplus.t122
-rw-r--r--bcc/misc/test/opsoft.t259
-rw-r--r--bcc/misc/test/puzzle.t178
-rw-r--r--bcc/misc/test/sierpin.t123
-rw-r--r--bcc/misc/test/sievec.t28
-rw-r--r--bcc/misc/test/sievecp.t45
-rw-r--r--bcc/misc/test/sievei.t28
-rw-r--r--bcc/misc/test/sort.t104
-rw-r--r--bcc/misc/test/stdio.t87
-rw-r--r--bcc/os.h78
-rw-r--r--bcc/output.c813
-rw-r--r--bcc/output.h14
-rw-r--r--bcc/parse.h19
-rw-r--r--bcc/preproc.c944
-rw-r--r--bcc/preserve.c216
-rw-r--r--bcc/proto.h397
-rw-r--r--bcc/reg.h139
-rw-r--r--bcc/sc.h27
-rw-r--r--bcc/scan.c806
-rw-r--r--bcc/scan.h201
-rw-r--r--bcc/sizes.h50
-rw-r--r--bcc/softop.c225
-rw-r--r--bcc/state.c793
-rw-r--r--bcc/table.c668
-rw-r--r--bcc/table.h71
-rw-r--r--bcc/tags341
-rw-r--r--bcc/type.c203
-rw-r--r--bcc/type.h98
-rw-r--r--bcc/types.h206
80 files changed, 22342 insertions, 0 deletions
diff --git a/bcc/6809/const.h b/bcc/6809/const.h
new file mode 100644
index 0000000..559680c
--- /dev/null
+++ b/bcc/6809/const.h
@@ -0,0 +1,52 @@
+/* const.h - constants for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* switches for code generation */
+
+#define DEBUG /* generate compiler-debugging code */
+/*#define I8088*/ /* target processor is Intel 8088 thru 80386 */
+#define MC6809 /* target processor is Motorola 6809 */
+#define SELFTYPECHECK /* check calculated type = runtime type */
+
+#ifdef I8088
+# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */
+# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */
+# define HOLDSTRINGS /* hold strings for dumping at end
+ * since assembler has only 1 data seg */
+#endif
+
+#ifdef MC6809
+# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */
+# define OP1 /* logical operators only use 1 byte */
+# define POSINDEPENDENT /* position indep code can (also) be gen */
+#endif
+
+/* switches for source and target operating system dependencies */
+
+/*#define SOS_EDOS*/ /* source O/S is EDOS */
+/*#define SOS_MSDOS*/ /* source O/S is MSDOS */
+#define TOS_EDOS /* target O/S is EDOS */
+
+/* switches for source machine dependencies */
+
+#ifndef SOS_EDOS
+# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */
+#endif
+
+#ifndef SOS_MSDOS /* need portable alignment for large model */
+# define UNPORTABLE_ALIGNMENT
+#endif
+
+/* local style */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
diff --git a/bcc/Makefile b/bcc/Makefile
new file mode 100644
index 0000000..eec2f83
--- /dev/null
+++ b/bcc/Makefile
@@ -0,0 +1,43 @@
+#
+# bcc Makefile
+# $Id$
+#
+BCCDEFS=-DLOCALPREFIX="\"/usr\"" -DDEFARCH=0
+
+ifneq ($(TOPDIR),)
+include $(TOPDIR)/Make.defs
+BCCDEFS=-DLOCALPREFIX="\"$(BCCHOME)\"" -DDEFARCH=0
+else
+CC=bcc
+LDFLAGS=-s
+endif
+
+OBJS = bcc-cc1.o codefrag.o debug.o declare.o express.o exptree.o floatop.o \
+ function.o gencode.o genloads.o glogcode.o hardop.o input.o label.o \
+ loadexp.o longop.o output.o preproc.o preserve.o scan.o softop.o \
+ state.o table.o type.o assign.o
+
+all: bcc bcc-cc1
+
+install: all
+ install -d $(LIBDIR)
+ install -m 755 bcc $(BINDIR)/bcc
+ install -m 755 bcc-cc1 $(LIBDIR)/bcc-cc1
+
+bcc: bcc.o
+ $(CC) -ansi $(LDFLAGS) bcc.o -o $@
+
+bcc.o: bcc.c
+ $(CC) -ansi $(CFLAGS) $(BCCDEFS) -c bcc.c
+
+bcc09: bcc.o
+ $(CC) -DMC6809 bcc.o $(LDFLAGS) -o $@
+
+ccc: bcc.o
+ $(CC) -DCCC bcc.o $(LDFLAGS) -o $@
+
+bcc-cc1: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o bcc-cc1
+
+clean:
+ rm -f bcc bcc-cc1 bcc09 ccc bcc.o $(OBJS)
diff --git a/bcc/align.h b/bcc/align.h
new file mode 100644
index 0000000..3c8971b
--- /dev/null
+++ b/bcc/align.h
@@ -0,0 +1,16 @@
+/* align.h - memory alignment requirements for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifndef S_ALIGNMENT
+# define align(x) (x)
+#else
+# ifdef UNPORTABLE_ALIGNMENT
+typedef unsigned pointerint_t;
+# define align(x) (((pointerint_t) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))
+# else
+# define align(x) ((char *) (x) + (- (int) (x) & (S_ALIGNMENT-1)))
+# endif
+#endif
+
+extern uoffset_t alignmask; /* general alignment mask */
diff --git a/bcc/assign.c b/bcc/assign.c
new file mode 100644
index 0000000..ebbc1fc
--- /dev/null
+++ b/bcc/assign.c
@@ -0,0 +1,387 @@
+/* assign.c - assignment and casting operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void blockmove P((struct symstruct *source, struct symstruct *target));
+FORWARD void call3 P((char *funcname, struct symstruct *target,
+ struct symstruct *source, uoffset_t size));
+FORWARD void fconvert P((struct symstruct *source, struct typestruct *type));
+
+PUBLIC void assign(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regpushed;
+ store_pt sourcereg;
+ scalar_t tscalar;
+
+ if (target->type->constructor & (ARRAY | FUNCTION) ||
+ target->flags == TEMP || target->flags == (LABELLED | STRING) ||
+ (target->indcount == 0 && target->flags != REGVAR))
+ {
+ bugerror("botched lvalue");
+ return;
+ }
+ if (source->storage != target->storage
+ || source->indcount != target->indcount
+ || source->level != target->level
+ || source->offset.offi != target->offset.offi /* kludge union cmp */
+ || source->type != target->type
+ || ((source->storage & (LOCAL | GLOBAL)
+ || source->level == OFFKLUDGELEVEL)
+ && ((source->flags ^ target->flags) & LABELLED
+ || (source->flags & LABELLED
+ && source->name.label != target->name.label)
+ || (!(source->flags & LABELLED)
+ && strcmp(source->name.namep, target->name.namep) != 0))))
+ {
+ tscalar = target->type->scalar;
+ if (tscalar & CHAR && source->storage == CONSTANT)
+ {
+ source->offset.offv &= CHMASKTO;
+ source->type = target->type;
+ }
+ regpushed = preslval(source, target);
+ if (!(tscalar & CHAR) || source->flags != TEMP ||
+ source->offset.offi != sp || source->type->typesize > itypesize)
+ cast(target->type, source);
+ if (tscalar & RSCALAR)
+ {
+ if (source->storage == CONSTANT && (!reguse & doubleregs))
+ load(source, doubleregs & ~DREG);
+ if (source->storage != CONSTANT && source->indcount == 0)
+ {
+ /* XXX - 386 only */
+ storereg(DREG, target);
+ if (tscalar & DOUBLE)
+ {
+ target->indcount = 1; /* XXX - outnnadr clobbers this */
+ target->offset.offi += accregsize;
+ storereg(doubleregs & ~DREG, target);
+ }
+ target->storage = source->storage;
+ target->offset.offi = 0;
+ }
+ else if (f_indirect(source) && tscalar & DOUBLE
+ && (!(reguse & OPREG) || target->storage == OPREG))
+ {
+ struct symstruct temptarg;
+
+ temptarg = *target;
+ pointat(&temptarg);
+ call("Fpull");
+ outntypechar(temptarg.type);
+ sp += dtypesize;
+ }
+ else
+ blockmove(source, target);
+ }
+ else if (target->type->constructor & STRUCTU)
+ blockmove(source, target);
+ else
+ {
+ if (tscalar & CHAR)
+ load(source, DREG);
+ else if (target->indcount == 0 && target->storage & regregs)
+ load(source, target->storage);
+ else
+ loadany(source);
+ if (tscalar & DLONG)
+ {
+ storereg(DREG, target);
+ target->indcount = 1;
+ target->offset.offi += accregsize;
+ }
+ if ((store_t) (sourcereg = source->storage) == DREG &&
+ target->type->scalar & CHAR)
+ sourcereg = BREG;
+ storereg(sourcereg, target);
+ if ((store_t) regpushed != 0)
+ {
+ /* DLONG */
+ target->indcount = 1;
+ target->offset.offi -= accregsize;
+ recovlist(regpushed);
+ }
+ else
+ {
+ target->storage = sourcereg;
+ target->offset.offi = 0;
+ if (target->level == OFFKLUDGELEVEL)
+ target->level = EXPRLEVEL;
+ }
+ }
+ }
+}
+
+/* block move assumes itypesize == accregsize && BREG size == 1 */
+
+PRIVATE void blockmove(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ struct symstruct oldtarget;
+ uoffset_t typesize;
+ struct symstruct worksource;
+
+ oldtarget = *target;
+ if ((typesize = target->type->typesize) >= 16 * itypesize ||
+ source->indcount + target->indcount != 2)
+ {
+ address(source);
+ address(target);
+ call3("_memcpy", target, source, typesize);
+ }
+ else
+ {
+ if (source->level == OFFKLUDGELEVEL)
+ addoffset(source); /* else kludge is lost and offsets big */
+ if (target->level == OFFKLUDGELEVEL)
+ addoffset(target);
+ worksource = *source;
+ for (; typesize >= itypesize; typesize -= itypesize)
+ {
+ loadreg(source, DREG);
+ worksource.offset.offi += itypesize;
+ *source = worksource;
+ storereg(DREG, target);
+ target->indcount = 1;
+ target->offset.offi += accregsize;
+ }
+ while (typesize-- != 0)
+ {
+ outload();
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ worksource.offset.offi += 1;
+ *source = worksource;
+ storereg(BREG, target);
+ target->indcount = 1;
+ target->offset.offi += 1;
+ }
+ }
+ *target = oldtarget;
+}
+
+PRIVATE void call3(funcname, target, source, size)
+char *funcname;
+struct symstruct *target;
+struct symstruct *source;
+uoffset_t size;
+{
+ store_pt regpushed;
+ offset_t spmark;
+ struct symstruct *length;
+
+ pushlist(regpushed = reguse & ~calleemask);
+ spmark = sp;
+ length = constsym((value_t) size);
+ length->type = uitype;
+ push(length);
+ push(source);
+ push(target);
+ call(funcname);
+ outnl();
+ if (regpushed)
+ {
+ modstk(spmark);
+ recovlist(regpushed);
+ }
+}
+
+PUBLIC void cast(type, target)
+struct typestruct *type;
+struct symstruct *target;
+{
+ scalar_t newscalar;
+ uoffset_t newsize;
+ scalar_t oldscalar;
+ uoffset_t oldsize;
+ store_pt targreg;
+
+ if (type->constructor & (ARRAY | FUNCTION)
+ || (type->constructor & STRUCTU && target->type != type))
+ {
+ bugerror("botched implicit cast");
+ return;
+ }
+ if (target->type == type)
+ return;
+ if (target->type->constructor == ARRAY)
+ oldsize = ptypesize;
+ else
+ oldsize = target->type->typesize;
+ newscalar = type->scalar;
+ oldscalar = target->type->scalar;
+ if ((newsize = type->typesize) == oldsize &&
+ !((newscalar | oldscalar) & RSCALAR))
+ ;
+ else if (newsize == ctypesize) /* char only */
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (target->indcount == 1)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+# if BIG_ENDIAN
+ target->offset.offi += oldsize - ctypesize;
+# else
+ {
+ if (oldscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+# endif
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+# if BIG_ENDIAN
+ target->offset.offi += ctypesize;
+# else
+ ;
+# endif
+#endif
+ }
+ else if (target->storage != CONSTANT)
+ {
+ load(target, DREG);
+ target->storage = BREG;
+ }
+ }
+ else if ((newscalar & (SHORT | INT | LONG) && !(newscalar & DLONG))
+ || type->constructor & POINTER)
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (oldsize < newsize)
+ extend(target);
+ else if (target->indcount == 1)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ if (oldscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+#endif
+ }
+ else
+ load(target, DREG);
+ }
+ else if (newscalar & DLONG)
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (target->storage != CONSTANT)
+ {
+ extend(target);
+ load(target, DREG);
+ target->storage = targreg = getindexreg();
+ if (oldscalar & (UNSIGNED | CHAR) ||
+ target->type->constructor & (ARRAY | FUNCTION | POINTER))
+ uitol(targreg);
+ else
+ itol(targreg);
+ }
+ }
+ else if (newscalar & RSCALAR)
+ {
+ saveopreg(); /* XXX */
+ if (oldscalar & (ISCALAR | FLOAT))
+ fpush(target);
+ if (newscalar & FLOAT)
+ {
+ pointat(target);
+ call("dto");
+ outntypechar(type);
+ justpushed(target); /* XXX - sets dtype wrong (harmless) and
+ * wastes (dtypesize - ftypesize) stack */
+ }
+ restoreopreg();
+ }
+ target->type = type;
+}
+
+/* extend char or short to int (unsigned if from unsigned) */
+
+PUBLIC void extend(target)
+struct symstruct *target;
+{
+ scalar_t tscalar;
+
+ if ((tscalar = target->type->scalar) & (CHAR | SHORT))
+ {
+ if (target->storage != CONSTANT &&
+ target->type->typesize < itypesize)
+ {
+ load(target, DREG);
+ if (target->type == sctype)
+ sctoi();
+#ifdef I8088
+ else if (tscalar & SHORT)
+ {
+ if (tscalar & UNSIGNED)
+ ustoi();
+ else
+ stoi();
+ }
+#endif
+ else
+ ctoi();
+ target->storage = DREG;
+ }
+ if (tscalar & UNSIGNED)
+ target->type = uitype;
+ else
+ target->type = itype;
+ }
+}
+
+PRIVATE void fconvert(source, type)
+struct symstruct *source;
+struct typestruct *type;
+{
+ offset_t spmark;
+
+ pushlist(reguse & OPREG);
+ spmark = sp;
+ pointat(source);
+ if (source->type->scalar & DOUBLE)
+ call("dto");
+ else
+ call("fto");
+ if (type->scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(type);
+ if (type->scalar & DLONG)
+ {
+ if (reguse & OPREG)
+ bugerror("loading long into used reg");
+ source->storage = OPREG;
+ }
+ else if (type->scalar & CHAR)
+ source->storage = BREG;
+ else
+ source->storage = DREG;
+ source->offset.offi =
+ source->flags =
+ source->indcount = 0;
+ modstk(spmark); /* could adjust later (load instead of pop) */
+ poplist(reguse & OPREG);
+}
diff --git a/bcc/bcc-cc1.c b/bcc/bcc-cc1.c
new file mode 100644
index 0000000..d6fece3
--- /dev/null
+++ b/bcc/bcc-cc1.c
@@ -0,0 +1,25 @@
+/* bcc-cc1.c - "pass 1" for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ growheap(0); /* init order is important */
+ syminit();
+ etreeinit();
+ ifinit();
+ predefine();
+ openio(argc, argv);
+ codeinit();
+ typeinit();
+ program();
+ finishup();
+
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/bcc/bcc.bugs b/bcc/bcc.bugs
new file mode 100644
index 0000000..52f6958
--- /dev/null
+++ b/bcc/bcc.bugs
@@ -0,0 +1,169 @@
+compiler limitations
+--------------------
+
+These are not implemented:
+
+a. bit fields
+ kludgily implemented (everything padded to char, int or long; can store
+ values wider than the specified field width)
+
+g. signed char type, other ANSI extensions
+
+compiler bugs
+-------------
+
+6. weird but doable casts are not always done for initializers
+
+15. calls to a (casted) absolute address produce an immediate prefix. as386
+ doesn't mind this but complains about the absolute address. as09 complains
+ about the prefix but can handle the absolute address
+
+23. char *f(); &f() is accepted as f() but produces botched nodetype
+ (calc char **).
+
+31. null byte in string initialiser should be ignored if it doesn't fit
+ Non-null bytes which don't fit should be ignored with a warning
+
+32. static char c = "xyz"; is allowed, and bad FCB is generated
+
+37. init of union will store multiple comma-separated entries
+
+38. arrays sizes larger than the amount of memory are accepted
+
+40. structure and union definitions are confused with each other. So
+ struct foo may be used in a declaration like "union foo bar;"
+
+42. pointer arithmetic is performed on pointers to undefined structures
+ (of unknown size). Size is taken as 0 although alignmask is set early
+
+59. preprocessor stuff (# lines or macro names) between the identifier for
+ a label and the colon for the label messes up the label
+
+60. some things involving switches are now broken for 6809 due to lack of
+ frame pointer
+
+61. assembler may get lost on lines of length exactly (?) 256
+
+65. expressions in emum lists or not properly checked for overflow. They
+ should fit in ints. The ordinal number is allowed to overflow
+
+66. sizeof has type int instead of size_t
+
+68. "return expr;" in a function returning a void is reported as a compiler
+ bug not as a semantic error
+
+69. an argument declared as float is (correctly) promoted to double, but
+ not demoted to float when it is used
+
+71. identifiers longer than 64 are botched (scanning of the identifier is
+ stopped but the remaining characters in the identifier are left to
+ mess up the input stream
+
+72. check for too many macro parameters is not working
+
+74. union { char a, b; } foo; gives the wrong offset for b. Unions work OK
+ if the declaration lists have length 1
+
+75. stack gets cleaned up too early in bee = foo ? bar : baz() where baz()
+ returns a struct although there is kludge to make plain bee = baz() work
+
+76. have reintroduced reduced-type bugs, so sizeof(1 ? 1 : 2) is 1
+
+78. fix to require comma in arg list may be half-baked
+
+79. compiler starts trying to load the void expression (i ? (void)0 : (void)0)
+
+80. (unsigned char *) - (char *) causes error and message is obscure
+
+81. 'defined' is a reserved word
+
+82. conditionals with voids don't work
+
+83. float = 1e100 gets overflow exception
+
+84. #endif seems to be seen in
+#if 1
+foo #endif bar
+
+85. line numbers from cpp are not quite right.
+
+bugs that may be fixed
+----------------------
+
+41. typedef's are not scoped properly
+
+nonstandard things that are not done quite right
+------------------------------------------------
+
+3. arguments declared as register are not being dumped by #asm, register
+ vars anyway not being passed to #asm
+
+26. should clear label ptrs when starting #asm
+
+things that have to be be done better
+-------------------------------------
+
+11. push order reversed in genloads.c (temp) - might try to get DP order right
+
+12. need to clean up handling of sc specs (maybe rename flags to sc)
+ And local statics and externs
+
+24. gvarsc is not returned properly for struct/union since the members
+ affect gvarsc (incorrectly). There should be a flag set when
+ inside a struct/union definition to disable sc specs. This could
+ replace the tests in abdeclarator and declselt
+ Best may be to carry the sc along with the type a bit more (in a
+ global symbol structure). Also, the symbol should record sc in a better
+ way than now
+
+25. need to check stack sometimes. Xenix cc does it when allocating >= 100
+ bytes locals and this is essential in Xenix as the stack is grown
+ dynamically
+
+68. overflow checking for constants
+
+things that could be done better
+--------------------------------
+
+4. install new 6809 code for branch patching (after redundancy checks)
+
+5. can improve code for compare with global adr in non-posindependent case
+
+6. char *s; long *pl;
+ code for *s += *pl is poor, for *s += (int) *pl is good
+
+7. most mov's from to ax would be faster and smaller done by xchg's
+
+7a. check ptr add/sub operations earlier
+
+8. tests for against 1 and -1 can sometimes be done with dec's and inc's
+
+9. __opreg is used unnec when the ptr is already in it
+
+9a. double indirect ptrs should maybe be made direct rather than singly
+ indirect by makelessindirect
+
+10. in cmpsmallconst(), the comparison constant should be incorporated in
+ the offset if the indcount is 0 and lea() called. It is harmless to
+ use the lea() trick for non-small constants
+
+20. when saved registers are popped in assign() they may overwrite the
+ expression value, anywhere else? May be fixed now
+
+27. better if loadexpression returned the register used
+
+28. better if source.c did not #include storage.h - it only references
+ DEFINITION, in some blank-skipping code which could be moved to
+ scan.c or preproc.c. preproc.c, scan.c and type.c also #include
+ storage.h, just to get at the DEFINITION and KEYWORD definitions
+
+29. need nodetype() to know about all optimisations in advance, including
+ int % small power of 2 (including 0, 1). Need to delete all type
+ assignments in final code gen, specially the one that convert short
+ to int
+
+30. overflow checking at runtime
+
+31. Use more than the first char from multiple character constants
+
+56. --i++ is not detected as an error in the parser
diff --git a/bcc/bcc.c b/bcc/bcc.c
new file mode 100644
index 0000000..810cbcb
--- /dev/null
+++ b/bcc/bcc.c
@@ -0,0 +1,961 @@
+/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define _POSIX_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FALSE 0
+#define FORWARD static
+#define NUL_PTR ((void*)0)
+#define PRIVATE static
+#define PUBLIC
+#define TRUE 1
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#define AS "as86"
+#define BAS86
+#define BCC86
+#define CC1 "bcc-cc1"
+#define CC1_MINUS_O_BROKEN FALSE
+#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
+#define CPPFLAGS "-E"
+#define CRT0 "crt0.o"
+#define GCC "gcc"
+#define LD "ld86"
+#ifndef NO_ANSI_SUPPORT
+#define UNPROTO "unproto"
+#endif
+#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/"
+#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/"
+#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/"
+#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/"
+#define DEFAULT_INCLUDE "-I" LOCALPREFIX "/include"
+#define DEFAULT_LIBDIR0 "-L" LOCALPREFIX "/lib/bcc/i86/"
+#define DEFAULT_LIBDIR3 "-L" LOCALPREFIX "/lib/bcc/i386/"
+
+#ifdef CCC
+#undef BCC86
+#undef CC1
+#define CC1 "c386"
+#undef CC1_MINUS_O_BROKEN
+#define CC1_MINUS_O_BROKEN TRUE
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#define STANDARD_CRT0_PREFIX "/usr/local/lib/i386/"
+#endif /* CCC */
+
+#ifdef MC6809
+#undef BAS86
+#undef BCC86
+#undef CRT0
+#undef GCC
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/"
+#endif /* MC6809 */
+
+#define ALLOC_UNIT 16 /* allocation unit for arg arrays */
+#define DIRCHAR '/'
+#define START_ARGS 4 /* number of reserved args */
+
+typedef unsigned char bool_T; /* boolean: TRUE if nonzero */
+
+struct arg_s
+{
+ char *prog;
+ bool_T minus_O_broken;
+ int argc;
+ char **argv;
+ unsigned nr_allocated;
+};
+
+struct prefix_s
+{
+ char *name;
+ struct prefix_s *next;
+};
+
+PRIVATE struct arg_s asargs = { AS, };
+PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, };
+PRIVATE struct arg_s cppargs = { CPP, };
+#ifndef NO_ANSI_SUPPORT
+PRIVATE struct arg_s unprotoargs = { UNPROTO, TRUE };
+#endif
+#ifdef STANDARD_CRT0_PREFIX
+PRIVATE struct prefix_s crt0_prefix = { STANDARD_CRT0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_0_PREFIX
+PRIVATE struct prefix_s crt0_0_prefix = { STANDARD_CRT0_0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_3_PREFIX
+PRIVATE struct prefix_s crt0_3_prefix = { STANDARD_CRT0_3_PREFIX, };
+#endif
+PRIVATE struct prefix_s exec_prefix;
+PRIVATE struct arg_s ldargs = { LD, };
+#ifdef BAS86
+PRIVATE struct arg_s ldrargs = { LD, };
+#endif
+PRIVATE char *progname;
+PRIVATE bool_T runerror; /* = FALSE */
+PRIVATE struct arg_s tmpargs; /* = empty */
+PRIVATE char *tmpdir;
+PRIVATE unsigned verbosity; /* = 0 */
+
+#ifdef REDECLARE_STDC_FUNCTIONS
+void exit P((int status));
+char *getenv P((const char *name));
+void *malloc P((size_t size));
+void *realloc P((void *ptr, size_t size));
+void (*signal P((int sig, void (*func) P((int sig))))) P((int sig));
+char *strcpy P((char *dest, const char *src));
+size_t strlen P((const char *s));
+char *strrchr P((const char *s, int c));
+#endif
+
+#ifdef REDECLARE_POSIX_FUNCTIONS
+int access P((const char *path, int amode));
+int execv P((const char *path, char * const *argv));
+pid_t fork P((void));
+pid_t getpid P((void));
+int unlink P((const char *path));
+pid_t wait P((int *status));
+ssize_t write P((int fd, const void *buf, size_t nbytes));
+#endif
+
+int main P((int argc, char **argv));
+
+FORWARD void addarg P((struct arg_s *argp, char *arg));
+FORWARD void addprefix P((struct prefix_s *prefix, char *name));
+FORWARD void fatal P((char *message));
+FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode));
+FORWARD void killtemps P((void));
+FORWARD void *my_malloc P((unsigned size, char *where));
+FORWARD char *my_mktemp P((void));
+FORWARD void my_unlink P((char *name));
+FORWARD void outofmemory P((char *where));
+FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp));
+FORWARD void set_trap P((void));
+FORWARD void show_who P((char *message));
+FORWARD void startarg P((struct arg_s *argp));
+FORWARD char *stralloc P((char *s));
+FORWARD char *stralloc2 P((char *s1, char *s2));
+FORWARD void trap P((int signum));
+FORWARD void unsupported P((char *option, char *message));
+FORWARD void writen P((void));
+FORWARD void writes P((char *s));
+FORWARD void writesn P((char *s));
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ int add_default_inc = 1;
+ int add_default_lib = 1;
+ int argcount = argc;
+ bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone");
+ bool_T as_only = FALSE;
+ char *basename;
+#ifdef BCC86
+#ifdef DEFARCH
+ bool_T bits32 = (DEFARCH != 0);
+#else
+ bool_T bits32 = sizeof (char *) >= 4;
+#endif
+ char *bits_arg;
+#endif
+ bool_T cc_only = FALSE;
+#ifndef NO_ANSI_SUPPORT
+ bool_T ansi_pass = FALSE;
+#endif
+#ifdef CCC
+ bool_T cpp_pass = TRUE;
+#else
+ bool_T cpp_pass = FALSE;
+#endif
+#ifdef BCC86
+ char *crt0;
+#endif
+ bool_T debug = FALSE;
+ bool_T echo = FALSE;
+ unsigned errcount = 0;
+ char ext;
+ char *f_out = NUL_PTR;
+ bool_T float_emulation = FALSE;
+#ifdef BAS86
+ bool_T gnu_objects = FALSE;
+#endif
+ char *in_name;
+ int length;
+ unsigned ncisfiles = 0;
+ unsigned nifiles = 0;
+ unsigned npass_specs;
+ bool_T optimize = FALSE;
+ char *out_name;
+ bool_T profile = FALSE;
+ bool_T prep_only = FALSE;
+ bool_T prep_line_numbers = FALSE;
+ int status;
+ char *temp;
+
+ progname = argv[0];
+ addarg(&cppargs, CPPFLAGS);
+#ifdef CCC
+ addarg(&asargs, "-j");
+#endif
+ addarg(&asargs, "-u");
+ addarg(&asargs, "-w");
+#ifdef BCC86
+ addarg(&ldargs, "-i");
+#endif
+#ifdef BAS86
+ addarg(&ldrargs, "-r");
+#endif
+
+ /* Pass 1 over argv to gather compile options. */
+ for (; --argc != 0;)
+ {
+ arg = *++argv;
+ *++argdone = TRUE;
+ if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0)
+ switch (arg[1])
+ {
+#ifdef BCC86
+ case '0':
+ bits32 = FALSE;
+ break;
+ case '3':
+ bits32 = TRUE;
+ break;
+#endif
+ case 'E':
+ prep_only = prep_line_numbers = cpp_pass = TRUE;
+ break;
+#ifdef BAS86
+ case 'G':
+ gnu_objects = TRUE;
+ break;
+#endif
+ case 'P':
+ prep_only = cpp_pass = TRUE;
+ prep_line_numbers = FALSE;
+ break;
+ case 'O':
+ optimize = TRUE; /* unsupported( arg, "optimize" ); */
+ break;
+ case 'S':
+ cc_only = TRUE;
+ break;
+ case 'V':
+ echo = TRUE;
+ break;
+ case 'c':
+ as_only = TRUE;
+ break;
+ case 'e':
+ cpp_pass = TRUE;
+ break;
+ case 'f':
+ float_emulation = TRUE;
+ ++errcount;
+ unsupported(arg, "float emulation");
+ break;
+ case 'g':
+ debug = TRUE; /* unsupported( arg, "debug" ); */
+ break;
+ case 'o':
+ if (--argc < 1)
+ {
+ ++errcount;
+ show_who("output file missing after -o\n");
+ }
+ else
+ {
+ if (f_out != NUL_PTR)
+ show_who("more than one output file\n");
+ f_out = *++argv;
+ *++argdone = TRUE;
+ }
+ break;
+ case 'p':
+ profile = TRUE;
+ ++errcount;
+ unsupported(arg, "profile");
+ break;
+ case 'v':
+ ++verbosity;
+ break;
+ case 'I':
+ add_default_inc = 0;
+ break;
+ case 'L':
+ add_default_lib = 0;
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else if (arg[0] == '-')
+ switch (arg[1])
+ {
+#ifndef NO_ANSI_SUPPORT
+ case 'a':
+ if (!strcmp(arg, "-ansi"))
+ {
+ ansi_pass=TRUE;
+ cpp_pass=TRUE;
+#ifndef CCC
+ /* NOTE I'm setting this to zero, this isn't a _real_ STDC */
+ addarg(&ccargs, "-D__STDC__=0");
+#endif
+ addarg(&cppargs, "-D__STDC__=0");
+#endif
+ }
+ break;
+ case 'A':
+ addarg(&asargs, arg + 2);
+ break;
+ case 'B':
+ addprefix(&exec_prefix, arg + 2);
+ break;
+ case 'C':
+ addarg(&ccargs, arg + 2);
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+#ifndef CCC
+ addarg(&ccargs, arg);
+#endif
+ addarg(&cppargs, arg);
+ break;
+ case 'X':
+ addarg(&ldargs, arg + 2);
+ break;
+ case 'L':
+ addarg(&ldargs, arg);
+ break;
+ case 'P':
+ addarg(&cppargs, arg + 2);
+ break;
+ case 'Q':
+ addarg(&ccargs, arg);
+ break;
+ case 'T':
+ tmpdir = arg + 2;
+ break;
+ case 't':
+ ++errcount;
+ unsupported(arg, "pass number");
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else
+ {
+ ++nifiles;
+ *argdone = FALSE;
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ ++ncisfiles;
+ }
+ }
+ npass_specs = prep_only + cc_only + as_only;
+ if (npass_specs != 0)
+ {
+ if (npass_specs > 1)
+ {
+ ++errcount;
+ show_who("more than 1 option from -E -P -S -c\n");
+ }
+ if (f_out != NUL_PTR && ncisfiles > 1)
+ {
+ ++errcount;
+ show_who("cannot have more than 1 input with non-linked output\n");
+ }
+ }
+ if (nifiles == 0)
+ {
+ ++errcount;
+ show_who("no input files\n");
+ }
+ if (errcount != 0)
+ exit(1);
+
+ if ((temp = getenv("BCC_EXEC_PREFIX")) != NUL_PTR)
+ addprefix(&exec_prefix, temp);
+ if( add_default_inc )
+ {
+#ifndef CCC
+ addarg(&ccargs, DEFAULT_INCLUDE);
+#endif
+ addarg(&cppargs, DEFAULT_INCLUDE);
+ }
+ if( add_default_lib )
+ {
+#ifdef BCC86
+ if( bits32 )
+ addarg(&ldargs, DEFAULT_LIBDIR3);
+ else
+#endif
+ addarg(&ldargs, DEFAULT_LIBDIR0);
+ }
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2);
+ cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK);
+ ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK);
+ asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK);
+ ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK);
+ ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK);
+#ifndef NO_ANSI_SUPPORT
+ unprotoargs.prog=fixpath(unprotoargs.prog, &exec_prefix, X_OK);
+#endif
+ if (tmpdir == NUL_PTR && (tmpdir = getenv("TMPDIR")) == NUL_PTR)
+ tmpdir = "/tmp";
+
+ if (prep_only && !prep_line_numbers)
+ addarg(&cppargs, "-P");
+#ifdef BCC86
+ if (bits32)
+ {
+ bits_arg = "-3";
+ crt0 = fixpath(CRT0, &crt0_3_prefix, R_OK);
+ }
+ else
+ {
+ bits_arg = "-0";
+ crt0 = fixpath(CRT0, &crt0_0_prefix, R_OK);
+ }
+ addarg(&ccargs, bits_arg);
+ addarg(&cppargs, bits_arg);
+ addarg(&asargs, bits_arg);
+#ifdef BAS86
+ if (!gnu_objects)
+ {
+ addarg(&ldargs, bits_arg);
+ addarg(&ldrargs, bits_arg);
+ /* addarg(&ldargs, crt0);*/
+ addarg(&ldargs, "-C0");
+ }
+#endif /* BAS86 */
+#endif /* BCC86 */
+#if defined(BAS86) && !defined(BCC86)
+ if (!gnu_objects)
+ addarg(&ldargs, fixpath(CRT0, &crt0_prefix, R_OK));
+#endif
+ set_trap();
+
+ /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and
+ * gather arguments for linker.
+ */
+ for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;)
+ {
+ arg = *++argv;
+ if (!*++argdone)
+ {
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ {
+ if (echo || verbosity != 0)
+ {
+ writes(arg);
+ writesn(":");
+ }
+ if ((basename = strrchr(arg, DIRCHAR)) == NUL_PTR)
+ basename = arg;
+ else
+ ++basename;
+ in_name = arg;
+ if (ext == 'c')
+ {
+ if (cpp_pass)
+ {
+#ifndef NO_ANSI_SUPPORT
+ if (prep_only && !ansi_pass)
+#else
+ if (prep_only)
+#endif
+ out_name = f_out;
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+#ifndef NO_ANSI_SUPPORT
+ if (ansi_pass)
+ {
+ if (prep_only)
+ out_name = f_out;
+ else
+ out_name = my_mktemp();
+
+ if (run(in_name, out_name, &unprotoargs) != 0)
+ continue;
+ in_name=out_name;
+ }
+#endif
+ }
+ ext = 'i';
+ }
+ if (ext == 'i')
+ {
+ if (prep_only)
+ continue;
+ if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &ccargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 'S')
+ {
+ if (prep_only)
+ out_name = f_out;
+ else if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 's')
+ {
+ if (prep_only || cc_only)
+ continue;
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ if (as_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ addarg(&asargs, "-n");
+ arg[length - 1] = 's';
+ addarg(&asargs, arg);
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ char *tmp_out_name;
+
+ tmp_out_name = my_mktemp();
+ status = run(in_name, tmp_out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ if (run(tmp_out_name, out_name, &ldrargs) != 0)
+ continue;
+ }
+ else
+#endif
+ {
+ status = run(in_name, out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ }
+ ext = 'o';
+ in_name = out_name;
+ }
+ if (ext == 'o')
+ {
+ if (prep_only || cc_only || as_only)
+ continue;
+ addarg(&ldargs, in_name);
+ }
+ }
+ else
+ addarg(&ldargs, arg);
+ }
+ }
+
+ if (!prep_only && !cc_only && !as_only && !runerror)
+ {
+ if (f_out == NUL_PTR)
+ f_out = "a.out";
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ /* Remove -i and -i-. */
+ for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc)
+ {
+ arg = ldargs.argv[argc];
+ if (arg[0] == '-' && arg[1] == 'i'
+ && (arg[2] == 0 || (arg[2] == '-' && arg[3] == 0)))
+ {
+ --ldargs.argc;
+ memmove(ldargs.argv + argc, ldargs.argv + argc + 1,
+ (ldargs.argc - argc) * sizeof ldargs.argv[0]);
+ ldargs.argv[ldargs.argc] = NUL_PTR;
+ }
+ }
+
+ ldargs.prog = fixpath(GCC, &exec_prefix, X_OK);
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ else
+#endif
+ {
+ addarg(&ldargs, "-lc");
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ }
+ killtemps();
+ return runerror ? 1 : 0;
+}
+
+PRIVATE void addarg(argp, arg)
+register struct arg_s *argp;
+char *arg;
+{
+ int new_argc;
+ char **new_argv;
+
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ new_argc = argp->argc + 1;
+ if (new_argc >= argp->nr_allocated)
+ {
+ argp->nr_allocated += ALLOC_UNIT;
+ new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv);
+ if (new_argv == NUL_PTR)
+ outofmemory("addarg");
+ argp->argv = new_argv;
+ }
+ argp->argv[argp->argc] = arg;
+ argp->argv[argp->argc = new_argc] = NUL_PTR;
+}
+
+PRIVATE void addprefix(prefix, name)
+struct prefix_s *prefix;
+char *name;
+{
+ struct prefix_s *new_prefix;
+
+ if (prefix->name == NUL_PTR)
+ prefix->name = name;
+ else
+ {
+ new_prefix = my_malloc(sizeof *new_prefix, "addprefix");
+ new_prefix->name = name;
+ new_prefix->next = NUL_PTR;
+ while (prefix->next != NUL_PTR)
+ prefix = prefix->next;
+ prefix->next = new_prefix;
+ }
+}
+
+PRIVATE void fatal(message)
+char *message;
+{
+ writesn(message);
+ killtemps();
+ exit(1);
+}
+
+PRIVATE char *fixpath(path, prefix, mode)
+char *path;
+struct prefix_s *prefix;
+int mode;
+{
+ char *ppath;
+
+ for (; prefix != NUL_PTR; prefix = prefix->next)
+ {
+ if (verbosity > 2)
+ {
+ show_who("searching for ");
+ if (mode == R_OK)
+ writes("readable file ");
+ else
+ writes("executable file ");
+ writes(path);
+ writes(" in ");
+ writesn(prefix->name);
+ }
+ ppath = stralloc2(prefix->name, path);
+ if (access(ppath, mode) == 0)
+ return ppath;
+ free(ppath);
+ }
+ return path;
+}
+
+PRIVATE void killtemps()
+{
+ while (tmpargs.argc > START_ARGS)
+ my_unlink(tmpargs.argv[--tmpargs.argc]);
+}
+
+PRIVATE void *my_malloc(size, where)
+unsigned size;
+char *where;
+{
+ void *block;
+
+ if ((block = malloc(size)) == NUL_PTR)
+ outofmemory(where);
+ return block;
+}
+
+PRIVATE char *my_mktemp()
+{
+ char *p;
+ unsigned digit;
+ unsigned digits;
+ char *template;
+ static unsigned tmpnum;
+
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX");
+ p += strlen(p);
+
+ digits = getpid();
+ while (*--p == 'X')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p = digit + '0';
+ digits /= 16;
+ }
+ digits = tmpnum;
+ while (*p == 'Y')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p-- = digit + '0';
+ digits /= 16;
+ }
+ ++tmpnum;
+ addarg(&tmpargs, template);
+ return template;
+}
+
+PRIVATE void my_unlink(name)
+char *name;
+{
+ if (verbosity > 1)
+ {
+ show_who("unlinking ");
+ writesn(name);
+ }
+ if (unlink(name) < 0)
+ {
+ show_who("error unlinking ");
+ writesn(name);
+ }
+}
+
+PRIVATE void outofmemory(where)
+char *where;
+{
+ show_who("out of memory in ");
+ fatal(where);
+}
+
+PRIVATE int run(in_name, out_name, argp)
+char *in_name;
+char *out_name;
+struct arg_s *argp;
+{
+ int arg0;
+ int i;
+ int status;
+
+ arg0 = 0;
+ if (in_name == NUL_PTR)
+ ++arg0;
+ if (out_name == NUL_PTR)
+ arg0 += 2;
+ else if (argp->minus_O_broken)
+ ++arg0;
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ argp->argv[arg0] = argp->prog;
+ i = arg0 + 1;
+ if (in_name != NUL_PTR)
+ argp->argv[i++] = in_name;
+ if (out_name != NUL_PTR)
+ {
+ if (!argp->minus_O_broken)
+ argp->argv[i++] = "-o";
+ argp->argv[i++] = out_name;
+ }
+ if (verbosity != 0)
+ {
+ for (i = arg0; i < argp->argc; ++i)
+ {
+ writes(argp->argv[i]);
+ writes(" ");
+ }
+ writen();
+ }
+ switch (fork())
+ {
+ case -1:
+ show_who("fork failed");
+ fatal("");
+ case 0:
+ execv(argp->prog, argp->argv + arg0);
+ show_who("exec of ");
+ writes(argp->prog);
+ fatal(" failed");
+ default:
+ wait(&status);
+ for (i = tmpargs.argc - 1; i >= START_ARGS; --i)
+ if (in_name == tmpargs.argv[i])
+ {
+ my_unlink(in_name);
+ --tmpargs.argc;
+ memmove(tmpargs.argv + i, tmpargs.argv + i + 1,
+ (tmpargs.argc - i) * sizeof tmpargs.argv[0]);
+ tmpargs.argv[tmpargs.argc] = NUL_PTR;
+ break;
+ }
+ if (status != 0)
+ {
+ killtemps();
+ runerror = TRUE;
+ }
+ return status;
+ }
+}
+
+PRIVATE void set_trap()
+{
+#ifndef NORDB
+#ifdef SIGINT
+ signal(SIGINT, trap);
+#endif
+#ifdef SIGQUIT
+ signal(SIGQUIT, trap);
+#endif
+
+#else
+ /* This is being too trap happy! */
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+ int signum;
+
+ for (signum = 0; signum <= _NSIG; ++signum)
+#ifdef SIGCHLD
+ if (signum != SIGCHLD)
+#endif
+ if (signal(signum, SIG_IGN) != SIG_IGN)
+ signal(signum, trap);
+#endif
+}
+
+PRIVATE void show_who(message)
+char *message;
+{
+ writes(progname);
+ writes(": ");
+ writes(message);
+}
+
+PRIVATE void startarg(argp)
+struct arg_s *argp;
+{
+ argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT)
+ * sizeof *argp->argv, "startarg");
+ argp->argc = START_ARGS;
+ argp->argv[START_ARGS] = NUL_PTR;
+}
+
+PRIVATE char *stralloc(s)
+char *s;
+{
+ return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s);
+}
+
+PRIVATE char *stralloc2(s1, s2)
+char *s1;
+char *s2;
+{
+ return strcat(strcpy(my_malloc(
+ strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2);
+}
+
+PRIVATE void trap(signum)
+int signum;
+{
+ signal(signum, SIG_IGN);
+ show_who("caught signal");
+ fatal("");
+}
+
+PRIVATE void unsupported(option, message)
+char *option;
+char *message;
+{
+ show_who("compiler option ");
+ writes(option);
+ writes(" (");
+ writes(message);
+ writesn(") not supported yet");
+}
+
+PRIVATE void writen()
+{
+ writes("\n");
+}
+
+PRIVATE void writes(s)
+char *s;
+{
+ write(2, s, strlen(s));
+}
+
+PRIVATE void writesn(s)
+char *s;
+{
+ writes(s);
+ writen();
+}
diff --git a/bcc/bcc.c.gnu b/bcc/bcc.c.gnu
new file mode 100644
index 0000000..8491c97
--- /dev/null
+++ b/bcc/bcc.c.gnu
@@ -0,0 +1,983 @@
+/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define _POSIX_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FALSE 0
+#define FORWARD static
+#define NUL_PTR ((void*)0)
+#define PRIVATE static
+#define PUBLIC
+#define TRUE 1
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#define AS "as86"
+#define BAS86
+#define BCC86
+#define CC1 "bcc-cc1"
+#define CC1_MINUS_O_BROKEN FALSE
+#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
+#define CPPFLAGS "-E"
+#define CRT0 "crt0.o"
+#define GCC "gcc"
+#define LD "ld86"
+#ifdef ANSI_SUPPORT
+#define UNPROTO "unprotoize"
+#define CP "/bin/cp"
+#endif
+#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/"
+#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/"
+#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/"
+#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/"
+#define DEFAULT_INCLUDE "-I" LOCALPREFIX "/include"
+#define DEFAULT_LIBDIR0 "-L" LOCALPREFIX "/lib/bcc/i86/"
+#define DEFAULT_LIBDIR3 "-L" LOCALPREFIX "/lib/bcc/i386/"
+
+#ifdef CCC
+#undef BCC86
+#undef CC1
+#define CC1 "c386"
+#undef CC1_MINUS_O_BROKEN
+#define CC1_MINUS_O_BROKEN TRUE
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#define STANDARD_CRT0_PREFIX "/usr/local/lib/i386/"
+#endif /* CCC */
+
+#ifdef MC6809
+#undef BAS86
+#undef BCC86
+#undef CRT0
+#undef GCC
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/"
+#endif /* MC6809 */
+
+#define ALLOC_UNIT 16 /* allocation unit for arg arrays */
+#define DIRCHAR '/'
+#define START_ARGS 4 /* number of reserved args */
+
+typedef unsigned char bool_T; /* boolean: TRUE if nonzero */
+
+struct arg_s
+{
+ char *prog;
+ bool_T minus_O_broken;
+ int argc;
+ char **argv;
+ unsigned nr_allocated;
+};
+
+struct prefix_s
+{
+ char *name;
+ struct prefix_s *next;
+};
+
+PRIVATE struct arg_s asargs = { AS, };
+PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, };
+PRIVATE struct arg_s cppargs = { CPP, };
+#ifdef ANSI_SUPPORT
+PRIVATE struct arg_s unprotoargs = { UNPROTO, };
+#endif
+#ifdef STANDARD_CRT0_PREFIX
+PRIVATE struct prefix_s crt0_prefix = { STANDARD_CRT0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_0_PREFIX
+PRIVATE struct prefix_s crt0_0_prefix = { STANDARD_CRT0_0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_3_PREFIX
+PRIVATE struct prefix_s crt0_3_prefix = { STANDARD_CRT0_3_PREFIX, };
+#endif
+PRIVATE struct prefix_s exec_prefix;
+PRIVATE struct arg_s ldargs = { LD, };
+#ifdef BAS86
+PRIVATE struct arg_s ldrargs = { LD, };
+#endif
+PRIVATE char *progname;
+PRIVATE bool_T runerror; /* = FALSE */
+PRIVATE struct arg_s tmpargs; /* = empty */
+PRIVATE char *tmpdir;
+PRIVATE unsigned verbosity; /* = 0 */
+
+#ifndef DONT_REDECLARE_STDC_FUNCTIONS
+void exit P((int status));
+char *getenv P((const char *name));
+void *malloc P((size_t size));
+void *realloc P((void *ptr, size_t size));
+void (*signal P((int sig, void (*func) P((int sig))))) P((int sig));
+char *strcpy P((char *dest, const char *src));
+size_t strlen P((const char *s));
+char *strrchr P((const char *s, int c));
+#endif
+
+#ifndef DONT_REDECLARE_POSIX_FUNCTIONS
+int access P((const char *path, int amode));
+int execv P((const char *path, char * const *argv));
+pid_t fork P((void));
+pid_t getpid P((void));
+int unlink P((const char *path));
+pid_t wait P((int *status));
+ssize_t write P((int fd, const void *buf, size_t nbytes));
+#endif
+
+int main P((int argc, char **argv));
+
+FORWARD void addarg P((struct arg_s *argp, char *arg));
+FORWARD void addprefix P((struct prefix_s *prefix, char *name));
+FORWARD void fatal P((char *message));
+FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode));
+FORWARD void killtemps P((void));
+FORWARD void *my_malloc P((unsigned size, char *where));
+FORWARD char *my_mktemp P((int c_extension));
+FORWARD void my_unlink P((char *name));
+FORWARD void outofmemory P((char *where));
+FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp));
+FORWARD void set_trap P((void));
+FORWARD void show_who P((char *message));
+FORWARD void startarg P((struct arg_s *argp));
+FORWARD char *stralloc P((char *s));
+FORWARD char *stralloc2 P((char *s1, char *s2));
+FORWARD void trap P((int signum));
+FORWARD void unsupported P((char *option, char *message));
+FORWARD void writen P((void));
+FORWARD void writes P((char *s));
+FORWARD void writesn P((char *s));
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ int add_default_inc = 1;
+ int add_default_lib = 1;
+ int argcount = argc;
+ bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone");
+ bool_T as_only = FALSE;
+ char *basename;
+#ifdef BCC86
+#ifdef DEFARCH
+ bool_T bits32 = (DEFARCH != 0);
+#else
+ bool_T bits32 = sizeof (char *) >= 4;
+#endif
+ char *bits_arg;
+#endif
+ bool_T cc_only = FALSE;
+#ifdef ANSI_SUPPORT
+ bool_T ansi_pass = FALSE;
+ bool_T quiet_ansi = TRUE;
+#endif
+#ifdef CCC
+ bool_T cpp_pass = TRUE;
+#else
+ bool_T cpp_pass = FALSE;
+#endif
+#ifdef BCC86
+ char *crt0;
+#endif
+ bool_T debug = FALSE;
+ bool_T echo = FALSE;
+ unsigned errcount = 0;
+ char ext;
+ char *f_out = NUL_PTR;
+ bool_T float_emulation = FALSE;
+#ifdef BAS86
+ bool_T gnu_objects = FALSE;
+#endif
+ char *in_name;
+ int length;
+ unsigned ncisfiles = 0;
+ unsigned nifiles = 0;
+ unsigned npass_specs;
+ bool_T optimize = FALSE;
+ char *out_name;
+ bool_T profile = FALSE;
+ bool_T prep_only = FALSE;
+ bool_T prep_line_numbers = FALSE;
+ int status;
+ char *temp;
+
+ progname = argv[0];
+ addarg(&cppargs, CPPFLAGS);
+#ifdef CCC
+ addarg(&asargs, "-j");
+#endif
+ addarg(&asargs, "-u");
+ addarg(&asargs, "-w");
+#ifdef BCC86
+ addarg(&ldargs, "-i");
+#endif
+#ifdef BAS86
+ addarg(&ldrargs, "-r");
+#endif
+
+ /* Pass 1 over argv to gather compile options. */
+ for (; --argc != 0;)
+ {
+ arg = *++argv;
+ *++argdone = TRUE;
+ if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0)
+ switch (arg[1])
+ {
+#ifdef BCC86
+ case '0':
+ bits32 = FALSE;
+ break;
+ case '3':
+ bits32 = TRUE;
+ break;
+#endif
+ case 'E':
+ prep_only = prep_line_numbers = cpp_pass = TRUE;
+ break;
+#ifdef BAS86
+ case 'G':
+ gnu_objects = TRUE;
+ break;
+#endif
+ case 'P':
+ prep_only = cpp_pass = TRUE;
+ prep_line_numbers = FALSE;
+ break;
+ case 'O':
+ optimize = TRUE; /* unsupported( arg, "optimize" ); */
+ break;
+ case 'S':
+ cc_only = TRUE;
+ break;
+ case 'V':
+ echo = TRUE;
+ break;
+ case 'c':
+ as_only = TRUE;
+ break;
+ case 'e':
+ cpp_pass = TRUE;
+ break;
+ case 'f':
+ float_emulation = TRUE;
+ ++errcount;
+ unsupported(arg, "float emulation");
+ break;
+ case 'g':
+ debug = TRUE; /* unsupported( arg, "debug" ); */
+ break;
+ case 'o':
+ if (--argc < 1)
+ {
+ ++errcount;
+ show_who("output file missing after -o\n");
+ }
+ else
+ {
+ if (f_out != NUL_PTR)
+ show_who("more than one output file\n");
+ f_out = *++argv;
+ *++argdone = TRUE;
+ }
+ break;
+ case 'p':
+ profile = TRUE;
+ ++errcount;
+ unsupported(arg, "profile");
+ break;
+ case 'v':
+ ++verbosity;
+#ifdef ANSI_SUPPORT
+ quiet_ansi=FALSE;
+#endif
+ break;
+ case 'I':
+ add_default_inc = 0;
+ break;
+ case 'L':
+ add_default_lib = 0;
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else if (arg[0] == '-')
+ switch (arg[1])
+ {
+#ifdef ANSI_SUPPORT
+ case 'a':
+ if (!strcmp(arg, "-ansi"))
+ {
+ ansi_pass=TRUE;
+#if 0
+#ifndef CCC
+ addarg(&ccargs, "-D__STDC__=1");
+#endif
+ addarg(&cppargs, "-D__STDC__=1");
+#endif
+ }
+ break;
+#endif
+ case 'A':
+ addarg(&asargs, arg + 2);
+ break;
+ case 'B':
+ addprefix(&exec_prefix, arg + 2);
+ break;
+ case 'C':
+ addarg(&ccargs, arg + 2);
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+#ifndef CCC
+ addarg(&ccargs, arg);
+#endif
+ addarg(&cppargs, arg);
+ break;
+ case 'X':
+ addarg(&ldargs, arg + 2);
+ break;
+ case 'L':
+ addarg(&ldargs, arg);
+ break;
+ case 'P':
+ addarg(&cppargs, arg + 2);
+ break;
+#ifdef CCC
+ case 'Q':
+ addarg(&ccargs, arg);
+ break;
+#endif
+ case 'T':
+ tmpdir = arg + 2;
+ break;
+ case 't':
+ ++errcount;
+ unsupported(arg, "pass number");
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else
+ {
+ ++nifiles;
+ *argdone = FALSE;
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ ++ncisfiles;
+ }
+ }
+ npass_specs = prep_only + cc_only + as_only;
+ if (npass_specs != 0)
+ {
+ if (npass_specs > 1)
+ {
+ ++errcount;
+ show_who("more than 1 option from -E -P -S -c\n");
+ }
+ if (f_out != NUL_PTR && ncisfiles > 1)
+ {
+ ++errcount;
+ show_who("cannot have more than 1 input with non-linked output\n");
+ }
+ }
+ if (nifiles == 0)
+ {
+ ++errcount;
+ show_who("no input files\n");
+ }
+ if (errcount != 0)
+ exit(1);
+
+ if ((temp = getenv("BCC_EXEC_PREFIX")) != NUL_PTR)
+ addprefix(&exec_prefix, temp);
+ if( add_default_inc )
+ {
+#ifndef CCC
+ addarg(&ccargs, DEFAULT_INCLUDE);
+#endif
+ addarg(&cppargs, DEFAULT_INCLUDE);
+ }
+ if( add_default_lib )
+ {
+#ifdef BCC86
+ if( bits32 )
+ addarg(&ldargs, DEFAULT_LIBDIR3);
+ else
+#endif
+ addarg(&ldargs, DEFAULT_LIBDIR0);
+ }
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2);
+ cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK);
+ ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK);
+ asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK);
+ ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK);
+ ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK);
+#ifdef ANSI_SUPPORT
+ unprotoargs.prog=fixpath(unprotoargs.prog, &exec_prefix, X_OK);
+#endif
+ if (tmpdir == NUL_PTR && (tmpdir = getenv("TMPDIR")) == NUL_PTR)
+ tmpdir = "/tmp";
+
+ if (prep_only && !prep_line_numbers)
+ addarg(&cppargs, "-P");
+#ifdef BCC86
+ if (bits32)
+ {
+ bits_arg = "-3";
+ crt0 = fixpath(CRT0, &crt0_3_prefix, R_OK);
+ }
+ else
+ {
+ bits_arg = "-0";
+ crt0 = fixpath(CRT0, &crt0_0_prefix, R_OK);
+ }
+ addarg(&ccargs, bits_arg);
+ addarg(&cppargs, bits_arg);
+ addarg(&asargs, bits_arg);
+#ifdef BAS86
+ if (!gnu_objects)
+ {
+ addarg(&ldargs, bits_arg);
+ addarg(&ldrargs, bits_arg);
+ /* addarg(&ldargs, crt0);*/
+ addarg(&ldargs, "-C0");
+ }
+#endif /* BAS86 */
+#endif /* BCC86 */
+#if defined(BAS86) && !defined(BCC86)
+ if (!gnu_objects)
+ addarg(&ldargs, fixpath(CRT0, &crt0_prefix, R_OK));
+#endif
+ set_trap();
+
+ /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and
+ * gather arguments for linker.
+ */
+ for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;)
+ {
+ arg = *++argv;
+ if (!*++argdone)
+ {
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ {
+ if (echo || verbosity != 0)
+ {
+ writes(arg);
+ writesn(":");
+ }
+ if ((basename = strrchr(arg, DIRCHAR)) == NUL_PTR)
+ basename = arg;
+ else
+ ++basename;
+ in_name = arg;
+ if (ext == 'c')
+ {
+#ifdef ANSI_SUPPORT
+ /* If this was done between CPP and CC1 then
+ * we could define __STDC__
+ */
+ if (ansi_pass)
+ {
+ char *old_tmpdir;
+ struct arg_s cpargs = { CP, TRUE, };
+
+ old_tmpdir=tmpdir;
+ tmpdir=".";
+ out_name=my_mktemp(TRUE);
+ tmpdir=old_tmpdir;
+ run(in_name, out_name, &cpargs);
+
+ addarg(&unprotoargs, out_name);
+ addarg(&unprotoargs, "-N");
+ if (quiet_ansi)
+ addarg(&unprotoargs, "-q");
+ run(NUL_PTR, NUL_PTR, &unprotoargs);
+ in_name=out_name;
+ }
+#endif
+ if (cpp_pass)
+ {
+ if (prep_only)
+ out_name = f_out;
+ else
+ out_name = my_mktemp(FALSE);
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ }
+ ext = 'i';
+ }
+ if (ext == 'i')
+ {
+ if (prep_only)
+ continue;
+ if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp(FALSE);
+ if (run(in_name, out_name, &ccargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 'S')
+ {
+ if (prep_only)
+ out_name = f_out;
+ else if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp(FALSE);
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 's')
+ {
+ if (prep_only || cc_only)
+ continue;
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ if (as_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ }
+ }
+ else
+ out_name = my_mktemp(FALSE);
+ addarg(&asargs, "-n");
+ arg[length - 1] = 's';
+ addarg(&asargs, arg);
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ char *tmp_out_name;
+
+ tmp_out_name = my_mktemp(FALSE);
+ status = run(in_name, tmp_out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ if (run(tmp_out_name, out_name, &ldrargs) != 0)
+ continue;
+ }
+ else
+#endif
+ {
+ status = run(in_name, out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ }
+ ext = 'o';
+ in_name = out_name;
+ }
+ if (ext == 'o')
+ {
+ if (prep_only || cc_only || as_only)
+ continue;
+ addarg(&ldargs, in_name);
+ }
+ }
+ else
+ addarg(&ldargs, arg);
+ }
+ }
+
+ if (!prep_only && !cc_only && !as_only && !runerror)
+ {
+ if (f_out == NUL_PTR)
+ f_out = "a.out";
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ /* Remove -i and -i-. */
+ for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc)
+ {
+ arg = ldargs.argv[argc];
+ if (arg[0] == '-' && arg[1] == 'i'
+ && (arg[2] == 0 || (arg[2] == '-' && arg[3] == 0)))
+ {
+ --ldargs.argc;
+ memmove(ldargs.argv + argc, ldargs.argv + argc + 1,
+ (ldargs.argc - argc) * sizeof ldargs.argv[0]);
+ ldargs.argv[ldargs.argc] = NUL_PTR;
+ }
+ }
+
+ ldargs.prog = fixpath(GCC, &exec_prefix, X_OK);
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ else
+#endif
+ {
+ addarg(&ldargs, "-lc");
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ }
+ killtemps();
+ return runerror ? 1 : 0;
+}
+
+PRIVATE void addarg(argp, arg)
+register struct arg_s *argp;
+char *arg;
+{
+ int new_argc;
+ char **new_argv;
+
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ new_argc = argp->argc + 1;
+ if (new_argc >= argp->nr_allocated)
+ {
+ argp->nr_allocated += ALLOC_UNIT;
+ new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv);
+ if (new_argv == NUL_PTR)
+ outofmemory("addarg");
+ argp->argv = new_argv;
+ }
+ argp->argv[argp->argc] = arg;
+ argp->argv[argp->argc = new_argc] = NUL_PTR;
+}
+
+PRIVATE void addprefix(prefix, name)
+struct prefix_s *prefix;
+char *name;
+{
+ struct prefix_s *new_prefix;
+
+ if (prefix->name == NUL_PTR)
+ prefix->name = name;
+ else
+ {
+ new_prefix = my_malloc(sizeof *new_prefix, "addprefix");
+ new_prefix->name = name;
+ new_prefix->next = NUL_PTR;
+ while (prefix->next != NUL_PTR)
+ prefix = prefix->next;
+ prefix->next = new_prefix;
+ }
+}
+
+PRIVATE void fatal(message)
+char *message;
+{
+ writesn(message);
+ killtemps();
+ exit(1);
+}
+
+PRIVATE char *fixpath(path, prefix, mode)
+char *path;
+struct prefix_s *prefix;
+int mode;
+{
+ char *ppath;
+
+ for (; prefix != NUL_PTR; prefix = prefix->next)
+ {
+ if (verbosity > 2)
+ {
+ show_who("searching for ");
+ if (mode == R_OK)
+ writes("readable file ");
+ else
+ writes("executable file ");
+ writes(path);
+ writes(" in ");
+ writesn(prefix->name);
+ }
+ ppath = stralloc2(prefix->name, path);
+ if (access(ppath, mode) == 0)
+ return ppath;
+ free(ppath);
+ }
+ return path;
+}
+
+PRIVATE void killtemps()
+{
+ while (tmpargs.argc > START_ARGS)
+ my_unlink(tmpargs.argv[--tmpargs.argc]);
+}
+
+PRIVATE void *my_malloc(size, where)
+unsigned size;
+char *where;
+{
+ void *block;
+
+ if ((block = malloc(size)) == NUL_PTR)
+ outofmemory(where);
+ return block;
+}
+
+PRIVATE char *my_mktemp(c_extension)
+int c_extension;
+{
+ char *p;
+ unsigned digit;
+ unsigned digits;
+ char *template;
+ static unsigned tmpnum;
+
+ if (c_extension)
+ {
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX.c");
+ p += strlen(p) - 2;
+ }
+ else
+ {
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX");
+ p += strlen(p);
+ }
+
+ digits = getpid();
+ while (*--p == 'X')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p = digit + '0';
+ digits /= 16;
+ }
+ digits = tmpnum;
+ while (*p == 'Y')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p-- = digit + '0';
+ digits /= 16;
+ }
+ ++tmpnum;
+ addarg(&tmpargs, template);
+ return template;
+}
+
+PRIVATE void my_unlink(name)
+char *name;
+{
+ if (verbosity > 1)
+ {
+ show_who("unlinking ");
+ writesn(name);
+ }
+ if (unlink(name) < 0)
+ {
+ show_who("error unlinking ");
+ writesn(name);
+ }
+}
+
+PRIVATE void outofmemory(where)
+char *where;
+{
+ show_who("out of memory in ");
+ fatal(where);
+}
+
+PRIVATE int run(in_name, out_name, argp)
+char *in_name;
+char *out_name;
+struct arg_s *argp;
+{
+ int arg0;
+ int i;
+ int status;
+
+ arg0 = 0;
+ if (in_name == NUL_PTR)
+ ++arg0;
+ if (out_name == NUL_PTR)
+ arg0 += 2;
+ else if (argp->minus_O_broken)
+ ++arg0;
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ argp->argv[arg0] = argp->prog;
+ i = arg0 + 1;
+ if (in_name != NUL_PTR)
+ argp->argv[i++] = in_name;
+ if (out_name != NUL_PTR)
+ {
+ if (!argp->minus_O_broken)
+ argp->argv[i++] = "-o";
+ argp->argv[i++] = out_name;
+ }
+ if (verbosity != 0)
+ {
+ for (i = arg0; i < argp->argc; ++i)
+ {
+ writes(argp->argv[i]);
+ writes(" ");
+ }
+ writen();
+ }
+ switch (fork())
+ {
+ case -1:
+ show_who("fork failed");
+ fatal("");
+ case 0:
+ execv(argp->prog, argp->argv + arg0);
+ show_who("exec of ");
+ writes(argp->prog);
+ fatal(" failed");
+ default:
+ wait(&status);
+ for (i = tmpargs.argc - 1; i >= START_ARGS; --i)
+ if (in_name == tmpargs.argv[i])
+ {
+ my_unlink(in_name);
+ --tmpargs.argc;
+ memmove(tmpargs.argv + i, tmpargs.argv + i + 1,
+ (tmpargs.argc - i) * sizeof tmpargs.argv[0]);
+ tmpargs.argv[tmpargs.argc] = NUL_PTR;
+ break;
+ }
+ if (status != 0)
+ {
+ killtemps();
+ runerror = TRUE;
+ }
+ return status;
+ }
+}
+
+PRIVATE void set_trap()
+{
+#ifndef NORDB
+#ifdef SIGINT
+ signal(SIGINT, trap);
+#endif
+#ifdef SIGQUIT
+ signal(SIGQUIT, trap);
+#endif
+
+#else
+ /* This is being too trap happy! */
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+ int signum;
+
+ for (signum = 0; signum <= _NSIG; ++signum)
+#ifdef SIGCHLD
+ if (signum != SIGCHLD)
+#endif
+ if (signal(signum, SIG_IGN) != SIG_IGN)
+ signal(signum, trap);
+#endif
+}
+
+PRIVATE void show_who(message)
+char *message;
+{
+ writes(progname);
+ writes(": ");
+ writes(message);
+}
+
+PRIVATE void startarg(argp)
+struct arg_s *argp;
+{
+ argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT)
+ * sizeof *argp->argv, "startarg");
+ argp->argc = START_ARGS;
+ argp->argv[START_ARGS] = NUL_PTR;
+}
+
+PRIVATE char *stralloc(s)
+char *s;
+{
+ return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s);
+}
+
+PRIVATE char *stralloc2(s1, s2)
+char *s1;
+char *s2;
+{
+ return strcat(strcpy(my_malloc(
+ strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2);
+}
+
+PRIVATE void trap(signum)
+int signum;
+{
+ signal(signum, SIG_IGN);
+ show_who("caught signal");
+ fatal("");
+}
+
+PRIVATE void unsupported(option, message)
+char *option;
+char *message;
+{
+ show_who("compiler option ");
+ writes(option);
+ writes(" (");
+ writes(message);
+ writesn(") not supported yet");
+}
+
+PRIVATE void writen()
+{
+ writes("\n");
+}
+
+PRIVATE void writes(s)
+char *s;
+{
+ write(2, s, strlen(s));
+}
+
+PRIVATE void writesn(s)
+char *s;
+{
+ writes(s);
+ writen();
+}
diff --git a/bcc/bcc.doc b/bcc/bcc.doc
new file mode 100644
index 0000000..1c5e930
--- /dev/null
+++ b/bcc/bcc.doc
@@ -0,0 +1,177 @@
+bcc options
+-----------
+
+bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option]
+ [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir]
+ [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles]
+
+The 6809 version does not support -0, -3 or -G.
+Only the c386 version supports -Q.
+
+defaults (off or none except for these):
+-03 native
+outfile stdout for preprocessor output
+ somewhere/file.[ci] -> file.s for compiler output
+ somewhere/file.[cis] -> file.o for assembler output
+ a.out for ld output
+
+-ansi Pass the source through '/usr/bin/unprotoize' first
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing)
+-B prefix for executable search path (as usual; the search order is all paths
+ specified using -B, in order, then the path given in the environment
+ variable BCC_EXEC_PREFIX if that is set, then the compiled-in defaults
+ (something like /usr/libexec/i386/bcc/ followed by /usr/bin/))
+-C pass remainder of option to cc1 (e.g. -C-c for caller-saves)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-G produce gnu-Minix objects (link with gnu ld)
+-Ix include search path (as usual)
+-I don't add default include to search list
+-Lx add dir name x to the head of the list of library dirs searched
+-L don't add default library to search list
+-X pass remainder of option to linker
+-O optimize (does nothing)
+-P produce preprocessor output with no line numbers (as usual)
+-Q pass full option to c386
+-S produce assembler file (as usual)
+-T temporary directory (overrides previous value and default; default is
+ from the environment variable TMPDIR if that is set, otherwise /tmp)
+-U undefine (as usual)
+-V print names of files being compiled
+-c produce object file (as usual)
+-e run the preprocess pass separately. This takes less memory, and may help
+ or harm by giving more traditional semantics like token pasting with /**/.
+-f error (float emulation not supported)
+-g produce debugging info (does nothing)
+-o output file name follows (assembler, object or executable) (as usual)
+-p error (profiling not supported)
+-t error (substitution of some cc passes not supported)
+-v print names and args of subprocesses being run. Two or more -v's:
+ print names of files being unlinked. Three or more -v's:
+ print names of paths being searched.
+
+Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s.
+The -i option is always passed to the linker but can be cancelled using -i-.
+
+This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L,
+-T, -V, -e, -v and where not supported.
+
+cc1 options
+----------
+
+cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile]
+
+The 6809 version does not support -0 or -3 but it supports -p.
+
+defaults (off or none except for these):
+-03 native
+-c on for 6809
+-f on for 6809
+outfile stdout
+infile stdin
+
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-I include search path (as usual)
+-P produce preprocessor output with no line numbers (as usual)
+-c produce code with caller saving regs before function calls
+-d print debugging information in assembly output
+-f produce code with 1st argument passed in a register
+-l produce code for 2 3 1 0 long byte order (only works in 16-bit versions)
+-o assembler output file name follows
+-p produce (almost) position-independent code
+-t print source code in assemby output
+-w print what cc1 thinks is the location counter in assembly output
+
+All the options except -D, -I and -o may be turned off by following the
+option letter by a '-'. Options are processed left to right so the last
+setting has precedence.
+
+The following is defined before option processing:
+
+__BCC__ 1
+
+The following may be defined after option processing:
+
+__AS09__ 1 if 6809 version
+__AS386_16__ 1 if -0 option on 80*86
+__AS386_32__ 1 if -3 option on 80*86
+__CALLER_SAVES__ 1 if -c option
+__FIRST_ARG_IN_AX__ 1 if -f option on 80*86
+__FIRST_ARG_IN_X__ 1 if -f option on 6809
+__LONG_BIG_ENDIAN__ 1 if -l option
+__POS_INDEPENDENT__ 1 if -p option on 6809
+
+The following are standard builtins:
+
+__FILE__ stringized name of current input file
+__LINE__ current line number
+
+as options
+----------
+
+as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src
+
+The 6809 version does not support -0, -3, -a or -j.
+
+defaults (off or none except for these; no output is produced without a flag):
+-03 native
+list stdout (beware of clobbering next arg)
+name basename of the source name
+
+-0 start with 16-bit code segment
+-3 start with 32-bit code segment
+-a enable partial compatibility with asld
+-b produce binary file, filename may follow (obsolete)
+-g only put global symbols in object file
+-j force all jumps to be long
+-l produce list file, filename may follow
+-m print macro expansions in listing
+-n name of module follows (goes in object instead of source name)
+-o produce object file, filename follows
+-s produce symbol file, filename follows (obsolete)
+-u take undefined symbols as imported-with-unspecified segment
+-w don't print warnings
+
+The -u and -w options are perhaps back to front because they are needed for
+cc1 output and Minix's make does the wrong thing with .s files left around.
+However, all assembler code not written by compilers should assemble with
+them turned off.
+
+ld options
+----------
+
+ld [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...
+
+The version that produces old Minix a.out format does not support -r.
+
+The 6809 version does not support -i or -r.
+
+defaults (off or none except for these):
+-03 native
+-L/usr/local/lib/m/ (m is machine-dependent)
+outfile a.out
+
+-0 produce header with 16-bit magic and use library subdir i86 for -lx
+-3 produce header with 32-bit magic and use library subdir i386 for -lx
+-Cx add file libdir-from-search/crtx.o to list of files linked
+-Lx add dir name x to the head of the list of library dirs searched
+-M print symbols linked on stdout
+-Ox add library libdir-from-search/x to list of files linked
+-T text base address follows (in format suitable for strtoul)
+-i separate I&D output
+-lx add library libdir-from-search/libx.a to list of files linked
+-m print modules linked on stdout
+-o output file name follows
+-r produce output suitable for further relocation
+-s strip symbols
+-t trace modules being looked at on stdout
+-z produce "unmapped zero page" executables
+
+All the options not taking an argument may be turned off by following the
+option letter by a '-', as for cc1.
diff --git a/bcc/byteord.h b/bcc/byteord.h
new file mode 100644
index 0000000..e7b19e0
--- /dev/null
+++ b/bcc/byteord.h
@@ -0,0 +1,13 @@
+/* byteord.h - byte order dependencies for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef I8088
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 1 /* longs are back to front for Xenix */
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/bcc/codefrag.c b/bcc/codefrag.c
new file mode 100644
index 0000000..e42b05b
--- /dev/null
+++ b/bcc/codefrag.c
@@ -0,0 +1,1843 @@
+/* codefrag.c - code fragments for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+
+#define DEFSTR_BYTEMAX 10
+#define DEFSTR_DELIMITER '"'
+#define DEFSTR_STRINGMAX 40
+#define EOS_TEXT '0'
+#define MAXPRINTCHAR '~'
+#define MINPRINTCHAR ' '
+
+/* segment numbers */
+
+#ifdef I8088
+# define CSEG 0
+# define outcseg() outop0str(".text\n")
+# define DSEG 1
+# define outdseg() outop0str(".data\n")
+# define BSSSEG 2
+# define outbssseg() outop0str(".bss\n")
+#endif
+
+#ifdef MC6809
+# define CSEG 0
+# define outcseg() outop0str("LOC\t0\n")
+# define DPSEG 2
+# define outdpseg() outop0str("LOC\t2\n")
+# define DSEG 3
+# define outdseg() outop0str("LOC\t3\n")
+# define STRSEG 1
+# define outstrseg() outop0str("LOC\t1\n")
+#endif
+
+#ifdef I8088
+FORWARD void adjcarry P((void));
+#endif
+FORWARD void clr P((store_pt reg));
+FORWARD bool_pt lowregisDreg P((void));
+#ifdef I8088
+FORWARD void outand P((void));
+FORWARD void outequate P((void));
+# ifdef XENIX_AS
+FORWARD void outexport P((void));
+# endif
+FORWARD void outmovsx P((void));
+FORWARD void outmovzx P((void));
+FORWARD void tfrhilo P((void));
+FORWARD void tfrlohi P((void));
+#endif
+#ifdef MC6809
+FORWARD void negBsbcA P((void));
+#endif
+FORWARD void outaccum P((void));
+FORWARD void outstackreg P((void));
+FORWARD void opregadr P((void));
+
+/* operator and miscellaneous strings */
+
+#ifdef I8088
+
+# define ACCHISTR "ah"
+# define ANDSTRING "and\t"
+# define DEFSTR_QUOTER '\\'
+# define EORSTRING "xor\t"
+# define MAX_INLINE_SHIFT 2 /* better 3 for 88, 1 for 186 and above */
+# define ORSTRING "or\t"
+# define TARGET_FIRST
+# define addfactor(reg) (outadd(), outregname(reg), outncregname(DXREG))
+# define defstorage() outop0str(".blkb\t")
+# define extBnegD() (ctoi(), negDreg())
+# define finishfactor() /* save/add/subfactor() ended already */
+# define outadc() outop3str("adc\t")
+# define outandac() (outand(), outaccum(), bumplc())
+# define outandlo() (outand(), outstr(acclostr))
+# define outbimmed() outbyte('*')
+# define outcommon() outop0str(".comm\t")
+# define outcwd() outnop1str("cwd")
+# define outdefstr() outop0str(".ascii\t\"")
+# define outexchange() outop1str("xchg\t")
+# define outglobl() outop0str(".globl\t")
+# ifdef XENIX_AS
+# define outimport() outexport()
+# else
+# define outexport() outop0str("export\t")
+# define outimport() outop0str("import\t")
+# endif
+# ifdef XENIX_AS
+# define outj1switch() outop3str("seg\tcs\nbr\t@");
+# else
+# define outj1switch() outop3str("seg\tcs\nbr\t");
+# endif
+# define outj2switch() \
+ (outindleft(), outstr(ireg0str), outindright(), bumplc2(), outnl())
+# define outlcommon() outop0str("\tlcomm\t")
+# define outlswitch() (outload(), outstr(ireg0str), outncregname(DREG))
+# define outnc1() outnstr(",*1")
+# define outsbc() outop3str("sbb\t")
+# define outset() outstr ("\tset\t")
+# define outsl() outop2str("shl\t")
+# define outsr() outop2str("sar\t")
+# define outtransfer() outload()
+# define outusr() outop2str("shr\t")
+# define outxor() outop2str(EORSTRING)
+# define reclaimfactor() /* factor in DXREG, DXREG now junk */
+# define savefactor(reg) regtransfer((reg), DXREG)
+# define smiDreg() (outcwd(), regexchange(DREG, DXREG))
+# define sr1() (outsr(), outaccum(), outnc1())
+# define subfactor(reg) (outsub(), outregname(reg), outncregname(DXREG))
+# define usr1() (outusr(), outaccum(), outnc1())
+PRIVATE void adjcarry()
+{
+ outop3str("rcl\t");
+ outregname(DXREG);
+ outncimmadr((offset_t) 9);
+ outand();
+ bumplc2();
+ bumplc2();
+ outregname(DXREG);
+ outncimmadr((offset_t) 0x100);
+}
+PUBLIC void clrBreg()
+{
+ outxor();
+ outstr(acclostr);
+ outncregname(BREG);
+}
+PUBLIC void comment()
+{
+ outstr("! ");
+}
+PUBLIC void ctoi()
+{
+ if (i386_32)
+ {
+ outmovzx();
+ outaccum();
+ outncregname(BREG);
+ }
+ else
+ {
+ outxor();
+ outhiaccum();
+ outcomma();
+ outhiaccum();
+ outnl();
+ }
+}
+PUBLIC void defbyte()
+{
+ outop0str(".byte\t");
+}
+#ifdef XENIX_AS
+PUBLIC void defword()
+{
+} /* don't have to print ".word\t" */
+#else
+PUBLIC void defword()
+{
+ outop0str(".word\t");
+}
+#endif
+PUBLIC void defdword()
+{
+ outop0str("dd\t");
+}
+PUBLIC void even()
+{
+ outop0str(".even\n");
+}
+PUBLIC void negDreg()
+{
+ outop2str("neg\t");
+ outnregname(DREG);
+}
+PUBLIC void comDreg()
+{
+ outop2str("not\t");
+ outnregname(DREG);
+}
+PUBLIC void outadd()
+{
+ outop2str("add\t");
+}
+PUBLIC void outaddsp()
+{
+ outadd();
+ outstackreg();
+ outcomma();
+ outimmed();
+ bumplc2();
+}
+PRIVATE void outand()
+{
+ outop2str(ANDSTRING);
+}
+#ifdef XENIX_AS
+PUBLIC void outcalladr()
+{
+ outop2str("call\t@");
+}
+#else
+PUBLIC void outcalladr()
+{
+ outop2str("call\t");
+}
+#endif
+PUBLIC void outcmp()
+{
+ outop2str("cmp\t");
+}
+PUBLIC void outdec()
+{
+ outop1str("dec\t");
+}
+PUBLIC void outdword()
+{
+ outstr("dword ");
+}
+PRIVATE void outequate()
+{
+ outop0str("\t=\t");
+}
+#ifdef XENIX_AS
+PRIVATE void outexport()
+{
+ outop0str(".globl\t");
+}
+#endif
+PUBLIC void outfail()
+{
+ outop0str(".fail\t");
+}
+PUBLIC void outinc()
+{
+ outop1str("inc\t");
+}
+#ifdef XENIX_AS
+PUBLIC void outindleft()
+{
+ outbyte('(');
+}
+PUBLIC void outindright()
+{
+ outbyte(')');
+}
+#else
+PUBLIC void outindleft()
+{
+ outbyte('[');
+}
+PUBLIC void outindright()
+{
+ outbyte(']');
+}
+#endif
+#ifndef FRAMEPOINTER
+PUBLIC void outindstackreg()
+{
+ outindleft();
+ outregname(STACKREG);
+ outindright();
+}
+#endif
+PUBLIC void outldaccum()
+{
+ outload();
+ outaccum();
+ outcomma();
+}
+PUBLIC void outldmulreg()
+{
+ outload();
+ outregname(MULREG);
+ outcomma();
+}
+PUBLIC void outlea()
+{
+ outop2str("lea\t");
+}
+PUBLIC void outleasp()
+{
+ outlea();
+ outstackreg();
+ outcomma();
+}
+PUBLIC void outload()
+{
+ outop2str("mov\t");
+}
+PRIVATE void outmovsx()
+{
+ outop3str("movsx\t");
+}
+PRIVATE void outmovzx()
+{
+ outop3str("movzx\t");
+}
+PUBLIC void outmulmulreg()
+{
+ outop2str("mul\t");
+ outnregname(MULREG);
+}
+PUBLIC void outopsep()
+{
+ outcomma();
+}
+PUBLIC void outpshs()
+{
+ outop1str("push");
+}
+PUBLIC void outpuls()
+{
+ outop1str("pop");
+}
+PUBLIC void outreturn()
+{
+ outnop1str("ret");
+}
+PUBLIC void outstore()
+{
+ outload();
+}
+PUBLIC void outsub()
+{
+ outop2str("sub\t");
+}
+PUBLIC void outtest()
+{
+ outop2str("test\t");
+}
+PUBLIC void outword()
+{
+ outstr("word ");
+}
+PUBLIC void sctoi()
+{
+ if (i386_32)
+ {
+ outmovsx();
+ outncregname(BREG);
+ }
+ else
+ outnop1str("cbw");
+}
+PUBLIC void stoi()
+{
+ outnop1str("cwde");
+}
+PRIVATE void tfrhilo()
+{
+ outload();
+ outstr(acclostr);
+ outcomma();
+ outhiaccum();
+ outnl();
+}
+PRIVATE void tfrlohi()
+{
+ outload();
+ outhiaccum();
+ outncregname(BREG);
+}
+PUBLIC void ustoi()
+{
+ outmovzx();
+ outaccum();
+ outcomma();
+ outshortregname(DREG);
+ outnl();
+}
+#endif /* I8088 */
+
+#ifdef MC6809
+
+# define ACCHISTR "A"
+# define ANDSTRING "AND"
+# define DEFSTR_QUOTER '"'
+# define EORSTRING "EOR"
+# define MAX_INLINE_SHIFT 16
+# define ORSTRING "OR"
+# define addfactor(reg) outop2str("ADDD\t,S")
+# define defstorage() outop0str("RMB\t")
+# define extBnegD() (ctoi(), negBsbcA())
+# define finishfactor() outnl()
+# define outadc() outop2str("ADC")
+# define outandhi() outop2str("ANDA")
+# define outandlo() outop2str("ANDB")
+# define outcommon() outop0str("\tCOMM\t")
+# define outdefstr() outop0str("FCC\t\"")
+# define outequate() outop0str("\tEQU\t")
+# define outexchange() outop2str("EXG\t")
+# define outexport() outop0str("EXPORT\t")
+# define outglobl() outop0str("GLOBL\t")
+# define outimport() outop0str("IMPORT\t")
+# define outjswitch() outnop2str("JMP\t[D,X]")
+# define outlcommon() outop0str("\tLCOMM\t")
+# define outlswitch() outop3str("LDX\t#")
+# define outpijswitch() outnop2str("JMP\tD,X")
+# define outpil1switch() outop3str("LEAX\t<")
+# define outpil2switch() outnop2str("LDD\tD,X")
+# define outrolhi() outnop1str("ROLA");
+# define outsbc() outop2str("SBC")
+# define outset() outstr ("\tSET\t")
+# define outsl() outop1str("LSL")
+# define outtransfer() outop2str("TFR\t")
+# define reclaimfactor() outnstr ("++") /* discard factor from stack */
+# define savefactor(reg) outop2str("PSHS\tD")
+# define smiDreg() (clrBreg(), outnop1str("ROLA"), \
+ outnop2str("SBCB\t#0"), sctoi())
+ /* this tricky sequence is twice as fast as TFR A,B; SEX; TFR A,B */
+ /* it gets the sign bit of A in the carry */
+ /* then subtracts it from 0 in D (effectively) */
+# define sr1() (outnop1str("ASRA"), outnop1str("RORB"))
+# define stackregstr "S"
+# define subfactor(reg) outop2str("SUBD\t,S")
+# define testhi() outnop1str("TSTA")
+# define tfrhilo() outnop2str("TFR\tA,B")
+# define tfrlohi() outnop2str("TFR\tB,A")
+# define usr1() (outnop1str("LSRA"), outnop1str("RORB"))
+PUBLIC void clrBreg()
+{
+ outnop1str("CLRB");
+}
+PUBLIC void comment()
+{
+ outstr("| ");
+}
+PUBLIC void defbyte()
+{
+ outop0str("FCB\t");
+}
+PUBLIC void defword()
+{
+ outop0str("FDB\t");
+}
+PUBLIC void negDreg()
+{
+ outnop1str("NEGA");
+ negBsbcA();
+}
+PRIVATE void negBsbcA()
+{
+ outnop1str("NEGB");
+ sbc0();
+}
+PUBLIC void comDreg()
+{
+ outnop1str("COMA");
+ outnop1str("COMB");
+}
+PUBLIC void outABX()
+{
+ outnop1str("ABX");
+}
+PUBLIC void outadd()
+{
+ outop2str("ADD");
+}
+PUBLIC void outaddsp()
+{
+ outleasp();
+ bumplc2();
+}
+PUBLIC void outcalladr()
+{
+ outop2str("JSR");
+}
+PUBLIC void outcmp()
+{
+ outop2str("CMP");
+}
+PUBLIC void outdec()
+{
+ outop1str("DEC");
+}
+PUBLIC void outdirectpage()
+{
+ outbyte('<');
+}
+PUBLIC void outextended()
+{
+ outbyte('>');
+}
+PUBLIC void outfail()
+{
+ outop0str("FAIL\t");
+}
+PUBLIC void outinc()
+{
+ outop1str("INC");
+}
+PUBLIC void outindleft()
+{
+ outbyte('[');
+}
+PUBLIC void outindright()
+{
+ outbyte(']');
+}
+PUBLIC void outldaccum()
+{
+ outload();
+ outaccum();
+}
+PUBLIC void outldmulreg()
+{
+ outop2str("LDA");
+}
+PUBLIC void outlea()
+{
+ outop2str("LEA");
+}
+PUBLIC void outleasp()
+{
+ outop2str("LEAS\t");
+}
+PUBLIC void outload()
+{
+ outop2str("LD");
+}
+PUBLIC void outmulmulreg()
+{
+ outnop1str("MUL");
+}
+PUBLIC void outncspregname()
+{
+ outcomma();
+ outstackreg();
+ outnl();
+}
+PUBLIC void outopsep()
+{
+} /* is tab, but already done by outadr() */
+PUBLIC void outpshs()
+{
+ outop2str("PSHS");
+}
+PUBLIC void outpuls()
+{
+ outop2str("PULS");
+}
+PUBLIC void outreturn()
+{
+ outnop1str("RTS");
+}
+PUBLIC void outstore()
+{
+ outop2str("ST");
+}
+PUBLIC void outsub()
+{
+ outop2str("SUB");
+}
+PUBLIC void outtest()
+{
+ outop1str("TST");
+}
+PUBLIC void sctoi()
+{
+ outnop1str("SEX");
+}
+PUBLIC void ctoi()
+{
+ outnop1str("CLRA");
+}
+#endif /* MC6809 */
+#ifdef FRAMEREG
+PUBLIC void outindframereg()
+{
+ outindleft();
+ outregname(FRAMEREG);
+ outindright();
+}
+#endif
+
+typedef fastin_t seg_t; /* range 0..3 */
+
+PRIVATE seg_t segment; /* current seg, depends on init to CSEG = 0 */
+
+/* add carry resulting from char addition */
+
+PUBLIC void adc0()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ adjcarry();
+ outadd();
+ outaccum();
+ outncregname(DXREG);
+ }
+ else
+#endif
+ {
+ outadc();
+ outhiaccum();
+ outncimmadr((offset_t) 0);
+ }
+}
+
+/* add constant to register */
+
+PUBLIC void addconst(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+#ifdef I8088
+ if ((i386_32 && (uoffset_t) offset + 1 <= 2) /* do -1 to 1 by dec/inc */
+ || (!i386_32 && (uoffset_t) offset + 2 <= 4)) /* do -2 to 2 */
+ {
+ if (reg == ALREG)
+ reg = AXREG; /* shorter and faster */
+ do
+ {
+ if (offset < 0)
+ {
+ outdec();
+ ++offset;
+ }
+ else /* if offset == 0, do inc + dec */
+ {
+ outinc();
+ --offset; /* shouldn't happen and harmless */
+ }
+ outnregname(reg);
+ }
+ while (offset);
+ }
+ else
+#endif
+#ifdef MC6809
+ if (!(reg & ALLDATREGS))
+ lea(offset, reg, reg);
+ else if (reg == BREG && (offset == 1 || offset == -1))
+ {
+ if (offset < 0)
+ outdec();
+ else
+ outinc();
+ outnregname(reg);
+ }
+ else
+#endif
+ {
+ outadd();
+ outimadj(offset, reg);
+ }
+}
+
+/* adjust lc for signed offset */
+
+PUBLIC void adjlc(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+ if (!(reg & CHARREGS))
+ {
+ bumplc();
+ if (!isbyteoffset(offset))
+ {
+#ifdef I8088
+ if ((store_t) reg != AXREG)
+#endif
+ bumplc();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ }
+ }
+}
+
+/* adjust stack ptr by adding a labelled constant less current sp */
+
+PUBLIC void adjsp(label)
+label_t label;
+{
+ outaddsp();
+ outbyte(LOCALSTARTCHAR);
+ outlabel(label);
+ if (switchnow != NULL)
+ {
+ outminus();
+ outswstacklab();
+ }
+ else
+ {
+ outplus();
+ outhex((uoffset_t) - sp);
+ }
+#ifdef MC6809
+ outcregname(LOCAL);
+#endif
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ outnl();
+}
+
+/* and accumulator with constant */
+
+PUBLIC void andconst(offset)
+offset_t offset;
+{
+ char_t botbits;
+ uoffset_t topbits;
+
+ if ((topbits = offset & ~(uoffset_t) CHMASKTO & intmaskto) != 0 &&
+ topbits != (~(uoffset_t) CHMASKTO & intmaskto))
+ /* if topbits == 0, callers reduce the type */
+ {
+#ifdef OP1
+ outandhi();
+ outncimmadr((offset_t) (topbits >> (INT16BITSTO - CHBITSTO)));
+#else
+ outandac();
+ if (i386_32)
+ bumplc2();
+ outncimmadr(offset);
+ return;
+#endif
+ }
+ if ((botbits = (char_t) offset & CHMASKTO) == 0)
+ clrBreg();
+ else if (botbits != CHMASKTO)
+ {
+ outandlo();
+ outncimmadr((offset_t) botbits);
+ }
+}
+
+#ifdef I8088
+
+/* set bss segment */
+
+PUBLIC void bssseg()
+{
+ if (segment != BSSSEG)
+ {
+ segment = BSSSEG;
+ outbssseg();
+ }
+}
+
+#endif
+
+/* jump to case of switch */
+
+PUBLIC label_t casejump()
+{
+ label_t jtablelab;
+
+#ifdef I8088
+ outlswitch();
+ outj1switch();
+ outlabel(jtablelab = getlabel());
+ outj2switch();
+ if (i386_32)
+ bumplc2();
+#endif
+#ifdef MC6809
+ if (posindependent)
+ {
+ outpil1switch();
+ outlabel(jtablelab = getlabel());
+ outncregname(GLOBAL);
+ outpil2switch();
+ outpijswitch();
+ }
+ else
+ {
+ outlswitch();
+ outnlabel(jtablelab = getlabel());
+ outjswitch();
+ }
+#endif
+ return jtablelab;
+}
+
+/* clear register to 0 */
+
+PRIVATE void clr(reg)
+store_pt reg;
+{
+ loadconst((offset_t) 0, reg);
+}
+
+/* define common storage */
+
+PUBLIC void common(name)
+char *name;
+{
+#ifdef I8088
+ outcommon();
+ outccname(name);
+ outcomma();
+#endif
+#ifdef MC6809
+ outccname(name);
+ outcommon();
+#endif
+}
+
+/* set code segment */
+
+PUBLIC void cseg()
+{
+ if (segment != CSEG)
+ {
+ segment = CSEG;
+ outcseg();
+ }
+}
+
+/* define long */
+
+PUBLIC void deflong(value)
+uoffset_t value;
+{
+ uoffset_t longhigh;
+ uoffset_t longlow;
+
+ longlow = value & (uoffset_t) intmaskto;
+#ifdef I8088
+ if (i386_32)
+ defdword();
+ else
+#endif
+ {
+ longhigh = (value >> INT16BITSTO) & (uoffset_t) intmaskto;
+ defword();
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ outnhex(longhigh);
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ outnhex(longlow);
+ longlow = longhigh;
+ }
+#endif
+ defword();
+ }
+ outnhex(longlow);
+}
+
+/* define null storage */
+
+PUBLIC void defnulls(nullcount)
+uoffset_t nullcount;
+{
+ if (nullcount != 0)
+ {
+ defstorage();
+ outnhex(nullcount);
+ }
+}
+
+/* define string */
+
+PUBLIC label_t defstr(sptr, stop, dataflag)
+char *sptr;
+char *stop;
+bool_pt dataflag;
+{
+ int byte; /* promoted char for output */
+ label_t strlab;
+ seg_t oldsegment;
+ fastin_t count; /* range 0..max(DEFSTR_BYTEMAX,DEFSTR_STRMAX) */
+
+#ifdef HOLDSTRINGS
+ if (!(bool_t) dataflag)
+ return holdstr(sptr, stop);
+#endif
+ oldsegment = segment;
+#ifdef I8088
+ dseg();
+#endif
+#ifdef MC6809
+ if (dataflag)
+ dseg();
+ else
+ {
+ segment = STRSEG; /* could use dseg() */
+ outstrseg(); /* this brings strings together */
+ }
+#endif
+ outnlabel(strlab = getlabel());
+ byte = (unsigned char) *sptr++;
+ while (sptr <= stop)
+ {
+ if ((unsigned char) byte >= MINPRINTCHAR
+ && (unsigned char) byte <= MAXPRINTCHAR)
+ {
+ outdefstr();
+ count = DEFSTR_STRINGMAX;
+ while (count-- > 0 && (unsigned char) byte >= MINPRINTCHAR
+ && (unsigned char) byte <= MAXPRINTCHAR && sptr <= stop)
+ {
+#if DEFSTR_DELIMITER - DEFSTR_QUOTER
+ if ((unsigned char) byte == DEFSTR_DELIMITER
+ || (unsigned char) byte == DEFSTR_QUOTER)
+#else
+ if ((unsigned char) byte == DEFSTR_DELIMITER)
+#endif
+ outbyte(DEFSTR_QUOTER);
+ outbyte(byte);
+ byte = (unsigned char) *sptr++;
+ }
+ outnbyte(DEFSTR_DELIMITER);
+ }
+ else
+ {
+ defbyte();
+ count = DEFSTR_BYTEMAX;
+ while (count-- > 0 && ((unsigned char) byte < MINPRINTCHAR
+ || (unsigned char) byte > MAXPRINTCHAR) && sptr <= stop)
+ {
+ if (count < DEFSTR_BYTEMAX - 1)
+ outcomma(); /* byte separator */
+ outhex((uoffset_t) byte);
+ byte = (unsigned char) *sptr++;
+ }
+ outnl();
+ }
+ }
+ defbyte();
+ outnbyte(EOS_TEXT);
+ switch (oldsegment)
+ {
+ case CSEG:
+ cseg();
+ break;
+ case DSEG:
+ dseg();
+ break;
+#ifdef I8088
+ case BSSSEG:
+ bssseg();
+ break;
+#endif
+#ifdef MC6809
+ case DPSEG:
+ dpseg();
+ break;
+#endif
+ }
+ return strlab;
+}
+
+/* divide D register by a constant if it is easy to do with shifts */
+
+PUBLIC bool_pt diveasy(divisor, uflag)
+value_t divisor;
+bool_pt uflag;
+{
+ bool_t sign;
+
+ sign = FALSE;
+ if (divisor < 0 && !(bool_t) uflag)
+ {
+ sign = TRUE;
+ divisor = -divisor;
+ }
+ if (bitcount((uvalue_t) divisor) > 1)
+ return FALSE;
+ if (divisor == 0)
+ clr(DREG);
+ else
+ {
+ if (sign)
+ negDreg();
+ srconst((value_t) highbit((uvalue_t) divisor), uflag);
+ }
+ return TRUE;
+}
+
+#ifdef MC6809
+
+/* set direct page segment */
+
+PUBLIC void dpseg()
+{
+ if (segment != DPSEG)
+ {
+ segment = DPSEG;
+ outdpseg();
+ }
+}
+
+#endif
+
+/* set data segment */
+
+PUBLIC void dseg()
+{
+ if (segment != DSEG)
+ {
+ segment = DSEG;
+ outdseg();
+ }
+}
+
+/* equate a name to an EOL-terminated string */
+
+PUBLIC void equ(name, string)
+char *name;
+char *string;
+{
+ outstr(name);
+ outequate();
+ outline(string);
+}
+
+/* equate a local label to a value */
+
+PUBLIC void equlab(label, offset)
+label_t label;
+offset_t offset;
+{
+ outbyte(LOCALSTARTCHAR);
+ outlabel(label);
+ outequate();
+ outshex(offset);
+ outnl();
+}
+
+/* import or export a variable */
+
+PUBLIC void globl(name)
+char *name;
+{
+ outglobl();
+ outnccname(name);
+}
+
+/* import a variable */
+
+PUBLIC void import(name)
+char *name;
+{
+ outimport();
+ outnccname(name);
+}
+
+/* extend an int to a long */
+
+PUBLIC void itol(reg)
+store_pt reg;
+{
+#define TEMP_LABEL_FOR_REGRESSION_TESTS
+#ifdef TEMP_LABEL_FOR_REGRESSION_TESTS
+ getlabel();
+#endif
+
+ if (lowregisDreg())
+ {
+#ifdef I8088
+ outcwd();
+ regtransfer(DXREG, reg);
+#else
+ label_t exitlab;
+
+ clr(reg);
+ testhi();
+ sbranch(GE, exitlab = getlabel());
+ loadconst((offset_t) - 1, reg);
+ outnlabel(exitlab);
+#endif
+ }
+ else
+ {
+ regtransfer(DREG, reg);
+ smiDreg();
+ }
+}
+
+/* define local common storage */
+
+PUBLIC void lcommlab(label)
+label_t label;
+{
+ outlabel(label);
+ outlcommon();
+}
+
+PUBLIC void lcommon(name)
+char *name;
+{
+ outccname(name);
+ outlcommon();
+}
+
+#ifdef MC6809
+
+/* load effective address */
+
+PUBLIC void lea(offset, sourcereg, targreg)
+offset_t offset;
+store_pt sourcereg;
+store_pt targreg;
+{
+ outlea();
+ outregname(targreg);
+ outtab();
+ outshex(offset);
+ outncregname(sourcereg);
+}
+
+#endif
+
+/* load constant into given register */
+
+PUBLIC void loadconst(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+#ifdef I8088
+ if (offset == 0)
+ {
+ outxor();
+ outregname(reg);
+ outncregname(reg);
+ }
+ else
+#endif
+#ifdef MC6809
+ if (offset == 0 && reg == BREG)
+ clrBreg();
+ else
+#endif
+ {
+ outload();
+ outregname(reg);
+#ifdef MC6809
+ if (reg == YREG)
+ bumplc2();
+ else
+#endif
+ if (reg != BREG)
+ {
+ bumplc();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ }
+ outncimmadr(offset);
+ }
+}
+
+/* convert index half of long reg pair into low half of pair */
+
+PRIVATE bool_pt lowregisDreg()
+{
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ return FALSE;
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ return TRUE;
+#endif
+}
+
+/* partially long shift left register by a constant (negative = infinity) */
+
+PUBLIC int lslconst(shift, reg)
+value_t shift;
+store_pt reg;
+{
+ if ((uvalue_t) shift >= INT16BITSTO)
+ {
+ slconst(shift - INT16BITSTO, lowregisDreg() ? DREG : reg);
+ regexchange(reg, DREG);
+ clr(lowregisDreg() ? DREG : reg);
+ return 0;
+ }
+#ifdef I8088
+ if (shift >= CHBITSTO)
+ {
+ if (long_big_endian)
+ {
+ tfrlohi();
+ outnop2str("mov\tal,bh");
+ outnop2str("mov\tbh,bl");
+ outnop2str("sub\tbl,bl");
+ }
+ else
+ {
+ outnop2str("mov\tbh,bl");
+ outnop2str("mov\tbl,ah");
+ tfrlohi();
+ clrBreg();
+ }
+ return (int) shift - CHBITSTO;
+ }
+#endif
+ return (int) shift;
+}
+
+/* partially long shift right register by a constant (negative = infinity) */
+
+PUBLIC int lsrconst(shift, reg, uflag)
+value_t shift;
+store_pt reg;
+bool_pt uflag;
+{
+ if ((uvalue_t) shift >= INT16BITSTO)
+ {
+ if (lowregisDreg())
+ regexchange(reg, DREG);
+ srconst(shift - INT16BITSTO, uflag);
+ if ((bool_t) uflag)
+ uitol(reg);
+ else
+ itol(reg);
+ return 0;
+ }
+#ifdef I8088
+ if (shift >= CHBITSTO)
+ {
+ if (long_big_endian)
+ {
+ outnop2str("mov\tbl,bh");
+ outnop2str("mov\tbh,al");
+ tfrhilo();
+ if ((bool_t) uflag)
+ ctoi();
+ else
+ sctoi();
+ }
+ else
+ {
+ tfrhilo();
+ outnop2str("mov\tah,bl");
+ outnop2str("mov\tbl,bh");
+ if ((bool_t) uflag)
+ outnop2str("sub\tbh,bh");
+ else
+ {
+ regexchange(reg, DREG);
+ sctoi();
+ regexchange(reg, DREG);
+ }
+ }
+ return (int) shift - CHBITSTO;
+ }
+#endif
+ return (int) shift;
+}
+
+/* take D register modulo a constant if it is easy to do with a mask */
+
+PUBLIC bool_pt modeasy(divisor, uflag)
+value_t divisor;
+bool_pt uflag;
+{
+ bool_t sign;
+
+ sign = FALSE;
+ if (divisor < 0 && !(bool_t) uflag)
+ {
+ sign = TRUE;
+ divisor = -divisor;
+ }
+ if (bitcount((uvalue_t) divisor) > 1)
+ return FALSE;
+ if (--divisor == 0)
+ clrBreg(); /* original divisor 1 or -1 yields 0 */
+ else
+ {
+ if (sign)
+ negDreg();
+ andconst((offset_t) divisor); /* if original divisor 0, this is
+ null */
+ if (sign)
+ negDreg();
+ }
+ return TRUE;
+}
+
+/* multiply register by a constant if it is easy to do with shifts */
+
+PUBLIC bool_pt muleasy(factor, reg)
+uvalue_t factor;
+store_pt reg;
+{
+ int mulstack[MAXINTBITSTO / 2 + 1]; /* must be signed, not a fastin_t */
+ fastin_pt count;
+ fastin_t single1skip;
+ fastin_t lastcount;
+ fastin_t mulsp;
+ int stackentry; /* signed */
+
+ if (factor == 0)
+ {
+ clr(reg);
+ return TRUE;
+ }
+ single1skip = 0;
+ mulsp = -1; /* may be unsigned, but bumps to 0 */
+ while (factor != 0)
+ {
+ for (lastcount = single1skip; (factor & 1) == 0; factor >>= 1)
+ ++lastcount;
+ mulstack[(int)++mulsp] = lastcount;
+ /* first time bumps mulsp to 0 even if an unsigned char */
+ for (count = 0; (factor & 1) != 0; factor >>= 1)
+ ++count;
+ single1skip = 1;
+ if (count == 2 && factor == 0)
+ /* 3 = 2 + 1 better than 3 = 4 - 1 */
+ /* but rest of algorithm messed up unless factor now 0 */
+ mulstack[(int)++mulsp] = 1;
+ else if (count > 1)
+ {
+ single1skip = 0;
+ if (lastcount == 1 && mulsp != 0)
+ mulstack[(int)mulsp] = -1 - count;
+ else
+ mulstack[(int)++mulsp] = -count;
+ }
+ }
+ if (mulsp > 3)
+ return FALSE;
+ if (mulsp != 0)
+ {
+ savefactor(reg); /* on stack or in reg as nec */
+ do
+ {
+ finishfactor(); /* finish save/add/subfactor() if nec */
+ stackentry = mulstack[(int)mulsp--];
+ if (stackentry < 0)
+ {
+#ifdef I8088
+ if (stackentry == -INT32BITSTO)
+ clr(reg); /* shifting would do nothing */
+ else
+#endif
+ slconst((value_t) - stackentry, reg);
+ subfactor(reg); /* from wherever put by savefactor() */
+ }
+ else
+ {
+ slconst((value_t) stackentry, reg);
+ addfactor(reg); /* from wherever put by savefactor() */
+ }
+ }
+ while (mulsp != 0);
+ reclaimfactor(); /* reclaim storage if nec */
+ }
+ slconst((value_t) mulstack[0], reg);
+ return TRUE;
+}
+
+/* negate a register */
+
+PUBLIC void negreg(reg)
+store_pt reg;
+{
+ if ((store_t) reg == BREG)
+ extBnegD();
+ else
+ negDreg();
+}
+
+/* return string of operator */
+
+PUBLIC char *opstring(op)
+op_pt op;
+{
+ switch (op)
+ {
+ case ANDOP:
+ return ANDSTRING;
+ case EOROP:
+ return EORSTRING;
+ case OROP:
+ return ORSTRING;
+ }
+ return "badop";
+}
+
+/* print DREG (accumulator) */
+
+PRIVATE void outaccum()
+{
+ outstr(accumstr);
+}
+
+/* print a c compiler name with leading CCNAMEPREXFIX */
+
+PUBLIC void outccname(name)
+char *name;
+{
+ outbyte(CCNAMEPREFIX);
+ outstr(name);
+}
+
+/* print high byte of word accumulator */
+
+PUBLIC void outhiaccum()
+{
+ outstr(ACCHISTR);
+}
+
+/* print immediate address */
+
+PUBLIC void outimmadr(offset)
+offset_t offset;
+{
+#ifdef I8088
+ if (!isbyteoffset(offset))
+ outimmed();
+ else
+ outbimmed();
+#else
+ outimmed();
+#endif
+ outshex(offset);
+}
+
+/* print register, comma, immediate address and adjust lc */
+
+PUBLIC void outimadj(offset, targreg)
+offset_t offset;
+store_pt targreg;
+{
+ outregname(targreg);
+ adjlc(offset, targreg);
+ outncimmadr(offset);
+}
+
+/* print immediate address designator */
+
+PUBLIC void outimmed()
+{
+ outbyte('#');
+}
+
+PUBLIC void outjumpstring()
+{
+ outop3str(jumpstring);
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+/* print cc name, then newline */
+
+PUBLIC void outnccname(name)
+char *name;
+{
+ outccname(name);
+ outnl();
+}
+
+/* print separator, immediate address, newline */
+
+PUBLIC void outncimmadr(offset)
+offset_t offset;
+{
+#ifdef I8088
+ outcomma();
+#endif
+#ifdef MC6809
+ outtab();
+#endif
+ outimmadr(offset);
+ outnl();
+}
+
+/* print signed offset and adjust lc */
+
+PUBLIC void outoffset(offset)
+offset_t offset;
+{
+#ifdef MC6809
+ if (!is5bitoffset(offset))
+#endif
+ adjlc(offset, INDREG0);
+ outshex(offset);
+}
+
+/* print stack register */
+
+PRIVATE void outstackreg()
+{
+ outstr(stackregstr);
+}
+
+PUBLIC void public(name)
+char *name;
+{
+#ifndef AS09
+ outexport();
+ outnccname(name);
+#endif
+ outccname(name);
+ outnbyte(PUBLICENDCHAR);
+}
+
+/* print cc name as a private label */
+
+PUBLIC void private(name)
+char *name;
+{
+#ifdef LABELENDCHAR
+ outccname(name);
+ outnbyte(LABELENDCHAR);
+#else
+ outnccname(name);
+#endif
+}
+
+/* exchange registers */
+
+PUBLIC void regexchange(sourcereg, targreg)
+store_pt sourcereg;
+store_pt targreg;
+{
+ outexchange();
+ outregname(sourcereg);
+ outncregname(targreg);
+#ifdef I8088
+ if (!((sourcereg | targreg) & AXREG))
+ bumplc();
+#endif
+}
+
+/* transfer a register */
+
+PUBLIC void regtransfer(sourcereg, targreg)
+store_pt sourcereg;
+store_pt targreg;
+{
+ outtransfer();
+#ifdef TARGET_FIRST
+ outregname(targreg);
+ outncregname(sourcereg);
+#else
+ outregname(sourcereg);
+ outncregname(targreg);
+#endif
+}
+
+/* subtract carry resulting from char addition */
+
+PUBLIC void sbc0()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ adjcarry();
+ outsub();
+ outaccum();
+ outncregname(DXREG);
+ }
+ else
+#endif
+ {
+ outsbc();
+ outhiaccum();
+ outncimmadr((offset_t) 0);
+ }
+}
+
+/* set a name to a value */
+
+PUBLIC void set(name, value)
+char *name;
+offset_t value;
+{
+ outccname(funcname);
+ outbyte(LOCALSTARTCHAR);
+ outstr(name);
+ outset();
+ outshex(value);
+ outnl();
+}
+
+/* shift left register by 1 */
+
+PUBLIC void sl1(reg)
+store_pt reg;
+{
+ outsl();
+#ifdef I8088
+ outregname(reg);
+ outnc1();
+#endif
+#ifdef MC6809
+ outnregname(BREG);
+ outrolhi();
+#endif
+}
+
+/* shift left register by a constant (negative = infinity) */
+
+PUBLIC void slconst(shift, reg)
+value_t shift;
+store_pt reg;
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ if ((shift = (uvalue_t) shift % INT32BITSTO) != 0)
+ {
+ outsl();
+ if (shift != 1)
+ bumplc();
+ outregname(reg);
+ outncimmadr((offset_t) shift);
+ }
+ return;
+ }
+#endif
+ if ((uvalue_t) shift >= INT16BITSTO)
+ clr(reg);
+ else
+ {
+ if (shift >= CHBITSTO && reg == DREG)
+ {
+ tfrlohi();
+ clrBreg();
+ shift -= CHBITSTO;
+ }
+#ifdef I8088
+# if MAX_INLINE_SHIFT < INT16BITSTO
+ if (shift > MAX_INLINE_SHIFT)
+ {
+ outload();
+ outregname(SHIFTREG);
+ outcomma();
+ outimmadr((offset_t) shift);
+ outnl();
+ outsl();
+ outregname(reg);
+ outncregname(SHIFTREG);
+ }
+ else
+# endif
+#endif
+ while (shift--)
+ sl1(reg);
+ }
+}
+
+/* shift right D register by a constant (negative = infinity) */
+
+PUBLIC void srconst(shift, uflag)
+value_t shift;
+bool_pt uflag;
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ if ((shift = (uvalue_t) shift % INT32BITSTO) != 0)
+ {
+ if (uflag)
+ outusr();
+ else
+ outsr();
+ if (shift != 1)
+ bumplc();
+ outaccum();
+ outncimmadr((offset_t) shift);
+ }
+ return;
+ }
+#endif
+ if ((uvalue_t) shift >= INT16BITSTO) /* covers negatives too */
+ {
+ if ((bool_t) uflag)
+ clr(DREG);
+ else /* make D == 0 if D >= 0, else D == -1 */
+ smiDreg(); /* special case of 68020 Scc instruction */
+ }
+ else
+ {
+ if (shift >= CHBITSTO)
+ {
+ tfrhilo();
+ if ((bool_t) uflag)
+ ctoi();
+ else
+ sctoi();
+ shift -= CHBITSTO;
+ }
+#ifdef I8088
+# if MAX_INLINE_SHIFT < INT16BITSTO
+ if (shift > MAX_INLINE_SHIFT)
+ {
+ outload();
+ outregname(SHIFTREG);
+ outcomma();
+ outimmadr((offset_t) shift);
+ outnl();
+ if ((bool_t) uflag)
+ outusr();
+ else
+ outsr();
+ outaccum();
+ outncregname(SHIFTREG);
+ }
+ else
+# endif
+#endif
+ while (shift--)
+ {
+ if ((bool_t) uflag)
+ usr1();
+ else
+ sr1();
+ }
+ }
+}
+
+/* extend an unsigned in DREG to a long */
+
+PUBLIC void uitol(reg)
+store_pt reg;
+{
+ if (lowregisDreg())
+ clr(reg);
+ else
+ {
+ regexchange(DREG, reg);
+ clr(DREG);
+ }
+}
+
+PRIVATE char opregstr[] = "_opreg";
+
+/*-----------------------------------------------------------------------------
+ opregadr()
+ outputs address of variable opreg where OPREG is saved
+-----------------------------------------------------------------------------*/
+
+PRIVATE void opregadr()
+{
+#ifdef I8088
+ outindleft();
+ outccname(opregstr);
+ outindright();
+ bumplc2();
+ if (i386_32)
+ bumplc2();
+#endif
+#ifdef MC6809
+ outregname(OPREG);
+ outtab();
+ if (posindependent)
+ {
+ outccname(opregstr);
+ outncregname(GLOBAL);
+ bumplc();
+ }
+ else
+ {
+ outextended();
+ outnccname(opregstr);
+ }
+ bumplc();
+#endif
+}
+
+/*-----------------------------------------------------------------------------
+ restoreopreg()
+ restores register OPREG from static location >opreg if it is was use
+-----------------------------------------------------------------------------*/
+
+PUBLIC void restoreopreg()
+{
+ if (reguse & OPREG)
+ {
+#ifdef I8088
+ outload();
+ outregname(OPREG);
+ outopsep();
+ opregadr();
+ outnl();
+#endif
+#ifdef MC6809
+ outload();
+ opregadr();
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ saveopreg()
+ saves register OPREG to static location >opreg if it is in use
+ this makes the flop routines non-reentrant. It is too messy to
+ push it because the flop routines leave results on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void saveopreg()
+{
+ if (reguse & OPREG)
+ {
+#ifdef I8088
+ bssseg();
+ common(opregstr);
+ outnhex(opregsize);
+ cseg();
+ outstore();
+ opregadr();
+ outncregname(OPREG);
+#endif
+#ifdef MC6809
+ dseg();
+ common(opregstr);
+ outnhex(opregsize);
+ cseg();
+ outstore();
+ opregadr();
+#endif
+ }
+}
diff --git a/bcc/condcode.h b/bcc/condcode.h
new file mode 100644
index 0000000..9b047df
--- /dev/null
+++ b/bcc/condcode.h
@@ -0,0 +1,16 @@
+/* condcode.h - condition codes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define EQ 0
+#define NE 1
+#define RA 2
+#define RN 3
+#define LT 4
+#define GE 5
+#define LE 6
+#define GT 7
+#define LO 8
+#define HS 9
+#define LS 10
+#define HI 11
diff --git a/bcc/const.h b/bcc/const.h
new file mode 100644
index 0000000..8df8bcb
--- /dev/null
+++ b/bcc/const.h
@@ -0,0 +1,52 @@
+/* const.h - constants for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* switches for code generation */
+
+#define DEBUG /* generate compiler-debugging code */
+#define I8088 /* target processor is Intel 8088 thru 80386 */
+/*#define MC6809*/ /* target processor is Motorola 6809 */
+#define SELFTYPECHECK /* check calculated type = runtime type */
+
+#ifdef I8088
+# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */
+# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */
+# define HOLDSTRINGS /* hold strings for dumping at end
+ * since assembler has only 1 data seg */
+#endif
+
+#ifdef MC6809
+# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */
+# define OP1 /* logical operators only use 1 byte */
+# define POSINDEPENDENT /* position indep code can (also) be gen */
+#endif
+
+/* switches for source and target operating system dependencies */
+
+/*#define SOS_EDOS*/ /* source O/S is EDOS */
+/*#define SOS_MSDOS*/ /* source O/S is MSDOS */
+/*#define TOS_EDOS*/ /* target O/S is EDOS */
+
+/* switches for source machine dependencies */
+
+#ifndef SOS_EDOS
+# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */
+#endif
+
+#ifndef SOS_MSDOS /* need portable alignment for large model */
+# define UNPORTABLE_ALIGNMENT
+#endif
+
+/* local style */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
diff --git a/bcc/debug.c b/bcc/debug.c
new file mode 100644
index 0000000..26f7bf8
--- /dev/null
+++ b/bcc/debug.c
@@ -0,0 +1,202 @@
+/* debug.c - print debug messages for operators for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+
+#ifdef DEBUG
+
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+PRIVATE char *opname[LASTOP - FIRSTOP + 1] = /* operator names */
+{ /* order must agree with op.h */
+ "cond?",
+ "or",
+ "eor",
+ "and",
+ "gt", "lt",
+ "add",
+ "div", "mod",
+ "lognot", "not",
+ "strucelt", "strucptr",
+ "eq",
+ "addab", "andab", "divab", "eorab", "modab", "mulab", "orab",
+ "slab", "srab", "subab",
+ "comma",
+ "cond:",
+ "logor",
+ "logand",
+ "logeq",
+ "ne",
+ "ge", "le",
+ "sl", "sr",
+ "sub",
+ "mul",
+ "address", "cast", "indirect", "neg",
+ "predec", "preinc", "postdec", "postinc",
+ "func", "list", "rootlist",
+ "leaf",
+ "ptraddab", "ptradd", "ptrsub",
+};
+
+FORWARD void outindchars P((int byte, indn_pt count));
+
+PUBLIC void dbitem(item)
+struct symstruct *item;
+{
+ dbtype(item->type);
+ if (item->storage == NOSTORAGE)
+ {
+ outbyte(' ');
+ outstr(item->name.namep + 2);
+ outstr(" (offset ");
+ outshex(item->offset.offi);
+ outbyte(')');
+ return;
+ }
+ if (item->storage == LOCAL)
+ {
+ outbyte(' ');
+ if (item->flags == TEMP)
+ outstr("(temp)");
+ else
+ outstr(item->name.namep);
+ }
+ outstr(" = ");
+ outindchars('[', item->indcount);
+ switch (item->storage)
+ {
+ case CONSTANT:
+ outstr("const ");
+ if (item->type->scalar & RSCALAR)
+ outstr("(whatever)");
+ else if (item->type->scalar & UNSIGNED)
+ outuvalue((uvalue_t) item->offset.offv);
+ else
+ outvalue(item->offset.offv);
+ break;
+ case BREG:
+ case DREG:
+ case INDREG0:
+ case INDREG1:
+ case INDREG2:
+#ifdef DATREG1
+ case DATREG1:
+#endif
+#ifdef DATREG2
+ case DATREG2:
+#endif
+ outregname(item->storage);
+ if (item->level == OFFKLUDGELEVEL)
+ {
+ outplus();
+ if (item->flags & LABELLED)
+ outlabel(item->name.label);
+ else
+ outccname(item->name.namep);
+ }
+ break;
+ case LOCAL:
+ outbyte('S');
+ if (sp <= 0)
+ outplus();
+ outshex(-sp);
+ break;
+ case GLOBAL:
+ if (item->flags & LABELLED)
+ outlabel(item->name.label);
+ else
+ outstr(item->name.namep);
+ break;
+ default:
+ outstr("bad storage (");
+ outhex((uoffset_t) item->storage);
+ outbyte(')');
+ outstr(" offset ");
+ }
+ if (item->storage != CONSTANT)
+ {
+ if (item->offset.offi >= 0)
+ outplus();
+ outshex(item->offset.offi);
+ }
+ outindchars(']', item->indcount);
+}
+
+PUBLIC void dbtype(type)
+struct typestruct *type;
+{
+ for ( ; type != NULL; type = type->nexttype)
+ {
+ outbyte(' ');
+ switch (type->constructor)
+ {
+ case ARRAY:
+ outbyte('[');
+ outhex(type->typesize / type->nexttype->typesize);
+ outbyte(']');
+ break;
+ case FUNCTION:
+ outstr("()");
+ break;
+ case POINTER:
+ outbyte('*');
+ break;
+ case STRUCTU:
+ outstr("struct ");
+ default:
+ if (type->scalar & UNSIGNED)
+ outstr("unsigned ");
+ outstr(type->tname);
+ break;
+ }
+ }
+}
+
+PUBLIC void debug(exp) /* sub-nodes must be leaves */
+struct nodestruct *exp;
+{
+ if (!debugon)
+ return;
+ comment();
+ if (exp->tag < FIRSTOP && exp->tag > LASTOP)
+ outstr("unknown op");
+ else
+ outstr(opname[exp->tag - FIRSTOP]);
+ if (exp->right != NULL && exp->tag != FUNCOP &&
+ exp->tag != LISTOP && exp->tag != ROOTLISTOP)
+ {
+ dbitem(exp->right->left.symptr);
+ outstr(" to");
+ }
+ dbitem(exp->left.nodeptr->left.symptr);
+ outstr(" (used reg = ");
+ if (reguse & INDREG0)
+ outregname(INDREG0);
+ if (reguse & INDREG1)
+ outregname(INDREG1);
+ if (reguse & INDREG2)
+ outregname(INDREG2);
+ outnstr(")");
+}
+
+PUBLIC void debugswap()
+{
+ if (debugon)
+ outnstr("* swapping");
+}
+
+PRIVATE void outindchars(byte, count)
+int byte;
+indn_pt count;
+{
+ while (count--)
+ outbyte(byte);
+}
+
+#endif /* DEBUG */
diff --git a/bcc/declare.c b/bcc/declare.c
new file mode 100644
index 0000000..1dd1314
--- /dev/null
+++ b/bcc/declare.c
@@ -0,0 +1,1124 @@
+/* declare.c - declaration routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "input.h" /* just for orig_cppmode */
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "parse.h"
+
+PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */
+PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */
+PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */
+
+#define gvarname (gvar2name + 2) /* last identifier declared */
+PRIVATE struct typestruct *gvartype; /* type of last identifier declared */
+PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */
+
+FORWARD struct typestruct *chainprefix P((struct typestruct *pretype,
+ struct typestruct *sufftype));
+FORWARD void declaf P((void));
+FORWARD void declarator P((void));
+FORWARD void declarg P((void));
+FORWARD struct typestruct *declenum P((void));
+FORWARD void declfunc P((void));
+FORWARD void declselt P((struct typestruct *structype, offset_t *psoffset,
+ struct typelist ** ptypelist));
+FORWARD bool_pt declspec P((void));
+FORWARD struct typestruct *declsu P((void));
+FORWARD void idecllist P((void));
+FORWARD void initarray P((struct typestruct *type));
+FORWARD void inititem P((struct typestruct *type));
+FORWARD void initstruct P((struct typestruct *type));
+FORWARD void lbrace P((void));
+FORWARD void multidecl P((char *sname));
+FORWARD void need P((int charneeded));
+FORWARD void rdeclarator P((void));
+FORWARD bool_pt regdecl P((void));
+
+PRIVATE struct typestruct *chainprefix(pretype, sufftype)
+struct typestruct *pretype;
+struct typestruct *sufftype;
+{
+ if (pretype->nexttype != NULL)
+ {
+ sufftype = chainprefix(pretype->nexttype, sufftype);
+ if (pretype->constructor != ARRAY)
+ return prefix(pretype->constructor, pretype->typesize, sufftype);
+ else
+ return prefix(ARRAY,
+ pretype->typesize / pretype->nexttype->typesize
+ * sufftype->typesize, sufftype);
+ }
+ return sufftype;
+}
+
+PUBLIC void colon()
+{
+ if (sym != COLON)
+ need(':');
+ else
+ nextsym();
+}
+
+/* decllist() - list of local declarations */
+/* this does the non-terminal symbols declaration-list, type-declaration */
+/* list and declaration */
+/* the different cases are and ";" at the end are decided by idecllist() */
+
+PUBLIC void decllist()
+{
+ while (declspec())
+ {
+ if (gvarsc == NULLDECL)
+ gvarsc = AUTODECL;
+ idecllist();
+ }
+}
+
+PRIVATE void declaf()
+{
+ uoffset_t asize;
+ bool_t levelnew;
+#ifdef TESTING_PROTOTYPES
+ char ogvarname[NAMESIZE];
+ sym_t ogvarsc;
+ struct symstruct *ogvarsymptr;
+ struct typestruct *ogvartype;
+#endif
+
+ if (sym == LPAREN) /* function */
+ {
+ nextsym();
+ if (argsallowed && level == GLBLEVEL)
+ {
+ newlevel();
+ levelnew = TRUE;
+ }
+ else
+ levelnew = FALSE;
+#ifdef TESTING_PROTOTYPES
+ strcpy(ogvarname, gvarname);
+ ogvarsc = gvarsc;
+ ogvarsymptr = gvarsymptr;
+ ogvartype = gvartype;
+ if (declspec())
+ {
+ if (level == ARGLEVEL)
+ outstr(gvarname);
+ outbyte('(');
+ do
+ {
+ declarator();
+ dbtype(gvartype);
+ outbyte(' ');
+#if 0
+ if (gvarname[0] != 0 && gsymptr != NULL
+ && gsymptr->level == level)
+ error("repeated argument");
+#endif
+ outstr(gvarname);
+ if (levelnew)
+ addloc(gsname, gvartype); /* adjust offsets later */
+ if (sym != COMMA)
+ break;
+ outcomma();
+ nextsym();
+ }
+ while (declspec());
+ if (sym == STRUCELTOP)
+ {
+ /* ... should be lexed. */
+ nextsym();
+ if (sym == STRUCELTOP)
+ {
+ nextsym();
+ if (sym == STRUCELTOP)
+ {
+ nextsym();
+ outstr(" ...");
+ }
+ }
+ }
+ outbyte(')');
+ if (level == ARGLEVEL)
+ outnl();
+ }
+ else
+ {
+#endif /* TESTING_PROTOTYPES */
+ while (sym == IDENT)
+ {
+ if (gsymptr != NULL && gsymptr->level == level)
+ error("repeated argument");
+ if (levelnew)
+ addloc(gsname, itype); /* adjust types and offsets later */
+ nextsym();
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+#ifdef TESTING_PROTOTYPES
+ }
+ strcpy(gvarname, ogvarname);
+ gvarsc = ogvarsc;
+ gvarsymptr = ogvarsymptr;
+ gvartype = ogvartype;
+#endif /* TESTING_PROTOTYPES */
+ rparen();
+ declaf();
+ switch (gvartype->constructor)
+ {
+ case ARRAY:
+ error("function returning array is illegal");
+ break;
+ case FUNCTION:
+ error("function returning function is illegal");
+ break;
+ }
+ gvartype = prefix(FUNCTION, ftypesize, gvartype);
+ }
+ else if (sym == LBRACKET)
+ {
+ nextsym();
+ if (sym == RBRACKET)
+ asize = 0;
+ else
+ asize = constexpression() & intmaskto; /* FIXME: warn overflow */
+ rbracket();
+ declaf();
+ if (gvartype->typesize == 0)
+ switch (gvartype->constructor)
+ {
+ case FUNCTION:
+ error("array of functions is illegal");
+ break;
+ case STRUCTU:
+ error("undefined structure");
+ break;
+ default: /* array */
+ error("null dimension");
+ gvartype->typesize = 1;
+ }
+ gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype);
+ }
+}
+
+PRIVATE void declarator()
+{
+ rdeclarator();
+ if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 &&
+ gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL)
+ error("undefined structure");
+}
+
+PRIVATE void declarg()
+{
+ if (gvarsymptr->level != ARGLEVEL)
+ error2error(gvarname, " not in argument list");
+ else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype)
+ multidecl(gvarname);
+ else
+ {
+ gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */
+ if (gvartype->constructor & (ARRAY | POINTER))
+ gvartype = pointype(gvartype->nexttype);
+ gvarsymptr->type = gvartype;
+ if (gvarsc == REGDECL && regdecl())
+ regarg = TRUE;
+ }
+}
+
+/*
+enum-specifier =
+ "enum" [identifier] "{" enumerator {, enumerator} "}"
+ | "enum" identifier.
+enumerator =
+ identifier
+ | identifier = constant-expression.
+*/
+
+PRIVATE struct typestruct *declenum()
+{
+ register struct symstruct *esymptr;
+ register struct typestruct *enumtype;
+ offset_t ordinal;
+
+ nextsym();
+ if (sym != IDENT && sym != TYPEDEFNAME)
+ enumtype = addstruct("");
+ else if ((esymptr = findstruct(gsname)) == NULL)
+ {
+ enumtype = addstruct(gsname);
+ nextsym();
+ }
+ else
+ {
+ nextsym();
+ enumtype = esymptr->type;
+ if (sym != LBRACE)
+ return enumtype;
+ if (esymptr->level != level)
+ enumtype = addstruct(esymptr->name.namea);
+ }
+ lbrace();
+ if (enumtype->typesize != 0)
+ multidecl(enumtype->tname);
+ else
+ {
+ enumtype->typesize = itypesize;
+ enumtype->alignmask = itype->alignmask;
+ }
+ if (sym != IDENT)
+ error("empty enumerator list");
+ ordinal = 0;
+ while (sym == IDENT)
+ {
+ if ((esymptr = gsymptr) != NULL && esymptr->level == level)
+ multidecl(gsname);
+ else
+ {
+ (esymptr = addlorg(gsname, itype))->storage = CONSTANT;
+ esymptr->indcount = 0;
+ }
+ nextsym();
+ if (sym == ASSIGNOP)
+ {
+ nextsym();
+ ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */
+ if (ordinal > maxintto)
+ ordinal -= (maxuintto + 1);
+ }
+ if (esymptr->storage == CONSTANT)
+ esymptr->offset.offv = ordinal++;
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ rbrace();
+ return enumtype;
+}
+
+/* declselt - get list of declarations for a structure/union member */
+
+PRIVATE void declselt(structype, psoffset, ptypelist)
+struct typestruct *structype;
+offset_t *psoffset;
+struct typelist **ptypelist;
+{
+ struct typestruct *basetype;
+ value_t fieldwidth;
+ value_t fwidth;
+ offset_t offset;
+ scalar_t scalar=0;
+
+ offset = *psoffset;
+ declspec();
+ if (gvarsc != NULLDECL)
+ error("illegal type name");
+ basetype = gvartype;
+ while (sym != SEMICOLON && sym != EOFSYM)
+ {
+ gvartype = basetype;
+ declarator();
+ fieldwidth = -1;
+ if (sym == COLON)
+ {
+ scalar = gvartype->scalar;
+ if (!(scalar & ISCALAR))
+ error("bitfield has non-integral type");
+ nextsym();
+ fwidth = constexpression();
+ if (fwidth < 0)
+ error("bitfield has negative width");
+ else if (fwidth > INT32BITSTO) /* XXX */
+ error("bitfield is too wide");
+ else
+ fieldwidth = fwidth;
+ }
+ if (gvarname[0] == 0)
+ {
+ if (fieldwidth == 0)
+ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask;
+ else
+ /* XXX - should really align to fieldwidth'th bit. */
+ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask;
+ }
+ else
+ {
+ if (fieldwidth == 0)
+ error("bitfield has zero width");
+ else if (fieldwidth > 0 && scalar & ISCALAR)
+ {
+ if (fieldwidth <= CHBITSTO) /* XXX! */
+ gvartype = ctype;
+ else if (fieldwidth <= INT32BITSTO) /* XXX */
+ gvartype = itype;
+ else
+ gvartype = ltype;
+ if (scalar & UNSIGNED)
+ gvartype = tounsigned(gvartype);
+ }
+ gvar2name[0] = structype->structkey[0];
+ gvar2name[1] = structype->structkey[1];
+ /* key provides unique name space */
+ if (findlorg(gvar2name) != NULL)
+ multidecl(gvarname);
+ else
+ {
+ (gvarsymptr = addlorg(gvar2name, gvartype))->storage
+ = NOSTORAGE;
+ structype->alignmask &= gvartype->alignmask;
+ offset = (gvarsymptr->offset.offi =
+ (offset+ ~gvartype->alignmask) & gvartype->alignmask)
+ + gvartype->typesize;
+ {
+ register struct typelist *newtypelist;
+
+ newtypelist = qmalloc(sizeof *newtypelist);
+#ifdef TS
+++ts_n_newtypelist;
+ts_s_newtypelist += sizeof *newtypelist;
+#endif
+ newtypelist->tlnext = NULL;
+ newtypelist->tltype = gvartype;
+ if (*ptypelist == NULL)
+ structype->listtype = newtypelist;
+ else
+ (*ptypelist)->tlnext = newtypelist;
+ *ptypelist = newtypelist;
+ }
+ }
+ }
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ semicolon();
+ *psoffset = offset;
+}
+
+PRIVATE bool_pt declspec()
+{
+ unsigned nsc;
+ unsigned ntype;
+ unsigned nunsigned;
+
+ gvarsc = NULLDECL;
+ gvartype = itype;
+ nunsigned = ntype = nsc = 0;
+ while (TRUE)
+ {
+ switch (sym)
+ {
+ case AUTODECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case ENUMDECL:
+ ++ntype;
+ declenum();
+ gvartype = itype; /* kludge - ignore type of enum */
+ break;
+ case EXTERNDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case REGDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case STATICDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case STRUCTDECL:
+ case UNIONDECL:
+ ++ntype;
+ gvartype = declsu();
+ break;
+ case TYPEDECL:
+ if (ntype == 1)
+ {
+ /* allow short int and long int */
+ if (gvartype == itype
+ && (gsymptr->type == stype || gsymptr->type == ltype))
+ ntype = 0;
+
+ /* allow int short and int long, blech */
+ if (gsymptr->type == itype
+ && (gvartype == stype || gvartype == ltype))
+ {
+ nextsym();
+ break;
+ }
+ }
+ ++ntype;
+ gvartype = gsymptr->type;
+ nextsym();
+ break;
+ case TYPEDEFDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case TYPEDEFNAME:
+ if (ntype != 0)
+ goto break2;
+ ++ntype;
+ gvartype = gsymptr->type;
+ nextsym();
+ break;
+ case UNSIGNDECL:
+ ++nunsigned;
+ nextsym();
+ break;
+ default:
+ goto break2;
+ }
+ }
+break2:
+ if (nunsigned > 0)
+ {
+ if (ntype == 0)
+ {
+ gvartype = uitype;
+ ntype = 1;
+ }
+ gvartype = tounsigned(gvartype);
+ if (nunsigned > 1)
+ ntype = 2;
+ }
+ if (nsc > 0)
+ {
+ if (ntype == 0)
+ ntype = 1;
+ if (nsc > 1)
+ error("multiple storage classes in declaration");
+ }
+ if (ntype > 1)
+ error("multiple types in declaration");
+ return nsc > 0 || ntype > 0;
+}
+
+/* declsu - get structure or union name and/or declaration, return type */
+
+PRIVATE struct typestruct *declsu()
+{
+ sym_t ogvarsc;
+ offset_t soffset;
+ offset_t struclength;
+ sym_t susym;
+ struct typelist *typelist;
+ struct typestruct *structype;
+
+ susym = sym;
+ nextsym();
+ if (sym != IDENT && sym != TYPEDEFNAME)
+ structype = addstruct("");
+ else if ((gvarsymptr = findstruct(gsname)) == NULL)
+ {
+ structype = addstruct(gsname);
+ nextsym();
+ }
+ else
+ {
+ nextsym();
+ if (sym == LBRACE && gvarsymptr->level != level)
+ structype = addstruct(gvarsymptr->name.namea);
+ else
+ structype = gvarsymptr->type;
+ }
+ if (sym != LBRACE)
+ return structype;
+ if (structype->typesize != 0)
+ multidecl(structype->tname);
+ nextsym();
+ ogvarsc = gvarsc;
+ struclength = soffset = 0;
+ typelist = NULL;
+ while (sym != RBRACE && sym != EOFSYM)
+ {
+ declselt(structype, &soffset, &typelist);
+ if (susym == STRUCTDECL)
+ struclength = soffset;
+ else
+ {
+ if (struclength < soffset)
+ struclength = soffset;
+ soffset = 0;
+ }
+ }
+ structype->typesize = (struclength + ~structype->alignmask) &
+ structype->alignmask;
+ rbrace();
+ gvarsc = ogvarsc;
+ return structype;
+}
+
+/* declfunc() - function name and parameter list */
+
+PRIVATE void declfunc()
+{
+ offset_t argsp;
+ uoffset_t argsize;
+ struct symstruct *symptr;
+
+ strcpy(funcname, gvarname);
+ if (gvarsymptr == NULL)
+ gvarsymptr = addglb(gvarname, gvartype);
+ else if (gvarsymptr->type != gvartype ||
+ (gvarsymptr->flags & INITIALIZED))
+ multidecl(gvarname); /* different type or full declare */
+ gvarsymptr->flags = INITIALIZED; /* show full declare */
+ cseg();
+ if (gvarsc == STATICDECL)
+ private(gvarname); /* don't need to put STATIC in flags */
+ else
+ public(gvarname);
+ callee1mask = calleemask;
+#ifdef FRAMEPOINTER
+ frame1list = framelist;
+#endif
+ func1saveregsize = funcsaveregsize;
+#if 0
+ if ((returntype = gvartype->nexttype)->scalar & RSCALAR)
+#else
+ if ((returntype = gvartype->nexttype)->scalar & DOUBLE)
+#endif
+ {
+ callee1mask &= ~doublreturnregs;
+#ifdef FRAMEPOINTER
+ frame1list &= ~doublreturnregs;
+#endif
+ func1saveregsize = funcdsaveregsize;
+ }
+
+ arg1size = /* would already be 0 unless last function empty */
+#ifdef FRAMEPOINTER
+ framep =
+ stackarg =
+#endif
+ reguse = 0; /* would already be 0 unless last f had reg vars */
+ decllist();
+ argsp = returnadrsize;
+ if (returntype->constructor & STRUCTU)
+ argsp += ptypesize;
+ softsp = -func1saveregsize;
+ for (symptr = &locsyms[0];
+ symptr < locptr && symptr->flags != STRUCTNAME &&
+ *symptr->name.namea >= 'A';
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ {
+ /* convert arg sizes to offsets */
+ if (symptr->type == fltype)
+ symptr->type = dtype;
+ argsize = symptr->type->typesize;
+#ifdef FRAMEPOINTER
+ if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR)
+ stackarg = TRUE;
+#endif
+ if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR)
+ {
+ if ((arg1size = argsize) < itypesize)
+ arg1size = itypesize;
+ argsp = softsp -= arg1size;
+ }
+#if BIG_ENDIAN
+ if (argsize < itypesize)
+ argsp += itypesize - argsize;
+ symptr->offset.offi = argsp;
+ argsp += argsize;
+#else
+ symptr->offset.offi = argsp;
+ if (argsize > itypesize)
+ argsp += argsize;
+ else
+ argsp += itypesize;
+#endif
+ if (arg1inreg && symptr == &locsyms[0])
+ argsp = returnadrsize; /* skip return adr after 1st arg */
+ }
+ lbrace();
+ compound();
+ clearfunclabels();
+}
+
+/* idecllist() - list of init-declarations with a given base type */
+/* this does the non-terminal symbols list( init-declarator ) ";" */
+/* and list( type-declaration ) ";" */
+/* and complete declarations of functions */
+
+PRIVATE void idecllist()
+{
+ struct typestruct *basetype;
+ struct typestruct *inittype;
+ scopelev_t levelmark;
+ uoffset_t newoffset;
+
+ argsallowed = level == GLBLEVEL;
+ levelmark = level;
+ basetype = gvartype;
+ while (sym != SEMICOLON)
+ {
+ gvartype = basetype;
+ declarator();
+ if (gvarname[0] == 0)
+ needvarname();
+ if (gvartype->constructor == FUNCTION)
+ {
+ if (sym != COMMA && sym != SEMICOLON)
+ {
+ if (level == ARGLEVEL && gvarsc != TYPEDEFDECL)
+ declfunc();
+ else
+ error("illegal non-external function");
+ if (level != levelmark)
+ {
+ oldlevel();
+ locptr = &locsyms[0];
+ }
+ argsallowed = FALSE;
+ return;
+ }
+ }
+ if (level != levelmark)
+ {
+ oldlevel();
+ locptr = &locsyms[0];
+ }
+ argsallowed = FALSE;
+ if (level == ARGLEVEL)
+ {
+ if (gvarsymptr == NULL)
+ gvarsymptr = addglb(gvarname, gvartype); /* error soon */
+ declarg();
+ }
+ else if (gvarsymptr != NULL && (gvarsymptr->level == level ||
+ gvartype->constructor == FUNCTION ||
+ (gvarsc == EXTERNDECL &&
+ gvarsymptr->level == GLBLEVEL)))
+ {
+ if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD)
+ multidecl(gvarname);
+ else if (gvarsymptr->type != gvartype)
+ {
+ if (gvartype->constructor != ARRAY ||
+ gvarsymptr->type->constructor != ARRAY ||
+ gvartype->nexttype != gvarsymptr->type->nexttype ||
+ (gvartype->typesize != 0 &&
+ gvarsymptr->type->typesize != 0))
+ multidecl(gvarname);
+ else if (gvartype->typesize != 0)
+ gvarsymptr->type = gvartype;
+ }
+ if (gvarsc == NULLDECL)
+ gvarsymptr->flags &= ~EXTERNAL;
+ }
+ else if (level == GLBLEVEL || gvartype->constructor == FUNCTION ||
+ gvarsc == EXTERNDECL)
+ {
+ gvarsymptr = addglb(gvarname, gvartype);
+#ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */
+ if (!(gvartype->constructor & ~POINTER))
+ gvarsymptr->flags = DIRECTPAGE;
+#endif
+ if (gvarsc == EXTERNDECL)
+ gvarsymptr->flags |= EXTERNAL;
+ }
+ else
+ {
+ gvarsymptr = addloc(gvarname, gvartype);
+ if ((gvarsc != REGDECL || !regdecl()) &&
+ gvartype->constructor != FUNCTION && gvarsc != STATICDECL &&
+ gvarsc != TYPEDEFDECL)
+ gvarsymptr->offset.offi = softsp =
+ (softsp & gvartype->alignmask) - gvartype->typesize;
+ }
+ if (gvarsc == STATICDECL)
+ {
+ gvarsymptr->flags &= ~EXTERNAL;
+ gvarsymptr->flags |= STATIC;
+ if (gvarsymptr->level != GLBLEVEL)
+ {
+ gvarsymptr->storage = GLOBAL;
+ gvarsymptr->offset.offlabel = getlabel();
+ /* must leave gvarsymptr->name.label alone */
+ /* since name is required for findlorg() */
+ /* label is activated by expression() */
+ }
+ }
+ if (gvarsc == TYPEDEFDECL)
+ {
+ gvarsymptr->flags = KEYWORD;
+ gvarsymptr->offset.offsym = TYPEDEFNAME;
+ }
+ if (sym == ASSIGNOP)
+ {
+ if (gvarsymptr->flags & INITIALIZED)
+ multidecl(gvarname);
+ nextsym();
+ if (level == GLBLEVEL || gvarsc == STATICDECL)
+ {
+#ifndef DIRECTPAGE
+ dseg();
+#else
+ if (gvarsymptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ if ((inittype = gvartype)->constructor == ARRAY)
+ inittype = inittype->nexttype;
+ newoffset = (dataoffset + ~inittype->alignmask)
+ & inittype->alignmask;
+ defnulls(newoffset - dataoffset);
+ dataoffset = newoffset;
+ if (gvarsc == STATICDECL)
+ {
+ if (level == GLBLEVEL)
+ private(gvarname);
+ else
+ outnlabel(gvarsymptr->offset.offlabel);
+ }
+ else
+ public(gvarname);
+ initlistflag = TRUE;
+ if (sym != LBRACE)
+ initlistflag = FALSE;
+ inititem(gvartype);
+ dataoffset += (gvarsymptr->type = gvartype)->typesize;
+ if (gvarsymptr->level == GLBLEVEL)
+ gvarsymptr->flags |= INITIALIZED;
+ if (level != GLBLEVEL)
+ cseg();
+ }
+ else
+ {
+ if (gvarsc == EXTERNDECL)
+ error("initialization of externs is illegal");
+ switch (gvartype->constructor)
+ {
+ case ARRAY:
+ error("initialization of auto arrays is illegal");
+ break;
+ case FUNCTION:
+ error("initialization of functions is illegal");
+ break;
+ default:
+ initexpression(gvartype);
+ break;
+ }
+ }
+ }
+ else if (level != GLBLEVEL && gvarsc == STATICDECL &&
+ gvartype->constructor != FUNCTION)
+ {
+#ifndef DIRECTPAGE
+ bssseg();
+#else
+ if (gvarsymptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ lcommlab(gvarsymptr->offset.offlabel);
+ outnhex(gvartype->typesize);
+ cseg();
+ }
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ semicolon();
+ argsallowed = FALSE;
+}
+
+PRIVATE void initarray(type)
+struct typestruct *type;
+{
+ uoffset_t basesize;
+ struct typestruct *basetype;
+ uoffset_t dimension;
+ char *stringend;
+ uoffset_t stringlength;
+ uoffset_t remaining;
+
+ if ((basesize = (basetype = type->nexttype)->typesize) == 0)
+ dimension = remaining = 0;
+ else
+ dimension = remaining = type->typesize / basesize;
+ if (sym == STRINGCONST && (basetype->scalar & CHAR))
+ {
+ stringlength = (stringend = charptr) - constant.value.s;
+ if (remaining != 0 && stringlength >= remaining)
+ /* same dim should be allowed but defstr always nullterms */
+ {
+ error("string longer than dimension");
+ stringend = constant.value.s + (/* size_t */ unsigned)
+ (stringlength = remaining - 1);
+ }
+ defstr(constant.value.s, stringend, TRUE);
+ remaining -= (stringlength + 1);
+ nextsym();
+ }
+ else
+ do
+ inititem(basetype);
+ while (--remaining != 0 && sym == COMMA && initlistflag &&
+ (nextsym(), sym != RBRACE));
+ if (dimension == 0)
+ {
+ if (type == gvartype)
+ gvartype = prefix(ARRAY, -remaining * basesize, basetype);
+ }
+ else
+ defnulls(remaining * basesize);
+}
+
+PRIVATE void inititem(type)
+struct typestruct *type;
+{
+ sym_t startsym;
+
+ if ((startsym = sym) == LBRACE)
+ nextsym();
+ switch (type->constructor)
+ {
+ case ARRAY:
+ initarray(type);
+ break;
+ case STRUCTU:
+ initstruct(type);
+ break;
+ case FUNCTION:
+ error("initialization of functions is illegal");
+ break;
+ default:
+ initexpression(type);
+ }
+ if (startsym == LBRACE)
+ {
+ if (sym == COMMA)
+ {
+ nextsym();
+ if (sym != RBRACE)
+ error("too many initializers");
+ }
+ rbrace();
+ }
+}
+
+PRIVATE void initstruct(type)
+struct typestruct *type;
+{
+ struct typestruct *memtype;
+ uoffset_t newoffset;
+ uoffset_t offset;
+ struct typelist *typelist;
+
+ offset = 0;
+ if ((typelist = type->listtype) != NULL)
+ do
+ {
+ memtype = typelist->tltype;
+ newoffset = (offset + ~memtype->alignmask) & memtype->alignmask;
+ defnulls(newoffset - offset);
+ offset = newoffset + memtype->typesize;
+ inititem(memtype);
+ }
+ while ((typelist = typelist->tlnext) != NULL && sym == COMMA &&
+ initlistflag && (nextsym(), sym != RBRACE));
+ /* eof here will break next time */
+ defnulls(type->typesize - offset);
+}
+
+PRIVATE void lbrace()
+{
+ if (sym != LBRACE)
+ need('{');
+ else
+ nextsym();
+}
+
+PUBLIC void lparen()
+{
+ if (sym != LPAREN)
+ need('(');
+ else
+ nextsym();
+}
+
+PRIVATE void multidecl(sname)
+char *sname;
+{
+ error2error(sname, " already declared");
+}
+
+PRIVATE void need(charneeded)
+int charneeded;
+{
+ static char message[] = "need 'x'";
+
+ message[6] = charneeded;
+ error(message);
+}
+
+PUBLIC void needvarname()
+{
+ error("need variable name");
+ nextsym();
+}
+
+PUBLIC void program()
+{
+ if (orig_cppmode)
+ cppscan();
+ else
+ {
+ nextsym();
+ while (sym != EOFSYM)
+ {
+ declspec();
+ idecllist();
+ }
+ }
+}
+
+PUBLIC void rbrace()
+{
+ if (sym != RBRACE)
+ need('}');
+ else
+ nextsym();
+}
+
+PUBLIC void rbracket()
+{
+ if (sym != RBRACKET)
+ need(']');
+ else
+ nextsym();
+}
+
+PRIVATE void rdeclarator()
+{
+ while (sym == STAR)
+ {
+ nextsym();
+ gvartype = pointype(gvartype);
+ }
+ if (sym == LPAREN)
+ {
+ struct typestruct *pretype;
+ struct typestruct *sufftype;
+
+ nextsym();
+ sufftype = gvartype;
+ gvartype = ctype;
+ rdeclarator();
+ rparen();
+ pretype = gvartype;
+ gvartype = sufftype;
+ declaf();
+ gvartype = chainprefix(pretype, gvartype);
+ }
+ else if (sym == IDENT || sym == TYPEDEFNAME)
+ {
+ strcpy(gvarname, gsname);
+ gvarsymptr = gsymptr;
+ nextsym();
+ }
+ else
+ {
+ gvarname[0] = 0;
+ gvarsymptr = NULL;
+ }
+ declaf();
+}
+
+PRIVATE bool_pt regdecl()
+{
+ store_t regavail;
+
+#if !NOTFINISHED
+ if (gvarsymptr->type->constructor != POINTER)
+ return FALSE;
+#endif
+#ifdef MC6809
+ if (gvarsymptr->type->constructor != POINTER)
+ return FALSE;
+#endif
+ if (!(regavail = regregs & ~reguse))
+ return FALSE;
+ gvarsymptr->flags = REGVAR;
+ gvarsymptr->indcount = 0;
+#define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */
+ reguse |= gvarsymptr->storage = LOWBITMASK(regavail);
+ return TRUE;
+}
+
+PUBLIC void rparen()
+{
+ if (sym != RPAREN)
+ need(')');
+ else
+ nextsym();
+}
+
+PUBLIC void semicolon()
+{
+ if (sym != SEMICOLON)
+ need(';');
+ else
+ nextsym();
+}
+
+PUBLIC struct typestruct *typename()
+{
+ char ogvarname[NAMESIZE];
+ sym_t ogvarsc;
+ struct symstruct *ogvarsymptr;
+ struct typestruct *ogvartype;
+ struct typestruct *type;
+
+ /* the global variable data must be preserved */
+ /* although this is only called for casts and sizeof, */
+ /* the casts can be in initialisers */
+ /* and the sizeof in an array size expression */
+ strcpy(ogvarname, gvarname);
+ ogvarsc = gvarsc;
+ ogvarsymptr = gvarsymptr;
+ ogvartype = gvartype;
+ if (declspec())
+ {
+ declarator();
+ if (gvarsc != NULLDECL || gvarname[0] != 0)
+ error("illegal type name");
+ type = gvartype;
+ }
+ else
+ type = NULL;
+ strcpy(gvarname, ogvarname);
+ gvarsc = ogvarsc;
+ gvarsymptr = ogvarsymptr;
+ gvartype = ogvartype;
+ return type;
+}
diff --git a/bcc/express.c b/bcc/express.c
new file mode 100644
index 0000000..e6ee64c
--- /dev/null
+++ b/bcc/express.c
@@ -0,0 +1,466 @@
+/* express.c - expression parsing routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h" /* just for charptr for string constant */
+#include "type.h"
+
+PRIVATE unsigned insizeof; /* nest level for getsizeof */
+ /* used to avoid aborting undefined idents */
+ /* to 0 when they appear in a cpp expression */
+ /* under sizeof */
+
+/* names of expression functions are related to the 15 precedence levels */
+/* on p49 of K & R */
+
+FORWARD struct nodestruct *cast_exp P((void));
+FORWARD struct nodestruct *exp2 P((void));
+FORWARD struct nodestruct *exp3to12 P((fastin_pt lprecedence));
+FORWARD struct nodestruct *listargs P((void));
+FORWARD struct nodestruct *postfix_exp P((bool_pt seenlp));
+FORWARD struct nodestruct *primary_exp P((void));
+FORWARD struct nodestruct *unary_exp P((void));
+
+PRIVATE struct nodestruct *cast_exp()
+{
+ struct nodestruct *nodeptr;
+ scalar_t scalar;
+ struct typestruct *vartype;
+
+ if (sym != LPAREN)
+ return unary_exp();
+ nextsym();
+ if ((vartype = typename()) == NULL)
+ return postfix_exp(TRUE);
+ rparen();
+ scalar = (nodeptr = cast_exp())->nodetype->scalar;
+ if (vartype->scalar & INT && scalar & (CHAR | SHORT | INT)
+ && !((vartype->scalar ^ scalar) & UNSIGNED))
+ {
+ nodeptr->flags &= ~LVALUE;
+ return nodeptr; /* skip casts that are default promotions */
+ }
+ return castnode(vartype, nodeptr);
+}
+
+PUBLIC struct nodestruct *assignment_exp()
+{
+ struct nodestruct *lhs;
+ op_pt op;
+
+ lhs = exp2();
+ if (sym >= ASSIGNOP && sym <= SUBABOP) /* assign-op syms in order! */
+ {
+ op = sym;
+ nextsym();
+ lhs = node(op, lhs, assignment_exp());
+ }
+ return lhs;
+}
+
+PUBLIC struct nodestruct *expression()
+{
+ struct nodestruct *lhs;
+
+ lhs = assignment_exp();
+ while (sym == COMMA)
+ {
+ nextsym();
+ lhs = node(COMMAOP, lhs, assignment_exp());
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *exp2()
+{
+ struct nodestruct *lhs;
+ struct nodestruct *rhs;
+
+ lhs = exp3to12(0);
+ if (sym == CONDOP)
+ {
+ nextsym();
+ rhs = expression();
+ colon();
+ lhs = node(CONDOP, lhs, node(COLONOP, rhs, exp2()));
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *exp3to12(lprecedence)
+fastin_pt lprecedence;
+{
+ struct nodestruct *lhs;
+ op_pt op;
+ fastin_t rprecedence;
+
+ lhs = cast_exp();
+ while (TRUE)
+ {
+ rprecedence = 0;
+ switch (sym)
+ {
+ case LOGOROP:
+ if ((fastin_t) lprecedence <= 1)
+ rprecedence = 2;
+ break;
+ case LOGANDOP:
+ if ((fastin_t) lprecedence <= 3)
+ rprecedence = 4;
+ break;
+ case OROP:
+ if ((fastin_t) lprecedence <= 5)
+ rprecedence = 6;
+ break;
+ case EOROP:
+ if ((fastin_t) lprecedence <= 7)
+ rprecedence = 8;
+ break;
+ case AMPERSAND:
+ if ((fastin_t) lprecedence <= 9)
+ {
+ sym = ANDOP;
+ rprecedence = 10;
+ }
+ break;
+ case EQOP:
+ case NEOP:
+ if ((fastin_t) lprecedence <= 11)
+ rprecedence = 12;
+ break;
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case LTOP:
+ if ((fastin_t) lprecedence <= 13)
+ rprecedence = 14;
+ break;
+ case SLOP:
+ case SROP:
+ if ((fastin_t) lprecedence <= 15)
+ rprecedence = 16;
+ break;
+ case HYPHEN:
+ if ((fastin_t) lprecedence <= 17)
+ {
+ sym = SUBOP;
+ rprecedence = 18;
+ }
+ break;
+ case ADDOP:
+ if ((fastin_t) lprecedence <= 17)
+ rprecedence = 18;
+ break;
+ case STAR:
+ if ((fastin_t) lprecedence <= 19)
+ {
+ sym = MULOP;
+ rprecedence = 20;
+ }
+ break;
+ case DIVOP:
+ case MODOP:
+ if ((fastin_t) lprecedence <= 19)
+ rprecedence = 20;
+ break;
+ }
+ if (rprecedence == 0)
+ break;
+ op = sym;
+ nextsym();
+ lhs = node(op, lhs, exp3to12(rprecedence));
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *listargs()
+{
+ struct nodestruct *parent;
+ struct nodestruct *nextright;
+
+ if (sym == RPAREN)
+ {
+ nextsym();
+ return NULLNODE;
+ }
+ parent = node(arg1op, assignment_exp(), NULLNODE);
+ nextright = parent;
+ while (sym == COMMA)
+ {
+ nextsym();
+ nextright = nextright->right
+ = node(LISTOP, assignment_exp(), NULLNODE);
+ }
+ rparen();
+ return parent;
+}
+
+PRIVATE struct nodestruct *postfix_exp(seenlp)
+bool_pt seenlp;
+{
+ struct nodestruct *nodeptr;
+ struct symstruct *symptr;
+
+ if (seenlp)
+ {
+ nodeptr = expression();
+ rparen();
+ }
+ else
+ nodeptr = primary_exp();
+ while (TRUE)
+ {
+ switch (sym)
+ {
+ case DECSYM:
+ nextsym();
+ nodeptr = node(POSTDECOP, nodeptr, NULLNODE);
+ continue;
+ case INCSYM:
+ nextsym();
+ nodeptr = node(POSTINCOP, nodeptr, NULLNODE);
+ continue;
+ case LBRACKET:
+ nextsym();
+ nodeptr = node(INDIRECTOP, node(ADDOP, nodeptr, expression()),
+ NULLNODE);
+ rbracket();
+ continue;
+ case LPAREN:
+ nextsym();
+ nodeptr = node(FUNCOP, nodeptr, listargs());
+ {
+ register struct nodestruct *np;
+
+ for (np = nodeptr->right; np != NULL; np = np->right)
+ {
+ if (np->nodetype->scalar & RSCALAR)
+ {
+ np = nodeptr->left.nodeptr;
+ if (np->tag != LEAF)
+ printf_fp = TRUE;
+ else
+ {
+ unsigned len;
+ register char *name;
+
+ name = np->left.symptr->name.namep;
+ if ((len = strlen(name)) >= 6
+ && strcmp(name + len - 6, "printf") == 0)
+ printf_fp = TRUE;
+ }
+ break;
+ }
+ }
+ for (np = nodeptr->right; np != NULL; np = np->right)
+ {
+ if (np->nodetype->constructor & POINTER
+ && np->nodetype->nexttype->scalar & RSCALAR)
+ {
+ np = nodeptr->left.nodeptr;
+ if (np->tag != LEAF)
+ scanf_fp = TRUE;
+ else
+ {
+ unsigned len;
+ register char *name;
+
+ name = np->left.symptr->name.namep;
+ if ((len = strlen(name)) >= 5
+ && strcmp(name + len - 5, "scanf") == 0)
+ scanf_fp = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ continue;
+ case STRUCPTROP:
+ nodeptr = node(INDIRECTOP, nodeptr, NULLNODE);
+ case STRUCELTOP:
+ nextsym();
+ gs2name[0] = nodeptr->nodetype->structkey[0];
+ gs2name[1] = nodeptr->nodetype->structkey[1];
+ if ((gsymptr = findlorg(gs2name)) == NULL)
+ {
+ error("undefined structure element");
+ gsymptr = addglb(gs2name, itype);
+ }
+ symptr = exprsym(gsymptr);
+ nextsym();
+ nodeptr = node(STRUCELTOP, nodeptr, leafnode(symptr));
+ continue;
+ default:
+ return nodeptr;
+ }
+ }
+}
+
+PRIVATE struct nodestruct *primary_exp()
+{
+ bool_t isdefined;
+ struct nodestruct *nodeptr;
+ uoffset_t stringlen;
+ struct symstruct *symptr;
+ struct symstruct *symptr1;
+ bool_t waslparen;
+
+ switch (sym)
+ {
+ case IDENT:
+ if (incppexpr && !insizeof)
+ {
+cpp_ident:
+ nextsym();
+ return leafnode(constsym((value_t) 0));
+ }
+ if ((symptr = gsymptr) != NULL)
+ nextsym();
+ else
+ {
+ symptr = addglb(gsname, fitype);
+ nextsym();
+ if (sym != LPAREN)
+ {
+ error2error(symptr->name.namea, " undeclared");
+ symptr->indcount = 1;
+ symptr->type = itype;
+ }
+ }
+ symptr1 = exprsym(symptr);
+ if (symptr->flags & STATIC && symptr->level != GLBLEVEL)
+ {
+ symptr1->flags |= LABELLED;
+ symptr1->offset.offi = 0;
+ symptr1->name.label = symptr->offset.offlabel;
+ }
+ nodeptr = leafnode(symptr1);
+ if (!(nodeptr->nodetype->constructor & (ARRAY | FUNCTION | VOID)))
+ nodeptr->flags = LVALUE;
+ return nodeptr;
+ case TYPEDEFNAME:
+ if (incppexpr && !insizeof)
+ goto cpp_ident; /* else fall through */
+ default:
+ error("bad expression");
+ constant.value.v = 0;
+ constant.type = itype;
+ case CHARCONST:
+ case INTCONST: /* this includes enumeration-constants */
+ symptr = constsym(constant.value.v);
+ symptr->type = constant.type;
+ if (!(ltype->scalar & LONG))
+ {
+ if (symptr->type == ltype)
+ symptr->type = itype;
+ else if (symptr->type == ultype)
+ symptr->type = uitype;
+ }
+ nextsym();
+ return leafnode(symptr);
+ case DEFINEDSYM:
+ waslparen = isdefined = FALSE;
+ if (!blanksident())
+ {
+ nextsym();
+ if (sym != LPAREN)
+ lparen();
+ else
+ waslparen = TRUE;
+ }
+ if (waslparen && !blanksident())
+ needvarname();
+ else
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ isdefined = TRUE;
+ nextsym();
+ }
+ if (waslparen)
+ rparen();
+ return leafnode(constsym((value_t) isdefined));
+ case FLOATCONST:
+ symptr = constsym((value_t) 0);
+ symptr->type = constant.type;
+ symptr->offset.offd = qmalloc(sizeof *symptr->offset.offd);
+ *symptr->offset.offd = constant.value.d;
+ nextsym();
+ return leafnode(symptr);
+ case LPAREN:
+ nextsym();
+ nodeptr = expression();
+ rparen();
+ return nodeptr;
+ case STRINGCONST:
+ symptr = constsym((value_t) 0);
+ symptr->storage = GLOBAL;
+ symptr->flags = LABELLED | STRING;
+ /* string length before defstr() or prefix() updates charptr */
+ stringlen = charptr - constant.value.s + 1;
+ symptr->name.label = defstr(constant.value.s, charptr, FALSE);
+ symptr->type = prefix(ARRAY, stringlen, ctype);
+ nextsym();
+ return leafnode(symptr);
+ }
+}
+
+PRIVATE struct nodestruct *unary_exp()
+{
+ value_t size;
+ struct typestruct *vartype;
+
+ switch (sym)
+ {
+ case ADDOP:
+ nextsym();
+ return cast_exp();
+ case AMPERSAND:
+ nextsym();
+ return node(ADDRESSOP, cast_exp(), NULLNODE); /* maybe unary_exp */
+ case DECSYM:
+ nextsym();
+ return node(PREDECOP, unary_exp(), NULLNODE);
+ case HYPHEN:
+ nextsym();
+ return node(NEGOP, cast_exp(), NULLNODE);
+ case INCSYM:
+ nextsym();
+ return node(PREINCOP, unary_exp(), NULLNODE);
+ case LOGNOTOP:
+ nextsym();
+ return node(LOGNOTOP, cast_exp(), NULLNODE);
+ case NOTOP:
+ nextsym();
+ return node(NOTOP, cast_exp(), NULLNODE);
+ case SIZEOFSYM:
+ nextsym();
+ ++insizeof;
+ if (sym != LPAREN)
+ size = unary_exp()->nodetype->typesize;
+ else
+ {
+ nextsym();
+ if ((vartype = typename()) != NULL)
+ {
+ rparen();
+ size = vartype->typesize;
+ }
+ else
+ size = postfix_exp(TRUE)->nodetype->typesize;
+ }
+ --insizeof;
+ return leafnode(constsym(size));
+ case STAR:
+ nextsym();
+ return node(INDIRECTOP, cast_exp(), NULLNODE); /* maybe unary_exp */
+ }
+ return postfix_exp(FALSE);
+}
diff --git a/bcc/exptree.c b/bcc/exptree.c
new file mode 100644
index 0000000..c4da1c4
--- /dev/null
+++ b/bcc/exptree.c
@@ -0,0 +1,1087 @@
+/* exptree.c - expression tree routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#define ETREESIZE 1200
+#define errtype itype
+#define redtype ctype
+#define uredtype uctype
+
+PRIVATE struct nodestruct etree[ETREESIZE]; /* expression tree */
+PRIVATE struct nodestruct *ettop;
+
+FORWARD void badlvalue P((struct nodestruct *nodeptr));
+FORWARD void binconvert P((struct nodestruct *nodeptr));
+FORWARD void castiright P((struct nodestruct *nodeptr));
+FORWARD void etreefull P((void));
+FORWARD void fixnode P((struct nodestruct *nodeptr));
+FORWARD bool_pt isconst0 P((struct nodestruct *nodeptr));
+FORWARD bool_pt isnodecharconst P((struct nodestruct *nodeptr));
+FORWARD void needint P((struct nodestruct *nodeptr));
+FORWARD void neednonstruct P((struct nodestruct *nodeptr));
+FORWARD void needscalar P((struct nodestruct *nodeptr));
+FORWARD void needspv P((struct nodestruct *nodeptr));
+FORWARD struct typestruct *nodetype P((struct nodestruct *nodeptr));
+FORWARD int redscalar P((struct nodestruct *nodeptr));
+FORWARD struct nodestruct *unconvert P((struct nodestruct *nodeptr));
+
+PRIVATE void badlvalue(nodeptr)
+struct nodestruct *nodeptr;
+{
+ error("invalid lvalue");
+ fixnode(nodeptr);
+}
+
+PRIVATE void binconvert(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ bool_t bothscalar;
+ value_t divisor;
+ scalar_t lscalar;
+ register struct nodestruct *right;
+ scalar_t rscalar;
+
+ rscalar = (right = nodeptr->right)->nodetype->scalar;
+ lscalar = nodeptr->left.nodeptr->nodetype->scalar;
+ if ((bothscalar = lscalar | rscalar) & RSCALAR)
+ {
+ nodeptr->nodetype = dtype;
+ if (!(lscalar & DOUBLE))
+ nodeptr->left.nodeptr = castnode(dtype, nodeptr->left.nodeptr);
+ if (!(rscalar & DOUBLE))
+ nodeptr->right = castnode(dtype, right);
+ }
+ else if (!(bothscalar & DLONG) && ((nodeptr->tag == ANDOP &&
+ (redscalar(nodeptr->left.nodeptr) | redscalar(right)) & CHAR) ||
+ ((nodeptr->tag == EOROP || nodeptr->tag == OROP) &&
+ redscalar(nodeptr->left.nodeptr) & redscalar(right) & CHAR) ||
+ (nodeptr->tag == MODOP && right->tag == LEAF &&
+ right->left.symptr->storage == CONSTANT &&
+ (divisor = right->left.symptr->offset.offv,
+ (uvalue_t) divisor <= MAXUCHTO + 1) &&
+ bitcount((uvalue_t) divisor) <= 1)))
+ {
+ /* result fits in char and extends correctly */
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uredtype;
+ else
+ nodeptr->nodetype = redtype;
+ }
+ else if (bothscalar & LONG)
+ {
+ nodeptr->nodetype = ltype;
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = ultype;
+ if (bothscalar & (DLONG | SHORT | INT))
+ {
+ /* XXX - otherwise both are long, or one is long with the same
+ * size as int and the other is char, and we want the lower level
+ * routines to handle the char.
+ */
+ if (!(lscalar & LONG))
+ nodeptr->left.nodeptr = castnode(nodeptr->nodetype,
+ nodeptr->left.nodeptr);
+ if (!(rscalar & LONG))
+ nodeptr->right = castnode(nodeptr->nodetype, right);
+ }
+ }
+#ifdef I8088
+ else if (i386_32 && bothscalar & SHORT)
+ {
+ nodeptr->nodetype = itype;
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uitype;
+ if (lscalar & SHORT)
+ nodeptr->left.nodeptr = castnode(nodeptr->nodetype,
+ nodeptr->left.nodeptr);
+ if (rscalar & SHORT)
+ nodeptr->right = castnode(nodeptr->nodetype, right);
+ }
+#endif
+ else if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uitype;
+ else
+ nodeptr->nodetype = itype;
+}
+
+PRIVATE void castiright(nodeptr)
+struct nodestruct *nodeptr;
+{
+ nodeptr->right = castnode(itype, nodeptr->right);
+}
+
+PUBLIC struct nodestruct *castnode(type, nodeptr)
+struct typestruct *type;
+struct nodestruct *nodeptr;
+{
+ struct symstruct *symptr;
+
+ (symptr = constsym((value_t) 0))->type = type;
+ return node(CASTOP, nodeptr, leafnode(symptr));
+}
+
+PRIVATE void etreefull()
+{
+ limiterror("expression too complex (1201 nodes)");
+}
+
+PUBLIC void etreeinit()
+{
+ ettop = (etptr = etree) + ETREESIZE;
+}
+
+PRIVATE void fixnode(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ nodeptr->tag = LEAF;
+ nodeptr->flags = nodeptr->weight = 0;
+ nodeptr->left.symptr = constsym((value_t) 0); /* this has type errtype */
+ nodeptr->nodetype = errtype;
+}
+
+PRIVATE bool_pt isconst0(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ register struct symstruct *symptr;
+
+ return nodeptr->tag == LEAF &&
+ (symptr = nodeptr->left.symptr)->storage == CONSTANT &&
+ symptr->offset.offv == 0 &&
+ symptr->type->scalar & ISCALAR;
+}
+
+PRIVATE bool_pt isnodecharconst(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ register struct symstruct *symptr;
+
+ if (nodeptr->tag == LEAF &&
+ (symptr = nodeptr->left.symptr)->storage == CONSTANT &&
+ ischarconst(symptr->offset.offv) &&
+ symptr->type->scalar & ISCALAR)
+ return TRUE;
+ return FALSE;
+}
+
+PUBLIC struct nodestruct *leafnode(source)
+struct symstruct *source;
+{
+ register struct nodestruct *leafptr;
+
+ if ((leafptr = etptr++) >= ettop)
+ etreefull();
+ leafptr->tag = LEAF;
+ leafptr->flags = leafptr->weight = 0;
+ leafptr->nodetype = source->type;
+ leafptr->left.symptr = source;
+ leafptr->right = NULL;
+ return leafptr;
+}
+
+PRIVATE void needint(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (!(nodeptr->nodetype->scalar & ISCALAR))
+ {
+ error("need integral type");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void neednonstruct(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & STRUCTU)
+ {
+ error("need non-structure type");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void needscalar(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (!nodeptr->nodetype->scalar)
+ {
+ error("need scalar");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void needspv(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION | STRUCTU))
+ {
+ error("need scalar or pointer or void");
+ fixnode(nodeptr);
+ }
+}
+
+PUBLIC struct nodestruct *node(t, p1, p2)
+op_pt t;
+struct nodestruct *p1;
+struct nodestruct *p2;
+{
+#if MAXREGS != 1
+ weight_t rightweight;
+#endif
+ double dsourceval = 0; /* for -Wall */
+ double dtargval = 0 ; /* for -Wall */
+ bool_t lflag;
+ scalar_t lscalar;
+ struct nodestruct *pswap;
+ struct symstruct *source = NULL; /* for -Wall */
+ value_t sourceval = 0 ; /* for -Wall */
+ struct symstruct *target;
+ offset_t targszdelta;
+ value_t targval = 0; /* for -Wall */
+ scalar_t rscalar = 0; /* for -Wall */
+ bool_t uflag;
+
+ switch ((op_t) t)
+ {
+ case ADDABOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ t = PTRADDABOP;
+ break;
+ case ADDOP:
+ if (p2->nodetype->constructor & (ARRAY | POINTER))
+ {
+ pswap = p1;
+ p1 = p2;
+ p2 = pswap;
+ }
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ t = PTRADDOP;
+ break;
+ case CONDOP:
+ /* Change structs to struct pointers so condop() doesn't have to know
+ * about structs.
+ */
+ if (p2->nodetype->constructor & STRUCTU)
+ {
+ p2 = node(COLONOP, node(ADDRESSOP, p2->left.nodeptr, NULLNODE),
+ node(ADDRESSOP, p2->right, NULLNODE));
+ return node(INDIRECTOP, node(CONDOP, p1, p2), NULLNODE);
+ }
+ break;
+ case FUNCOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ p1 = node(INDIRECTOP, p1, NULLNODE);
+ break;
+ case SUBABOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ {
+ t = PTRADDABOP;
+ p2 = node(NEGOP, p2, NULLNODE);
+ break;
+ }
+ case SUBOP:
+#if 0
+ /* This works but sometimes pessimizes the code by converting small
+ * constants into large negative constants. It makes the most
+ * difference for longs by avoiding stack tangles. longop could be
+ * more careful. Only the case (regpair) - constant is naturally
+ * tangled.
+ */
+ if (p2->tag == LEAF && p2->nodetype->scalar
+ && (source = p2->left.symptr)->storage == CONSTANT)
+ {
+ if (source->type->scalar & RSCALAR)
+ *source->offset.offd = -*source->offset.offd;
+ else
+ source->offset.offv = -source->offset.offv;
+ return node((op_t) t == SUBOP ? ADDOP : ADDABOP, p1, p2);
+ }
+#endif
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ {
+ if (p2->nodetype->nexttype == p1->nodetype->nexttype)
+ t = PTRSUBOP;
+ else
+ {
+ t = PTRADDOP;
+ p2 = node(NEGOP, p2, NULLNODE);
+ }
+ }
+ break;
+ }
+ if (((op_t) t == PTRADDABOP || (op_t) t == PTRADDOP) &&
+ p1->nodetype->nexttype->constructor & (FUNCTION | VOID))
+ error("arithmetic on pointer to function or void");
+ if (p1->tag != LEAF)
+ goto node1;
+ target = p1->left.symptr;
+ switch ((op_t) t)
+ {
+ case ADDRESSOP:
+ if (target->indcount == 0 && target->flags == REGVAR)
+ error("register variable addressed");
+ else if (target->type->constructor & ARRAY)
+ {
+ if (target->indcount != 0)
+ bugerror("botched array indirection count");
+ target->type = pointype(target->type);
+ }
+ else if (!(p1->flags & LVALUE))
+ badlvalue(p1);
+ else
+ {
+ address(target); /* change p1, no code generated */
+ if (target->indcount == 2) /* XXX - MAXINDIRECT? */
+ /* just became direct enough */
+ p1->weight = 1;
+ }
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ case CASTOP:
+ needspv(p2);
+ if (p1->nodetype == p2->nodetype)
+ {
+ p1->flags &= ~LVALUE;
+ return p1;
+ }
+ if ((rscalar = p2->nodetype->scalar) & ISCALAR)
+ neednonstruct(p1);
+ else if (rscalar & RSCALAR)
+ needscalar(p1);
+ else /* POINTER */
+ neednonstruct(p1); /* H & S say functions & arrays must match */
+ if (((lscalar = p1->nodetype->scalar) | rscalar) & RSCALAR)
+ {
+ if (target->storage != CONSTANT)
+ goto node1;
+ if (lscalar & RSCALAR && !(rscalar & RSCALAR))
+ {
+ double val;
+ static double MAXULONG = (double)0xFFFFFFFFL +1;
+
+ val = *target->offset.offd;
+ if (val > maxlongto)
+ val -= MAXULONG;
+ target->offset.offv = (value_t) val;
+ }
+ if (!(lscalar & RSCALAR) && rscalar & RSCALAR)
+ {
+ value_t val;
+
+ val = target->offset.offv;
+ target->offset.offd = qmalloc(sizeof *target->offset.offd);
+ if (lscalar & UNSIGNED)
+ *target->offset.offd = (uvalue_t) val;
+ else
+ *target->offset.offd = val;
+ }
+ }
+ if (target->storage == CONSTANT)
+ {
+ if (rscalar & CHAR)
+ target->offset.offv &= CHMASKTO;
+ else if (rscalar & SHORT)
+ {
+ target->offset.offv &= shortmaskto;
+ if (!(rscalar & UNSIGNED) && target->offset.offv > maxshortto)
+ target->offset.offv -= (maxushortto + 1);
+ }
+ else if (rscalar & INT)
+ {
+ target->offset.offv &= intmaskto;
+ if (!(rscalar & UNSIGNED) && target->offset.offv > maxintto)
+ target->offset.offv -= (maxuintto + 1);
+ }
+ else if (rscalar & FLOAT)
+ *target->offset.offd = (float) *target->offset.offd;
+ }
+ else if ((targszdelta =
+ ((p1->nodetype->constructor & (ARRAY | POINTER)) ?
+ ptypesize : p1->nodetype->typesize) -
+ p2->nodetype->typesize) == 0)
+ ;
+ else if (target->indcount == 1 && targszdelta > 0 &&
+ target->flags != REGVAR)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+# if BIG_ENDIAN
+ target->offset.offi += targszdelta;
+# else
+ {
+ if (lscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+# endif
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+# if BIG_ENDIAN
+ {
+ if (rscalar & CHAR)
+ target->offset.offi += ctypesize;
+ }
+# else
+ ;
+# endif
+#endif
+ }
+ else
+ goto node1;
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type = p2->nodetype;
+ return p1;
+ case INDIRECTOP:
+ if (!(target->type->constructor & (ARRAY | POINTER)))
+ error("illegal indirection");
+ else
+ {
+ indirec(target);
+ if (target->indcount == 3) /* XXX - MAXINDIRECT + 1? */
+ /* just became too indirect */
+ p1->weight = 1;
+ p1->flags |= LVALUE;
+ p1->nodetype = target->type;
+ }
+ return p1;
+ case STRUCELTOP: /* p2 known leaf */
+ if (target->indcount != 1)
+ break; /* struc() would generate code */
+ struc(p2->left.symptr, target);
+ p1->flags |= LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ }
+ if (target->indcount != 0)
+ goto node1;
+ lscalar = target->type->scalar;
+ if (target->storage == CONSTANT)
+ {
+ if (lscalar & RSCALAR)
+ dtargval = *target->offset.offd;
+ else
+ targval = target->offset.offv;
+ switch ((op_t) t)
+ {
+ case COMMAOP:
+ return p2;
+ case CONDOP:
+ if ((lscalar & RSCALAR && dtargval != FALSE)
+ || (!(lscalar & RSCALAR) && targval != FALSE))
+ {
+ p2->left.nodeptr->nodetype = p2->nodetype;
+ return p2->left.nodeptr;
+ }
+ p2->right->nodetype = p2->nodetype;
+ return p2->right;
+ case LOGANDOP:
+ if ((lscalar & RSCALAR && dtargval != FALSE)
+ || (!(lscalar & RSCALAR) && targval != FALSE))
+ break;
+ p1->nodetype = target->type = itype;
+ return p1;
+ case LOGOROP:
+ if ((lscalar & RSCALAR && dtargval == FALSE)
+ || (!(lscalar & RSCALAR) && targval == FALSE))
+ break;
+ target->offset.offv = TRUE;
+ p1->nodetype = target->type = itype;
+ return p1;
+ }
+ }
+ switch ((op_t) t)
+ {
+ case COLONOP:
+ case FUNCOP:
+ case LISTOP:
+ case ROOTLISTOP:
+ goto node1;
+ case PTRADDOP:
+ if (p2->tag == LEAF &&
+ (source = p2->left.symptr)->storage == CONSTANT &&
+ source->type->scalar & ISCALAR)
+ {
+ indexadr(source, target);
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ }
+ }
+ if (target->storage != CONSTANT ||
+ !((lscalar & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP) ||
+ (p2 != NULL &&
+ (p2->tag != LEAF || (source = p2->left.symptr)->storage != CONSTANT ||
+ (!((rscalar = source->type->scalar) & (ISCALAR | RSCALAR))
+ && (op_t) t != PTRSUBOP))))
+ goto node1;
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ if (p2 != NULL)
+ {
+ if (rscalar & RSCALAR)
+ dsourceval = *source->offset.offd;
+ else
+ {
+ sourceval = source->offset.offv;
+ lflag |= rscalar & LONG;
+ uflag |= rscalar & UNSIGNED;
+ }
+ }
+ if (lscalar & RSCALAR || (p2 != NULL && rscalar & RSCALAR))
+ {
+ if (!(lscalar & RSCALAR))
+ {
+ if (uflag)
+ dtargval = (uvalue_t) targval;
+ else
+ dtargval = targval;
+ }
+ if (p2 != NULL && !(rscalar & RSCALAR))
+ {
+ if (rscalar & UNSIGNED)
+ dsourceval = (uvalue_t) sourceval;
+ else
+ dsourceval = sourceval;
+ }
+ switch ((op_t) t)
+ {
+ case ADDOP:
+ dtargval += dsourceval;
+ break;
+ case DIVOP:
+ if (dsourceval == 0)
+ {
+ error("divison by 0");
+ dsourceval = 1;
+ }
+ dtargval /= dsourceval;
+ break;
+ case EQOP:
+ targval = dtargval == dsourceval;
+ goto intconst;
+ case GEOP:
+ targval = dtargval >= dsourceval;
+ goto intconst;
+ case GTOP:
+ targval = dtargval > dsourceval;
+ goto intconst;
+ case LEOP:
+ targval = dtargval <= dsourceval;
+ goto intconst;
+ case LOGANDOP:
+ targval = dtargval && dsourceval;
+ goto intconst;
+ case LOGNOTOP:
+ targval = !dtargval;
+ goto intconst;
+ case LOGOROP:
+ targval = dtargval || dsourceval;
+ goto intconst;
+ case LTOP:
+ targval = dtargval < dsourceval;
+ goto intconst;
+ case MULOP:
+ dtargval *= dsourceval;
+ break;
+ case NEGOP:
+ dtargval = -dtargval;
+ break;
+ case NEOP:
+ targval = dtargval != dsourceval;
+ goto intconst;
+ case SUBOP:
+ dtargval -= dsourceval;
+ break;
+ }
+ /* XXX - leaks memory */
+ target->offset.offd = qmalloc(sizeof *target->offset.offd);
+ *target->offset.offd = dtargval;
+ p1->nodetype = target->type = dtype;
+ return p1;
+ }
+ switch ((op_t) t)
+ {
+ case ADDOP:
+ targval += sourceval;
+ break;
+ case ANDOP:
+ targval &= sourceval;
+ break;
+ case DIVOP:
+ if (sourceval == 0)
+ {
+ error("divison by 0");
+ sourceval = 1;
+ }
+ if (uflag)
+ targval = (uvalue_t) targval / sourceval;
+ else
+ targval /= sourceval;
+ break;
+ case EOROP:
+ targval ^= sourceval;
+ break;
+ case EQOP:
+ targval = targval == sourceval;
+ break;
+ case GEOP:
+ if (uflag)
+ targval = (uvalue_t) targval >= sourceval;
+ else
+ targval = targval >= sourceval;
+ goto intconst;
+ case GTOP:
+ if (uflag)
+ targval = (uvalue_t) targval > sourceval;
+ else
+ targval = targval > sourceval;
+ goto intconst;
+ case LEOP:
+ if (uflag)
+ targval = (uvalue_t) targval <= sourceval;
+ else
+ targval = targval <= sourceval;
+ goto intconst;
+ case LOGANDOP:
+ targval = targval && sourceval;
+ goto intconst;
+ case LOGNOTOP:
+ targval = !targval;
+ goto intconst;
+ case LOGOROP:
+ targval = targval || sourceval;
+ goto intconst;
+ case LTOP:
+ if (uflag)
+ targval = (uvalue_t) targval < sourceval;
+ else
+ targval = targval < sourceval;
+ goto intconst;
+ break;
+ case MODOP:
+ if (sourceval == 0)
+ {
+ error("modulo by 0");
+ sourceval = 1;
+ }
+ if (uflag)
+ targval = (uvalue_t) targval % sourceval;
+ else
+ targval %= sourceval;
+ break;
+ case MULOP:
+ targval *= sourceval;
+ break;
+ case NEGOP:
+ targval = -targval;
+ break;
+ case NEOP:
+ targval = targval != sourceval;
+ goto intconst;
+ case NOTOP:
+ targval = ~targval;
+ break;
+ case OROP:
+ targval |= sourceval;
+ break;
+ case PTRSUBOP:
+ if (targval < sourceval)
+ targval = -((uvalue_t) (sourceval - targval) /
+ target->type->nexttype->typesize);
+ else
+ targval = (uvalue_t) (targval - sourceval) /
+ target->type->nexttype->typesize;
+ uflag = FALSE;
+ break;
+ case SLOP:
+ targval <<= sourceval; /* assume shiftcount treated as unsigned */
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ break;
+ case SROP:
+ if (uflag)
+ targval = (uvalue_t) targval >> sourceval;
+ else
+ targval >>= sourceval;
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ break;
+ case SUBOP:
+ targval -= sourceval;
+ break;
+ }
+ if (lflag)
+ {
+ target->type = ltype;
+ if (uflag)
+ target->type = ultype;
+ }
+ else
+ {
+ targval &= intmaskto;
+ if (uflag)
+ target->type = uitype;
+ else
+ {
+ target->type = itype;
+ if (targval > maxintto)
+ targval -= (maxuintto + 1);
+ }
+ }
+ target->offset.offv = targval;
+ p1->nodetype = target->type;
+ return p1;
+
+intconst:
+ target->offset.offv = targval;
+ p1->nodetype = target->type = itype;
+ return p1;
+
+node1:
+ {
+ register struct nodestruct *nodeptr;
+ register struct nodestruct *regp2;
+
+ if ((nodeptr = etptr++) >= ettop)
+ etreefull();
+ regp2 = p2;
+ nodeptr->tag = t;
+ nodeptr->left.nodeptr = p1;
+ nodeptr->right = regp2;
+ if ((op_t) t == FUNCOP)
+ nodeptr->weight = MAXREGS + 1;
+ else
+ {
+#if MAXREGS == 1
+ if ((nodeptr->weight = p1->weight) <= MAXREGS &&
+ (regp2 == NULL ||
+ (nodeptr->weight = regp2->weight) < MAXREGS))
+ nodeptr->weight = MAXREGS;
+#else
+ nodeptr->weight = p1->weight;
+ if (regp2 == NULL)
+ rightweight = 1; /* could do POST-ops with 0 */
+ else /* 0 more approp for LIST-ops but 1 OK */
+ rightweight = regp2->weight;
+ if (nodeptr->weight < rightweight)
+ nodeptr->weight = rightweight;
+ else if (nodeptr->weight == rightweight &&
+ nodeptr->weight < MAXREGS)
+ ++nodeptr->weight;
+#endif
+ }
+ nodeptr->nodetype = nodetype(nodeptr);
+ return nodeptr;
+ }
+}
+
+PRIVATE struct typestruct *nodetype(nodeptr)
+struct nodestruct *nodeptr;
+{
+ scalar_t bothscalar;
+ scalar_t lscalar;
+ scalar_t rscalar;
+ struct nodestruct *left;
+ struct nodestruct *right;
+ struct typestruct *targtype;
+
+ if (nodeptr->tag == LEAF)
+ return nodeptr->left.symptr->type;
+ targtype = (left = nodeptr->left.nodeptr)->nodetype;
+ right = nodeptr->right;
+ switch (nodeptr->tag)
+ {
+ case FUNCOP:
+ if (!(targtype->constructor & FUNCTION))
+ {
+ error("call of non-function");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ return targtype->nexttype;
+ case INDIRECTOP:
+ if (!(targtype->constructor & (ARRAY | POINTER)))
+ {
+ error("illegal indirection");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ nodeptr->flags |= LVALUE;
+ return targtype->nexttype;
+ case LISTOP:
+ case ROOTLISTOP:
+ nodeptr->left.nodeptr = unconvert(left);
+ return promote(targtype);
+ case CASTOP:
+ needspv(right);
+ case COMMAOP:
+ case CONDOP:
+ return right->nodetype;
+
+ case STRUCELTOP:
+ nodeptr->flags |= LVALUE;
+ return right->nodetype;
+
+ case ADDRESSOP:
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ return pointype(targtype);
+ case LOGNOTOP:
+ neednonstruct(left);
+ return redtype;
+ case NEGOP:
+ needscalar(left);
+ return promote(left->nodetype);
+ case NOTOP:
+ needint(left);
+ return promote(left->nodetype);
+ case PREDECOP:
+ case PREINCOP:
+ case POSTDECOP:
+ case POSTINCOP:
+ neednonstruct(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ break;
+
+ case ANDOP:
+ case EOROP:
+ case MODOP:
+ case OROP:
+ needint(left);
+ needint(right);
+ /* fall through to redundant check and code to cast to same types */
+ case ADDOP:
+ case DIVOP:
+ case MULOP:
+ case SUBOP:
+ needscalar(left);
+ needscalar(right);
+ binconvert(nodeptr);
+ return nodeptr->nodetype;
+
+ case PTRADDABOP:
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ case PTRADDOP: /* right type conversion to same size as ptr */
+ needint(right);
+ if (right->nodetype->scalar & LONG)
+ castiright(nodeptr);
+ break;
+ case PTRSUBOP: /* already checked */
+ return itype;
+ case SLOP: /* right type conversion always to int */
+ case SROP: /* ulong strictly to unsigned but no matter */
+ needint(left);
+ needint(right);
+ if (right->nodetype->scalar & LONG)
+ castiright(nodeptr);
+ return promote(left->nodetype);
+
+ case LTOP:
+ case LEOP:
+ case GTOP:
+ case GEOP:
+ case EQOP:
+ case LOGOROP:
+ case LOGANDOP:
+ case NEOP:
+ neednonstruct(left);
+ neednonstruct(right);
+ nodeptr->left.nodeptr = left = unconvert(left);
+ nodeptr->right = right = unconvert(right);
+#ifdef MAYBE_DO_LATER /* OK if pointers fit in uitype */
+ if (left->nodetype->constructor & POINTER)
+ nodeptr->left.nodeptr = left = castnode(uitype, left);
+ if (right->nodetype->constructor & POINTER)
+ nodeptr->right = right = castnode(uitype, right);
+#endif
+ binconvert(nodeptr);
+ return redtype;
+
+ case COLONOP:
+ if (isnodecharconst(left) && isnodecharconst(right))
+ {
+ targtype = (targtype->scalar | right->nodetype->scalar) & UNSIGNED
+ ? uctype : ctype;
+ left = castnode(targtype, left);
+ right = castnode(targtype, right);
+ }
+ nodeptr->left.nodeptr = left = unconvert(left);
+ nodeptr->right = right = unconvert(right);
+ if ((targtype = left->nodetype) == right->nodetype)
+ return targtype; /* XXX - reduced from promote(targtype) */
+ if ((lscalar = targtype->scalar) != 0 &&
+ (rscalar = right->nodetype->scalar) != 0)
+ {
+ /* promote minimally without using binconvert for char/short */
+ if ((bothscalar = lscalar | rscalar) & (LONG | RSCALAR))
+ {
+ binconvert(nodeptr);
+ return nodeptr->nodetype;
+ }
+ if (bothscalar & INT || (lscalar ^ rscalar) & UNSIGNED)
+ targtype = itype;
+ else if (bothscalar & SHORT)
+ targtype = stype;
+ else
+ targtype = ctype;
+ if (bothscalar & UNSIGNED)
+ targtype = tounsigned(targtype);
+ if ((!(bothscalar & INT) || (left->tag == LEAF && lscalar & INT)) ||
+ (right->tag == LEAF && rscalar & INT))
+ {
+ /* this is correct even when the if fails (the casts have to */
+ /* be considered at a lower level) but gives worse code */
+ if (left->nodetype != targtype)
+ nodeptr->left.nodeptr = castnode(targtype, left);
+ if (right->nodetype != targtype)
+ nodeptr->right = castnode(targtype, right);
+ }
+ return targtype; /* XXX - reduced from promote(targtype) */
+ }
+ if (targtype->constructor & POINTER &&
+ (isconst0(right) || (right->nodetype->constructor & POINTER &&
+ right->nodetype->nexttype->constructor & VOID)))
+ return targtype;
+ if (right->nodetype->constructor & POINTER &&
+ (isconst0(left) || (targtype->constructor & POINTER &&
+ targtype->nexttype->constructor & VOID)))
+ return right->nodetype;
+ error("mismatched types");
+ fixnode(left); /* XXX - better to fix the CONDOP */
+ fixnode(right);
+ return errtype;
+
+ case ASSIGNOP:
+ if (right->nodetype->constructor & VOID)
+ {
+ error("assignment of void");
+ fixnode(right);
+ }
+ if (targtype->constructor & (ARRAY | FUNCTION | VOID))
+ {
+ error("assignment to array, function or void");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ if ((targtype->constructor | right->nodetype->constructor)
+ & STRUCTU && targtype != right->nodetype)
+ {
+ error("assignment to/from struct/union of a different type");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+#if 0
+ /* XXX - this is done at the lowest levels, with too many chances for
+ * errors.
+ */
+ if (targtype != right->nodetype)
+ nodeptr->right = castnode(left->nodetype, right);
+#endif
+ break;
+ case ANDABOP:
+ case EORABOP:
+ case MODABOP:
+ case ORABOP:
+ needint(right);
+ needint(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ /* fall through to redundant check and code to cast to same types */
+ case ADDABOP:
+ case SUBABOP:
+ case DIVABOP:
+ case MULABOP:
+ needscalar(right);
+ needscalar(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ rscalar = right->nodetype->scalar;
+ if ((lscalar = (targtype = left->nodetype)->scalar) & RSCALAR)
+ {
+ if (!(rscalar & DOUBLE))
+ nodeptr->right = castnode(dtype, right);
+ }
+ else if (lscalar & LONG)
+ {
+ if (!(rscalar & LONG))
+ nodeptr->right = castnode(rscalar & UNSIGNED
+ ? ultype : targtype, right);
+ }
+#ifdef I8088
+ else if (i386_32 && lscalar & INT)
+ {
+ if (rscalar & SHORT)
+ nodeptr->right = castnode(rscalar & UNSIGNED
+ ? uitype : targtype, right);
+ }
+#endif
+ break;
+ case SLABOP:
+ case SRABOP:
+ needint(right);
+ needint(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ if (!(right->nodetype->scalar & INT))
+ castiright(nodeptr);
+ break;
+ }
+ return left->nodetype;
+}
+
+PRIVATE int redscalar(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ if (isnodecharconst(nodeptr))
+ return CHAR;
+ return nodeptr->nodetype->scalar;
+}
+
+PRIVATE struct nodestruct *unconvert(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION))
+ return castnode(pointype(nodeptr->nodetype->constructor & ARRAY ?
+ nodeptr->nodetype->nexttype :
+ nodeptr->nodetype), nodeptr);
+ return nodeptr;
+}
diff --git a/bcc/floatop.c b/bcc/floatop.c
new file mode 100644
index 0000000..fb9c54d
--- /dev/null
+++ b/bcc/floatop.c
@@ -0,0 +1,173 @@
+/* floatop.c - software operations on floats and doubles for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ f_indirect(target leaf)
+ make the float or double target indirect if it is not already
+ return nonzero iff the result is a temp double on the base of the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC bool_pt f_indirect(target)
+struct symstruct *target;
+{
+ if (target->indcount == 0)
+ {
+ if (target->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ if (target->type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *target->offset.offd;
+ push(constsym(((value_t *) &val)[0]));
+ }
+ else
+ {
+ push(constsym(((value_t *) target->offset.offd)[1]));
+ push(constsym(((value_t *) target->offset.offd)[0]));
+ }
+ }
+ else if (target->type->scalar & FLOAT)
+ pushlist(target->storage); /* XXX - floatregs */
+ else
+ pushlist(doubleregs);
+ onstack(target);
+ }
+ return target->flags == TEMP && target->type->scalar & DOUBLE
+ && target->offset.offi == sp;
+}
+
+/*-----------------------------------------------------------------------------
+ float1op(operation code, source leaf)
+ handles all flop unary operations except inc/dec
+ result is double on stack (or in condition codes for EQOP)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void float1op(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ saveopreg();
+ pointat(source);
+ if ((op_t) op == NEGOP)
+ call("Fneg");
+ else /* op == EQOP */
+ call("Ftst");
+ outntypechar(source->type);
+ if ((op_t) op != EQOP)
+ justpushed(source);
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ floatop(operation code, source leaf, target leaf)
+ handles all flop binary operations
+ result is double on stack (or in condition codes for EQOP)
+----------------------------------------------------------------------------*/
+
+PUBLIC void floatop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+ bool_t sflag;
+
+ regmark = reguse;
+ saveopreg();
+ (void) f_indirect(source);
+ if (!(reguse & OPREG) && (source->storage == OPREG))
+ {
+ reguse |= source->storage;
+ saveopreg();
+ }
+ fpush(target);
+ sflag = TRUE;
+ if (source->flags != TEMP || source->offset.offi != sp + dtypesize)
+ {
+ sflag = FALSE;
+ if (source->storage == OPREG)
+ restoreopreg();
+ pointat(source);
+ }
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("Fadd");
+ break;
+ case DIVOP:
+ call("Fdiv");
+ break;
+ case EQOP:
+ call("Fcomp");
+ sp += dtypesize; /* target is popped */
+ break; /* target symbol now invalid but is not used */
+ case MULOP:
+ call("Fmul");
+ break;
+ case SUBOP:
+ call("Fsub");
+ break;
+ }
+ if (sflag)
+ {
+ outnl();
+ sp += dtypesize; /* source is popped */
+ }
+ else
+ outntypechar(source->type);
+ onstack(target);
+ reguse = regmark; /* early so opreg is not reloaded if source */
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ fpush(source leaf of scalar type)
+ converts source to double and pushes it to stack
+ OPREG must be free
+-----------------------------------------------------------------------------*/
+
+PUBLIC void fpush(source)
+struct symstruct *source;
+{
+ scalar_t scalar;
+
+ if ((scalar = source->type->scalar) & RSCALAR)
+ {
+ if (f_indirect(source))
+ return;
+ pointat(source);
+ }
+ else if (scalar & DLONG)
+ load(source, OPREG);
+ else
+ load(source, DREG);
+ call("Fpush");
+ if (scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(source->type);
+ justpushed(source);
+}
+
+/*-----------------------------------------------------------------------------
+ justpushed(target leaf)
+ records that target has just been pushed to a double on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void justpushed(target)
+struct symstruct *target;
+{
+ sp -= dtypesize;
+ onstack(target);
+ target->type = dtype;
+}
diff --git a/bcc/function.c b/bcc/function.c
new file mode 100644
index 0000000..1d48a19
--- /dev/null
+++ b/bcc/function.c
@@ -0,0 +1,413 @@
+/* function.c - function call protocol for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "table.h"
+#include "type.h"
+
+#ifdef I8088
+# define ADJUSTLONGRETURN
+# define CANHANDLENOFRAME
+# undef CANHANDLENOFRAME
+# define STUPIDFRAME
+#endif
+
+FORWARD void out_callstring P((void));
+
+/* call a named (assembly interface) procedure, don't print newline after */
+
+PUBLIC void call(name)
+char *name;
+{
+ out_callstring();
+ outstr(name);
+}
+
+PUBLIC void function(source)
+struct symstruct *source;
+{
+ if (source->indcount == 0 && source->storage == GLOBAL &&
+ !(source->flags & LABELLED) && *source->name.namep != 0)
+ {
+ out_callstring();
+ outnccname(source->name.namep);
+ }
+ else
+ {
+#ifdef XENIX_AS
+ if (source->indcount == 0) /* fix call fixed address */
+ out_callstring();
+ else
+#endif
+ outcalladr();
+#ifdef MC6809
+ if (source->indcount == 1)
+ ++source->indcount; /* fake for outadr */
+#endif
+ outadr(source);
+ }
+ source->type = source->type->nexttype;
+#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+ if (source->type->scalar & DLONG)
+ {
+# ifdef ADJUSTLONGRETURN
+# if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2);
+ regexchange(LONGREG2, DXREG);
+ }
+# endif
+# if DYNAMIC_LONG_ORDER
+ else
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ regtransfer(DXREG, LONGRETURNREGS & ~LONGREG2);
+# endif
+# endif
+ source->storage = LONGRETURNREGS & ~LONGREG2;
+ }
+ else
+#endif
+ if (source->type->scalar & CHAR)
+ {
+#if RETURNREG != DREG
+ transfer(source, DREG);
+#endif
+ source->storage = BREG;
+ }
+ else if (source->type->scalar & DOUBLE)
+ source->storage = doublreturnregs & ~DREG;
+#if 0
+ else if (source->type->scalar & FLOAT)
+ source->storage = floatreturnregs /* XXX? & ~DREG */;
+#endif
+ else
+ source->storage = RETURNREG;
+ source->offset.offi = source->indcount = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ if (source->type->constructor & STRUCTU)
+ {
+ transfer(source, getindexreg()); /* so it can be indirected
+ * and/or preserved in blockmove() */
+ source->indcount = 1;
+ source->flags = TEMP; /* kludge so blockpush can be avoided */
+ }
+}
+
+PUBLIC void ldregargs()
+{
+ register struct symstruct *symptr;
+ store_pt targreg;
+ struct symstruct temptarg;
+
+ for (symptr = &locsyms[0]; symptr < locptr && symptr->level == ARGLEVEL;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ {
+ if ((store_t) (targreg = symptr->storage) & allregs)
+ {
+
+ /* load() is designed to work on expression symbols, so don't
+ * trust it on reg variables although it almost works.
+ */
+ temptarg = *symptr;
+ if (arg1inreg && symptr == &locsyms[0])
+ {
+ temptarg.storage = ARGREG;
+ temptarg.offset.offi = 0;
+ }
+ else
+ {
+ temptarg.storage = LOCAL;
+ temptarg.indcount = 1;
+ }
+ load(&temptarg, targreg);
+ symptr->offset.offi = 0;
+ }
+ }
+ regarg = FALSE;
+}
+
+PUBLIC void loadretexpression()
+{
+ if (returntype->constructor & STRUCTU)
+ {
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct symstruct *structarg;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = expression();
+ makeleaf(exp);
+ structarg = constsym((value_t) 0);
+ structarg->type = pointype(returntype);
+ onstack(structarg);
+ indirec(structarg);
+ structarg->flags = 0; /* assign() doesn't like TEMP even for indir */
+ structarg->offset.offi = returnadrsize;
+ assign(exp->left.symptr, structarg);
+ etptr = etmark;
+ exprptr = exprmark;
+ }
+#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+ else if (returntype->scalar & DLONG)
+ {
+ loadexpression(LONGRETURNREGS & ~LONGREG2, returntype);
+# ifdef ADJUSTLONGRETURN
+# if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ regexchange(LONGREG2, DXREG);
+ regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2);
+ }
+# endif
+# if DYNAMIC_LONG_ORDER
+ else
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ regtransfer(LONGRETURNREGS & ~LONGREG2, DXREG);
+# endif
+# endif
+ }
+ else
+#endif
+ if (returntype->scalar & DOUBLE)
+ loadexpression(doublreturnregs & ~DREG, returntype);
+#if 0
+ else if (returntype->scalar & FLOAT)
+ loadexpression(floatreturnregs /* XXX? & ~DREG */, returntype);
+#endif
+ else
+ loadexpression(RETURNREG, returntype);
+}
+
+PUBLIC void listo(target, lastargsp)
+struct symstruct *target;
+offset_t lastargsp;
+{
+ extend(target);
+ push(target);
+ if (lastargsp != 0 && sp != lastargsp - target->type->typesize)
+ {
+ loadany(target);
+ modstk(lastargsp);
+ push(target);
+ if (sp != lastargsp - target->type->typesize)
+ {
+ bugerror("botched push of arg");
+#ifdef DEBUG
+ outstr("arg type is ");
+ dbtype(target->type);
+ outnl();
+#endif
+ }
+ }
+}
+
+PUBLIC void listroot(target)
+struct symstruct *target;
+{
+ extend(target);
+ /* necessary regs are free since they were saved for function */
+ if (target->type->scalar & DLONG)
+ load(target, LONGARGREGS & ~LONGREG2);
+ else
+ load(target, ARGREG);
+}
+
+PRIVATE void out_callstring()
+{
+ outop3str(callstring);
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+#ifdef FRAMEPOINTER
+
+PUBLIC void popframe()
+{
+ poplist(frame1list);
+}
+
+#endif
+
+/* reserve storage for locals if necessary */
+/* also push 1st function arg and load register args if necessary */
+
+PUBLIC void reslocals()
+{
+#ifdef FRAMEPOINTER
+# ifndef STUPIDFRAME
+ bool_t loadframe = FALSE;
+
+# endif
+#endif
+
+ if (switchnow != NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (framep == 0 && softsp != sp)
+ bugerror("local variables in switch statement messed up, sorry");
+#else
+ if (sp != softsp)
+ bugerror("local variables in switch statement don't work, sorry");
+#endif
+ if (lowsp > softsp)
+ lowsp = softsp;
+ sp = softsp;
+ return;
+ }
+#ifdef FRAMEPOINTER
+ if (framep == 0)
+ {
+# ifdef STUPIDFRAME
+ pushreg(FRAMEREG);
+ regtransfer(STACKREG, FRAMEREG);
+ framep = sp;
+ pushlist(callee1mask);
+# else /* not STUPIDFRAME */
+# ifdef CANHANDLENOFRAME
+ if (stackarg || softsp != -frameregsize) /* args or locals */
+# endif
+ {
+ pushlist(frame1list);
+ loadframe = TRUE;
+ }
+# endif /* not STUPIDFRAME */
+ }
+#else
+ if (sp == 0)
+ pushlist(callee1mask);
+#endif /* FRAMEPOINTER */
+ if (arg1size)
+ {
+ switch ((fastin_t) arg1size)
+ {
+ case 8:
+ pushlist(doubleargregs);
+ break;
+ case 4:
+# ifdef I8088
+ if (!i386_32)
+# endif
+ {
+ pushlist(LONGARGREGS);
+ break;
+ }
+ case 2:
+# ifdef I8088
+ pushlist(ARGREG);
+# endif
+# ifdef MC6809
+ switch (sp - softsp)
+ {
+ case 3:
+ pushlist(LOC1REGS | ARGREG);
+ break;
+ case 4:
+ pushlist(LOC2REGS | ARGREG);
+ break;
+ case 5:
+ pushlist(LOC3REGS | ARGREG);
+ break;
+ case 6:
+ pushlist(LOC4REGS | ARGREG);
+ break;
+ default:
+ pushlist(ARGREG);
+ break;
+ }
+# endif /* MC6809 */
+ }
+ arg1size = 0; /* show 1st arg allocated */
+ }
+#ifdef FRAMEPOINTER
+# ifndef STUPIDFRAME /* else this moved above for compat with Xenix cc frame */
+ if (loadframe || softsp != -frameregsize)
+ modstk(softsp);
+ /* else avoid modstk() because softsp holds space for frame pointer only) */
+ /* but pointer has not been pushed (must keep softsp for later levels) */
+ if (loadframe)
+ {
+ regtransfer(STACKREG, FRAMEREG);
+ framep = sp;
+ }
+# else /* STUPIDFRAME */
+ modstk(softsp);
+# endif /* STUPIDFRAME */
+#else /* no FRAMEPOINTER */
+ modstk(softsp);
+#endif /* FRAMEPOINTER */
+ if (regarg)
+ ldregargs();
+}
+
+/* clean up stack and return from a function */
+
+PUBLIC void ret()
+{
+#ifdef FRAMEPOINTER
+ offset_t newsp;
+
+ if (framep != 0)
+ {
+ newsp = -(offset_t) func1saveregsize;
+ if (switchnow != NULL || newsp - sp >= 0x80)
+ changesp(newsp, TRUE);
+ else
+ modstk(newsp);
+ popframe();
+ }
+ outreturn();
+#else /* no FRAMEPOINTER */
+# ifdef MC6809
+ store_pt reglist;
+
+ switch (sp)
+ {
+ case -1:
+ reglist = JUNK1REGS | PCREG;
+ break;
+ case -2:
+ reglist = JUNK2REGS | PCREG;
+ break;
+ case -3:
+ reglist = JUNK3REGS | PCREG;
+ break;
+ case -4:
+ reglist = JUNK4REGS | PCREG;
+ break;
+ default:
+ modstk(0);
+ outreturn();
+ return;
+ }
+ poplist(reglist);
+#else
+ if (sp != 0)
+ {
+ modstk(-(offset_t) func1saveregsize);
+ poplist(callee1mask);
+ }
+ outreturn();
+# endif /* no MC6809 */
+#endif /* no FRAMEPOINTER */
+}
diff --git a/bcc/gencode.c b/bcc/gencode.c
new file mode 100644
index 0000000..fa098ea
--- /dev/null
+++ b/bcc/gencode.c
@@ -0,0 +1,736 @@
+/* gencode.c - generate code for an expression tree for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define islvalop(op) \
+ (((op) >= ASSIGNOP && (op) <= SUBABOP) || (op) == PTRADDABOP)
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "condcode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "gencode.h"
+#include "sizes.h"
+
+#define FIRSTOPDATA GTOP
+
+#if MAXINDIRECT <= 1
+# define istooindirect(t) ((t)->indcount > MAXINDIRECT)
+#else
+# define istooindirect(t) ((t)->indcount >= MAXINDIRECT && \
+ ((t)->indcount > MAXINDIRECT || \
+ (t)->type->typesize > maxregsize || \
+ (t)->type->constructor & FUNCTION))
+#endif
+
+#ifdef I8088
+#if NOTFINISHED
+PUBLIC store_pt allregs = BREG | DREG | DATREG1 | DATREG2
+ | INDREG0 | INDREG1 | INDREG2;
+#else
+PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2;
+#endif
+PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2;
+PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0001;
+PUBLIC bool_t arg1inreg = FALSE;
+PUBLIC store_pt calleemask = INDREG1 | INDREG2;
+PUBLIC bool_t callersaves = FALSE;
+PUBLIC char *callstring = "call\t";
+PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC offset_t jcclonger = 3;
+PUBLIC offset_t jmplonger = 1;
+PUBLIC char *jumpstring = "br \t";
+PUBLIC char *regpulllist = "f2ax2ax2bx2si2di2bp2qx2qx2cx2dx2";
+PUBLIC char *regpushlist = "dx2cx2qx2qx2bp2di2si2bx2ax2ax2f2";
+#if NOTFINISHED
+PUBLIC store_pt regregs = INDREG1 | INDREG2 | DATREG1 | DATREG2;
+#else
+PUBLIC store_pt regregs = INDREG1 | INDREG2;
+#endif
+
+PUBLIC char *acclostr = "al";
+PUBLIC char *accumstr = "ax";
+PUBLIC char *badregstr = "qx";
+PUBLIC char *dreg1str = "cx";
+PUBLIC char *dreg1bstr = "cl";
+PUBLIC char *dreg2str = "dx";
+PUBLIC char *ireg0str = "bx";
+PUBLIC char *ireg1str = "si";
+PUBLIC char *ireg2str = "di";
+#ifdef FRAMEPOINTER
+PUBLIC char *localregstr = "bp";
+#else
+PUBLIC char *localregstr = "sp";
+#endif
+PUBLIC char *stackregstr = "sp";
+#endif
+
+#ifdef MC6809
+PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2;
+PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0000;
+PUBLIC bool_t arg1inreg = TRUE;
+PUBLIC store_pt calleemask = INDREG1 | INDREG2;
+PUBLIC bool_t callersaves = TRUE;
+PUBLIC char *callstring = "JSR\t>";
+PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC offset_t jcclonger = 2;
+PUBLIC offset_t jmplonger = 1;
+PUBLIC char *jumpstring = "JMP\t>";
+PUBLIC char *regpulllist = "CC1B1D2X2U2Y2DP1PC2";
+PUBLIC char *regpushlist = "PC2DP1Y2U2X2D2B1CC1";
+PUBLIC store_pt regregs = INDREG1 | INDREG2;
+
+PUBLIC char *acclostr = "B";
+PUBLIC char *accumstr = "D";
+PUBLIC char *badregstr = "Q";
+PUBLIC char *ireg0str = "X";
+PUBLIC char *ireg1str = "U";
+PUBLIC char *ireg2str = "Y";
+PUBLIC char *localregstr = "S";
+#endif
+
+PUBLIC uoffset_t accregsize = 2;
+#ifdef FRAMEPOINTER
+PUBLIC uoffset_t frameregsize = 2;
+#endif
+PUBLIC uoffset_t maxregsize = 2;
+PUBLIC uoffset_t opregsize = 2;
+PUBLIC uoffset_t pshregsize = 2;
+PUBLIC uoffset_t returnadrsize = 2;
+
+#ifndef MC6809
+PUBLIC uvalue_t intmaskto = 0xFFFFL;
+PUBLIC uvalue_t maxintto = 0x7FFFL;
+PUBLIC uvalue_t maxlongto = 0x7FFFFFFFL;
+PUBLIC uvalue_t maxoffsetto = 0x7FFFL;
+PUBLIC uvalue_t maxshortto = 0x7FFFL;
+PUBLIC uvalue_t maxuintto = 0xFFFFL;
+PUBLIC uvalue_t maxushortto = 0xFFFFL;
+PUBLIC uvalue_t shortmaskto = 0xFFFFL;
+#endif
+
+PRIVATE store_pt callermask;
+PRIVATE offset_t lastargsp;
+
+PRIVATE smalin_t opdata[] =
+{
+/* GTOP, LTOP, ADDOP, DIVOP, */
+ GT, LT, 0, 0,
+/* MODOP, LOGNOTOP, NOTOP, STRUCELTOP, */
+ 0, 0, 0, 0,
+/* STRUCPTROP, ASSIGNOP, ADDABOP, ANDABOP, */
+ 0, 0, 0, ANDOP,
+/* DIVABOP, EORABOP, MODABOP, MULABOP, */
+ DIVOP, EOROP, MODOP, MULOP,
+/* ORABOP, SLABOP, SRABOP, SUBABOP, */
+ OROP, SLOP, SROP, 0,
+/* COMMAOP, COLONOP, LOGOROP, LOGANDOP, */
+ 0, 0, 0, 0,
+/* EQOP, NEOP, GEOP, LEOP, */
+ EQ, NE, GE, LE,
+};
+
+FORWARD void abop P((op_pt op, struct symstruct *source,
+ struct symstruct *target));
+FORWARD void smakeleaf P((struct nodestruct *exp));
+FORWARD void tcheck P((struct nodestruct *exp));
+
+PRIVATE void abop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regmark;
+ store_pt regpushed;
+ store_pt regtemp;
+ struct symstruct temptarg;
+
+ regpushed = preslval(source, target);
+ temptarg = *target;
+ if ((source->type->scalar ^ target->type->scalar) & (DLONG | RSCALAR)
+ && op != SLABOP && op != SRABOP) /* XXX - perhaps not float */
+ {
+ pres2(target, source);
+ cast(source->type, &temptarg);
+ }
+ switch (op)
+ {
+ case ADDABOP:
+ add(source, &temptarg);
+ break;
+ case ANDABOP:
+ case EORABOP:
+ case ORABOP:
+ op1((opdata - FIRSTOPDATA)[op], source, &temptarg);
+ break;
+ case DIVABOP:
+ case MODABOP:
+ case MULABOP:
+ case SLABOP:
+ case SRABOP:
+ softop((opdata - FIRSTOPDATA)[op], source, &temptarg);
+ break;
+ case PTRADDABOP:
+ regtemp = 0;
+ if ((reguse & allindregs) == allindregs)
+ {
+ /* free a temporary index not used for source or target */
+
+ regmark = reguse;
+ reguse = source->storage | temptarg.storage;
+ pushreg(regtemp = getindexreg());
+ reguse = regmark & ~regtemp;
+ }
+ indexadr(source, &temptarg);
+ if (regtemp)
+ {
+ load(&temptarg, DREG);
+ recovlist(regtemp);
+ }
+ break;
+ case SUBABOP:
+ sub(source, &temptarg);
+ break;
+ }
+ assign(&temptarg, target);
+ recovlist(regpushed);
+}
+
+PUBLIC void bileaf(exp)
+struct nodestruct *exp;
+{
+ bool_t commutop;
+ bool_t tookaddress;
+ store_t regmark;
+ struct nodestruct *indchase;
+ struct nodestruct *left;
+ struct nodestruct *right;
+ struct symstruct *source;
+ struct symstruct *target;
+
+ left = exp->left.nodeptr;
+ if ((right = exp->right) == NULL)
+ {
+ makeleaf(left);
+#ifdef DEBUG
+ debug(exp);
+#endif
+ return;
+ }
+ switch (exp->tag)
+ {
+ case ADDOP:
+ case ANDOP:
+ case EOROP:
+ case OROP:
+ case EQOP:
+ case NEOP:
+ case MULOP:
+ commutop = TRUE;
+ break;
+ case FUNCOP:
+ makeleaf(left);
+ if ((target = left->left.symptr)->storage & allregs
+ && right->tag != LEAF && target->flags != REGVAR)
+ {
+ if (target->indcount == 0)
+ push(target);
+ else
+ {
+ --target->indcount;
+ push(target);
+ ++target->indcount;
+ }
+ }
+ default:
+ commutop = FALSE;
+ break;
+ }
+ regmark = reguse;
+ if (right->tag != LEAF)
+ {
+ if (left->tag != LEAF && commutop && left->weight > right->weight)
+ {
+ exp->left.nodeptr = right;
+ right = exp->right = left;
+ left = exp->left.nodeptr;
+#ifdef DEBUG
+ debugswap();
+#endif
+ }
+ makeleaf(right);
+ }
+ else if (left->tag != LEAF)
+ makeleaf(left);
+ source = right->left.symptr;
+ if (left->tag != LEAF)
+ {
+ for (indchase = left;
+ indchase->tag == INDIRECTOP || indchase->tag == STRUCELTOP;
+ indchase = indchase->left.nodeptr)
+ ;
+ tookaddress = FALSE;
+ if (source->storage & allindregs || indchase->tag != LEAF)
+ {
+ if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP)
+ {
+ address(source);
+ tookaddress = TRUE;
+ }
+ if (source->storage & allindregs && source->indcount == 0 &&
+ (source->type->scalar & (DLONG | RSCALAR) ||
+ (left->tag == FUNCOP && source->flags != REGVAR)))
+ push(source); /* XXX - perhaps not float */
+ else
+ preserve(source);
+ }
+ makeleaf(left);
+ if (tookaddress)
+ indirec(source);
+ }
+ target = left->left.symptr;
+ if (istooindirect(source))
+ {
+ /* want to makelessindirect(source) */
+ /* this uses source->storage if that is a free index */
+ /* otherwise, must preserve target if that is an index */
+
+ tookaddress = FALSE;
+ if (!(source->storage & ~reguse & allindregs) &&
+ target->storage & allindregs)
+ {
+ /* want to pres2(source, target) */
+ /* this requires target to be < MAXINDIRECT indirect */
+ /* it is safe to makelessindirect(target) */
+ /* since source is not a free index */
+
+ if (islvalop(exp->tag) && target->indcount != 0)
+ {
+ address(target);
+ tookaddress = TRUE;
+ }
+ if (istooindirect(target))
+ makelessindirect(target);
+ pres2(source, target);
+ }
+ makelessindirect(source);
+ if (tookaddress)
+ indirec(target);
+ }
+ if (istooindirect(target))
+ {
+ tookaddress = FALSE;
+ if (!(target->storage & ~reguse & allindregs) &&
+ source->storage & allindregs)
+ {
+ if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP)
+ {
+ address(source);
+ tookaddress = TRUE;
+ }
+ pres2(target, source);
+ }
+ makelessindirect(target);
+ if (tookaddress)
+ indirec(source);
+ }
+ reguse = regmark;
+#ifdef DEBUG
+ debug(exp);
+#endif
+ if (commutop
+ && ((target->storage == CONSTANT
+ && !(target->type->scalar & (DLONG | RSCALAR)))
+ || source->storage & ALLDATREGS
+ || (source->type->scalar & (DLONG | RSCALAR)
+ && source->indcount == 0 && target->indcount != 0)))
+ {
+ exp->left.nodeptr = right;
+ exp->right = left;
+#ifdef DEBUG
+ debugswap();
+#endif
+ }
+}
+
+PUBLIC fastin_pt bitcount(number)
+register uvalue_t number;
+{
+ register fastin_pt count;
+
+ for (count = 0; number != 0; number >>= 1)
+ if (number & 1)
+ ++count;
+ return count;
+}
+
+PUBLIC void codeinit()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ /* Need DATREG2 for doubles although handling of extra data regs is
+ * not finished.
+ * XXX - might need more regs for 16-bit mode doubles or floats.
+ */
+ allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2
+ | DATREG1 | DATREG1B | DATREG2;
+#if NOTFINISHED
+ allindregs = INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG2;
+#else
+ allindregs = INDREG0 | INDREG1 | INDREG2;
+#endif
+ alignmask = ~(uoffset_t) 0x00000003;
+ calleemask = INDREG0 | INDREG1 | INDREG2;
+ doubleargregs = DREG | DATREG2;
+ doubleregs = DREG | DATREG2;
+ doublreturnregs = DREG | DATREG2;
+ jcclonger = 4;
+ jmplonger = 3;
+ regpulllist = "fd4eax4eax4ebx4esi4edi4ebp4qx4qx4ecx4edx4";
+ regpushlist = "edx4ecx4qx4qx4ebp4edi4esi4ebx4eax4eax4fd4";
+
+ accumstr = "eax";
+ dreg1str = "ecx";
+ dreg2str = "edx";
+ ireg0str = "ebx";
+ ireg1str = "esi";
+ ireg2str = "edi";
+#ifdef FRAMEPOINTER
+ localregstr = "ebp";
+#else
+ localregstr = "esp";
+#endif
+ stackregstr = "esp";
+
+ opregsize =
+ returnadrsize =
+ pshregsize =
+ maxregsize =
+#ifdef FRAMEPOINTER
+ frameregsize =
+#endif
+ accregsize = 4;
+
+ intmaskto = (unsigned long) 0xFFFFFFFFL;
+ maxintto = 0x7FFFFFFFL;
+ maxoffsetto = 0x7FFFFFFFL;
+ maxuintto = (unsigned long) 0xFFFFFFFFL;
+ }
+#endif
+#ifdef POSINDEPENDENT
+ if (posindependent)
+ {
+# ifdef MC6809
+ callstring = "LBSR\t";
+ jumpstring = "LBRA\t";
+# endif
+ }
+#endif
+ if (callersaves)
+ calleemask = 0;
+ callermask = ~calleemask;
+#ifdef FRAMEPOINTER
+ funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize
+ + frameregsize;
+ funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs)
+ * maxregsize + frameregsize;
+ framelist = FRAMEREG | calleemask;
+#else
+ funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize;
+ funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs)
+ * maxregsize;
+#endif
+}
+
+PUBLIC fastin_pt highbit(number)
+register uvalue_t number;
+{
+ register fastin_pt bit;
+
+ for (bit = -1; number != 0; number >>= 1)
+ ++bit;
+ return bit;
+}
+
+PUBLIC void makeleaf(exp)
+struct nodestruct *exp;
+{
+ ccode_t condtrue;
+ op_pt op;
+ store_t regmark;
+ offset_t saveargsp = 0; /* for -Wall */
+ store_t savelist = 0; /* for -Wall */
+ offset_t saveoffset = 0; /* for -Wall */
+ struct symstruct *source;
+ offset_t spmark;
+ struct symstruct *structarg = 0; /* for -Wall */
+ struct symstruct *target;
+
+ if ((op_t) (op = exp->tag) == LEAF)
+ {
+ target = exp->left.symptr;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == INDIRECTOP || (op_t) op == STRUCELTOP)
+ {
+ smakeleaf(exp);
+ target = exp->left.symptr;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == COMMAOP)
+ {
+ spmark = sp;
+ makeleaf(exp->left.nodeptr);
+ modstk(spmark);
+ makeleaf(exp->right);
+ exp->tag = LEAF;
+ exp->left.symptr = exp->right->left.symptr;
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == CONDOP)
+ {
+ condop(exp);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == LOGANDOP || (op_t) op == LOGNOTOP
+ || (op_t) op == LOGOROP)
+ {
+ logop(exp);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ regmark = reguse;
+ if ((op_t) op == FUNCOP)
+ {
+ saveargsp = lastargsp;
+ lastargsp = savelist = 0;
+ if (exp->nodetype->constructor & STRUCTU)
+ {
+ modstk(sp - (offset_t) exp->nodetype->typesize);
+ onstack(structarg = constsym((value_t) 0));
+ }
+ else
+ {
+ if (exp->nodetype->scalar & DOUBLE)
+ {
+ if (regmark & doublreturnregs)
+ savelist = doublreturnregs;
+ }
+ else if (regmark & RETURNREG)
+ savelist = exp->nodetype->scalar & DLONG
+ ? LONGRETURNREGS : RETURNREG;
+ if (savelist != 0)
+ modstk(saveoffset = sp - exp->nodetype->typesize);
+ }
+ pushlist(regmark & callermask);
+ }
+ spmark = sp;
+ bileaf(exp);
+ if (exp->right != NULL)
+ source = exp->right->left.symptr;
+ else
+ source = NULL;
+ target = exp->left.nodeptr->left.symptr;
+ switch ((op_t) op)
+ {
+ case ADDABOP:
+ case ANDABOP:
+ case DIVABOP:
+ case EORABOP:
+ case SUBABOP:
+ case MODABOP:
+ case MULABOP:
+ case ORABOP:
+ case PTRADDABOP:
+ case SLABOP:
+ case SRABOP:
+ abop(op, source, target);
+ break;
+ case ADDOP:
+ add(source, target);
+ break;
+ case ADDRESSOP:
+ address(target);
+ break;
+ case ANDOP:
+ case EOROP:
+ case OROP:
+ op1(op, source, target);
+ break;
+ case ASSIGNOP:
+ assign(source, target);
+ break;
+ case CASTOP:
+ cast(source->type, target);
+ break;
+ case DIVOP:
+ case MODOP:
+ case MULOP:
+ case SLOP:
+ case SROP:
+ softop(op, source, target);
+ break;
+ case EQOP:
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case LTOP:
+ case NEOP:
+ condtrue = (opdata - FIRSTOPDATA)[op];
+ cmp(source, target, &condtrue);
+ break;
+ case FUNCOP:
+ /* kludge update pushed regs */
+ /* may only work for si, di */
+ /* -2 skips for ax and bx */
+ /* need dirtymask to mostly avoid this */
+ savereturn(regmark & callermask & regregs,
+ spmark - 2 * (offset_t) pshregsize);
+ if (exp->nodetype->constructor & STRUCTU)
+ {
+ address(structarg);
+ push(structarg);
+ }
+ function(target);
+ break;
+ case INDIRECTOP:
+ indirec(target);
+ break;
+ case LISTOP:
+ listo(target, lastargsp);
+ lastargsp = sp;
+ break;
+ case NEGOP:
+ neg(target);
+ break;
+ case NOTOP:
+ not(target);
+ break;
+ case POSTDECOP:
+ case POSTINCOP:
+ case PREDECOP:
+ case PREINCOP:
+ incdec(op, target);
+ break;
+ case PTRADDOP:
+ indexadr(source, target);
+ break;
+ case PTRSUBOP:
+ ptrsub(source, target);
+ break;
+ case ROOTLISTOP:
+ listroot(target);
+ lastargsp = sp;
+ break;
+ case STRUCELTOP:
+ struc(source, target);
+ break;
+ case SUBOP:
+ sub(source, target);
+ break;
+ }
+ if (target->storage == LOCAL && target->offset.offi < spmark &&
+ target->flags == TEMP)
+ spmark = target->offset.offi;
+#if 1 /* XXX - why does sp get changed without this? */
+ if ((op_t) op != ROOTLISTOP)
+#endif
+ modstk(spmark);
+ if ((op_t) op == FUNCOP)
+ {
+ lastargsp = saveargsp;
+ if (savelist != 0)
+ {
+ savereturn(savelist, saveoffset);
+ onstack(target);
+ target->offset.offi = saveoffset;
+ }
+ recovlist(regmark & callermask);
+ }
+ reguse = regmark;
+ exp->tag = LEAF;
+ exp->left.symptr = target;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+}
+
+PRIVATE void smakeleaf(exp)
+struct nodestruct *exp;
+{
+ struct nodestruct *left;
+
+ left = exp->left.nodeptr;
+ if (left->tag == INDIRECTOP || left->tag == STRUCELTOP)
+ smakeleaf(left);
+ else if (left->tag != LEAF)
+ makeleaf(left);
+ if (exp->tag == INDIRECTOP)
+ indirec(left->left.symptr);
+ else
+ {
+ if (left->left.symptr->indcount > MAXINDIRECT + 1)
+ makelessindirect(left->left.symptr);
+ struc(exp->right->left.symptr, left->left.symptr);
+ }
+ exp->tag = LEAF;
+ exp->left.symptr = left->left.symptr;
+}
+
+#ifdef SELFTYPECHECK
+
+PRIVATE void tcheck(exp)
+register struct nodestruct *exp;
+{
+ register struct symstruct *target;
+
+ if (exp->nodetype != (target = exp->left.symptr)->type)
+ {
+ {
+ bugerror("botched nodetype calculation");
+#ifdef DEBUG
+ comment();
+ outstr("runtime type is ");
+ dbtype(target->type);
+ outstr(", calculated type is ");
+ dbtype(exp->nodetype);
+ outnl();
+#endif
+ }
+ }
+}
+
+#endif /* SELFTYPECHECK */
diff --git a/bcc/gencode.h b/bcc/gencode.h
new file mode 100644
index 0000000..370817a
--- /dev/null
+++ b/bcc/gencode.h
@@ -0,0 +1,101 @@
+/* gencode.h - code generation for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef MC6809
+# define CANABXCUTOFF 7 /* favour ABX over MUL before this */
+#endif
+#define EXPRLEVEL 126 /* level for symbols in exptree, > real levs */
+#define OFFKLUDGELEVEL 127 /* level for expr sym with offset from name */
+#define OPERANDSEPARATOR ',' /* char separating operands */
+#define OPSEPARATOR '\t' /* char separating op string and operand */
+
+EXTERN uoffset_t arg1size; /* size of 1st arg to function */
+ /* zero after allocation of 1st arg */
+EXTERN store_pt callee1mask; /* calleemask with doubleregs masked if nec */
+EXTERN uoffset_t dataoffset; /* amount of initialized data so far */
+#ifdef DEBUG
+EXTERN bool_t debugon; /* nonzero to print debugging messages */
+ /* depends on zero init */
+#endif
+#ifdef FRAMEPOINTER
+EXTERN store_pt framelist; /* bit pattern for frame and saved regs */
+EXTERN store_pt frame1list; /* framelist with doubleregs masked if nec */
+EXTERN offset_t framep; /* hardware relative frame ptr */
+#endif
+EXTERN uoffset_t func1saveregsize; /* choice of next two values */
+EXTERN uoffset_t funcdsaveregsize; /* funcsaveregsize adjusted for doubles */
+EXTERN uoffset_t funcsaveregsize; /* tot size of framelist/calleemask regs */
+#ifdef I8088
+EXTERN bool_t i386_32; /* nonzero to generate 386 32 bit code */
+ /* depends on zero init */
+#endif
+#ifdef DYNAMIC_LONG_ORDER
+EXTERN bool_t long_big_endian; /* nonzero if high long word is first */
+ /* depends on zero init */
+#endif
+EXTERN offset_t lowsp; /* low water sp (collects locals in switch) */
+#ifdef POSINDEPENDENT
+EXTERN bool_t posindependent; /* nonzero to generate pos-independent code */
+ /* depends on zero init */
+#endif
+EXTERN bool_t printf_fp; /* nonzero if *printf called with FP arg */
+EXTERN bool_t regarg; /* nonzero to show unloaded register arg */
+ /* depends on zero init */
+EXTERN store_t reguse; /* registers in use */
+EXTERN bool_t scanf_fp; /* nonzero if *scanf called with ptr-to-FP */
+EXTERN offset_t softsp; /* software sp (leads sp during declares) */
+EXTERN offset_t sp; /* hardware relative stack ptr */
+ /* depends on zero init */
+#ifdef FRAMEPOINTER
+EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */
+#endif
+EXTERN struct switchstruct *switchnow; /* currently active switch */
+ /* depends on NULL init */
+
+/* variables to be initialised to nonzero */
+
+extern store_pt allindregs; /* mask (in) for index registers */
+extern store_pt allregs; /* mask (in) for registers */
+extern bool_t arg1inreg; /* nonzero to pass 1st arg in reg */
+extern store_pt calleemask; /* mask (in) for regs to be saved by callee */
+extern bool_t callersaves; /* nonzero to make caller save regs */
+extern char *callstring; /* opcode string for call */
+extern store_pt doubleargregs; /* mask (in) for regs for 1st arg if double */
+extern store_pt doubleregs; /* mask (in) for regs to temp contain double */
+extern store_pt doublreturnregs; /* mask (in) for regs for returning double */
+extern offset_t jcclonger; /* amount jcc long jumps are longer */
+extern offset_t jmplonger; /* amount long jumps is longer */
+extern char *jumpstring; /* opcode string for jump */
+extern char *regpulllist; /* reg names and sizes (0 store_t bit first) */
+extern char *regpushlist; /* reg names and sizes (0 store_t bit last) */
+extern store_pt regregs; /* mask (in) for regs which can be reg vars */
+
+/* register names */
+
+extern char *acclostr;
+extern char *accumstr;
+extern char *badregstr;
+#ifdef I8088
+extern char *dreg1str;
+extern char *dreg1bstr;
+extern char *dreg2str;
+#endif
+extern char *ireg0str;
+extern char *ireg1str;
+extern char *ireg2str;
+extern char *localregstr;
+#ifdef I8088
+extern char *stackregstr;
+#endif
+
+/* register sizes */
+
+extern uoffset_t accregsize;
+#ifdef FRAMEPOINTER
+extern uoffset_t frameregsize;
+#endif
+extern uoffset_t maxregsize;
+extern uoffset_t opregsize;
+extern uoffset_t pshregsize;
+extern uoffset_t returnadrsize;
diff --git a/bcc/genloads.c b/bcc/genloads.c
new file mode 100644
index 0000000..2056cb7
--- /dev/null
+++ b/bcc/genloads.c
@@ -0,0 +1,1255 @@
+/* genloads.c - generate loads of registers and memory for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void badaddress P((void));
+FORWARD void blockpush P((struct symstruct *source));
+FORWARD void loadadr P((struct symstruct *source, store_pt targreg));
+FORWARD void loadlongindirect P((struct symstruct *source, store_pt targreg));
+FORWARD void outnamoffset P((struct symstruct *adr));
+FORWARD void outnnadr P((struct symstruct *adr));
+FORWARD fastin_pt pushpull P((store_pt reglist, bool_pt pushflag));
+
+PUBLIC void addoffset(source)
+struct symstruct *source;
+{
+#ifdef I8088
+ if (source->level == OFFKLUDGELEVEL)
+ {
+ outadd();
+ outregname(source->storage);
+ outcomma();
+ outnamoffset(source);
+ outnl();
+ if (source->storage & (AXREG | ALREG))
+ unbumplc();
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0;
+ }
+ else
+#endif
+ if (source->offset.offi != 0)
+ {
+ addconst(source->offset.offi, source->storage);
+ source->offset.offi = 0;
+ }
+}
+
+PUBLIC void address(source)
+struct symstruct *source;
+{
+ if (source->indcount == 0)
+ bugerror("taking address of non-lvalue");
+ else
+ {
+ if (source->type->constructor & (ARRAY | FUNCTION))
+ bugerror("botched indirect array or function");
+ else if (--source->indcount == 0 && source->storage == GLOBAL &&
+ !(source->flags & LABELLED) && *source->name.namep == 0)
+ source->storage = CONSTANT;
+ source->type = pointype(source->type);
+ }
+}
+
+PRIVATE void badaddress()
+{
+ bugerror("bad address");
+}
+
+PRIVATE void blockpush(source)
+struct symstruct *source;
+{
+ struct symstruct *length;
+ offset_t spmark;
+ uoffset_t typesize;
+
+ typesize = source->type->typesize;
+ length = constsym((value_t) typesize);
+ length->type = uitype;
+ address(source);
+ modstk(spmark = sp - (offset_t) typesize);
+#ifdef STACKREG
+ regtransfer(STACKREG, DREG);
+#else
+#ifdef MC6809 /* XXX ? */
+ regtransfer(LOCAL, DREG);
+#else
+#include "need STACKREG and stackregstr"
+#endif
+#endif
+ push(length);
+ push(source);
+ pushreg(DREG);
+ call("_memcpy");
+ outnl();
+ modstk(spmark);
+ indirec(source);
+}
+
+PUBLIC void exchange(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t tempreg;
+
+ regexchange(source->storage, target->storage);
+ tempreg = target->storage;
+ target->storage = source->storage;
+ source->storage = tempreg;
+}
+
+/*-----------------------------------------------------------------------------
+ getindexreg()
+ returns the "best" available index register
+-----------------------------------------------------------------------------*/
+
+PUBLIC store_pt getindexreg()
+{
+ if (!(reguse & INDREG0))
+ return INDREG0;
+ if (!(reguse & INDREG1))
+ return INDREG1;
+ if (!(reguse & INDREG2))
+ return INDREG2;
+#if NOTFINISHED
+#ifdef I8088
+ if (i386_32)
+ {
+ if (!(reguse & DATREG1))
+ return DATREG1;
+ if (!(reguse & DATREG2))
+ return DATREG2;
+ }
+#endif
+#endif
+ bugerror("out of index regs");
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ indexadr(index leaf, pointer leaf)
+ is used by the index and add and subtract (pointer) routines
+ it handles expressions like
+ pointer + index
+ &array[index]
+ the target becomes register direct with offset
+ (except for index = 0, when nothing is changed)
+ constant indexes are optimised by leaving them as offsets
+ register direct pointers are optimised by leaving the offset alone
+ (except for PC register direct, since there is no LEAX D,PC)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void indexadr(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+#ifdef MC6809
+ bool_t canABX;
+#endif
+ uoffset_t size;
+ store_pt sourcereg;
+ struct typestruct *targtype;
+ store_pt targreg;
+
+ if (!(target->type->constructor & (ARRAY | POINTER)))
+ {
+ bugerror("cannot index");
+ return;
+ }
+ size = target->type->nexttype->typesize;
+ if (source->storage == CONSTANT)
+ {
+ if (source->offset.offv != 0)
+ {
+ if (target->indcount != 0)
+ loadany(target);
+ target->offset.offi += source->offset.offv * size;
+ }
+ return;
+ }
+ if (target->storage & ALLDATREGS)
+ push(target);
+ if ((store_t) (sourcereg = target->storage) & ~reguse & allindregs)
+ targreg = sourcereg;
+ else
+ targreg = getindexreg();
+#ifdef I8088
+ if ((store_t) sourcereg == GLOBAL && target->indcount == 0 &&
+ !(source->type->scalar & CHAR) && source->storage != DREG)
+ load(source, targreg);
+ else
+#endif
+ load(source, DREG);
+
+#ifdef I8088
+ softop(MULOP, constsym((value_t) size), source);
+#endif
+#ifdef MC6809
+
+/*-----------------------------------------------------------------------------
+ do some calculations in advance to decide if index can be done with ABX
+-----------------------------------------------------------------------------*/
+
+ if ((store_t) targreg == XREG && source->type->scalar & CHAR &&
+ size < CANABXCUTOFF)
+ canABX = TRUE;
+ else
+ {
+ canABX = FALSE;
+ softop(MULOP, constsym((value_t) size), source);
+ }
+
+#endif
+
+/*-----------------------------------------------------------------------------
+ deal with constant target - constant becomes offset, result in DREG
+-----------------------------------------------------------------------------*/
+
+ if (target->storage == CONSTANT)
+ {
+ target->storage = DREG;
+ return;
+ }
+
+/*-----------------------------------------------------------------------------
+ load target if it is indirect or GLOBAL or canABX so D or B can be added
+ otherwise, it is register direct (maybe S register, maybe with offset)
+ and the offset can be left after adding DREG
+-----------------------------------------------------------------------------*/
+
+#ifdef I8088
+ if (target->indcount != 0)
+ {
+ targtype = target->type;
+ target->type = itype;
+ add(source, target);
+ target->type = targtype;
+ return;
+ }
+ if ((store_t) sourcereg == GLOBAL)
+ {
+ target->storage = source->storage;
+ target->level = OFFKLUDGELEVEL;
+ return;
+ }
+#endif
+#ifdef MC6809
+ if (canABX || (store_t) sourcereg == GLOBAL)
+ {
+ load(target, targreg);
+ sourcereg = targreg;
+ }
+ else if (target->indcount != 0)
+ {
+ targtype = target->type;
+ target->type = itype;
+ add(source, target);
+ target->type = targtype;
+ return;
+ }
+ if (canABX)
+ while (size--)
+ outABX();
+ else
+#endif
+ {
+#ifdef I8088
+ if ((store_t) targreg != (store_t) sourcereg)
+ regtransfer(sourcereg, targreg);
+ outadd();
+ outregname(targreg);
+ outncregname(DREG);
+#endif
+#ifdef MC6809
+ outlea();
+ outregname(targreg);
+ outtab();
+ outregname(DREG);
+ outncregname(sourcereg);
+#endif
+ }
+ if ((store_t) sourcereg == LOCAL)
+#ifdef FRAMEPOINTER
+ target->offset.offi -= framep;
+#else
+ target->offset.offi -= sp;
+#endif
+ target->storage = targreg;
+}
+
+PUBLIC void indirec(source)
+struct symstruct *source;
+{
+ if (!(source->type->constructor & (ARRAY | POINTER)))
+ bugerror("illegal indirection");
+ else if (source->indcount == (indn_t) - 1)
+ limiterror("too many indirections (256)");
+ else
+ {
+ if (source->storage & ALLDATREGS)
+ transfer(source, getindexreg());
+ if (!((source->type = source->type->nexttype)->constructor &
+ (ARRAY | FUNCTION)))
+ ++source->indcount;
+ if (source->storage == CONSTANT)
+ source->storage = GLOBAL;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ load(source leaf, target register)
+ loads the specified register without changing any others (except CC)
+ if the type is long or float, DREG is paired with the target register
+ the result has no offset
+-----------------------------------------------------------------------------*/
+
+PUBLIC void load(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if (source->type->scalar & DLONG)
+ {
+ if (source->storage == CONSTANT)
+ loadreg(source, targreg);
+ else if (source->indcount == 0)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (!long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ if ((store_t) targreg == DREG)
+ source->storage = DREG;
+ }
+#endif
+ if (source->storage != (store_t) targreg)
+ transfer(source, targreg);
+ if (source->offset.offi != 0)
+ bugerror("loading direct long with offset not implemented");
+ }
+ else
+ loadlongindirect(source, targreg);
+ }
+ else if (source->type->scalar & DOUBLE)
+ {
+ if (source->storage == targreg && source->indcount == 0)
+ return;
+ if (source->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ loadconst(((offset_t *) source->offset.offd)[0], DREG);
+ loadconst(((offset_t *) source->offset.offd)[1], targreg);
+ }
+ else
+ {
+ push(source);
+ poplist(targreg | DREG); /* actually it's the full reg list */
+ }
+ source->storage = targreg; /* XXX - multi for non-386 */
+ source->indcount = 0;
+ source->flags = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0;
+ }
+ else if (source->type->scalar & FLOAT && source->storage == CONSTANT)
+ {
+ float val;
+
+ val = *source->offset.offd;
+ loadconst(((offset_t *) &val)[0], targreg);
+ }
+ else if (source->indcount == 0 && source->storage != CONSTANT)
+ loadadr(source, targreg);
+ else if (source->type->scalar ||
+ source->type->constructor & (ARRAY | POINTER))
+ loadreg(source, targreg);
+ else
+ bugerror("attempting to load non-scalar non-pointer");
+}
+
+PRIVATE void loadadr(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if ((store_t) targreg & ALLDATREGS)
+ {
+ if (source->storage == GLOBAL)
+ {
+#ifdef MC6809
+ if (posindependent)
+ {
+ pushreg(INDREG0);
+ loadreg(source, INDREG0);
+ transfer(source, DREG);
+ recovlist(INDREG0);
+ }
+ else
+#endif
+ loadreg(source, targreg);
+ }
+ if (source->storage == LOCAL)
+#ifdef FRAMEPOINTER
+ source->offset.offi -= framep;
+#else
+ source->offset.offi -= sp;
+#endif
+ if (source->type->scalar & CHAR)
+ targreg = BREG;
+#ifdef I8088
+ if (source->storage == DREG)
+ addoffset(source);
+#endif
+ if (source->storage != (store_t) targreg)
+ transfer(source, targreg);
+ addoffset(source);
+ }
+ else if (source->storage & ALLDATREGS)
+ {
+ addoffset(source);
+ transfer(source, targreg);
+ }
+ else if (source->storage != (store_t) targreg ||
+ source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)
+ loadreg(source, targreg);
+}
+
+PUBLIC void loadany(source)
+struct symstruct *source;
+{
+ if (source->indcount != 0 || source->offset.offi != 0 || /* kludge u cmp */
+ source->level == OFFKLUDGELEVEL || !(source->storage & allregs))
+ {
+ if (source->type->scalar & RSCALAR)
+ load(source, doubleregs & ~DREG);
+ else if ((source->storage == CONSTANT &&
+ !(source->type->scalar & DLONG))
+ || source->type->scalar & CHAR)
+ load(source, DREG);
+ else if (source->storage & ~reguse & allregs)
+ load(source, source->storage);
+ else if (((reguse & allindregs) == allindregs ||
+ ((!(source->type->constructor & (ARRAY | POINTER)) &&
+ source->indcount != 0) &&
+ !(source->type->scalar & DLONG))))
+ load(source, DREG);
+ else
+ load(source, getindexreg());
+ }
+}
+
+PRIVATE void loadlongindirect(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ sc_t flags;
+ offset_t offset;
+ store_t reg;
+ struct typestruct *type;
+
+ if (source->level == OFFKLUDGELEVEL)
+ addoffset(source); /* else kludge is lost and offsets big */
+ flags = source->flags;
+ offset = source->offset.offi;
+ reg = source->storage;
+ type = source->type;
+ source->type = itype;
+ loadreg(source, DREG);
+ source->flags = flags;
+ source->storage = reg;
+ source->indcount = 1;
+ source->offset.offi = offset + accregsize;
+ loadreg(source, targreg);
+ source->type = type;
+}
+
+PUBLIC void loadreg(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ offset_t longhigh;
+ offset_t longlow;
+
+ if (source->storage == CONSTANT)
+ {
+ if (source->type->scalar & CHAR && (store_t) targreg & ALLDATREGS)
+ targreg = BREG;
+ longlow = (offset_t) source->offset.offv;
+ if (source->type->scalar & DLONG)
+ {
+ longlow &= (offset_t) intmaskto;
+ longhigh = (offset_t) (source->offset.offv >> INT16BITSTO)
+ & (offset_t) intmaskto;
+ if ((store_t) targreg != LONGREG2) /* loading the whole long */
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ loadconst(longhigh, DREG);
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ loadconst(longlow, DREG);
+ longlow = longhigh;
+ }
+#endif
+ }
+ }
+ loadconst(longlow, targreg);
+ source->storage = targreg;
+ source->offset.offi = 0;
+ }
+ else
+ {
+#ifdef I8088
+ if (source->indcount == 0 && source->storage != GLOBAL &&
+ (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL))
+ {
+ if ((store_t) targreg == source->storage)
+ {
+ addoffset(source);
+ return;
+ }
+ source->indcount = 1; /* fake for outadr() to produce "()" */
+ outlea();
+ }
+ else
+ {
+ outload();
+ if (source->storage == GLOBAL && source->indcount != 0 &&
+ (store_t) targreg & (AXREG | ALREG))
+ unbumplc();
+ }
+#endif
+#ifdef MC6809
+ if (source->indcount == 0 &&
+ (source->storage != GLOBAL || posindependent))
+ outlea();
+ else
+ {
+ outload();
+ if ((store_t) targreg == YREG)
+ bumplc();
+ }
+#endif
+ movereg(source, targreg);
+ }
+}
+
+PUBLIC void makelessindirect(source)
+struct symstruct *source;
+{
+ store_pt lreg;
+
+ if (!((store_t) (lreg = source->storage) & ~reguse & allindregs))
+ lreg = getindexreg();
+ while (source->indcount > MAXINDIRECT)
+ loadreg(source, lreg);
+#if MAXINDIRECT > 1
+ if (source->indcount == MAXINDIRECT &&
+ (source->type->typesize > maxregsize ||
+ source->type->constructor & FUNCTION))
+ {
+ source->indcount = 1;
+ loadreg(source, lreg);
+ source->indcount = 1;
+ }
+#endif
+}
+
+PUBLIC void movereg(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if ((store_t) targreg & ALLDATREGS && source->type->scalar & CHAR)
+ targreg = BREG;
+#ifdef I8088
+ if (i386_32 && source->type->scalar & SHORT &&
+ source->indcount <= 1)
+ {
+ outshortregname(targreg);
+ bumplc();
+ }
+ else
+#endif
+ outregname(targreg);
+ if (source->storage == CONSTANT)
+ adjlc((offset_t) source->offset.offv, targreg);
+#ifdef I8088
+ outcomma();
+#endif
+ outadr(source);
+ source->storage = targreg; /* in register for further use */
+ source->flags = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0; /* indcount was adjusted by outadr */
+}
+
+PUBLIC void onstack(target)
+register struct symstruct *target;
+{
+ target->storage = LOCAL;
+ target->flags = TEMP;
+ if (target->level == OFFKLUDGELEVEL)
+ target->level = EXPRLEVEL;
+ target->indcount = 1;
+ target->offset.offi = sp;
+}
+
+PUBLIC void outadr(adr)
+struct symstruct *adr;
+{
+ outnnadr(adr);
+ outnl();
+}
+
+PUBLIC void outcregname(reg)
+store_pt reg;
+{
+ outcomma();
+ outregname(reg);
+}
+
+PRIVATE void outnamoffset(adr)
+struct symstruct *adr;
+{
+ outimmed();
+ if (adr->flags & LABELLED)
+ outlabel(adr->name.label);
+ else
+ outccname(adr->name.namep);
+ if (adr->offset.offi != 0)
+ {
+ if (adr->offset.offi > 0)
+ outplus();
+ outshex(adr->offset.offi);
+ }
+ bumplc2();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+/* print comma, then register name, then newline */
+
+PUBLIC void outncregname(reg)
+store_pt reg;
+{
+ outcomma();
+ outnregname(reg);
+}
+
+PRIVATE void outnnadr(adr)
+struct symstruct *adr;
+{
+ bool_t indflag;
+
+ indflag = FALSE;
+#ifdef I8088
+ if (adr->indcount >= MAXINDIRECT)
+ indflag = TRUE;
+#endif
+#ifdef MC6809
+ outtab();
+ if (adr->indcount >= MAXINDIRECT && (adr->indcount & 1) == 0)
+ {
+ indflag = TRUE; /* indirection means double indirect */
+ outindleft();
+ }
+#endif
+ switch (adr->storage)
+ {
+ case CONSTANT:
+ outimmadr((offset_t) adr->offset.offv);
+ break;
+#ifdef I8088
+ case DREG:
+ if (indflag || adr->offset.offi != 0 || adr->level == OFFKLUDGELEVEL)
+ badaddress();
+ else
+ outregname(DREG);
+ break;
+#endif
+#ifdef I8088
+ case DATREG1:
+ case DATREG2:
+ if (indflag && !i386_32)
+ {
+ outnl();
+ badaddress();
+ break;
+ }
+#endif
+ case INDREG0:
+ case INDREG1:
+ case INDREG2:
+ if (adr->level == OFFKLUDGELEVEL)
+ outnamoffset(adr);
+#ifndef MC6809
+ else if (adr->offset.offi != 0)
+#endif
+ outoffset(adr->offset.offi);
+#ifdef I8088
+ if (indflag)
+ outindleft();
+ outregname(adr->storage);
+# ifdef XENIX_AS
+ if (indflag)
+ outindright();
+# endif
+#endif
+#ifdef MC6809
+ if (indflag && adr->offset.offi != 0 && is5bitoffset(adr->offset.offi))
+ bumplc();
+ outcregname(adr->storage);
+#endif
+ break;
+ case LOCAL:
+#ifdef I8088
+# ifdef FRAMEPOINTER
+ if (framep == 0)
+ bugerror("no frame pointer");
+ if (indflag)
+ {
+ if (adr->offset.offi == framep)
+ bumplc();
+ else
+ {
+ if (switchnow != NULL && adr->flags == TEMP)
+ outswoffset(adr->offset.offi);
+ else
+ outoffset(adr->offset.offi - framep);
+ }
+ outindleft();
+ }
+ else if (adr->offset.offi != framep)
+ badaddress();
+ outregname(LOCAL);
+# else
+ if (indflag)
+ {
+ bumplc();
+ if (adr->offset.offi != sp)
+ outoffset(adr->offset.offi - sp);
+ outindleft();
+ }
+ else if (adr->offset.offi != sp)
+ badaddress();
+ outregname(LOCAL);
+# endif /* FRAMEPOINTER */
+# ifdef XENIX_AS
+ if (indflag)
+ outindright();
+# endif
+#endif /* I8088 */
+#ifdef MC6809
+ if (adr->flags == TEMP && adr->offset.offi == sp &&
+ adr->indcount == 1)
+ {
+ outcregname(LOCAL);
+ outplus();
+ ++sp;
+ if (adr->type->typesize != 1)
+ {
+ outplus();
+ ++sp;
+ }
+ break;
+ }
+ outoffset(adr->offset.offi - sp);
+ if (indflag && adr->offset.offi != sp &&
+ is5bitoffset(adr->offset.offi - sp))
+ bumplc();
+ outcregname(LOCAL);
+#endif /* MC6809 */
+ break;
+ case GLOBAL:
+#ifdef I8088
+ bumplc();
+ if (i386_32)
+ bumplc2();
+ if (!indflag)
+ outimmed();
+ else
+ {
+# ifndef XENIX_AS
+ outindleft();
+# endif
+ bumplc();
+ }
+#endif
+#ifdef MC6809
+ if (!posindependent)
+ {
+ if (adr->indcount == 0)
+ {
+ outimmed();
+ bumplc();
+ }
+ else if (indflag)
+ {
+ outextended();
+ bumplc2();
+ }
+ else if (adr->flags & DIRECTPAGE)
+ outdirectpage();
+ else
+ {
+ outextended();
+ bumplc();
+ }
+ }
+#endif
+ if (adr->flags & LABELLED)
+ outlabel(adr->name.label);
+ else if (*adr->name.namep == 0) /* constant address */
+ {
+ outhex((uoffset_t) adr->offset.offi);
+ break;
+ }
+ else
+ outccname(adr->name.namep);
+ if (adr->offset.offi != 0)
+ {
+ if (adr->offset.offi > 0)
+ outplus();
+ outshex(adr->offset.offi);
+ }
+#ifdef MC6809
+ if (posindependent)
+ {
+ outcregname(GLOBAL);
+ bumplc2();
+ }
+#endif
+ break;
+ default:
+ outnl();
+ badaddress();
+ break;
+ }
+#ifdef I8088
+ if (indflag)
+ {
+ --adr->indcount;
+# ifndef XENIX_AS
+ outindright();
+# endif
+ }
+#endif
+#ifdef MC6809
+ if (indflag)
+ {
+ outindright();
+ adr->indcount -= MAXINDIRECT;
+ }
+ else if (adr->indcount != 0)
+ --adr->indcount;
+#endif
+}
+
+/* print register name, then newline */
+
+PUBLIC void outnregname(reg)
+store_pt reg;
+{
+ outregname(reg);
+ outnl();
+}
+
+/* print register name */
+
+PUBLIC void outregname(reg)
+store_pt reg;
+{
+ switch ((store_t) reg)
+ {
+ case BREG:
+ outstr(acclostr);
+ break;
+ case DREG:
+ outstr(accumstr);
+ break;
+#ifdef MC6809
+ case GLOBAL:
+ outstr("PC");
+ break;
+#endif
+ case INDREG0:
+ outstr(ireg0str);
+ break;
+ case INDREG1:
+ outstr(ireg1str);
+ break;
+ case INDREG2:
+ outstr(ireg2str);
+ break;
+ case LOCAL:
+ outstr(localregstr);
+ break;
+#ifdef STACKREG
+ case STACKREG:
+ outstr(stackregstr);
+ break;
+#endif
+#ifdef DATREG1
+ case DATREG1:
+ outstr(dreg1str);
+ break;
+#endif
+#ifdef DATREG1B
+ case DATREG1B:
+ outstr(dreg1bstr);
+ break;
+#endif
+#ifdef DATREG2
+ case DATREG2:
+ outstr(dreg2str);
+ break;
+#endif
+ default:
+ outstr(badregstr);
+ break;
+ }
+}
+
+#ifdef I8088
+/* print register name for short type */
+
+PUBLIC void outshortregname(reg)
+store_pt reg;
+{
+ switch ((store_t) reg)
+ {
+ case DREG:
+ outstr(accumstr + 1);
+ break;
+ case INDREG0:
+ outstr(ireg0str + 1);
+ break;
+ case INDREG1:
+ outstr(ireg1str + 1);
+ break;
+ case INDREG2:
+ outstr(ireg2str + 1);
+ break;
+ case DATREG1:
+ outstr(dreg1str + 1);
+ break;
+ case DATREG2:
+ outstr(dreg2str + 1);
+ break;
+ default:
+ outstr(badregstr);
+ break;
+ }
+}
+
+#endif
+
+/*-----------------------------------------------------------------------------
+ pointat(target leaf)
+ point OPREG at target
+ target must be singly indirect or float or double
+-----------------------------------------------------------------------------*/
+
+PUBLIC void pointat(target)
+struct symstruct *target;
+{
+ if (target->type->scalar & RSCALAR)
+ (void) f_indirect(target);
+ address(target);
+ load(target, OPREG);
+ target->type = target->type->nexttype;
+}
+
+PUBLIC void poplist(reglist)
+store_pt reglist;
+{
+ if (reglist)
+ sp += pushpull(reglist, FALSE);
+}
+
+PUBLIC void push(source)
+struct symstruct *source;
+{
+ store_t reg;
+#ifdef I8088
+ uoffset_t size;
+#endif
+ scalar_t sscalar;
+
+ if (source->type->constructor & STRUCTU)
+ {
+ if (source->flags != TEMP) /* TEMP must be from last function */
+ blockpush(source);
+ }
+ else if ((sscalar = source->type->scalar) & RSCALAR)
+ {
+ if (!f_indirect(source))
+ {
+ saveopreg();
+ fpush(source);
+ restoreopreg();
+ }
+ }
+#ifdef I8088
+ else if ((source->indcount == 1 &&
+ (sscalar & (SHORT | INT | LONG | FLOAT) ||
+ source->type->constructor & POINTER)) ||
+ (source->storage == CONSTANT && i386_32))
+ {
+ size = source->type->typesize;
+ if (size == 1)
+ size = 2;
+ if (sscalar & DLONG)
+ {
+ source->offset.offi += itypesize;
+ outpshs();
+ bumplc();
+ outtab();
+ outadr(source);
+ source->indcount = 1;
+ source->offset.offi -= itypesize;
+ }
+ outpshs();
+ bumplc();
+ outtab();
+ if (i386_32)
+ {
+ if (source->storage == CONSTANT)
+ {
+ unbumplc();
+ adjlc((offset_t) source->offset.offv, INDREG0);
+ }
+ if (size == 2)
+ {
+ outword();
+ bumplc();
+ }
+ else
+ outdword();
+ }
+ outadr(source);
+ sp -= size;
+ }
+#endif
+ else
+ {
+ reg = source->storage;
+ loadany(source);
+ if (sscalar & DLONG)
+ pushlist(DREG | source->storage);
+ else if (sscalar & CHAR)
+ pushchar();
+ else
+ pushreg(source->storage);
+ if (source->flags != REGVAR)
+ reguse &= ~(reg | source->storage);
+ }
+ onstack(source);
+}
+
+PUBLIC void pushlist(reglist)
+store_pt reglist;
+{
+ if ((store_t) reglist)
+ sp -= pushpull(reglist, TRUE);
+}
+
+PRIVATE fastin_pt pushpull(reglist, pushflag)
+store_pt reglist;
+bool_pt pushflag;
+{
+ store_pt lastregbit;
+ void (*ppfunc) P((void));
+ char *regptr;
+
+#ifdef MC6809
+ int separator; /* promoted char for output */
+
+#endif
+ fastin_t bytespushed;
+ store_pt regbit;
+
+ if ((bool_t) pushflag)
+ {
+ ppfunc = outpshs;
+#ifdef I8088
+ regbit = 1 << 10;
+#else
+ regbit = 1 << 7;
+#endif
+ regptr = regpushlist;
+ lastregbit = 1;
+ }
+ else
+ {
+ ppfunc = outpuls;
+ regbit = 1;
+ regptr = regpulllist;
+#ifdef I8088
+ lastregbit = 1 << 10;
+#else
+ lastregbit = 1 << 7;
+#endif
+ }
+#ifdef MC6809 /* temp use pull strings to keep old order */
+ regbit = 1;
+ regptr = regpulllist;
+ lastregbit = 1 << 7;
+#endif
+#ifdef MC6809
+ separator = OPSEPARATOR;
+ (*ppfunc) ();
+#endif
+ bytespushed = 0;
+ while (TRUE)
+ {
+ if (regbit & reglist)
+ {
+#ifdef I8088
+ (*ppfunc)();
+ if (*regptr != FLAGSREGCHAR)
+ outtab();
+#endif
+#ifdef MC6809
+ outbyte(separator);
+#endif
+ do
+ outbyte(*regptr++);
+ while (*regptr >= MINREGCHAR);
+ bytespushed += *regptr++ - '0';
+#ifdef I8088
+ outnl();
+#endif
+#ifdef MC6809
+ separator = OPERANDSEPARATOR;
+#endif
+ }
+ else
+ do
+ ;
+ while (*regptr++ >= MINREGCHAR);
+ if (regbit == lastregbit)
+ break;
+#ifdef MC6809 /* temp use pull strings to keep old order */
+ regbit <<= 1;
+#else /* this should normally be unconditional */
+ if ((bool_t) pushflag)
+ regbit >>= 1;
+ else
+ regbit <<= 1;
+#endif
+ }
+#ifdef MC6809
+ outnl();
+#endif
+ return bytespushed;
+}
+
+PUBLIC void pushreg(reg)
+store_pt reg;
+{
+ outpshs();
+ outtab();
+ outnregname(reg);
+ sp -= pshregsize;
+}
+
+PUBLIC void storereg(sourcereg, target)
+store_pt sourcereg;
+struct symstruct *target;
+{
+ store_pt targreg;
+
+ if (target->indcount == 0)
+ {
+ if (target->offset.offi != 0 || target->level == OFFKLUDGELEVEL ||
+ !(target->storage & allregs) || target->storage & CHARREGS)
+ bugerror("bad register store");
+ else if ((store_t) (targreg = target->storage) != (store_t) sourcereg)
+ {
+ target->storage = sourcereg;
+ loadadr(target, targreg); /* do LEA or TFR */
+ }
+ }
+ else
+ {
+ outstore();
+#ifdef I8088
+ if (target->storage == GLOBAL && (store_t) sourcereg & (AXREG | ALREG))
+ unbumplc();
+ outnnadr(target);
+ outcomma();
+#ifdef I8088
+ if (i386_32 && target->type->scalar & SHORT)
+ {
+ outshortregname(sourcereg);
+ bumplc();
+ outnl();
+ }
+ else
+#endif
+ outnregname(sourcereg);
+#endif
+#ifdef MC6809
+ if ((store_t) sourcereg == YREG)
+ bumplc();
+ outregname(sourcereg);
+ outadr(target);
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ struc(element leaf, structure leaf)
+ evaluates the expression
+ structure.element
+-----------------------------------------------------------------------------*/
+
+PUBLIC void struc(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ address(target);
+ if (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)
+ {
+ if (target->indcount != 0 || target->level == OFFKLUDGELEVEL)
+ load(target, getindexreg());
+ target->offset.offi += source->offset.offi;
+ }
+ if (source->indcount == 0)
+ target->type = source->type;
+ else
+ {
+ target->type = pointype(source->type); /* lost by = */
+ indirec(target);
+ }
+}
+
+PUBLIC void transfer(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ regtransfer(source->storage, targreg);
+ source->storage = targreg;
+}
diff --git a/bcc/glogcode.c b/bcc/glogcode.c
new file mode 100644
index 0000000..e2d086b
--- /dev/null
+++ b/bcc/glogcode.c
@@ -0,0 +1,560 @@
+/* glogcode.c - generate code for logical expressions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#define cc_signed(cc) ((cc) >= 4 && (cc) < 8)
+
+PRIVATE char oppcc[] = /* opposite condition codes LT --> GE etc */
+/* EQ, NE, RA, RN, LT, GE, LE, GT, LO, HS, LS, HI, indices */
+{
+ NE, EQ, RN, RA, GE, LT, GT, LE, HS, LO, HI, LS,
+};
+
+PRIVATE char reverscc[] = /* reverse condition codes LT --> GT etc */
+{
+ EQ, NE, RN, RA, GT, LE, GE, LT, HI, LS, HS, LO,
+};
+
+PRIVATE char testcc[] = /* test condition codes LS --> EQ etc */
+{
+ EQ, NE, RA, RN, LT, GE, LE, GT, RN, RA, EQ, NE,
+};
+
+PRIVATE char unsigncc[] = /* unsigned condition codes LT --> LO etc */
+{
+ EQ, NE, RA, RN, LO, HS, LS, HI, LO, HS, LS, HI,
+};
+
+FORWARD void cmplocal P((struct symstruct *source, struct symstruct *target,
+ ccode_t *pcondtrue));
+#ifdef MC6809
+FORWARD void cmporsub P((struct symstruct *target));
+FORWARD bool_pt cmpsmallconst P((value_t intconst, struct symstruct *target,
+ ccode_t *pcondtrue));
+#endif
+FORWARD void comparecond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void jumpcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void loadlogical P((struct symstruct *source, label_t falselab));
+FORWARD void logandcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void logorcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void reduceconst P((struct symstruct *source));
+FORWARD void test P((struct symstruct *target, ccode_t *pcondtrue));
+FORWARD void testcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+
+PUBLIC void cmp(source, target, pcondtrue)
+struct symstruct *source;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ label_t falselab;
+
+ cmplocal(source, target, pcondtrue);
+#if 0
+#ifdef I8088
+ if (i386_32)
+ {
+ if (*pcondtrue == LO)
+ {
+ getlabel();
+ getlabel();
+ outnop2str("sbb\teax,eax");
+ outnop1str("inc eax");
+ target->storage = BREG;
+ target->type = ctype;
+ return;
+ }
+ if (*pcondtrue == HS)
+ {
+ getlabel();
+ getlabel();
+ outnop2str("sbb\teax,eax");
+ outnop2str("neg eax");
+ target->storage = BREG;
+ target->type = ctype;
+ return;
+ }
+ }
+#endif
+#endif
+ sbranch(oppcc[(int)*pcondtrue], falselab = getlabel());
+ loadlogical(target, falselab);
+}
+
+PRIVATE void cmplocal(source, target, pcondtrue)
+struct symstruct *source;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ scalar_t sscalar;
+ scalar_t tempscalar;
+ scalar_t tscalar;
+
+ reduceconst(source);
+ reduceconst(target);
+ sscalar = source->type->scalar;
+ tscalar = target->type->scalar;
+ if ((source->storage != CONSTANT &&
+ (target->storage == CONSTANT ||
+ (sscalar & CHAR && !(tscalar & CHAR)) ||
+ ((sscalar & CHAR || !(tscalar & CHAR)) &&
+ source->indcount == 0 && target->indcount != 0))) ||
+ (tscalar & DLONG && target->indcount != 0))
+ {
+ swapsym(target, source);
+ *pcondtrue = reverscc[(int)*pcondtrue];
+ tempscalar = sscalar;
+ sscalar = tscalar;
+ tscalar = tempscalar;
+ }
+ if ((sscalar & CHAR && tscalar & CHAR &&
+ (source->type != sctype || target->type != sctype)) ||
+ (sscalar | tscalar) & UNSIGNED ||
+ (source->type->constructor | target->type->constructor) &
+ (ARRAY | POINTER))
+ *pcondtrue = unsigncc[(int)*pcondtrue];
+ if (source->type->scalar & DLONG)
+ {
+ longop(EQOP, source, target);
+ return;
+ }
+ if (source->type->scalar & RSCALAR)
+ {
+ floatop(EQOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ if (sscalar & CHAR)
+ {
+ if (tscalar & CHAR)
+ *pcondtrue = unsigncc[(int)*pcondtrue];
+ else
+ {
+ source->type = iscalartotype(sscalar);
+ sscalar = source->type->scalar;
+ }
+ }
+ if (source->offset.offv == 0)
+ {
+ test(target, pcondtrue);
+ return;
+ }
+#ifdef MC6809
+ if (cmpsmallconst(source->offset.offv, target, pcondtrue))
+ return;
+#endif
+ }
+ if (!(sscalar & CHAR) && tscalar & CHAR)
+ {
+ loadpres(target, source);
+ extend(target);
+ }
+#ifndef MC6809
+# define posindependent 0
+#endif
+ if (source->indcount == 0 && source->storage != CONSTANT &&
+ (posindependent || source->storage != GLOBAL))
+ {
+ loadpres(source, target);
+#ifdef MC6809
+ push(source);
+#endif
+ }
+ loadpres(target, source);
+#ifdef MC6809
+ cmporsub(target);
+#else
+ outcmp();
+#endif
+#ifdef I8088
+ if (source->storage == GLOBAL && source->indcount == 0 &&
+ !(target->storage & (AXREG | ALREG)))
+ bumplc();
+#endif
+ movereg(source, target->storage);
+}
+
+#ifdef MC6809
+
+PRIVATE void cmporsub(target)
+struct symstruct *target;
+{
+ if (target->storage & ALLDATREGS)
+ outsub();
+ else
+ {
+ outcmp();
+ if (target->storage != XREG)
+ bumplc();
+ }
+}
+
+PRIVATE bool_pt cmpsmallconst(intconst, target, pcondtrue)
+value_t intconst;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ store_pt targreg;
+
+ if ((*pcondtrue == EQ || *pcondtrue == NE) &&
+ !(target->storage & ALLDATREGS) && !(target->type->scalar & CHAR) &&
+ isnegbyteoffset(intconst) &&
+ (reguse & (XREG | YREG)) != (XREG | YREG))
+ {
+ targreg = XREG;
+ if (reguse & XREG)
+ targreg = YREG;
+ if (target->indcount != 0)
+ load(target, targreg);
+ target->offset.offi -= (offset_t) intconst;
+ loadreg(target, targreg);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#endif
+
+PRIVATE void comparecond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ ccode_t condtrue;
+ store_t regmark;
+ struct symstruct *source;
+ offset_t spmark;
+ struct symstruct *target;
+
+ regmark = reguse;
+ spmark = sp;
+ bileaf(exp);
+ target = exp->left.nodeptr->left.symptr;
+ source = exp->right->left.symptr; /* exp->right != NULL since cond */
+ switch (exp->tag)
+ {
+ case GEOP:
+ condtrue = GE;
+ break;
+ case GTOP:
+ condtrue = GT;
+ break;
+ case LEOP:
+ condtrue = LE;
+ break;
+ case EQOP:
+ condtrue = EQ;
+ break;
+ case LTOP:
+ condtrue = LT;
+ break;
+ case NEOP:
+ condtrue = NE;
+ break;
+ }
+ cmplocal(source, target, &condtrue);
+ changesp(spmark, FALSE);
+ reguse = regmark;
+ if ((bool_t) nojump)
+ lbranch(oppcc[(int)condtrue], falselab);
+ else
+ lbranch(condtrue, truelab);
+}
+
+PUBLIC void condop(exp)
+struct nodestruct *exp;
+{
+ label_t exitlab;
+ label_t falselab;
+ struct nodestruct *falsenode;
+ struct symstruct *falsesym;
+ label_t truelab;
+ struct nodestruct *truenode;
+ struct symstruct *truesym;
+
+ jumpcond(exp->left.nodeptr, truelab = getlabel(),
+ falselab = getlabel(), ~0);
+ deflabel(truelab);
+ makeleaf(truenode = exp->right->left.nodeptr);
+ loadany(truesym = truenode->left.symptr);
+ if (truesym->storage & reguse)
+ {
+ /* This can happen if truesym was a reg variable. */
+ if (truesym->type->scalar & RSCALAR)
+ /* XXX - always happens for non-386 with 2 regs vars assigned. */
+ bugerror("loaded float or double into used reg");
+ load(truesym, DREG);
+ }
+ falsenode = exp->right->right;
+ if (/* falsenode->tag != LEAF || XXX */
+ truesym->type != falsenode->left.symptr->type)
+ cast(truenode->nodetype == falsenode->nodetype ?
+ truenode->nodetype : exp->nodetype, truesym);
+ jump(exitlab = getlabel());
+ deflabel(falselab);
+ makeleaf(falsenode);
+ falsesym = falsenode->left.symptr;
+ if (falsesym->type != truesym->type)
+ cast(truesym->type, falsesym);
+ load(falsesym, truesym->storage);
+ deflabel(exitlab);
+ exp->tag = LEAF;
+ exp->left.symptr = truesym;
+}
+
+PRIVATE void jumpcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ switch (exp->tag)
+ {
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case EQOP:
+ case LTOP:
+ case NEOP:
+ comparecond(exp, truelab, falselab, nojump);
+ break;
+ case LOGANDOP:
+ logandcond(exp, truelab, falselab, nojump);
+ break;
+ case LOGNOTOP:
+ jumpcond(exp->left.nodeptr, falselab, truelab, ~nojump);
+ break;
+ case LOGOROP:
+ logorcond(exp, truelab, falselab, nojump);
+ break;
+ default:
+ testcond(exp, truelab, falselab, nojump);
+ break;
+ }
+}
+
+PUBLIC void jumpfalse(exp, label)
+struct nodestruct *exp;
+label_t label;
+{
+ label_t truelab;
+
+ jumpcond(exp, truelab = getlabel(), label, ~0);
+ deflabel(truelab);
+}
+
+PUBLIC void jumptrue(exp, label)
+struct nodestruct *exp;
+label_t label;
+{
+ label_t falselab;
+
+ jumpcond(exp, label, falselab = getlabel(), 0);
+ deflabel(falselab);
+}
+
+PRIVATE void loadlogical(source, falselab)
+struct symstruct *source;
+label_t falselab;
+{
+ label_t exitlab;
+ struct symstruct *target;
+
+ target = constsym((value_t) TRUE);
+ target->type = ctype;
+ loadreg(target, DREG);
+ sbranch(RA, exitlab = getlabel());
+ deflabel(falselab);
+ target = constsym((value_t) FALSE);
+ target->type = ctype;
+ *source = *target;
+ loadreg(source, DREG);
+ outnlabel(exitlab);
+}
+
+PRIVATE void logandcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ label_t andlab;
+
+ andlab = getlabel();
+ jumpcond(exp->left.nodeptr, andlab, falselab, ~0);
+ deflabel(andlab);
+ jumpcond(exp->right, truelab, falselab, nojump);
+}
+
+PUBLIC void logop(exp)
+struct nodestruct *exp;
+{
+ label_t falselab;
+ struct symstruct *target;
+ label_t truelab;
+
+ jumpcond(exp, truelab = getlabel(), falselab = getlabel(), ~0);
+ deflabel(truelab);
+ target = constsym((value_t) 0); /* anything, loadlogical makes B reg */
+ target->type = ctype;
+ loadlogical(target, falselab);
+ exp->tag = LEAF;
+ exp->left.symptr = target;
+}
+
+PRIVATE void logorcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ label_t orlab;
+
+ orlab = getlabel();
+ jumpcond(exp->left.nodeptr, truelab, orlab, 0);
+ deflabel(orlab);
+ jumpcond(exp->right, truelab, falselab, nojump);
+}
+
+PRIVATE void reduceconst(source)
+struct symstruct *source;
+{
+ if (source->storage == CONSTANT && ischarconst(source->offset.offv) &&
+ (source->type->scalar & (CHAR | SHORT | INT | DLONG)) != DLONG)
+ {
+ if (source->type->scalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ }
+}
+
+PRIVATE void test(target, pcondtrue)
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+#ifdef I8088
+ store_t targreg;
+#endif
+
+ *pcondtrue = testcc[(int)*pcondtrue];
+ if (target->type->scalar & DLONG)
+ {
+ long1op(EQOP, target);
+ return;
+ }
+ if (target->type->scalar & RSCALAR)
+ {
+ float1op(EQOP, target);
+ return;
+ }
+#ifdef I8088
+ if (target->indcount != 0 ||
+ (target->storage == LOCAL && target->offset.offi != sp))
+ load(target, DREG);
+ if (target->storage == GLOBAL)
+ load(target, getindexreg());
+ if (target->type->scalar & CHAR)
+ load(target, DREG);
+ targreg = target->storage;
+ if (target->offset.offi != 0 && cc_signed(*pcondtrue))
+ load(target, targreg);
+
+ /* Extension was not done in exptree for the == 0 case, to allow
+ * optimization here - which we don't do for shorts. (foo--) is
+ * newfoo == -1 here and used to be missed.
+ */
+ if (i386_32 && target->type->scalar & SHORT)
+ extend(target);
+
+ if (target->offset.offi == 0)
+ {
+ outtest();
+ outregname(targreg);
+ outcomma();
+ outnregname(targreg);
+ return;
+ }
+ outcmp();
+ outimadj(-target->offset.offi, targreg);
+#endif
+#ifdef MC6809
+ if (target->indcount != 0 ||
+ target->storage == LOCAL && target->offset.offi != sp)
+ {
+ load(target, DREG);
+ return;
+ }
+ if (cmpsmallconst(0, target, pcondtrue))
+ return;
+ if (target->storage == GLOBAL)
+ load(target, getindexreg());
+ if (target->type->scalar & CHAR)
+ load(target, DREG);
+ if (target->offset.offi != 0 && cc_signed(*pcondtrue))
+ load(target, target->storage);
+ if (target->type->scalar & CHAR)
+ {
+ if (target->offset.offi == 0)
+ {
+ outtest();
+ outnregname(BREG);
+ return;
+ }
+ outcmp();
+ outimadj(-target->offset.offi, BREG);
+ }
+ else
+ {
+ cmporsub(target);
+ outimadj(-target->offset.offi, target->storage);
+ }
+#endif
+}
+
+/* test expression and jump depending on NE/EQ */
+
+PRIVATE void testcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ ccode_t condtrue;
+ struct symstruct *source;
+
+ makeleaf(exp);
+ source = exp->left.symptr;
+ reduceconst(source);
+ if (source->storage != CONSTANT)
+ {
+ condtrue = NE;
+ test(source, &condtrue);
+ if ((bool_t) nojump)
+ lbranch(oppcc[(int)condtrue], falselab);
+ else
+ lbranch(condtrue, truelab);
+ }
+ else if (source->offset.offi == 0)
+ {
+ if ((bool_t) nojump)
+ jump(falselab);
+ }
+ else if (!(bool_t) nojump)
+ jump(truelab);
+}
diff --git a/bcc/hardop.c b/bcc/hardop.c
new file mode 100644
index 0000000..098d22b
--- /dev/null
+++ b/bcc/hardop.c
@@ -0,0 +1,510 @@
+/* hardop.c - hardware operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void sub1 P((struct symstruct *source, struct symstruct *target));
+
+PUBLIC void add(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ scalar_t sscalar;
+
+ if (source->indcount == 0 && source->storage != CONSTANT &&
+ (target->indcount != 0 || target->storage & ALLDATREGS))
+ swapsym(target, source);
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(ADDOP, source, target);
+ return;
+ }
+ if (sscalar & RSCALAR)
+ {
+ floatop(ADDOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+ if (target->indcount != 0 || target->storage & reguse)
+ loadany(target);
+ target->offset.offi += (offset_t) source->offset.offv;
+ }
+ else if (source->indcount == 0)
+ {
+ /* target is also direct */
+ sscalar |= target->type->scalar; /* remember if unsigned/long */
+ target->type = pctype; /* fake to use indexadr() */
+ indexadr(source, target);
+ }
+ else
+ {
+ /* source is indirect and not DREG */
+ extend(target);
+ load(target, DREG);
+ outadd();
+ movereg(source, DREG);
+ if (source->type->scalar & CHAR)
+ adc0();
+ }
+ target->type = iscalartotype(target->type->scalar | sscalar);
+}
+
+PUBLIC void incdec(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ offset_t bump;
+ bool_t postflag;
+ store_t regmark;
+ struct symstruct *target;
+ struct symstruct targ;
+#ifdef MC6809
+ store_pt targreg;
+#endif
+
+ *(target = &targ) = *source;
+ bump = 1;
+ if (targ.type->constructor & POINTER)
+ bump = targ.type->nexttype->typesize;
+ if (op == PREDECOP || op == POSTDECOP)
+ bump = -bump;
+ postflag = FALSE;
+ if (op == POSTDECOP || op == POSTINCOP)
+ postflag = TRUE;
+ reguse |= targ.storage;
+ if (targ.type->scalar & DLONG) /* cannot be direct */
+ {
+ if (postflag)
+ {
+ regmark = reguse;
+ if (((reguse |= OPREG) & allindregs) == allindregs)
+ {
+ saveopreg();
+ load(source, OPREG);
+ pushreg(source->storage);
+ restoreopreg();
+ }
+ else
+ {
+ loadany(source);
+ reguse = regmark | source->storage;
+ saveopreg();
+ }
+ }
+ else
+ saveopreg();
+ pointat(target);
+ switch (op)
+ {
+ case PREDECOP:
+ case POSTDECOP:
+ call("ldec");
+ break;
+ case PREINCOP:
+ case POSTINCOP:
+ call("linc");
+ break;
+ }
+ outlongendian();
+ restoreopreg();
+ if (postflag && source->storage == OPREG)
+ poplist(OPREG);
+ return;
+ }
+ if (targ.type->scalar & RSCALAR)
+ {
+ saveopreg();
+ pointat(target);
+ switch (op)
+ {
+ case PREDECOP:
+ call("Fpredec");
+ break;
+ case PREINCOP:
+ call("Fpreinc");
+ break;
+ case POSTDECOP:
+ call("Fpostdec");
+ break;
+ case POSTINCOP:
+ call("Fpostinc");
+ break;
+ }
+ outntypechar(targ.type);
+ restoreopreg();
+ if (postflag)
+ {
+ justpushed(source);
+ source->type = targ.type;
+ }
+ return;
+ }
+ loadany(source);
+#ifdef MC6809
+ if (postflag && targ.flags != REGVAR &&
+ !(source->storage & ALLDATREGS) &&
+ ((reguse |= source->storage) & allindregs) != allindregs)
+ {
+ targreg = getindexreg();
+ outlea();
+ outregname(targreg);
+ outtab();
+ outshex(bump);
+ outncregname(source->storage);
+ }
+ else
+ {
+ addconst(bump, targreg = source->storage);
+ if (postflag)
+ source->offset.offi = -bump;
+ }
+ storereg(targreg, target);
+ target->storage = targreg;
+ target->offset.offi = 0;
+#else
+ addconst(bump, source->storage);
+ if (postflag)
+ source->offset.offi = -bump;
+ storereg(source->storage, target);
+ target->storage = source->storage;
+ target->offset.offi = 0;
+#endif
+}
+
+PUBLIC void neg(target)
+struct symstruct *target;
+{
+ scalar_t scalar;
+ struct symstruct *source;
+
+ if ((scalar = target->type->scalar) & DLONG)
+ long1op(NEGOP, target);
+ else if (scalar & RSCALAR)
+ float1op(NEGOP, target);
+ else
+ {
+ if (scalar & SHORT)
+ extend(target);
+ if (!(target->storage & ALLDATREGS))
+ {
+ /* load 0, subtract is shorter than load, negate */
+ /* if no hardware integer negate; about the same if there is */
+ sub1(target, source = constsym((value_t) 0));
+ *target = *source;
+ }
+ else
+ {
+ load(target, DREG);
+ negreg(target->storage);
+ target->storage = DREG;
+ }
+ target->type = iscalartotype(scalar);
+ }
+}
+
+PUBLIC void not(target)
+struct symstruct *target;
+{
+ if (target->type->scalar & DLONG)
+ long1op(NOTOP, target);
+ else
+ {
+ extend(target);
+ load(target, DREG);
+ comDreg();
+ }
+}
+
+/* 1-byte ops like AND acting on integers (not both constant) */
+
+PUBLIC void op1(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ char *opstr;
+#ifdef OP1
+# if MAXINDIRECT > 1
+ indn_t indcount;
+# endif
+#endif
+ bool_t resultchar;
+ scalar_t resultscalar;
+ scalar_t sscalar;
+ scalar_t tscalar;
+
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(op, source, target);
+ return;
+ }
+ /* Emergency fix. The types of constants should be reduced here and in
+ * other low-level routines anyway, and not in exptree.c and table.c,
+ * and for the 80386 and maybe the 8086 they would be better not
+ * reduced.
+ */
+ if (source->storage == CONSTANT && ischarconst(source->offset.offv))
+ {
+ if (sscalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ sscalar = source->type->scalar;
+ }
+ tscalar = target->type->scalar;
+ if (target->storage == CONSTANT && ischarconst(target->offset.offv))
+ {
+ if (sscalar & UNSIGNED)
+ target->type = uctype;
+ else
+ target->type = ctype;
+ tscalar = target->type->scalar;
+ }
+ resultscalar = sscalar | tscalar;
+ if (op != ANDOP)
+ resultchar = sscalar & tscalar & CHAR;
+ else if ((resultchar = (sscalar | tscalar) & CHAR) != 0 &&
+ source->storage == CONSTANT)
+ {
+ source->offset.offv &= CHMASKTO;
+ if (sscalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ sscalar = source->type->scalar;
+ }
+ if (target->indcount != 0 &&
+ ((tscalar & CHAR && !(sscalar & CHAR) &&
+ op != ANDOP) || (source->indcount == 0 && source->storage != CONSTANT)))
+ {
+ swapsym(target, source);
+ sscalar = tscalar;
+ tscalar = target->type->scalar;
+ }
+ if (source->indcount == 0 && source->storage != CONSTANT)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+#if MAXINDIRECT > 1
+ else if (source->indcount >= MAXINDIRECT && !(sscalar & CHAR))
+ {
+ address(source);
+ if (!(target->storage & ALLDATREGS))
+ preserve(target);
+ load(source, getindexreg());
+ indirec(source);
+ }
+#endif
+ if (!(tscalar & CHAR) &&
+ op == ANDOP && sscalar & CHAR && target->indcount == 1)
+ cast(ctype, target);
+ if (!(target->storage & ALLDATREGS) || target->indcount != 0)
+ pres2(target, source);
+ load(target, DREG);
+ opstr = opstring(op);
+ if (source->storage == CONSTANT && op == ANDOP)
+ andconst((offset_t) source->offset.offv);
+#ifdef OP1
+ else if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP)
+ outload();
+ else
+ outop2str(opstr);
+#else /* OP1 */
+ else
+ {
+ if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP)
+ extend(target);
+ outop2str(opstr);
+ }
+#endif /* OP1 */
+ if (source->storage == CONSTANT)
+ {
+ if (op != ANDOP)
+ {
+#ifdef OP1
+ if (!(sscalar & CHAR))
+ {
+ outhiaccum();
+ outncimmadr((offset_t) ((uoffset_t) source->offset.offv
+ >> (INT16BITSTO - CHBITSTO)));
+ outop2str(opstr);
+ }
+ outregname(BREG);
+ outncimmadr((offset_t) source->offset.offv & CHMASKTO);
+#else /* OP1 */
+ if (!(sscalar & CHAR))
+ {
+ outregname(DREG);
+ bumplc();
+ }
+ else
+ outregname(BREG);
+# ifdef I8088
+ if (i386_32 && !(sscalar & CHAR))
+ bumplc2();
+# endif
+ outncimmadr((offset_t) source->offset.offv);
+
+#endif /* OP1 */
+ }
+ }
+ else if (sscalar & CHAR)
+ {
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ }
+ else
+ {
+#ifdef MC6809
+ source->type = ctype; /* fool outadr to avoid ,S++ */
+#endif
+#ifdef OP1
+ if (!(tscalar & CHAR) || op != ANDOP)
+ {
+ outhiaccum();
+# if MAXINDIRECT > 1
+ indcount = source->indcount;
+# endif
+ outopsep();
+# if BIG_ENDIAN == 0
+ ++source->offset.offi;
+# endif
+ outadr(source);
+# if BIG_ENDIAN == 0
+ --source->offset.offi;
+# endif
+# if MAXINDIRECT > 1
+ source->indcount = indcount;
+# else
+ source->indcount = 1;
+# endif
+ outop2str(opstr);
+ }
+ outregname(BREG);
+ outopsep();
+# if BIG_ENDIAN
+ ++source->offset.offi;
+# endif
+ outadr(source);
+ }
+#else /* OP1 */
+ if (!(tscalar & CHAR) || op != ANDOP)
+ outregname(DREG);
+ else
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ }
+#endif /* OP1 */
+ if (resultchar)
+ {
+ target->storage = BREG;
+ if (resultscalar & UNSIGNED)
+ target->type = uctype;
+ else
+ target->type = ctype;
+ }
+ else
+ {
+ target->storage = DREG;
+ target->type = iscalartotype(resultscalar);
+ }
+}
+
+PUBLIC void ptrsub(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ label_t exitlab;
+ uoffset_t factor;
+ label_t usignlab;
+
+ if (source->indcount == 0 && source->storage != CONSTANT)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+ if (target->indcount == 0)
+ {
+ pres2(target, source);
+ load(target, DREG);
+ }
+ factor = target->type->nexttype->typesize;
+ source->type = target->type = itype;
+ sub1(source, target);
+ if (factor != 1)
+ {
+ pushlist(CCREG);
+ sbranch(HS, usignlab = getlabel()); /* HS == no carry */
+ negDreg();
+ outnlabel(usignlab);
+ target->type = uitype;
+ softop(DIVOP, constsym((value_t) factor), target);
+ target->type = itype;
+ poplist(CCREG);
+ sbranch(HS, exitlab = getlabel());
+ negDreg();
+ outnlabel(exitlab);
+ }
+}
+
+PUBLIC void sub(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ scalar_t sscalar;
+
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(SUBOP, source, target);
+ return;
+ }
+ if (sscalar & RSCALAR)
+ {
+ floatop(SUBOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+ if (target->indcount != 0 || target->storage & reguse)
+ loadany(target);
+ target->offset.offi -= (offset_t) source->offset.offv;
+ }
+ else
+ sub1(source, target);
+ target->type = iscalartotype(target->type->scalar | sscalar);
+}
+
+PRIVATE void sub1(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ if (source->storage == CONSTANT)
+ source->type = itype;
+ else if (source->indcount == 0)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+ extend(target);
+ load(target, DREG);
+ outsub();
+ movereg(source, DREG);
+ if (source->type->scalar & CHAR)
+ sbc0();
+}
diff --git a/bcc/input.c b/bcc/input.c
new file mode 100644
index 0000000..4cf699a
--- /dev/null
+++ b/bcc/input.c
@@ -0,0 +1,771 @@
+/* input.c - input for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define ARBITRARY_BACKSLASH_NEWLINES_NOT
+#define INSERT_BACKSLASH_NEWLINES_NOT
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "output.h"
+#include "os.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "input.h"
+
+#define INBUFSIZE 2048
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char *fname; /* file name */
+ bool_t fname_malloced; /* nonzero if fname was malloced */
+ char pushback[3]; /* allows pushback to 2 before start of fbuf
+ * XXX 3 chars before?
+ * XXX should do everything in fbuf */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+};
+
+struct inclist /* list of include file directories */
+{
+ char *incdirname;
+ struct inclist *incnext;
+};
+
+PRIVATE char filemacro[] = "__FILE__";
+PRIVATE struct inclist incabsolute; /* dummy list for absolute names */
+ /* depends on zero (NULL) init */
+PRIVATE struct inclist incfirst;
+ /* begin include searches here for "" */
+ /* at next in list for <> */
+ /* -I directories are put in list */
+ /* between first and last */
+PRIVATE struct inclist inclast =
+{
+#ifdef DEFAULT_INCLUDE_DIR
+ DEFAULT_INCLUDE_DIR,
+#endif
+ NULL,
+};
+PRIVATE fastin_t inclevel; /* nest level of include files */
+ /* depends on zero init */
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+ /* depends on zero (NULL) init */
+PRIVATE bool_t suppress_line_numbers;
+
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+FORWARD void backslash P((void));
+#endif
+FORWARD void definefile P((char *fname));
+FORWARD void inputinit P((char *fname, fd_t fd));
+FORWARD void leaveinclude P((void));
+FORWARD void usage P((void));
+
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+PRIVATE void backslash()
+{
+ static unsigned nbackslash;
+
+ if (nbackslash != 0)
+ --nbackslash;
+more:
+ ++nbackslash;
+ while (*(lineptr + 1) == '\\')
+ {
+ ++nbackslash;
+ ++lineptr;
+ }
+ if (*(lineptr + 1) != EOL)
+ {
+ if (--nbackslash != 0)
+ *--lineptr = '\\'; /* force look at current backslash again */
+ return;
+ }
+ ch = *++lineptr;
+more1:
+ if (!eof && lineptr >= input.limit)
+ skipeol();
+ if (ch == EOL)
+ {
+ --nbackslash;
+ if (eof)
+ eofin("backslash-newline");
+ else
+ {
+ skipeol();
+ if (ch == EOL && !eof && lineptr >= input.limit)
+ skipeol();
+#ifdef COEOL /* XXX - this should go through specialchar() */
+ if (ch == COEOL)
+ {
+ ch = *++lineptr;
+ if (ch == EOL && !eof && lineptr >= input.limit)
+ skipeol();
+ }
+#endif
+ }
+ if (ch == '\\')
+ goto more;
+ if (nbackslash != 0 && ch == EOL && !eof)
+ goto more1;
+ if (nbackslash != 0)
+ {
+ ch = *--lineptr = '\\';
+ if (--nbackslash != 0)
+ ch = *--lineptr = '\\';
+ }
+ return;
+ }
+ if (ch == '\\')
+ goto more;
+ if (ch == EOL && !eof)
+ goto more1;
+ ch = *--lineptr = '\\'; /* pushback */
+ if (--nbackslash != 0)
+ ch = *--lineptr = '\\';
+}
+#endif
+
+PUBLIC void closein()
+{
+#ifdef FAKE_INBUFSIZE_1
+ fclose(input.fp);
+#else
+ close(input.fd);
+#endif
+ while (inclevel != 0)
+ leaveinclude();
+}
+
+PRIVATE void definefile(fname)
+char *fname;
+{
+ char *def;
+
+ def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1);
+ strcpy(def, filemacro);
+ strcat(def, "=\"");
+ strcat(def, fname);
+ strcat(def, "\"");
+ definestring(def);
+ ourfree(def);
+}
+
+PUBLIC void errorloc()
+{
+ register struct fbufstruct *infbuf;
+
+ if ((infbuf = inputbuf) == NULL)
+ return;
+ outstr(infbuf->fname);
+ outbyte(':');
+ if (eof)
+ outstr("eof");
+ else
+ {
+ outudec(input.linenumber);
+ outbyte('.');
+ if (maclevel == 0)
+ outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset);
+ else
+ {
+ outudec((unsigned) (savedlineptr() - inputbuf->fbuf)
+ - input.lineoffset);
+ outstr(" (macro level ");
+ outudec((unsigned) maclevel);
+ outbyte(')');
+ }
+ }
+ infbuf->fcb.includer = input.includer;
+ while ((infbuf = infbuf->fcb.includer) != NULL)
+ {
+ outstr(" (from ");
+ outstr(infbuf->fname);
+ outbyte(':');
+ outudec(infbuf->fcb.linenumber);
+ outbyte(')');
+ }
+ outstr(": ");
+}
+
+/* gch1() - get next char, advance ptr (only works on current line) */
+
+PUBLIC void gch1()
+{
+ if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR)
+ return;
+ specialchar();
+}
+
+/* process #include */
+
+PUBLIC void include()
+{
+ char *dirnameptr;
+ char *dirnamend;
+ unsigned dirnamelen;
+ fd_t fd;
+ char *fnameptr;
+ char *fullnameptr;
+ struct inclist *incptr;
+ char terminator;
+
+ while (blanksident())
+ {
+ if ((gsymptr = findlorg(gsname)) == NULL ||
+ gsymptr->flags != DEFINITION)
+ break;
+ entermac();
+ }
+ if ((terminator = ch) == '<')
+ terminator = '>';
+ else if (terminator != '"')
+ {
+ error("bad file name");
+ return;
+ }
+ gch1();
+ fnameptr = charptr;
+ while (TRUE)
+ {
+ if (ch == EOL) /* no escapes in file names */
+ break;
+ if (ch == terminator)
+ {
+ gch1();
+ break;
+ }
+ if (charptr >= chartop)
+ fnameptr = growobject(fnameptr, 1);
+#ifdef TS
+++ts_n_filename;
+++ts_s_filename;
+++ts_s_filename_tot;
+#endif
+ *charptr++ = ch;
+ gch1();
+ }
+ if (charptr >= chartop)
+ fnameptr = growobject(fnameptr, 1);
+#ifdef TS
+++ts_n_filename_term;
+++ts_s_filename_term;
+++ts_s_filename_tot;
+#endif
+ *charptr++ = 0;
+ dirnamend = NULL;
+ if (isabspath(fnameptr, &ch))
+ incptr = &incabsolute;
+ else
+ {
+ incptr = &incfirst;
+ if (terminator == '>')
+ incptr = incptr->incnext;
+ else
+ {
+ dirnameptr = inputbuf->fname;
+ if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL)
+ incptr->incdirname = NULL;
+ else
+ {
+ *dirnamend = 0;
+ incptr->incdirname = dirnameptr;
+ }
+ }
+ }
+ do
+ {
+ if (incptr->incdirname == NULL)
+ {
+ fullnameptr = ourmalloc(strlen(fnameptr) + 1);
+#ifdef TS
+++ts_n_pathname;
+ts_s_pathname += strlen(fnameptr) + 1;
+ts_s_pathname_tot += strlen(fnameptr) + 1;
+#endif
+ strcpy(fullnameptr, fnameptr);
+ }
+ else
+ {
+ dirnamelen = strlen(incptr->incdirname);
+ fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr)
+ + 2);
+ /* 2 extra for null and maybe DIRCHAR */
+#ifdef TS
+++ts_n_pathname;
+ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2;
+ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2;
+#endif
+ dirnameptr = fullnameptr + dirnamelen;
+ strcpy(fullnameptr, incptr->incdirname);
+ if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR)
+ strcat(fullnameptr, DIRSTRING);
+ strcat(fullnameptr, fnameptr);
+ if (dirnamend != NULL)
+ {
+ *dirnamend = DIRCHAR;
+ dirnamend = NULL;
+ }
+ }
+ fd = open(fullnameptr, 0);
+ if (fd >= 0)
+ {
+#ifdef TS
+ts_s_filename_tot -= charptr - fnameptr;
+#endif
+ charptr = fnameptr;
+ input.lineptr = lineptr;
+ inputbuf->fcb = input;
+ ++inclevel; /* XXX - will run out of memory before overflow */
+ inputinit(fullnameptr, fd);
+ inputbuf->fname_malloced = TRUE;
+ return;
+ }
+#ifdef TS
+ts_s_pathname_tot -= strlen(fullnameptr) + 1;
+#endif
+ ourfree(fullnameptr);
+ }
+ while ((incptr = incptr->incnext) != NULL);
+
+ fullnameptr = ourmalloc(strlen(fnameptr) + 40);
+ strcpy(fullnameptr, "cannot find include file ");
+ strcat(fullnameptr, fnameptr);
+ error(fullnameptr);
+ ourfree(fullnameptr);
+
+#ifdef TS
+ts_s_filename_tot -= charptr - fnameptr;
+#endif
+ charptr = fnameptr;
+}
+
+/* initialise current input file */
+
+PRIVATE void inputinit(fname, fd)
+char *fname;
+fd_t fd;
+{
+ register struct fbufstruct *newinputbuf;
+
+ /* don't allocate after saying input.includer = inputbuf (to save a reg)
+ * or an error in the alloc would cycle trying to print the include list
+ */
+ newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf);
+#ifdef TS
+++ts_n_inputbuf;
+ts_s_inputbuf += sizeof *inputbuf;
+ts_s_inputbuf_tot += sizeof *inputbuf;
+#endif
+ input.fd = fd;
+#ifdef FAKE_INBUFSIZE_1
+ input.fp = fdopen(fd, "r");
+#endif
+ input.linenumber = 0;
+ input.lineoffset = 0;
+ input.includer = inputbuf;
+ inputbuf = newinputbuf;
+ newinputbuf->fname = fname;
+ newinputbuf->fname_malloced = FALSE;
+ undefinestring(filemacro);
+ definefile(fname);
+ if (orig_cppmode && !suppress_line_numbers)
+ outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1");
+ *(input.limit = newinputbuf->fbuf) = EOL;
+
+ /* dummy line so #include processing can start with skipline() */
+ ch = *(lineptr = newinputbuf->fbuf - 1) = EOL;
+}
+
+PUBLIC void linecontol()
+{
+static char linename[32];
+ char * ptr;
+ int i=0;
+
+ blanks();
+ input.linenumber = atoi(lineptr)-1;
+ while( SYMOFCHAR(ch) == INTCONST ) gch1();
+ blanks();
+ if( ch != '"' ) return;
+ for(ptr=lineptr+1; *ptr
+ && *ptr != EOL
+ && *ptr != '"'
+ && i<sizeof(linename)-1; i++, ptr++)
+ linename[i] = *ptr;
+ linename[i] = '\0';
+
+ if (inputbuf->fname_malloced)
+{
+#ifdef TS
+ts_s_pathname_tot -= strlen(inputbuf->fname) + 1;
+#endif
+ ourfree(inputbuf->fname);
+}
+ inputbuf->fname_malloced = FALSE;
+ inputbuf->fname = linename;
+
+ ptr=lineptr;
+ undefinestring(filemacro);
+ definefile(inputbuf->fname);
+ ch = *(lineptr = ptr);
+}
+
+/* switch from include file to file which included it */
+
+PRIVATE void leaveinclude()
+{
+ --inclevel;
+ if (inputbuf->fname_malloced)
+{
+#ifdef TS
+ts_s_pathname_tot -= strlen(inputbuf->fname) + 1;
+#endif
+ ourfree(inputbuf->fname);
+}
+#ifdef TS
+ts_s_inputbuf_tot -= sizeof *inputbuf;
+#endif
+ ourfree((char *) inputbuf);
+ close(input.fd);
+#ifdef FAKE_INBUFSIZE_1
+ fclose(input.fp);
+#endif
+ inputbuf = input.includer;
+ input = inputbuf->fcb;
+ undefinestring(filemacro);
+ definefile(inputbuf->fname);
+ ch = *(lineptr = input.lineptr);
+ skipline();
+ if (orig_cppmode && !suppress_line_numbers)
+ outcpplinenumber(input.linenumber, inputbuf->fname, " 2");
+}
+
+/* open input and output files and get options */
+
+PUBLIC void openio(argc, argv)
+int argc;
+char *argv[];
+{
+ register char *arg;
+ int argn;
+ fd_t fd;
+ char *fname;
+ struct inclist *incnew;
+ struct inclist *incptr;
+ bool_t flag[128];
+
+#if 0
+ lineptr = "\n"; /* empty line in case error message */
+#endif
+ fd = 0; /* standard input */
+ memset(flag, 0, sizeof flag);
+ flag['3'] = sizeof (int) >= 4;
+ fname = "stdin";
+ (incptr = &incfirst)->incnext = &inclast;
+ initout();
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ {
+ if (fd != 0)
+ fatalerror("more than one input file");
+ fname = arg;
+ if ((fd = open(arg, 0)) < 0)
+ fatalerror("cannot open input");
+ }
+ else
+ switch (arg[1])
+ {
+#ifdef I8088
+ case '0': /* generate 16-bit code */
+ case '3': /* generate 32-bit code */
+#endif
+ case 'c': /* caller saves */
+#ifdef DEBUG
+ case 'd': /* print debugging information in asm output */
+#endif
+ case 'E': /* acting as cpp */
+ case 'f': /* pass first argument in register */
+#ifdef DYNAMIC_LONG_ORDER
+ case 'l': /* long big-endian */
+#endif
+ case 'P': /* if acting as cpp, suppress line numbers */
+#ifdef POSINDEPENDENT
+ case 'p': /* generate almost-position-independent code */
+#endif
+ case 't': /* print source code in asm output */
+ case 'w': /* watch location counter */
+ if (arg[2] == 0)
+ flag[(int)arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[(int)arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = TRUE + FALSE - flag['0'];
+ break;
+ case 'D':
+ definestring(arg + 2);
+ break;
+ case 'I':
+ (incnew = (struct inclist *) ourmalloc(sizeof *incnew))
+ ->incdirname = arg + 2;
+#ifdef TS
+++ts_n_includelist;
+ts_s_includelist += sizeof *incnew;
+#endif
+ incnew->incnext = incptr->incnext;
+ incptr = incptr->incnext = incnew;
+ break;
+ case 'U':
+ undefinestring(arg + 2);
+ break;
+ case 'o':
+ if (arg[2] != 0 || ++argn >= argc)
+ usage();
+ openout(argv[argn]);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+#ifdef I8088
+ if (flag['3'])
+ {
+ i386_32 = TRUE;
+ definestring("__AS386_32__");
+ }
+ else
+ definestring("__AS386_16__");
+#endif
+#ifdef MC6809
+ definestring("__AS09__");
+#endif
+ if (flag['c'])
+ {
+ callersaves = TRUE;
+ definestring("__CALLER_SAVES__");
+ }
+#ifdef DEBUG
+ debugon = flag['d'];
+#endif
+ orig_cppmode = cppmode = flag['E'];
+ if (flag['f'])
+ {
+ arg1inreg = TRUE;
+#ifdef I8088
+ definestring("__FIRST_ARG_IN_AX__");
+#endif
+#ifdef MC6808
+ definestring("__FIRST_ARG_IN_X__");
+#endif
+ }
+ arg1op = arg1inreg ? ROOTLISTOP : LISTOP;
+#ifdef DYNAMIC_LONG_ORDER
+ if (flag['l'])
+ {
+ long_big_endian = TRUE;
+ definestring("__LONG_BIG_ENDIAN__");
+ }
+#endif
+ suppress_line_numbers = flag['P'];
+#ifdef POSINDEPENDENT
+ if (flag['p'])
+ {
+ posindependent = TRUE;
+ definestring("__POS_INDEPENDENT__");
+ }
+#endif
+ ctext = flag['t'];
+ watchlc = flag['w'];
+ setoutbufs();
+ inputinit(fname, fd);
+}
+
+/* advance over EOL sentinel to new line */
+
+PUBLIC void skipeol()
+{
+#ifdef FAKE_INBUFSIZE_1
+ static int ich;
+#endif
+#ifdef INSERT_BACKSLASH_NEWLINES
+ static int bs_state;
+ static bool_t skip_printing_nl;
+#endif
+ int nread;
+
+ if (eof)
+ return;
+ if (lineptr < input.limit)
+ {
+ ++input.linenumber;
+ ch = *++lineptr;
+ if (ctext && !asmmode)
+ {
+ comment();
+ outudec(input.linenumber);
+ outbyte(' ');
+ outline(lineptr);
+ }
+ if (orig_cppmode && !asmmode)
+#ifdef INSERT_BACKSLASH_NEWLINES
+ if (!skip_printing_nl)
+#endif
+
+ outbyte('\n');
+#ifdef INSERT_BACKSLASH_NEWLINES
+ if (bs_state == 1 && *(lineptr - 1) == EOL)
+#endif
+ input.lineoffset = (int) (lineptr - inputbuf->fbuf);
+ return;
+ }
+ input.lineoffset -= (int) (lineptr - inputbuf->fbuf);
+#ifdef FAKE_INBUFSIZE_1
+ lineptr = inputbuf->fbuf;
+#ifdef INSERT_BACKSLASH_NEWLINES
+ switch (bs_state)
+ {
+case0:
+ case 0:
+ bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1;
+ skip_printing_nl = FALSE;
+ break;
+ case 1:
+ if (ich == '\\')
+ goto case0; /* avoid chance of splitting \EOL */
+ ich = '\\';
+ nread = 1;
+ bs_state = 2;
+ ++input.lineoffset;
+ break;
+ case 2:
+ ich = EOL;
+ nread = 1;
+ bs_state = 0;
+ skip_printing_nl = TRUE;
+ ++input.lineoffset;
+ --input.linenumber;
+ break;
+ }
+#else
+ nread = (ich = getc(input.fp)) == EOF ? 0 : 1;
+#endif
+ *lineptr = ich;
+#else
+ nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE);
+#endif
+ if (nread < 0)
+ fatalerror("input error");
+ *(input.limit = lineptr + nread) = EOL;
+ ch = *lineptr;
+ if (nread == 0)
+ {
+ if (inclevel == 0)
+ {
+ eof = TRUE;
+ checknotinif();
+ }
+ else
+ {
+ leaveinclude();
+ skipeol();
+ }
+ return;
+ }
+ if (ctext && !asmmode)
+ {
+ comment();
+ outudec(input.linenumber);
+ outbyte(' ');
+ outline(lineptr);
+ }
+}
+
+PUBLIC void specialchar()
+{
+ if (maclevel != 0)
+ {
+ if (ch == EOL) /* it might also be backslash or COEOL */
+ leavemac();
+ if (ch != EOL)
+ return;
+ }
+more:
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ backslash();
+#endif
+ if (!eof && lineptr >= input.limit)
+ {
+ skipeol();
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ backslash();
+#endif
+ }
+#ifndef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ {
+ if (*(lineptr + 1) == EOL)
+ {
+ if (lineptr + 1 >= input.limit)
+ {
+ ++lineptr;
+ skipeol();
+ ch = *--lineptr = '\\'; /* pushback */
+ }
+ if (*(lineptr + 1) == EOL)
+ {
+ if (eof)
+ eofin("backslash-newline");
+ else
+ {
+ ++lineptr;
+ skipeol();
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ {
+#ifdef COEOL
+ if (ch != COEOL
+ || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR)
+#endif
+ goto more;
+ }
+ }
+ }
+ }
+#endif
+ }
+#ifdef COEOL
+ if (ch == EOL && !eof)
+ {
+ if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit)
+ {
+ ++lineptr;
+ skipeol(); /* refill buffer */
+ ch = *--lineptr = EOL; /* pushback */
+ }
+ if (*(lineptr + 1) == COEOL)
+ *++lineptr = EOL; /* discard COEOL */
+ }
+#endif
+}
+
+PRIVATE void usage()
+{
+ fatalerror(
+#ifdef MC6809
+"usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]");
+#else
+"usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]");
+#endif
+}
diff --git a/bcc/input.h b/bcc/input.h
new file mode 100644
index 0000000..0563059
--- /dev/null
+++ b/bcc/input.h
@@ -0,0 +1,37 @@
+/* input.h - input for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define FAKE_INBUFSIZE_1_NOT
+
+#ifdef FAKE_INBUFSIZE_1
+#include <stdio.h>
+FILE *fdopen();
+#endif
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+#ifdef FAKE_INBUFSIZE_1
+ FILE *fp;
+#endif
+ unsigned linenumber; /* current line in file */
+ int lineoffset; /* offset to start of current line in buf */
+ char *lineptr; /* current spot in line */
+ char *limit; /* end of used part of input buffer */
+ struct fbufstruct *includer;
+ /* buffer of file which included current one */
+};
+
+EXTERN bool_t asmmode; /* nonzero when processing assembler code */
+ /* depends on zero init */
+EXTERN char ch; /* current char */
+EXTERN bool_t cppmode; /* nonzero if acting as cpp not as compiler */
+EXTERN bool_t eof; /* nonzero after end of main file reached */
+ /* depends on zero init */
+EXTERN struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+EXTERN char *lineptr; /* ptr to current char */
+EXTERN maclev_t maclevel; /* nest level of #defined identifiers */
+ /* depends on zero init */
+EXTERN bool_t orig_cppmode; /* same as cppmode ex. not varied while in # */
diff --git a/bcc/label.c b/bcc/label.c
new file mode 100644
index 0000000..5b07af9
--- /dev/null
+++ b/bcc/label.c
@@ -0,0 +1,429 @@
+/* label.c - label handling routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#ifdef I8088
+# define outlbranch() outop3str( "b")
+# define outsbranch() outop2str( "j")
+#endif
+#ifdef MC6809
+# define outlbranch() outop3str( "LB")
+# define outsbranch() outop2str( "B")
+#endif
+
+#define MAXVISLAB 32
+
+struct labdatstruct
+{
+ label_t labnum; /* 0 if not active */
+ offset_t lablc; /* location counter for branch or label */
+ char *labpatch; /* buffer ptr for branch, NULL for label */
+ ccode_t labcond; /* condition code for branch */
+};
+
+#ifdef I8088
+PRIVATE char lcondnames[][2] = /* names of long condition codes */
+{
+ { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', },
+ { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', },
+ { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' },
+};
+PRIVATE char scondnames[][2] = /* names of short condition codes */
+{
+ { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, },
+ { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', },
+ { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', },
+};
+#endif
+
+#ifdef MC6809
+PRIVATE char condnames[][2] = /* names of condition codes */
+{
+ { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', },
+ { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', },
+ { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', },
+};
+#endif
+
+PRIVATE label_t lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */
+ /* lint */
+PRIVATE label_t lastlab; /* bss init to 0 */
+PRIVATE offset_t lc; /* bss init to 0 */
+
+PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */
+PRIVATE smalin_t nextvislab; /* bss init to NULL */
+PRIVATE struct symstruct *namedfirst; /* bss init to NULL */
+PRIVATE struct symstruct *namedlast; /* bss init to NULL */
+
+FORWARD void addlabel P((ccode_pt cond, label_t label, char *patch));
+FORWARD struct labdatstruct *findlabel P((label_t label));
+
+/* add label to circular list */
+
+PRIVATE void addlabel(cond, label, patch)
+ccode_pt cond;
+label_t label;
+char *patch;
+{
+ register struct labdatstruct *labptr;
+
+ labptr = &vislab[(int)nextvislab];
+ labptr->labcond = cond;
+ labptr->labnum = label;
+ labptr->lablc = lc;
+ labptr->labpatch = patch;
+ if (++nextvislab == MAXVISLAB)
+ nextvislab = 0;
+}
+
+/* bump location counter */
+
+PUBLIC void bumplc()
+{
+ ++lc;
+}
+
+/* bump location counter by 2 */
+
+PUBLIC void bumplc2()
+{
+ lc += 2;
+}
+
+/* bump location counter by 3 */
+
+PUBLIC void bumplc3()
+{
+ lc += 3;
+}
+
+/* clear out labels in function */
+
+PUBLIC void clearfunclabels()
+{
+ register struct symstruct *symptr;
+ register struct symstruct *tmp;
+
+ for (symptr = namedfirst; symptr != NULL;)
+ {
+ if (symptr->indcount == 2)
+ error("undefined label");
+ symptr->indcount = 0;
+ tmp = symptr;
+ symptr = (struct symstruct *) symptr->type;
+ tmp->type = NULL;
+ }
+ namedlast = namedfirst = NULL;
+}
+
+/* clear out labels no longer in buffer */
+
+PUBLIC void clearlabels(patchbuf, patchtop)
+char *patchbuf;
+char *patchtop;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+ register char *labpatch;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop)
+ labptr->labnum = 0;
+}
+
+/* clear out labels in switch statement */
+
+PUBLIC void clearswitchlabels()
+{
+ register struct symstruct *symptr;
+
+ for (symptr = namedfirst; symptr != NULL;
+ symptr = (struct symstruct *) symptr->type)
+ if (symptr->indcount == 3)
+ {
+ equlab(symptr->offset.offlabel, lowsp);
+ symptr->indcount = 4;
+ }
+}
+
+/* return location counter */
+
+PUBLIC uoffset_t getlc()
+{
+ return (uoffset_t) lc;
+}
+
+/* define location of label and backpatch references to it */
+
+PUBLIC void deflabel(label)
+label_t label;
+{
+ char *cnameptr;
+ struct labdatstruct *labmin;
+ struct labdatstruct *labmax;
+ struct labdatstruct *labmid;
+ struct labdatstruct *labptrsave;
+ offset_t nlonger;
+
+ outnlabel(label);
+ {
+ register struct labdatstruct *labptr;
+ register char *labpatch;
+
+ labmin = &vislab[0];
+ labmax = &vislab[MAXVISLAB];
+ labptr = labmid = &vislab[(int)nextvislab];
+ if (!watchlc)
+ do
+ {
+ if (labptr == labmin)
+ labptr = &vislab[MAXVISLAB];
+ --labptr;
+ if (labptr->labnum == label)
+ {
+ if ((labpatch = labptr->labpatch) != NULL &&
+ isshortbranch(lc - labptr->lablc))
+ {
+#ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */
+ *labpatch = 'j';
+ *(labpatch + 1) =
+ *(cnameptr = scondnames[(int)labptr->labcond]);
+#endif
+#ifdef MC6809
+# ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ *labpatch = 'B';
+ *(labpatch + 4) = '\t'; /* redundant unless JMP */
+ *(labpatch + 1) =
+ *(cnameptr = condnames[labptr->labcond]);
+# else
+ if (labptr->labcond == RA)
+ strncpy(labpatch, "BRA\t\t", 5);
+ else
+ *labpatch = '\t';
+ goto over;
+# endif
+#endif
+ *(labpatch + 2) = *(cnameptr + 1);
+ *(labpatch + 3) = ' ';
+#ifdef MC6809
+# ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ over: ; /* temp regression test kludge */
+# endif
+#endif
+ nlonger = jcclonger;
+ if (labptr->labcond == RA)
+ nlonger = jmplonger;
+ lc -= nlonger;
+ labptrsave = labptr;
+ while (++labptr != labmid)
+ if (labptr == labmax)
+ labptr = &vislab[-1];
+ else
+ labptr->lablc -= nlonger;
+ labptr = labptrsave;
+ }
+ }
+ }
+ while (labptr != labmid);
+ }
+ addlabel((ccode_pt) 0, label, (char *) NULL);
+}
+
+PRIVATE struct labdatstruct *findlabel(label)
+label_t label;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if (labptr->labnum == label)
+ {
+ if (labptr->labpatch != 0)
+ break;
+ return labptr;
+ }
+ return (struct labdatstruct *) NULL;
+}
+
+/* reserve a new label, from top down to temp avoid renumbering low labels */
+
+PUBLIC label_t gethighlabel()
+{
+ return --lasthighlab;
+}
+
+/* reserve a new label */
+
+PUBLIC label_t getlabel()
+{
+ return ++lastlab;
+}
+
+/* jump to label */
+
+PUBLIC void jump(label)
+label_t label;
+{
+ lbranch(RA, label);
+}
+
+/* long branch on condition to label */
+
+PUBLIC void lbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+#endif
+ struct labdatstruct *labptr;
+ char *oldoutptr;
+
+ if ((ccode_t) cond == RN)
+ return;
+ if ((labptr = findlabel(label)) != NULL &&
+ isshortbranch(lc - labptr->lablc + 2))
+ {
+ sbranch(cond, label);
+ return;
+ }
+ oldoutptr = outbufptr;
+ if (cond == RA)
+ outjumpstring();
+ else
+ {
+ outlbranch();
+#ifdef I8088
+ outbyte(*(cnameptr = lcondnames[(int) cond]));
+ outbyte(*(cnameptr + 1));
+ if ((ccode_t) cond == LS || (ccode_t) cond == HS)
+ outbyte('s'); /* "blos" or "bhis" */
+ else
+ outbyte(' ');
+ outtab();
+ bumplc2();
+ if (i386_32)
+ bumplc();
+#endif
+#ifdef MC6809
+ outcond(cond);
+ bumplc();
+#endif
+ }
+ outlabel(label);
+ outnl();
+ if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */
+ addlabel(cond, label, oldoutptr);
+}
+
+/* look up the name gsname in label space, install it if new */
+
+PUBLIC struct symstruct *namedlabel()
+{
+ struct symstruct *symptr;
+
+ gs2name[1] = 0xFF;
+ if ((symptr = findlorg(gs2name + 1)) == NULL)
+ {
+ symptr = addglb(gs2name + 1, vtype);
+ symptr->flags = LABELLED;
+ }
+ if (symptr->indcount < 2)
+ {
+ symptr->indcount = 2;
+ symptr->offset.offlabel = gethighlabel();
+ if (namedfirst == NULL)
+ namedfirst = symptr;
+ else
+ namedlast->type = (struct typestruct *) symptr;
+ namedlast = symptr;
+ symptr->type = NULL;
+ }
+ return symptr;
+}
+
+#ifdef MC6809
+
+/* print condition code name */
+
+PUBLIC void outcond(cond)
+ccode_pt cond;
+{
+ char *cnameptr;
+
+ outbyte(*(cnameptr = condnames[(ccode_t) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+}
+
+#endif
+
+/* print label */
+
+PUBLIC void outlabel(label)
+label_t label;
+{
+ outbyte(LABELSTARTCHAR);
+ outhexdigs((uoffset_t) label);
+}
+
+/* print label and newline */
+
+PUBLIC void outnlabel(label)
+label_t label;
+{
+ outlabel(label);
+#ifdef LABELENDCHAR
+ outnbyte(LABELENDCHAR);
+#else
+ outnl();
+#endif
+}
+
+/* short branch on condition to label */
+
+PUBLIC void sbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+ if ((ccode_t) cond != RN)
+ {
+ outsbranch();
+ outbyte(*(cnameptr = scondnames[(int) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+ outlabel(label);
+ outnl();
+ }
+#endif
+#ifdef MC6809
+ outsbranch();
+ outcond(cond);
+ outlabel(label);
+ outnl();
+#endif
+}
+
+/* reverse bump location counter */
+
+PUBLIC void unbumplc()
+{
+ --lc;
+}
diff --git a/bcc/label.h b/bcc/label.h
new file mode 100644
index 0000000..89c83d7
--- /dev/null
+++ b/bcc/label.h
@@ -0,0 +1,24 @@
+/* label.h - assembler-specific label characters for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* defaults */
+
+#define CCNAMEPREFIX '_'
+# define LABELENDCHAR ':' /* last char of ALL labels */
+#define LABELSTARTCHAR '.' /* first char of names of generated labels */
+#define LOCALSTARTCHAR '.' /* first char of local names */
+#define PUBLICENDCHAR ':'
+
+/* adjustments for other assemblers */
+
+#ifdef AS09
+# undef LABELENDCHAR
+#endif
+
+#ifdef XENIX_AS
+# undef LABELSTARTCHAR
+# define LABELSTARTCHAR 'L'
+# undef LOCALSTARTCHAR
+# define LOCALSTARTCHAR 'L'
+#endif
diff --git a/bcc/loadexp.c b/bcc/loadexp.c
new file mode 100644
index 0000000..632c2ad
--- /dev/null
+++ b/bcc/loadexp.c
@@ -0,0 +1,180 @@
+/* loadexp.c - load expressions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+PUBLIC value_t constexpression()
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct symstruct *symptr;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = assignment_exp();
+ etptr = etmark;
+ exprptr = exprmark;
+ if (exp->tag == LEAF && (symptr = exp->left.symptr)->storage == CONSTANT
+ && symptr->type->scalar & ISCALAR)
+ return symptr->offset.offv;
+ error("constant expression required");
+ return 1;
+}
+
+PUBLIC void initexpression(type)
+struct typestruct *type;
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct nodestruct *lhs;
+ struct symstruct *symptr;
+ uoffset_t value;
+
+ if (gvarsymptr->storage != GLOBAL)
+ reslocals();
+ exprmark = exprptr;
+ etmark = etptr;
+ exp = assignment_exp();
+ if (gvarsymptr->storage != GLOBAL)
+ {
+ lhs = leafnode(exprsym(gvarsymptr));
+ if (!(lhs->nodetype->constructor & (ARRAY | FUNCTION | VOID)))
+ lhs->flags = LVALUE;
+ makeleaf(node(ASSIGNOP, lhs, exp));
+ }
+ else if (exp->tag != LEAF ||
+ ((symptr = exp->left.symptr)->storage != CONSTANT &&
+ (symptr->storage != GLOBAL || symptr->indcount != 0 ||
+ type->scalar & DLONG)) ||
+ (type->constructor | (symptr->type->constructor & ~FUNCTION)) &
+ ~(ARRAY | POINTER))
+ error("initializer too complicated");
+ else
+ {
+ if ((symptr->type->scalar | type->scalar) & RSCALAR)
+ {
+ /* Can only afford castnode if result known constant. */
+ exp = castnode(type, exp);
+ symptr = exp->left.symptr;
+ }
+ if (type->scalar & RSCALAR)
+ {
+ if (type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *symptr->offset.offd;
+ deflong(((uoffset_t *) &val)[0]);
+ }
+ else
+ {
+ deflong(((uoffset_t *) symptr->offset.offd)[0]);
+ deflong(((uoffset_t *) symptr->offset.offd)[1]);
+ }
+ etptr = etmark; /* XXX - stuff from end of function */
+ exprptr = exprmark;
+ return;
+ }
+ if (type->typesize == 1)
+ defbyte();
+ else if (type->typesize == 2)
+ defword();
+#ifdef I8088
+ else if (!(type->scalar & DLONG))
+ defdword();
+#endif
+ switch (symptr->storage)
+ {
+ case CONSTANT:
+ value = (uoffset_t) symptr->offset.offv;
+ if (type->scalar & DLONG)
+ {
+ deflong(value);
+ break;
+ }
+ /* XXX - put sizes in type struct to avoid tests */
+ if (type->scalar & CHAR)
+ value &= CHMASKTO;
+ else if (type->scalar & SHORT)
+ value &= shortmaskto;
+ else if (type->scalar & INT)
+ value &= intmaskto;
+ /* XXX - no longmaskto */
+ outnhex(value);
+ break;
+ case GLOBAL:
+ if (symptr->flags & LABELLED)
+ {
+ outlabel(symptr->name.label);
+ outplus();
+ outnhex((uoffset_t) symptr->offset.offi);
+ break;
+ }
+ if (*symptr->name.namep == 0) /* constant address */
+ {
+ outnhex((uoffset_t) symptr->offset.offi);
+ break;
+ }
+ outccname(symptr->name.namep);
+ if (symptr->offset.offi != 0)
+ {
+ if (symptr->offset.offi > 0)
+ outplus();
+ outshex(symptr->offset.offi);
+ }
+ outnl();
+ break;
+ }
+ }
+ etptr = etmark;
+ exprptr = exprmark;
+}
+
+PUBLIC struct typestruct *loadexpression(targreg, targtype)
+store_pt targreg;
+struct typestruct *targtype;
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = expression();
+ if (targtype != NULL)
+ exp = castnode(targtype, exp);
+ makeleaf(exp);
+ if (targtype == NULL) /* this is for a switch */
+ {
+ targtype = exp->left.symptr->type;
+ if (!(targtype->scalar & (CHAR | INT))
+ && (targtype->scalar & (LONG | DLONG)) != LONG)
+ {
+ if (targtype->scalar & SHORT)
+ targtype = promote(targtype);
+ else
+ {
+ error("non-integral selector in switch");
+ targtype = itype;
+ }
+ makeleaf(exp = castnode(targtype, exp));
+ }
+ }
+ load(exp->left.symptr, targreg); /* resets stack if value was there */
+ etptr = etmark;
+ exprptr = exprmark;
+ return exp->left.symptr->type;
+}
diff --git a/bcc/longop.c b/bcc/longop.c
new file mode 100644
index 0000000..f678e11
--- /dev/null
+++ b/bcc/longop.c
@@ -0,0 +1,169 @@
+/* longop.c - software operations on longs for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ longop(operation code, source leaf, target leaf)
+ handles all binary operations on longs
+ source and target must already have been converted to long,
+ (except source is int for shifts) and not more than singly indirect
+ hence they must be direct (in an index reg paired with DREG),
+ or singly indirect (local, global, or from an index reg)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void longop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt reglist;
+ store_t regmark;
+ bool_t shiftflag;
+ scalar_t scalar;
+ offset_t spmark;
+
+ pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG));
+ reguse &= ~reglist;
+ spmark = sp;
+ shiftflag = FALSE;
+ scalar = target->type->scalar;
+ if ((op_t) op == SLOP || (op_t) op == SROP)
+ shiftflag = TRUE;
+ else
+ scalar |= source->type->scalar;
+ if ((source->indcount == 0 && !shiftflag) ||
+ source->storage & (DREG | OPREG | OPWORKREG))
+ {
+ pres2(source, target);
+ push(source);
+ }
+ if (!shiftflag)
+ address(source);
+ load(target, OPREG);
+ if (source->storage == CONSTANT && shiftflag)
+ {
+ if (scalar & UNSIGNED)
+ target->type = ultype;
+ if ((op_t) op == SLOP)
+ source->offset.offv = lslconst(source->offset.offv,
+ target->storage);
+ else
+ source->offset.offv = lsrconst(source->offset.offv,
+ target->storage, scalar & UNSIGNED);
+ if (source->offset.offv == 0)
+ goto shiftdone;
+ }
+ load(source, OPWORKREG);
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("ladd");
+ break;
+ case ANDOP:
+ call("land");
+ break;
+ case DIVOP:
+ call("ldiv");
+ break;
+ case EOROP:
+ call("leor");
+ break;
+ case EQOP:
+ call("lcmp");
+ break;
+ case MODOP:
+ call("lmod");
+ break;
+ case MULOP:
+ call("lmul");
+ break;
+ case OROP:
+ call("lor");
+ break;
+ case SLOP:
+ call("lsl");
+ break;
+ case SROP:
+ call("lsr");
+ break;
+ case SUBOP:
+ call("lsub");
+ break;
+ }
+ if (scalar & UNSIGNED)
+ {
+ outbyte('u');
+ target->type = ultype;
+ }
+ outlongendian();
+
+shiftdone:
+ if ((reguse = regmark) & OPREG && op != EQOP)
+ load(target, getindexreg());
+ if (reglist)
+ {
+#ifdef I8088
+ if (op == EQOP)
+ changesp(spmark, FALSE);
+ else
+#endif
+ modstk(spmark);
+ poplist(reglist);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ long1op(operation code, target leaf)
+ handles all unary operations on longs except inc/dec
+ target must be not more than singly indirect
+ hence it must be direct (in an index reg paired with DREG),
+ or singly indirect (local, global, or from an index reg)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void long1op(op, target)
+op_pt op;
+struct symstruct *target;
+{
+ pushlist(reguse & OPREG);
+ load(target, OPREG);
+ if (op == NOTOP)
+ call("lcom");
+ else if (op == NEGOP)
+ call("lneg");
+ else
+ call("ltst");
+ outlongendian();
+ if (reguse & OPREG)
+ {
+ if (op != EQOP)
+ load(target, getindexreg());
+ poplist(reguse & OPREG);
+ }
+}
+
+PUBLIC void outlongendian()
+{
+#ifdef MC6809
+ outbyte('_');
+#endif
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ outnbyte('b');
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ outnbyte('l');
+#endif
+}
diff --git a/bcc/misc/sformat b/bcc/misc/sformat
new file mode 100644
index 0000000..3dcb0c4
--- /dev/null
+++ b/bcc/misc/sformat
@@ -0,0 +1,56 @@
+int x;
+.comm _x,2
+
+int x = 1;
+.global _x
+.data
+_x:
+1
+
+static int x;
+.bss
+_x:
+.=.+2
+
+static int x = 1;
+.bss | implicit
+.data
+_x:
+1
+
+char x[10];
+.comm _x,12
+
+char x[10] = "1";
+.globl _x
+.data
+_x:
+.byte 61,0
+.=.+10
+
+static char x[10];
+.bss;
+_cc:
+.=.+12
+
+static char x[10] = "1";
+.data
+_x:
+.byte 61,0
+.=.+10
+
+test()
+.globl _test
+.text
+_test:
+
+{
+static int x;
+.bss
+L3:
+.=.+2
+
+static int x = 1;
+.bss
+.data
+L5:1
diff --git a/bcc/misc/test/8queens.pas b/bcc/misc/test/8queens.pas
new file mode 100644
index 0000000..f4f1b47
--- /dev/null
+++ b/bcc/misc/test/8queens.pas
@@ -0,0 +1,33 @@
+program eightqueens;
+
+var i: integer;
+ a: array[ 1..8 ] of boolean;
+ b: array[ 2..16] of boolean;
+ c: array[-7..7 ] of boolean;
+ x: array[ 1..8 ] of integer;
+
+procedure print;
+var k: integer;
+begin
+ for k:= 1 to 8 do write(x[k]:4);
+ writeln;
+end;
+
+procedure try(i: integer);
+var j: integer;
+begin
+ for j:= 1 to 8 do if a[j] and b[i+j] and c[i-j] then
+ begin
+ x[i]:= j;
+ a[j]:= false; b[i+j]:= false; c[i-j]:= false;
+ if i < 8 then try(i+1) else print;
+ a[j]:= true; b[i+j]:= true; c[i-j]:= true;
+ end;
+end;
+
+begin
+ for i:= 1 to 8 do a[i]:= true;
+ for i:= 2 to 16 do b[i]:= true;
+ for i:= -7 to 7 do c[i]:= true;
+ try(1);
+end.
diff --git a/bcc/misc/test/8queens.t b/bcc/misc/test/8queens.t
new file mode 100644
index 0000000..8d20a4d
--- /dev/null
+++ b/bcc/misc/test/8queens.t
@@ -0,0 +1,74 @@
+/* 8queens - straightforward translation of pascal version */
+
+#define TRUE 1
+#define FALSE 0
+
+int i;
+char a[8],b[15],c[15],x[8];
+
+main()
+{
+ for (i=0;i<8;i++)
+ a[i]=TRUE;
+ for (i=0;i<15;i++)
+ b[i]=TRUE;
+ for (i=0;i<15;i++)
+ c[i]=TRUE;
+ try(0);
+}
+
+print()
+{
+ int k;
+
+ for (k=0;k<8;k++)
+ write(x[k]);
+ writeln();
+}
+
+write(i)
+int i;
+{
+ {
+#asm
+ LDA #$20
+ JSR $E820
+ LDD .i,S
+ JSR $C682
+#endasm
+ }
+}
+
+writeln()
+{
+ {
+#asm
+ LDA #13
+ JSR $E820
+ LDA #10
+ JSR $E820
+#endasm
+ }
+}
+
+try(i)
+int i;
+{
+ int j;
+
+ for(j=0;j<8;j++)
+ if (a[j] && b[i+j] && c[7+i-j])
+ {
+ x[i]=j;
+ a[j]=FALSE;
+ b[i+j]=FALSE;
+ c[7+i-j]=FALSE;
+ if (i<7)
+ try(i+1);
+ else
+ print();
+ a[j]=TRUE;
+ b[i+j]=TRUE;
+ c[7+i-j]=TRUE;
+ }
+}
diff --git a/bcc/misc/test/atol.t b/bcc/misc/test/atol.t
new file mode 100644
index 0000000..79c78b7
--- /dev/null
+++ b/bcc/misc/test/atol.t
@@ -0,0 +1,29 @@
+/* atol.c - long atol( char *s ) */
+
+/* atol converts s to a long */
+/* leading spaces and tabs are ignored, an optional sign is recognised, */
+/* and the digits (0 to 9) following determine the long */
+
+long atol( s )
+register char *s;
+{
+ char signflag;
+ long number;
+
+ while ( *s == ' ' || *s == '\t')
+ s++;
+ signflag = 0;
+ if ( *s == '+' )
+ s++;
+ else if ( *s == '-' )
+ {
+ signflag = 1;
+ s++;
+ }
+ number = 0;
+ while ( *s >= '0' && *s <= '9' )
+ number = 10 * number + *s++ - '0';
+ if ( signflag )
+ return -number;
+ return number;
+}
diff --git a/bcc/misc/test/bigsievec.t b/bcc/misc/test/bigsievec.t
new file mode 100644
index 0000000..f3f76b2
--- /dev/null
+++ b/bcc/misc/test/bigsievec.t
@@ -0,0 +1,29 @@
+#define TRUE 1
+#define FALSE 0
+#define NITER 10
+#define SIZE 100000
+
+char flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<NITER;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/bt.t b/bcc/misc/test/bt.t
new file mode 100644
index 0000000..b88836c
--- /dev/null
+++ b/bcc/misc/test/bt.t
@@ -0,0 +1,373 @@
+/* bt.t - bug tests */
+
+test1()
+{
+ char *p, *q;
+
+ q += *p++;
+}
+
+test2()
+{
+ int i,j,k,a[2],b[2],c[2];
+
+ i = a[i] + b[j] + c[k];
+}
+
+test3()
+{
+ int *p, *q;
+ int i;
+
+ i = p - q;
+}
+
+test4()
+{
+ int a[2];
+ int *p;
+
+ p = a;
+ test4(a);
+}
+
+test5()
+{
+ char c;
+
+ test4(c);
+}
+
+test6(a,b)
+int b,a;
+{
+ int i;
+
+ i = b;
+ i = a;
+}
+
+test7()
+{
+ int a[2];
+ int *p;
+
+ p = a + 1;
+}
+
+int *test8();
+
+int *test8()
+{
+ int i;
+
+ if ( test8() == i )
+ ;
+ i = *test8();
+}
+
+test9()
+{
+ int i,j,k,n;
+
+ if ((i < 0 || j > 100) && (k < 0 || n > 50))
+ i = 1;
+}
+
+struct complex
+{
+ int re;
+ int im;
+}
+ znum, *zptr, zarr[10], *zptrarr[10];
+
+test10()
+{
+ int i;
+
+ znum.re = i;
+ znum.im = 1;
+ zptr -> re = 1;
+ zptr -> im = i;
+ zarr[3].im = i;
+ zptrarr[4] -> im = 1;
+}
+
+test11()
+{
+ char symtab[100];
+
+ char *p;
+
+ if (p > symtab)
+ ;
+}
+
+test12()
+{
+char symtab[100];
+
+ char *p;
+
+ p = symtab - 21;
+}
+
+test13()
+{
+ char a[10];
+ int i;
+
+ i = a - 1;
+}
+
+test14()
+{
+ int i, **pi;
+
+ **pi = i;
+}
+
+test15()
+{
+ int i, j;
+
+ if ( (i = j ) == 2 )
+ test();
+}
+
+test16()
+{
+ struct cx3
+ {
+ int re3;
+ char im3;
+ }
+ z[10], *pz, *pz1;
+ int i;
+
+ i = z[i].re3;
+ i = pz1 - pz;
+}
+
+test17()
+{
+ int i;
+ char c;
+
+ c &= ~i;
+}
+
+test18()
+{
+ typedef int (*PFI)();
+ PFI h();
+
+ (*h())( 0 );
+}
+
+test19()
+{
+ register int *p, *q;
+ int ***z,i,a[10];
+
+ test(***z + a[i]);
+}
+
+char a[2][3][5];
+
+char *p = a;
+char *q = a[1];
+char *r = a[1][2];
+
+char test20();
+char (*test21)();
+
+test22()
+{
+ char i,k;
+ char *p;
+
+ p = a;
+ p = a[1];
+ p = a[1][2];
+ p = a[k];
+ p = a[k][k];
+ i = sizeof a;
+ i = sizeof a[k];
+ i = sizeof a[k][k];
+ i = sizeof test20;
+ i = sizeof test21;
+ i = sizeof test20();
+ i = sizeof (*test21)();
+}
+
+test23()
+{
+ long *pl;
+ int i;
+ char *s;
+
+ *pl += i;
+ *s += *pl;
+}
+
+test24()
+{
+ float f;
+ double *dp1(), *dp2();
+
+ f = *dp1()++; /* illegal */
+ f = *++dp1(); /* illegal */
+ f = *dp1() + *dp2(); /* bad code (pushes ptr to doubly indirect) */
+}
+
+test25()
+{
+ test25( "2"[1] ); /* added 1 to label number, not label address */
+}
+
+struct stat
+{
+ int st_dev;
+};
+
+test26( buf )
+struct stat buf; /* wrong declare, s.b. struct stat *buf */
+{
+ buf->st_dev = 1; /* error caused null pointer to be dereferenced */
+}
+
+union
+{
+ long l;
+}
+ test27;
+
+test28()
+{
+ test27.l = test27.l + 1; /* produced poor code */
+}
+
+int test29 = (char) 1; /* cast was clobbering the global symptr */
+
+struct { int i; } test30;
+
+test31()
+{
+ return test30; /* a structure cannot be returned (yet) */
+}
+
+int *test32, test33() {} /* this is illegal */
+
+test35()
+{
+ char a[1];
+ char b[1];
+ int i;
+
+ i = i == 1 ? a : b; /* arrays were not converted to ptrs */
+}
+
+test36()
+{
+ struct fp
+ {
+ struct filp *fp_filp[1];
+ };
+ struct filp
+ {
+ int filp_int;
+ long filp_long;
+ };
+ int i;
+ register char *junk;
+ register struct fp *cp;
+
+ cp->fp_filp[i]->filp_int++; /* used to push lvalue */
+ cp->fp_filp[i]->filp_long++; /* used to push lvalue */
+ cp->fp_filp[i]->filp_int += 1; /* was OK */
+ cp->fp_filp[i]->filp_long += 1; /* used to load long into DREG:DREG */
+}
+
+test37()
+{
+ unsigned u;
+
+ u = -u; /* used to give botched nodetype */
+}
+
+test38()
+{
+ char c;
+ int i;
+
+ i = -c; /* did i = (char) -c for a time */
+}
+
+test39()
+{
+ int i;
+
+ i = (char) 1000; /* the constant wasn't being truncated */
+}
+
+#define test40(x) (x)
+
+test41()
+{
+ int i;
+ int j;
+ int k;
+
+ i = test40( j + /* was confused by EOL in macro argument */
+ k );
+}
+
+test42()
+{
+ register char *junk1;
+ register char *junk2;
+ long *longptr;
+ long longfn();
+
+ *longptr = longfn(); /* used to run out of index regs */
+}
+
+test43()
+{
+ register char *jnk1, *junk2;
+ unsigned char *bp;
+ struct FILE_BUF
+ {
+ char *bufp;
+ } *op;
+
+ *op->bufp++ = *bp; /* used to push lvalue */
+}
+
+test44()
+{
+ register char *x, *y;
+ int i;
+ char a[2];
+ char **p;
+
+ a[**p] = **p; /* used to push lvalue */
+}
+
+struct test45
+{
+ int i;
+ int j;
+} test45[10];
+
+test46()
+{
+ register char *p, *q;
+ int i;
+ int j;
+
+ test45[i] = test45[j]; /* used to push lvalue */
+}
+
+int (*test100( x )() {} /* this is legal, keep last avoid swallowing */
diff --git a/bcc/misc/test/cast.t b/bcc/misc/test/cast.t
new file mode 100644
index 0000000..554cb93
--- /dev/null
+++ b/bcc/misc/test/cast.t
@@ -0,0 +1,144 @@
+/* cast.t */
+
+char c;
+unsigned char uc;
+short s;
+unsigned short us;
+int i;
+unsigned int ui;
+long l;
+unsigned long ul;
+float f;
+double d;
+int *p;
+
+cast()
+{
+ c = (char) c;
+ uc = (unsigned char) c;
+ s = (short) c;
+ us = (unsigned short) c;
+ i = (int) c;
+ ui = (unsigned int) c;
+ l = (long) c;
+ ul = (unsigned long) c;
+ f = (float) c;
+ d = (double) c;
+ p = (int *) c;
+
+ c = (char) uc;
+ uc = (unsigned char) uc;
+ s = (short) uc;
+ us = (unsigned short) uc;
+ i = (int) uc;
+ ui = (unsigned int) uc;
+ l = (long) uc;
+ ul = (unsigned long) uc;
+ f = (float) uc;
+ d = (double) uc;
+ p = (int *) uc;
+
+ c = (char) s;
+ uc = (unsigned char) s;
+ s = (short) s;
+ us = (unsigned short) s;
+ i = (int) s;
+ ui = (unsigned int) s;
+ l = (long) s;
+ ul = (unsigned long) s;
+ f = (float) s;
+ d = (double) s;
+ p = (int *) s;
+
+ c = (char) us;
+ uc = (unsigned char) us;
+ s = (short) us;
+ us = (unsigned short) us;
+ i = (int) us;
+ ui = (unsigned int) us;
+ l = (long) us;
+ ul = (unsigned long) us;
+ f = (float) us;
+ d = (double) us;
+ p = (int *) us;
+
+ c = (char) i;
+ uc = (unsigned char) i;
+ s = (short) i;
+ us = (unsigned short) i;
+ i = (int) i;
+ ui = (unsigned int) i;
+ l = (long) i;
+ ul = (unsigned long) i;
+ f = (float) i;
+ d = (double) i;
+ p = (int *) i;
+
+ c = (char) ui;
+ uc = (unsigned char) ui;
+ s = (short) ui;
+ us = (unsigned short) ui;
+ i = (int) ui;
+ ui = (unsigned int) ui;
+ l = (long) ui;
+ ul = (unsigned long) ui;
+ f = (float) ui;
+ d = (double) ui;
+ p = (int *) ui;
+
+ c = (char) l;
+ uc = (unsigned char) l;
+ s = (short) l;
+ us = (unsigned short) l;
+ i = (int) l;
+ ui = (unsigned int) l;
+ l = (long) l;
+ ul = (unsigned long) l;
+ f = (float) l;
+ d = (double) l;
+ p = (int *) l;
+
+ c = (char) ul;
+ uc = (unsigned char) ul;
+ s = (short) ul;
+ us = (unsigned short) ul;
+ i = (int) ul;
+ ui = (unsigned int) ul;
+ l = (long) ul;
+ ul = (unsigned long) ul;
+ f = (float) ul;
+ d = (double) ul;
+ p = (int *) ul;
+
+ c = (char) f;
+ uc = (unsigned char) f;
+ s = (short) f;
+ us = (unsigned short) f;
+ i = (int) f;
+ ui = (unsigned int) f;
+ l = (long) f;
+ ul = (unsigned long) f;
+ f = (float) f;
+ d = (double) f;
+
+ c = (char) d;
+ uc = (unsigned char) d;
+ s = (short) d;
+ us = (unsigned short) d;
+ i = (int) d;
+ ui = (unsigned int) d;
+ l = (long) d;
+ ul = (unsigned long) d;
+ f = (float) d;
+ d = (double) d;
+
+ c = (char) p;
+ uc = (unsigned char) p;
+ s = (short) p;
+ us = (unsigned short) p;
+ i = (int) p;
+ ui = (unsigned int) p;
+ l = (long) p;
+ ul = (unsigned long) p;
+ p = (int *) p;
+}
diff --git a/bcc/misc/test/cast1.t b/bcc/misc/test/cast1.t
new file mode 100644
index 0000000..a4c15d5
--- /dev/null
+++ b/bcc/misc/test/cast1.t
@@ -0,0 +1,144 @@
+/* cast1.t */
+
+char c;
+unsigned char uc;
+short s;
+unsigned short us;
+int i;
+unsigned int ui;
+long l;
+unsigned long ul;
+float f;
+double d;
+int *p;
+
+cast()
+{
+ c = c;
+ uc = c;
+ s = c;
+ us = c;
+ i = c;
+ ui = c;
+ l = c;
+ ul = c;
+ f = c;
+ d = c;
+ p = c;
+
+ c = uc;
+ uc = uc;
+ s = uc;
+ us = uc;
+ i = uc;
+ ui = uc;
+ l = uc;
+ ul = uc;
+ f = uc;
+ d = uc;
+ p = uc;
+
+ c = s;
+ uc = s;
+ s = s;
+ us = s;
+ i = s;
+ ui = s;
+ l = s;
+ ul = s;
+ f = s;
+ d = s;
+ p = s;
+
+ c = us;
+ uc = us;
+ s = us;
+ us = us;
+ i = us;
+ ui = us;
+ l = us;
+ ul = us;
+ f = us;
+ d = us;
+ p = us;
+
+ c = i;
+ uc = i;
+ s = i;
+ us = i;
+ i = i;
+ ui = i;
+ l = i;
+ ul = i;
+ f = i;
+ d = i;
+ p = i;
+
+ c = ui;
+ uc = ui;
+ s = ui;
+ us = ui;
+ i = ui;
+ ui = ui;
+ l = ui;
+ ul = ui;
+ f = ui;
+ d = ui;
+ p = ui;
+
+ c = l;
+ uc = l;
+ s = l;
+ us = l;
+ i = l;
+ ui = l;
+ l = l;
+ ul = l;
+ f = l;
+ d = l;
+ p = l;
+
+ c = ul;
+ uc = ul;
+ s = ul;
+ us = ul;
+ i = ul;
+ ui = ul;
+ l = ul;
+ ul = ul;
+ f = ul;
+ d = ul;
+ p = ul;
+
+ c = f;
+ uc = f;
+ s = f;
+ us = f;
+ i = f;
+ ui = f;
+ l = f;
+ ul = f;
+ f = f;
+ d = f;
+
+ c = d;
+ uc = d;
+ s = d;
+ us = d;
+ i = d;
+ ui = d;
+ l = d;
+ ul = d;
+ f = d;
+ d = d;
+
+ c = p;
+ uc = p;
+ s = p;
+ us = p;
+ i = p;
+ ui = p;
+ l = p;
+ ul = p;
+ p = p;
+}
diff --git a/bcc/misc/test/castest.t b/bcc/misc/test/castest.t
new file mode 100644
index 0000000..ae27f7b
--- /dev/null
+++ b/bcc/misc/test/castest.t
@@ -0,0 +1,74 @@
+/* castest.c */
+
+/*
+#define signedchar
+#define bigints
+*/
+#define unsigchar
+#define unsigshort
+#define unsiglong
+
+#define TEST(u,c) if ( (u) != (c) )\
+ { printf( "u != c\n" ); ++bad; } ++possible
+
+main()
+{
+ int bad;
+ int possible;
+ char c;
+#ifdef signedchar
+ signed char sc;
+#endif
+#ifdef unsigchar
+ unsigned char uc;
+#endif
+ short s;
+#ifdef unsigshort
+ unsigned short us;
+#endif
+ int i;
+ unsigned u;
+ long l;
+#ifdef unsiglong
+ unsigned long ul;
+#endif
+
+ bad = possible = 0;
+ u = 0x1ff;
+ c = (char) u;
+ if ( c < 0 )
+ printf( "characters are signed\n" );
+ TEST((char)u,c);
+ i = (int)(char) u;
+ TEST(i,(int)c);
+ TEST((int)(char)u,i);
+
+#ifdef signedchar
+ sc = (signed char) u;
+ if ( sc >= 0 )
+ printf( "??? signed char not signed\n" );
+ TEST((signed char)u,sc);
+ TEST((int)(signed char)u,(int)sc);
+ i = (int) sc;
+ TEST((int)(signed char)u,i);
+#endif
+
+#ifdef bigints
+ u = 0x1ffff;
+ s = (short) u;
+ TEST((short)u,s);
+ TEST((int)(short)u,(int)s);
+ i = (int) s;
+ TEST((int)(short)u,i);
+
+#ifdef unsigshort
+ us = (unsigned short) u;
+ TEST((unsigned short)u,us);
+ TEST((int)(unsigned short)u,(int)us);
+ i = (int) us;
+ TEST((int)(unsigned short)u,i);
+#endif
+#endif
+
+ printf( "%d bad out of a possible %d\n", bad, possible );
+}
diff --git a/bcc/misc/test/ctype.t b/bcc/misc/test/ctype.t
new file mode 100644
index 0000000..93b3e4f
--- /dev/null
+++ b/bcc/misc/test/ctype.t
@@ -0,0 +1,38 @@
+/* ctype.h */
+
+#define _C 1 /* control */
+#define _D 2 /* digit */
+#define _L 4 /* lower */
+#define _P 8 /* punctuation */
+#define _S 16 /* space */
+#define _U 32 /* upper */
+#define _UN 64 /* underline */
+#define _X '\200' /* hex digit, not digit */
+
+extern char _ctype_[];
+
+#define _ct1_ (_ctype_+1)
+
+#define isalnum(c) (_ct1_[c]&(_U|_L|_D))
+#define isalpha(c) (_ct1_[c]&(_U|_L))
+#define isascii(i) ((unsigned)(i)<=0x7f)
+#define isalpha(c) (_ct1_[c]&(_U|_L))
+#define iscntrl(c) (_ct1_[c]&_C)
+#define iscsym(c) (_ct1_[c]&(_U|_L|_D|_UN))
+#define iscsymf(c) (_ct1_[c]&(_U|_L|_UN))
+#define isdigit(c) (_ct1_[c]&_D)
+#define isgraph(c) (_ct1_[c]&(_U|_L|_D|_P))
+#define islower(c) (_ct1_[c]&_L)
+/* isodigit(i) is a function */
+/* isprint(i) is a function */
+#define ispunct(c) (_ct1_[c]&_P)
+#define isspace(c) (_ct1_[c]&_S)
+#define isupper(c) (_ct1_[c]&_U)
+#define isxdigit(c) (_ct1_[c]&(_D|_X))
+
+#define toascii(i) ((i)&0x7f)
+/* toint(i) is a function */
+/* tolower(i) is a function */
+#define _tolower(c) ((c)+('a'-'A'))
+/* toupper(i) is a function */
+#define _toupper(c) ((c)+('A'-'a'))
diff --git a/bcc/misc/test/error.t b/bcc/misc/test/error.t
new file mode 100644
index 0000000..24e302a
--- /dev/null
+++ b/bcc/misc/test/error.t
@@ -0,0 +1,78 @@
+static char *errorstring[] =
+{
+ "# in a macro: not preprocessed",
+ "already declared",
+ "array of functions is illegal",
+ "bad address",
+ "bad case label",
+ "bad character constant",
+ "bad character",
+ "bad control",
+ "bad default label",
+ "bad expression",
+ "bad file name",
+ "bad indirection count",
+ "bad initializer address",
+ "bad register store",
+ "call of non-function",
+ "can't continue in switch",
+ "can't index",
+ "can't load char to index reg",
+ "can't open",
+ "can't open input",
+ "can't open output",
+ "case can't be reached with char switch",
+ "constant expression expected",
+ "else without if",
+ "end of file in #asm",
+ "end of file in #define",
+ "end of file in comment",
+ "end of file in failed #if",
+ "end of file in macro parameter expansion",
+ "end of file in string constant",
+ "end of line in string constant",
+ "endif without if",
+ "function returning array is illegal",
+ "function returning function is illegal",
+ "function returning structure is illegal",
+ "if stack overflow",
+ "illegal indirection",
+ "illegal macro name",
+ "illegal non-external function",
+ "illegal symbol name",
+ "illegal type conversion",
+ "illegal type name",
+ "initializer too complicated",
+ "input error",
+ "load of long constants not implemented",
+ "loading direct long with offset not implemented",
+ "local symbol table overflow",
+ "macro stack overflow",
+ "missing '('",
+ "missing while at end of do-while",
+ "need '",
+ "need int or char",
+ "need lvalue",
+ "need scalar or ptr type",
+ "need structure",
+ "no active fors, switches or whiles",
+ "not in a compound statement",
+ "null dimension",
+ "out of index registers",
+ "redefined macro",
+ "repeated argument",
+ "repeated default label",
+ "repeated parameter",
+ "table full",
+ "too few macro parameters",
+ "too many active whiles",
+ "too many cases",
+ "too many macro parameters",
+ "too many open compound statements",
+ "too many parameters",
+ "undeclared variable",
+ "undefined structure element",
+ "undefined structure",
+ "unsigned ints only",
+ "variable not in argument list"
+};
diff --git a/bcc/misc/test/extern.t b/bcc/misc/test/extern.t
new file mode 100644
index 0000000..dac5f5c
--- /dev/null
+++ b/bcc/misc/test/extern.t
@@ -0,0 +1,236 @@
+/* extern.c - external declarations (K & R p218-9) */
+
+#include "def.h"
+#include "globvar.h"
+#include "symbol.h"
+
+struct typestruct *declarator();
+struct typestruct *extypespec();
+int paramlist();
+struct typestruct *typespec();
+
+/*=============================================================================
+ -- notation is 1st attempt at EBNF (see Modula-2 book)
+ program = { type-definition | function-or-data-definition }.
+ type-definition = "typedef" type-definition-list.
+=============================================================================*/
+
+program()
+{
+ nextsym();
+ while ( sym != EOFSYM )
+ {
+ if ( sym = TYPEDEFDECL )
+ deftypes();
+ else
+ functordata();
+ }
+}
+
+/*=============================================================================
+ type-definition-list. -- not implemented
+=============================================================================*/
+
+deftypes()
+{}
+
+/*=============================================================================
+ function-or-data-definition = external-type-specification
+ ( function-definition | init-declarators ).
+ function-definition = "(" parameter-list ")" arg-list compound-statement.
+ -- this is different from K & R who omit typedefs and static functions
+=============================================================================*/
+
+functordata()
+{
+ struct typestruct *type;
+ int nargs;
+
+ type = extypespec();
+ if ( sym == LPAREN )
+ {
+ nextsym();
+ nargs = paramlist();
+ need( RPAREN );
+ arglist( nargs );
+ need( LBRACE );
+ compound( 1 + locptr-pstartloc );/* 1 = function flag, rest = nargs */
+ oldlevel();
+ }
+ else
+ initdecl( type );
+}
+
+/*=============================================================================
+ external-type-specification = extern-sc type-specifier declarator.
+ extern-sc = [ extern | static ].
+=============================================================================*/
+
+struct typestruct *extypespec()
+{
+ int sc;
+
+ switch( sym )
+ {
+ case EXTERNDECL:
+ case STATICDECL:
+ sc = sym; nextsym(); break;
+ default:
+ sc = EXTERNDECL; break;
+ }
+ return declarator( typespec() );
+}
+
+/*=============================================================================
+ parameter-list = [identifier { "," identifier }].
+=============================================================================*/
+
+int paramlist()
+{
+ int nargs;
+
+ locptr = pstartloc;
+ newlevel();
+ nargs = 0;
+ while ( sym == IDENT )
+ {
+ addloc( gsname, itype, 0 ); /* fix up types and offsets later */
+ nextsym();
+ ++nargs;
+ if ( sym != COMMA )
+ break;
+ nextsym();
+ }
+ return nargs;
+}
+
+/*=============================================================================
+ arg-list =
+=============================================================================*/
+
+arglist( nargs )
+int nargs;
+{
+ struct symstruct *symptr;
+ int argsize, argsp;
+ int lastsym;
+ struct typestruct *basetype;
+ char declflag;
+
+ declflag = TRUE;
+ do
+ {
+ switch( sym )
+ {
+ case TYPEDECL:
+ basetype = gsymptr->type;
+ nextsym();
+ getarg1( basetype );
+ break;
+ case STRUCTDECL:
+ case UNIONDECL:
+ lastsym = sym;
+ nextsym();
+ getarg( declsu( lastsym ) );
+ break;
+ case AUTODECL:
+ case EXTERNDECL:
+ case REGDECL:
+ case STATICDECL:
+ case SEMICOLON:
+ nextsym();
+ break;
+ default:
+ declflag = FALSE;
+ break;
+ }
+ }
+ while ( declflag );
+ argsp = -2;
+ symptr = pstartloc;
+ while ( nargs && symptr < locptr ) /* convert arg sizes to offsets */
+ {
+ argsize = symptr->offset;
+ if ( symptr->type == ctype )
+ {
+ ++argsp;
+ --argsize;
+ }
+ symptr->offset = argsp;
+ argsp += argsize;
+ if ( symptr == pstartloc )
+ argsp += 2;
+ --nargs;
+ ++symptr;
+ }
+ if ( nargs )
+ error( "arguments not all declared" );
+}
+
+/* getarg( basetype ) - fill in argument types and sizes */
+
+getarg1( basetype )
+struct typestruct *basetype;
+{
+ char sname[NAMESIZE];
+ struct typestruct *type;
+ int size;
+ struct symstruct *symptr;
+
+ if ( sym != SEMICOLON )
+ while ( TRUE )
+ {
+ type = basetype;
+ size = getvar( sname, &type );
+ if ( (symptr = findlorg( sname )) == NULL || symptr->level != ARGLEVEL )
+ error( "variable not in argument list" );
+ else if ( symptr->offset != 0 ) /* already in arg list */
+ multidecl( sname, type, symptr );
+ else
+ {
+ if ( size < 2 || type->typeop == ATYPEOP )
+ size = 2;
+ symptr->offset = size;
+ symptr->type = type;
+ }
+ if ( sym == COMMA )
+ nextsym();
+ else
+ break;
+ }
+ ns();
+}
+
+struct typestruct *declarator( basetype )
+struct typestruct *basetype;
+{
+ char sname[NAMESIZE];
+ int size;
+ struct symstruct *multi;
+
+ size = getvar( sname, &type );
+ if ( multi = findlorg( sname ) )
+ multidecl( sname, type, multi );
+ else
+ addglb( sname, type, size );
+ nextsym();
+}
+
+struct typestruct *typespec()
+{
+ int lastsym;
+
+ switch( sym )
+ {
+ case TYPEDECL:
+ nextsym();
+ return gsymptr->type;
+ case STRUCTDECL:
+ case UNIONDECL:
+ lastsym = sym;
+ nextsym();
+ return declsu( lastsym );
+ default:
+ return itype;
+ }
+}
diff --git a/bcc/misc/test/hilbert.t b/bcc/misc/test/hilbert.t
new file mode 100644
index 0000000..e18dc63
--- /dev/null
+++ b/bcc/misc/test/hilbert.t
@@ -0,0 +1,169 @@
+/* hilbert.c */
+
+/* S1 stuff
+
+#define PIFBUF ( *(struct IFBUF **) 0xf010 )
+#define PSET 2
+
+struct IFBUF
+{
+ char ERR;
+ char COMMAND;
+ char COLOR;
+ char PLOTOPTION;
+ int LINESTYLE;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char BFFLAG;
+};
+end of S1 stuff */
+
+/* L3 stuff */
+
+#define PIFBUF ( (struct IFBUF *) 0xa1 )
+#define PSET 1
+
+struct IFBUF
+{
+ char PLOTOPTION;
+ char junk1[0xa8-0xa2];
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char junk2[0xf0-0xb0];
+ char ERR; /* this to BFFLAG are dummies to keep S1 code */
+ char COMMAND;
+ int LINESTYLE;
+ char BFFLAG;
+ char junk3[0x3ea-0xf5];
+ char COLOR;
+};
+
+#define H0 512 /* square size */
+#define XOFFS 80 /* offset to centre square */
+#define XNUM 15 /* scale 512 * 15/16 = 480 */
+#define XDENOM 16
+#define YNUM 25 /* scale 512 * 25/64 = 200 */
+#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */
+
+int h, x, y;
+
+main()
+{
+ int i, x0, y0;
+ char color;
+
+ PIFBUF->PLOTOPTION = PSET;
+ PIFBUF->LINESTYLE = /* normal */
+ PIFBUF->COMMAND = /* ?? */
+ PIFBUF->BFFLAG = 0; /* not a box */
+ color = i = 0;
+ x0 = y0 = (h = H0)/2;
+ while ( h > 1 )
+ {
+ ++i;
+ h = h/2;
+ if ( ++color > 7 )
+ color = 1;
+ gcolor( color );
+ x = x0 += h/2;
+ y = y0 += h/2;
+ glocate();
+ a( i );
+ }
+}
+
+a( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ d( i ); x -= h; plot();
+ a( i ); y -= h; plot();
+ a( i ); x += h; plot();
+ b( i );
+ }
+}
+
+b( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ c( i ); y += h; plot();
+ b( i ); x += h; plot();
+ b( i ); y -= h; plot();
+ a( i );
+ }
+}
+
+c( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ b( i ); x += h; plot();
+ c( i ); y += h; plot();
+ c( i ); x -= h; plot();
+ d( i );
+ }
+}
+
+d( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ a( i ); y -= h; plot();
+ d( i ); x -= h; plot();
+ d( i ); y += h; plot();
+ c( i );
+ }
+}
+
+glocate()
+{
+ PIFBUF->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS;
+ PIFBUF->Y2 = (y * YNUM) / YDENOM;
+}
+
+/* S1 gcolor and plot
+
+gcolor( color )
+int color;
+{
+ PIFBUF->COLOR = color;
+}
+
+plot()
+{
+ PIFBUF->X1 = PIFBUF->X2;
+ PIFBUF->Y1 = PIFBUF->Y2;
+ glocate();
+#asm
+ SWI2
+ FDB $4201 call LINEMA
+#endasm
+}
+
+end S1 plot */
+
+gcolor( color )
+int color;
+{
+ PIFBUF->COLOR = color | 0x10;
+}
+
+plot()
+{
+ PIFBUF->X1 = PIFBUF->X2;
+ PIFBUF->Y1 = PIFBUF->Y2;
+ glocate();
+#asm
+ JSR $D709
+ JSR $D79A
+#endasm
+}
diff --git a/bcc/misc/test/longtest.c b/bcc/misc/test/longtest.c
new file mode 100644
index 0000000..0c0bfe0
--- /dev/null
+++ b/bcc/misc/test/longtest.c
@@ -0,0 +1,24 @@
+int i,j;
+long m,n;
+
+main()
+{
+ while ( 1 )
+ {
+ if ( scanf( "%ld %ld", &m, &n ) <= 0 )
+ exit( 0 );
+ printf( "m = %ld n = %ld m + n = %ld m - n = %ld m * n = %ld\n",
+ m, n, m + n, m - n, m * n );
+ printf( "m = %ld n = %ld m / n = %ld m %% n = %ld\n",
+ m, n, m / n, m % n );
+ printf( "m = %ld n = %ld m&n = %ld m | n = %ld m^n = %ld\n",
+ m, n, m & n, m | n, m ^ n );
+ printf( "m = %ld n = %ld m << n = %ld m >> n = %ld\n",
+ m, n, m << (int) n, m >> (int) n );
+ printf(
+ "m = %ld n = %ld m < n is %d m == n is %d m > n is %d m == 0 is %d\n",
+ m, n, m < n, m == n, m > n, m == 0 );
+ printf( "m = %ld n = %ld -m = %ld ~m = %ld ++m = %ld --n = %ld\n",
+ m, n, -m, ~m, ++m, --n );
+ }
+}
diff --git a/bcc/misc/test/longtest.dat b/bcc/misc/test/longtest.dat
new file mode 100644
index 0000000..a1c7998
--- /dev/null
+++ b/bcc/misc/test/longtest.dat
@@ -0,0 +1,15 @@
+1 1
+-1 1
+1 -1
+-1 -1
+2 3
+4 5
+234234 34554
+4534534 34535
+345324523 3245325
+345435345 319755
+34534 345
+-352351235 23535
+533512351 -3535345
+-351351313 -12235
+123456789 987654321
diff --git a/bcc/misc/test/longtest.mak b/bcc/misc/test/longtest.mak
new file mode 100755
index 0000000..454a4e8
--- /dev/null
+++ b/bcc/misc/test/longtest.mak
@@ -0,0 +1,3 @@
+cc -o cclongtest longtest.c
+sc longtest.c sclongtest.s
+cc -o sclongtest sclongtest.s $HOME/lib/libcb.a $HOME/lib/liblb.a
diff --git a/bcc/misc/test/longtest.sh b/bcc/misc/test/longtest.sh
new file mode 100755
index 0000000..e76f98a
--- /dev/null
+++ b/bcc/misc/test/longtest.sh
@@ -0,0 +1,4 @@
+./sclongtest < longtest.dat >scl.out
+./cclongtest < longtest.dat >ccl.out
+diff scl.out ccl.out >longtest.diff
+cat longtest.diff
diff --git a/bcc/misc/test/miniltest.t b/bcc/misc/test/miniltest.t
new file mode 100644
index 0000000..78097d4
--- /dev/null
+++ b/bcc/misc/test/miniltest.t
@@ -0,0 +1,72 @@
+long x;
+int i;
+unsigned u;
+
+long test1(x)
+long x;
+{
+ return x;
+}
+
+long test2(x)
+int x;
+{
+ return x;
+}
+
+main()
+{
+ printlong( "x=1 is ", x = 1 );
+ printlong( "test1(x) is ", test1(x) );
+ printlong( "test1(1L) is ", test1(1L) );
+ printlong( "x = test1(1L) is ", x = test1(1L) );
+ printlong( "x = test1(x=1) is ", x = test1(x=1) );
+ printlong( "i=1 is ", (long) (i = 1) );
+ printlong( "test2(i) is ", test2(i) );
+ printlong( "test2(1) is ", test2(1) );
+ printlong( "i = test2(1) is ", (long) (i = test2(1)) );
+ printlong( "i = test2(i=1) is ", (long) (i = test2(i=1)) );
+ printlong( "(long) (i = -1) is ", (long) (i=-1) );
+ printlong( "(long) (u = -1) is ", (long) (u=-1) );
+ printlong( "x = -1 is ", x = -1 );
+}
+
+printlong( s, x )
+char *s;
+long x;
+{
+ printf( "%s", s );
+ if ( x & 0x80000000 )
+ {
+ putchar( '-' );
+ x = -x;
+ }
+ printf( "%08lx", (x >> 16) + (x << 16) );
+ putchar( '\n' );
+}
+
+outulhex( pnum )
+char *pnum;
+{
+ int i;
+
+ for ( i = 3; i >=0; --i )
+ p2( pnum[i] );
+}
+
+p2(i)
+int i;
+{
+ p1(i>>4);
+ p1(i);
+}
+
+p1(num)
+int num;
+{
+ int digit;
+
+ if ( (digit = num & 0xf) >= 10 )
+ digit += 'A' - ('9' + 1);
+ putchar( digit + '0' );
+}
diff --git a/bcc/misc/test/op1.t b/bcc/misc/test/op1.t
new file mode 100644
index 0000000..614e093
--- /dev/null
+++ b/bcc/misc/test/op1.t
@@ -0,0 +1,120 @@
+/* op1.t - test and, or (eor same as or ) */
+
+char cfn();
+int ifn();
+
+char *op1()
+{
+ char c, *pc, **ppc;
+ int i, *pi, **ppi;
+
+ i = c & 1;
+ i = 1 & c;
+ i = i & 1;
+ i = 1 & i;
+
+ i = c & 500;
+ i = 500 & c;
+ i = i & 500;
+ i = 500 & i;
+
+ i = c | 1;
+ i = 1 | c;
+ i = i | 1;
+ i = 1 | i;
+
+ i = c | 500;
+ i = 500 | c;
+ i = i | 500;
+ i = 500 | i;
+
+ i = c & c;
+ i = c & i;
+ i = i & c;
+ i = i & i;
+
+ i = c | c;
+ i = c | i;
+ i = i | c;
+ i = i | i;
+
+ i = c & c++;
+ i = c & i++;
+ i = i & c++;
+ i = i & i++;
+
+ i = c++ & c;
+ i = i++ & c;
+ i = c++ & i;
+ i = i++ & i;
+
+ i = c | c++;
+ i = c | i++;
+ i = i | c++;
+ i = i | i++;
+
+ i = c++ | c;
+ i = i++ | c;
+ i = c++ | i;
+ i = i++ | i;
+
+ i = c & cfn();
+ i = c & ifn();
+ i = i & cfn();
+ i = i & ifn();
+
+ i = cfn() & c;
+ i = ifn() & c;
+ i = cfn() & i;
+ i = ifn() & i;
+
+ i = c | cfn();
+ i = c | ifn();
+ i = i | cfn();
+ i = i | ifn();
+
+ i = cfn() | c;
+ i = ifn() | c;
+ i = cfn() | i;
+ i = ifn() | i;
+
+ i = *pc & c++;
+ i = *pc & i++;
+ i = *pi & c++;
+ i = *pi & i++;
+
+ i = c++ & *pc;
+ i = i++ & *pc;
+ i = c++ & *pi;
+ i = i++ & *pi;
+
+ i = *pc | c++;
+ i = *pc | i++;
+ i = *pi | c++;
+ i = *pi | i++;
+
+ i = c++ | *pc;
+ i = i++ | *pc;
+ i = c++ | *pi;
+ i = i++ | *pi;
+
+ i = **ppc & c++;
+ i = **ppc & i++;
+ i = **ppi & c++;
+ i = **ppi & i++;
+
+ i = c++ & **ppc;
+ i = i++ & **ppc;
+ i = c++ & **ppi;
+ i = i++ & **ppi;
+
+ i = **ppc | c++;
+ i = **ppc | i++;
+ i = **ppi | c++;
+ i = **ppi | i++;
+
+ i = c++ | **ppc;
+ i = i++ | **ppc;
+ i = c++ | **ppi;
+ i = i++ | **ppi;
+}
diff --git a/bcc/misc/test/opcmp.t b/bcc/misc/test/opcmp.t
new file mode 100644
index 0000000..28bd1a2
--- /dev/null
+++ b/bcc/misc/test/opcmp.t
@@ -0,0 +1,106 @@
+/* opcmp.t - test logical compare operations */
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* all examples < */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ unsigned u, *pu, **ppu, ufn();
+
+ c < 0;
+ 0 < c;
+ i < 0;
+ 0 < i;
+
+ s < 0;
+ 0 < s;
+
+ 0 < u;
+ u < 0;
+ 1 < u;
+ u < 1;
+
+ c < 1;
+ 1 < c;
+ c < 500;
+ 500 < c;
+
+ c < c;
+ c < i;
+ i < c;
+ i < i;
+
+ s < c;
+ i < u;
+
+ c < c++;
+ c < i++;
+ i < c++;
+ i < i++;
+
+ s < i++;
+ c < u++;
+
+ c++ < c;
+ i++ < c;
+ c++ < i;
+ i++ < i;
+
+ s++ < c;
+ i++ < u;
+
+ c < cfn();
+ c < ifn();
+ i < cfn();
+ i < ifn();
+
+ s < cfn();
+ c < ufn();
+
+ cfn() < c;
+ ifn() < c;
+ cfn() < i;
+ ifn() < i;
+
+ sfn() < c;
+ ifn() < u;
+
+ *pc < c++;
+ *pc < i++;
+ *pi < c++;
+ *pi < i++;
+
+ *ps < c++;
+ *pi < u++;
+
+ c++ < *pc;
+ i++ < *pc;
+ c++ < *pi;
+ i++ < *pi;
+
+ s++ < *pc;
+ i++ < *pu;
+
+ **ppc < c++;
+ **ppc < i++;
+ **ppi < c++;
+ **ppi < i++;
+
+ **pps < c++;
+ **ppi < u++;
+
+ c++ < **ppc;
+ i++ < **ppc;
+ c++ < **ppi;
+ i++ < **ppi;
+
+ s++ < **ppc;
+ i++ < **ppu;
+}
diff --git a/bcc/misc/test/oplong.t b/bcc/misc/test/oplong.t
new file mode 100644
index 0000000..b452243
--- /dev/null
+++ b/bcc/misc/test/oplong.t
@@ -0,0 +1,264 @@
+/* oplong.t - test long operations */
+
+/* this is just opsoft.t with int defined as long */
+
+#define int long
+#define UNSIGNED unsigned long
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* most examples for DIVOP */
+/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ UNSIGNED u, *pu, **ppu, ufn();
+
+ i = c / 0;
+ i = 0 / c;
+ i = i / 0;
+ i = 0 / i;
+
+ i = s / 0;
+ i = 0 / u;
+
+ i = c / 1;
+ i = 1 / c;
+ i = i / 1;
+ i = 1 / i;
+
+ i = s / 1;
+ i = 1 / u;
+
+ i = c / 2;
+ i = 2 / c;
+ i = i / 2;
+ i = 2 / i;
+
+ i = s / 2;
+ i = 2 / u;
+
+ i = c / 500;
+ i = 500 / c;
+ i = i / 500;
+ i = 500 / i;
+
+ i = s / 500;
+ i = 500 / u;
+
+ i = c / c;
+ i = c / i;
+ i = i / c;
+ i = i / i;
+
+ i = s / c;
+ i = i / u;
+
+ i = c / c++;
+ i = c / i++;
+ i = i / c++;
+ i = i / i++;
+
+ i = s / i++;
+ i = c / u++;
+
+ i = c++ / c;
+ i = i++ / c;
+ i = c++ / i;
+ i = i++ / i;
+
+ i = s++ / c;
+ i = i++ / u;
+
+ i = c / cfn();
+ i = c / ifn();
+ i = i / cfn();
+ i = i / ifn();
+
+ i = s / cfn();
+ i = c / ufn();
+
+ i = cfn() / c;
+ i = ifn() / c;
+ i = cfn() / i;
+ i = ifn() / i;
+
+ i = sfn() / c;
+ i = ifn() / u;
+
+ i = *pc / c++;
+ i = *pc / i++;
+ i = *pi / c++;
+ i = *pi / i++;
+
+ i = *ps / c++;
+ i = *pi / u++;
+
+ i = c++ / *pc;
+ i = i++ / *pc;
+ i = c++ / *pi;
+ i = i++ / *pi;
+
+ i = s++ / *pc;
+ i = i++ / *pu;
+
+ i = **ppc / c++;
+ i = **ppc / i++;
+ i = **ppi / c++;
+ i = **ppi / i++;
+
+ i = **pps / c++;
+ i = **ppi / u++;
+
+ i = c++ / **ppc;
+ i = i++ / **ppc;
+ i = c++ / **ppi;
+ i = i++ / **ppi;
+
+ i = s++ / **ppc;
+ i = i++ / **ppu;
+
+ i = c * 0;
+ i = 0 * c;
+ i = i * 0;
+ i = 0 * i;
+
+ i = s * 0;
+ i = 0 * u;
+
+ i = c * 1;
+ i = 1 * c;
+ i = i * 1;
+ i = 1 * i;
+
+ i = s * 1;
+ i = 1 * u;
+
+ i = c * 2;
+ i = 2 * c;
+ i = i * 2;
+ i = 2 * i;
+
+ i = s * 2;
+ i = 2 * u;
+
+ i = c * 500;
+ i = 500 * c;
+ i = i * 500;
+ i = 500 * i;
+
+ i = s * 500;
+ i = 500 * u;
+
+ i = c * c;
+ i = c * c++;
+ i = c++ * c;
+ i = c * cfn();
+ i = cfn() * c;
+ i = *pc * c++;
+ i = c++ * *pc;
+ i = **ppc * c++;
+ i = c++ * **ppc;
+
+ i = c % 0;
+ i = 0 % c;
+ i = i % 0;
+ i = 0 % i;
+
+ i = s % 0;
+ i = 0 % u;
+
+ i = c % 1;
+ i = 1 % c;
+ i = i % 1;
+ i = 1 % i;
+
+ i = s % 1;
+ i = 1 % u;
+
+ i = c % 2;
+ i = 2 % c;
+ i = i % 2;
+ i = 2 % i;
+
+ i = s % 2;
+ i = 2 % u;
+
+ i = c % 500;
+ i = 500 % c;
+ i = i % 500;
+ i = 500 % i;
+
+ i = s % 500;
+ i = 500 % u;
+
+ i = c << 0;
+ i = 0 << c;
+ i = i << 0;
+ i = 0 << i;
+
+ i = s << 0;
+ i = 0 << u;
+
+ i = c << 1;
+ i = 1 << c;
+ i = i << 1;
+ i = 1 << i;
+
+ i = s << 1;
+ i = 1 << u;
+
+ i = c << 8;
+ i = 8 << c;
+ i = i << 8;
+ i = 8 << i;
+
+ i = s << 8;
+ i = 8 << u;
+
+ i = c << 9;
+ i = 9 << c;
+ i = i << 9;
+ i = 9 << i;
+
+ i = s << 9;
+ i = 9 << u;
+
+ i = c >> 0;
+ i = 0 >> c;
+ i = i >> 0;
+ i = 0 >> i;
+
+ i = s >> 0;
+ i = 0 >> u;
+
+ i = c >> 1;
+ i = 1 >> c;
+ i = i >> 1;
+ i = 1 >> i;
+
+ i = s >> 1;
+ i = 1 >> u;
+
+ i = c >> 8;
+ i = 8 >> c;
+ i = i >> 8;
+ i = 8 >> i;
+
+ i = s >> 8;
+ i = 8 >> u;
+
+ i = c >> 9;
+ i = 9 >> c;
+ i = i >> 9;
+ i = 9 >> i;
+
+ i = s >> 9;
+ i = 9 >> u;
+}
diff --git a/bcc/misc/test/opplus.t b/bcc/misc/test/opplus.t
new file mode 100644
index 0000000..88e31e9
--- /dev/null
+++ b/bcc/misc/test/opplus.t
@@ -0,0 +1,122 @@
+/* op+-.t - test plus, minus operators */
+
+/* only doing chars and ints, not shorts, longs, floats, doubles */
+/* not doing pointer arithmetic */
+
+op1()
+{
+ char cfn();
+ int ifn();
+ char c, *pc, **ppc;
+ int i, *pi, **ppi;
+
+ i = c + 1;
+ i = 1 + c;
+ i = i + 1;
+ i = 1 + i;
+
+ i = c + 500;
+ i = 500 + c;
+ i = i + 500;
+ i = 500 + i;
+
+ i = c - 1;
+ i = 1 - c;
+ i = i - 1;
+ i = 1 - i;
+
+ i = c - 500;
+ i = 500 - c;
+ i = i - 500;
+ i = 500 - i;
+
+ i = c + c;
+ i = c + i;
+ i = i + c; /* -2 cycles, +1 byte different from c + i, lhs loaded 1st */
+ i = i + i;
+
+ i = c - c;
+ i = c - i;
+ i = i - c;
+ i = i - i;
+
+ i = c + c++;
+ i = c + i++;
+ i = i + c++;
+ i = i + i++;
+
+ i = c++ + c;
+ i = i++ + c;
+ i = c++ + i;
+ i = i++ + i;
+
+ i = c - c++;
+ i = c - i++;
+ i = i - c++;
+ i = i - i++;
+
+ i = c++ - c;
+ i = i++ - c;
+ i = c++ - i;
+ i = i++ - i;
+
+ i = c + cfn();
+ i = c + ifn();
+ i = i + cfn();
+ i = i + ifn();
+
+ i = cfn() + c;
+ i = ifn() + c;
+ i = cfn() + i;
+ i = ifn() + i;
+
+ i = c - cfn();
+ i = c - ifn();
+ i = i - cfn();
+ i = i - ifn();
+
+ i = cfn() - c;
+ i = ifn() - c;
+ i = cfn() - i;
+ i = ifn() - i;
+
+ i = *pc + c++;
+ i = *pc + i++;
+ i = *pi + c++;
+ i = *pi + i++;
+
+ i = c++ + *pc;
+ i = i++ + *pc;
+ i = c++ + *pi;
+ i = i++ + *pi;
+
+ i = *pc - c++;
+ i = *pc - i++;
+ i = *pi - c++;
+ i = *pi - i++;
+
+ i = c++ - *pc;
+ i = i++ - *pc;
+ i = c++ - *pi;
+ i = i++ - *pi;
+
+ i = **ppc + c++;
+ i = **ppc + i++;
+ i = **ppi + c++;
+ i = **ppi + i++;
+
+ i = c++ + **ppc;
+ i = i++ + **ppc;
+ i = c++ + **ppi;
+ i = i++ + **ppi;
+
+ i = **ppc - c++;
+ i = **ppc - i++;
+ i = **ppi - c++;
+ i = **ppi - i++;
+
+ i = c++ - **ppc;
+ i = i++ - **ppc;
+ i = c++ - **ppi;
+ i = i++ - **ppi;
+}
diff --git a/bcc/misc/test/opsoft.t b/bcc/misc/test/opsoft.t
new file mode 100644
index 0000000..346df4d
--- /dev/null
+++ b/bcc/misc/test/opsoft.t
@@ -0,0 +1,259 @@
+/* opsoft.t - test software operations */
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* most examples for DIVOP */
+/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ unsigned u, *pu, **ppu, ufn();
+
+ i = c / 0;
+ i = 0 / c;
+ i = i / 0;
+ i = 0 / i;
+
+ i = s / 0;
+ i = 0 / u;
+
+ i = c / 1;
+ i = 1 / c;
+ i = i / 1;
+ i = 1 / i;
+
+ i = s / 1;
+ i = 1 / u;
+
+ i = c / 2;
+ i = 2 / c;
+ i = i / 2;
+ i = 2 / i;
+
+ i = s / 2;
+ i = 2 / u;
+
+ i = c / 500;
+ i = 500 / c;
+ i = i / 500;
+ i = 500 / i;
+
+ i = s / 500;
+ i = 500 / u;
+
+ i = c / c;
+ i = c / i;
+ i = i / c;
+ i = i / i;
+
+ i = s / c;
+ i = i / u;
+
+ i = c / c++;
+ i = c / i++;
+ i = i / c++;
+ i = i / i++;
+
+ i = s / i++;
+ i = c / u++;
+
+ i = c++ / c;
+ i = i++ / c;
+ i = c++ / i;
+ i = i++ / i;
+
+ i = s++ / c;
+ i = i++ / u;
+
+ i = c / cfn();
+ i = c / ifn();
+ i = i / cfn();
+ i = i / ifn();
+
+ i = s / cfn();
+ i = c / ufn();
+
+ i = cfn() / c;
+ i = ifn() / c;
+ i = cfn() / i;
+ i = ifn() / i;
+
+ i = sfn() / c;
+ i = ifn() / u;
+
+ i = *pc / c++;
+ i = *pc / i++;
+ i = *pi / c++;
+ i = *pi / i++;
+
+ i = *ps / c++;
+ i = *pi / u++;
+
+ i = c++ / *pc;
+ i = i++ / *pc;
+ i = c++ / *pi;
+ i = i++ / *pi;
+
+ i = s++ / *pc;
+ i = i++ / *pu;
+
+ i = **ppc / c++;
+ i = **ppc / i++;
+ i = **ppi / c++;
+ i = **ppi / i++;
+
+ i = **pps / c++;
+ i = **ppi / u++;
+
+ i = c++ / **ppc;
+ i = i++ / **ppc;
+ i = c++ / **ppi;
+ i = i++ / **ppi;
+
+ i = s++ / **ppc;
+ i = i++ / **ppu;
+
+ i = c * 0;
+ i = 0 * c;
+ i = i * 0;
+ i = 0 * i;
+
+ i = s * 0;
+ i = 0 * u;
+
+ i = c * 1;
+ i = 1 * c;
+ i = i * 1;
+ i = 1 * i;
+
+ i = s * 1;
+ i = 1 * u;
+
+ i = c * 2;
+ i = 2 * c;
+ i = i * 2;
+ i = 2 * i;
+
+ i = s * 2;
+ i = 2 * u;
+
+ i = c * 500;
+ i = 500 * c;
+ i = i * 500;
+ i = 500 * i;
+
+ i = s * 500;
+ i = 500 * u;
+
+ i = c * c;
+ i = c * c++;
+ i = c++ * c;
+ i = c * cfn();
+ i = cfn() * c;
+ i = *pc * c++;
+ i = c++ * *pc;
+ i = **ppc * c++;
+ i = c++ * **ppc;
+
+ i = c % 0;
+ i = 0 % c;
+ i = i % 0;
+ i = 0 % i;
+
+ i = s % 0;
+ i = 0 % u;
+
+ i = c % 1;
+ i = 1 % c;
+ i = i % 1;
+ i = 1 % i;
+
+ i = s % 1;
+ i = 1 % u;
+
+ i = c % 2;
+ i = 2 % c;
+ i = i % 2;
+ i = 2 % i;
+
+ i = s % 2;
+ i = 2 % u;
+
+ i = c % 500;
+ i = 500 % c;
+ i = i % 500;
+ i = 500 % i;
+
+ i = s % 500;
+ i = 500 % u;
+
+ i = c << 0;
+ i = 0 << c;
+ i = i << 0;
+ i = 0 << i;
+
+ i = s << 0;
+ i = 0 << u;
+
+ i = c << 1;
+ i = 1 << c;
+ i = i << 1;
+ i = 1 << i;
+
+ i = s << 1;
+ i = 1 << u;
+
+ i = c << 8;
+ i = 8 << c;
+ i = i << 8;
+ i = 8 << i;
+
+ i = s << 8;
+ i = 8 << u;
+
+ i = c << 9;
+ i = 9 << c;
+ i = i << 9;
+ i = 9 << i;
+
+ i = s << 9;
+ i = 9 << u;
+
+ i = c >> 0;
+ i = 0 >> c;
+ i = i >> 0;
+ i = 0 >> i;
+
+ i = s >> 0;
+ i = 0 >> u;
+
+ i = c >> 1;
+ i = 1 >> c;
+ i = i >> 1;
+ i = 1 >> i;
+
+ i = s >> 1;
+ i = 1 >> u;
+
+ i = c >> 8;
+ i = 8 >> c;
+ i = i >> 8;
+ i = 8 >> i;
+
+ i = s >> 8;
+ i = 8 >> u;
+
+ i = c >> 9;
+ i = 9 >> c;
+ i = i >> 9;
+ i = 9 >> i;
+
+ i = s >> 9;
+ i = 9 >> u;
+}
diff --git a/bcc/misc/test/puzzle.t b/bcc/misc/test/puzzle.t
new file mode 100644
index 0000000..9d2c4ab
--- /dev/null
+++ b/bcc/misc/test/puzzle.t
@@ -0,0 +1,178 @@
+/* puzzle.t - from C puzzle book */
+
+#define puzzle(which) ( puts( "-----which-----\n" ), which() )
+
+main()
+{
+ puzzle( op1 );
+ puzzle( op2 );
+ puzzle( op3 );
+ puzzle( op4 );
+ puzzle( op5 );
+ puzzle( op6 );
+ puzzle( prep1 );
+ puzzle( prep2 );
+}
+
+op1()
+{
+ int x;
+
+ x = - 3 + 4 * 5 - 6; printf("%d\n",x);
+ x = 3 + 4 % 5 - 6; printf("%d\n",x);
+ x = - 3 * 4 % - 6 / 5; printf("%d\n",x);
+ x = ( 7 + 6 ) % 5 /2; printf("%d\n",x);
+}
+
+#define PRINTX printf( "%d\n", x )
+
+op2()
+{
+ int x, y, z;
+
+ x = 2;
+ x *= 3 + 2; PRINTX;
+ x *= y = z = 4; PRINTX;
+ x = y == z; PRINTX;
+ x == (y == z); PRINTX;
+}
+
+#define PRINT(int) printf( "int = %d\n", int )
+
+op3()
+{
+ int x, y, z;
+
+ x = 2; y = 1; z = 0;
+ x = x && y || z; PRINT(x);
+ PRINT( x || ! y && z );
+
+ x = y = 1;
+ z = x ++ - 1; PRINT(x); PRINT(z);
+ z += - x ++ + ++ y;PRINT(x);PRINT(z);
+ z = x / ++ x; PRINT(z);
+}
+
+op4()
+{
+ int x, y, z;
+
+ x = 03; y = 02; z = 01;
+ PRINT( x | y & z );
+ PRINT( x | y & ~ z );
+ PRINT( x ^ y & ~ z );
+ PRINT( x & y && z );
+
+ x = 1; y = -1;
+ PRINT( ! x | x );
+ PRINT( ~ x | x );
+ PRINT( x ^ x );
+ x <<= 3; PRINT(x);
+ y <<= 3; PRINT(y);
+ y >>= 3; PRINT(y);
+}
+
+op5()
+{
+ int x, y, z;
+
+ x = 1; y = 1; z = 1;
+
+ x += y += z;
+ PRINT( x < y ? y : x );
+
+ PRINT( x < y ? x ++ : y ++ );
+ PRINT(x); PRINT(y);
+
+ PRINT( z += x < y ? x ++ : y ++ );
+ PRINT(y); PRINT(z);
+
+ x = 3; y=z=4;
+ PRINT( (z >= y >= x) ? 1 : 0 );
+ PRINT( z >= y && y >= x );
+}
+
+#define PRINT3(x,y,z) printf("x=%d\ty=%d\tz=%d\n",x,y,z)
+
+op6()
+{
+ int x, y, z;
+
+ x = y = z = 1;
+ ++x || ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = 1;
+ ++x && ++y || ++z; PRINT3(x,y,z);
+
+ x = y = z = 1;
+ ++x && ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x && ++y || ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x || ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x && ++y && ++z; PRINT3(x,y,z);
+}
+
+#define FUDGE(k) k+3
+#define PR(a) printf("a= %d\t",(int)(a))
+#define PRINTNEW(a) PR(a); putchar( '\n' );
+#define PRINT2(a,b) PR(a); PRINT(b)
+#define PRINT3NEW(a,b,c) PR(a); PRINT2(b,c)
+#define MAX(a,b) (a<b ? b : a )
+
+prep1()
+{
+ {
+ int x;
+ x = 2;
+ PRINTNEW( x*FUDGE(2) );
+ }
+ {
+ int cel;
+ for( cel=0; cel<=100; cel+=50 )
+ PRINT2( cel, 9/5*cel+32 );
+ }
+ {
+ int x, y;
+ x=1; y=2;
+ PRINT3NEW( MAX(x++,y),x,y );
+ PRINT3NEW( MAX(x++,y),x,y );
+ }
+}
+
+#define NEG(a)-a
+#define weeks(mins) (days(mins)/7)
+#define days(mins) (hours(mins)/24)
+#define hours(mins) (mins/60)
+#define mins(secs) (secs/60)
+#define TAB(c,i,oi,tx) if(c=='\t')\
+ for(tx=8-(i-oi-1)%8,oi=i; tx; tx--)\
+ putchar(' ')
+
+static char *input = "\twhich\tif?";
+
+prep2()
+{
+ {
+ int x;
+ x=1;
+ PRINT( -NEG(x) );
+ }
+ {
+ PRINT( weeks(10080) );
+ PRINT( days(mins(86400)) );
+ }
+ {
+ char c;
+ int i, oldi, temp;
+
+ for( oldi= -1,i=0; (c=input[i])!='\0'; i++ )
+ if( c<' ' ) TAB(c,i,oldi,temp);
+ else putchar(c);
+ putchar('\n');
+ }
+}
diff --git a/bcc/misc/test/sierpin.t b/bcc/misc/test/sierpin.t
new file mode 100644
index 0000000..79016f7
--- /dev/null
+++ b/bcc/misc/test/sierpin.t
@@ -0,0 +1,123 @@
+/* sierpin.t */
+
+#define PPIFBUF 0xf010 /* address of ptr to IFBUF */
+#define PSET 2 /* use this plot option */
+
+struct IFBUF
+{
+ char ERR;
+ char COMMAND;
+ char COLOR;
+ char PLOTOPTION;
+ int LINESTYLE;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char BFFLAG;
+};
+
+#define H0 512 /* square size */
+#define XOFFS 80 /* offset to centre square */
+#define XNUM 15 /* scale 512 * 15/16 = 480 */
+#define XDENOM 16
+#define YNUM 25 /* scale 512 * 25/64 = 200 */
+#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */
+
+struct IFBUF *pifbuf;
+int h, x, y;
+
+main()
+{
+ struct IFBUF **ppifbuf; /* required since no casts */
+ int i, x0, y0;
+ char color;
+
+ pifbuf = *(ppifbuf = PPIFBUF); /* pifbuf = *(struct IFBUF **)PPIFBUF; */
+ pifbuf->PLOTOPTION = PSET;
+ pifbuf->LINESTYLE = /* normal */
+ pifbuf->COMMAND = /* ?? */
+ pifbuf->BFFLAG = 0; /* not a box */
+ color = i = 0;
+ x0 = 2 * (h = H0/4);
+ y0 = 3 * (H0/4);
+ while ( h > 1 )
+ {
+ ++i;
+ if ( ++color > 7 )
+ color = 1;
+ pifbuf->COLOR = color;
+ x = x0 -= h;
+ y = y0 += h /= 2;
+ glocate();
+ a( i ); x += h; y -= h; plot();
+ b( i ); x -= h; y -= h; plot();
+ c( i ); x -= h; y += h; plot();
+ d( i ); x += h; y += h; plot();
+ }
+}
+
+a( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ a( i ); x += h; y -=h; plot();
+ b( i ); x += 2*h; plot();
+ d( i ); x += h; y += h; plot();
+ a( i );
+ }
+}
+
+b( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ b( i ); x -= h; y -=h; plot();
+ c( i ); y -= 2*h; plot();
+ a( i ); x += h; y -= h; plot();
+ b( i );
+ }
+}
+
+c( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ c( i ); x -= h; y +=h; plot();
+ d( i ); x -= 2*h; plot();
+ b( i ); x -= h; y -= h; plot();
+ c( i );
+ }
+}
+
+d( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ d( i ); x += h; y +=h; plot();
+ a( i ); y += 2*h; plot();
+ c( i ); x -= h; y += h; plot();
+ d( i );
+ }
+}
+
+glocate()
+{
+ pifbuf->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS;
+ pifbuf->Y2 = (y * YNUM) / YDENOM;
+}
+
+plot()
+{
+ pifbuf->X1 = pifbuf->X2;
+ pifbuf->Y1 = pifbuf->Y2;
+ glocate();
+#asm
+ SWI2
+ FDB $4201 call LINEMA
+#endasm
+}
diff --git a/bcc/misc/test/sievec.t b/bcc/misc/test/sievec.t
new file mode 100644
index 0000000..1b51fdb
--- /dev/null
+++ b/bcc/misc/test/sievec.t
@@ -0,0 +1,28 @@
+#define TRUE 1
+#define FALSE 0
+#define SIZE 8190
+
+char flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<10;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/sievecp.t b/bcc/misc/test/sievecp.t
new file mode 100644
index 0000000..185b031
--- /dev/null
+++ b/bcc/misc/test/sievecp.t
@@ -0,0 +1,45 @@
+/* sieve using pointers */
+
+#define TRUE 1
+#define FALSE 0
+#define NITER 100
+#define SIZE 8191 /* last prime <= 2*this+3 */
+#define SQRSIZE 63 /* last divisor tested = 2*this+3 */
+
+char flags[SIZE+2*SQRSIZE+3]; /* avoid ptr+=prime overflowing */
+
+main()
+{
+ int i,count,iter;
+ register char *ptr;
+ char *endptr;
+ int prime;
+
+ for (iter=0;iter<NITER;iter++)
+ {
+ count=0;
+ ptr=flags;
+ endptr=flags+SIZE;
+ while (ptr<endptr)
+ *ptr++=TRUE;
+ for (i=0;i<SQRSIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ ptr=flags+i+prime; /* ptr<endptr since i<SQRSIZE */
+ while (ptr<endptr)
+ {
+ *ptr=FALSE;
+ ptr+=prime; /* does not overflow since in flags */
+ }
+ count++;
+ }
+ }
+ ptr=flags+SQRSIZE;
+ while (ptr<endptr)
+ if (*ptr++)
+ count++;
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/sievei.t b/bcc/misc/test/sievei.t
new file mode 100644
index 0000000..d4910dc
--- /dev/null
+++ b/bcc/misc/test/sievei.t
@@ -0,0 +1,28 @@
+#define TRUE 1
+#define FALSE 0
+#define SIZE 8190
+
+int flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<10;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/sort.t b/bcc/misc/test/sort.t
new file mode 100644
index 0000000..34bcb9e
--- /dev/null
+++ b/bcc/misc/test/sort.t
@@ -0,0 +1,104 @@
+unsigned t[10000];
+unsigned s[10000];
+unsigned size,repet;
+unsigned comp=0,swap=0; /* s.b. long */
+
+main(argc)
+{
+ int i,zz;
+
+/*
+ printf("size?");
+ scanf("%d",&size);
+ printf("repet?");
+ scanf("%d",&repet);
+*/
+ if ( argc > 20 )
+ {
+ printf( "usage: sort [args], where 500*argc is the array size\n" );
+ exit( 1 );
+ }
+ size = 500 * argc;
+ repet = 1;
+ for (i = 0; i < size; i++)
+ s[i] = size-i;
+ printf("\npress key to begin shell sorting\n");
+ getchar();
+ for (zz=0;zz<repet;zz++)
+ {
+ comp=swap=0;
+ for (i=0;i<size;i++)
+ t[i]=s[i];
+ sort();
+ }
+ printf("\nsorted\n");
+ printf("\ncompares = %d, swaps = %d\n",comp,swap);
+ printf("\npress key to begin quick sorting\n");
+ getchar();
+ for (zz=0;zz<repet;zz++)
+ {
+ comp=swap=0;
+ for (i=0;i<size;i++)
+ t[i]=s[i];
+ qqsort();
+ }
+ printf("\nsorted\n");
+ printf("\ncompares = %d, swaps = %d\n",comp,swap);
+}
+
+sort()
+{
+ int i,j,h,temp;
+
+ h=1;
+ while (9*h+4<size)
+ h=3*h+1;
+ while (h>0)
+ {
+ for (j=h; j<size; j++)
+ for (i=j-h; i>=0; i-=h)
+ {
+ ++comp;
+ if (t[i]<=t[i+h])
+ break;
+ ++swap;
+ temp=t[i];
+ t[i]=t[i+h];
+ t[i+h]=temp;
+ }
+ h=(h-1)/3;
+ }
+}
+
+qqsort()
+{
+ qsort(0,size-1);
+}
+
+qsort(l,r)
+int l,r;
+{
+ int i,j;
+ unsigned x,w;
+
+ i=l;j=r;
+ x=t[(l+r)>>1];
+ do
+ {
+ while (t[i] < x)
+ {
+ ++comp;
+ i++;
+ }
+ while (x < t[j]) {--j;}
+ if (i<=j)
+ {
+ ++swap;
+ w=t[i];t[i]=t[j];t[j]=w;
+ i++;j--;
+ }
+ }
+ while (i<=j);
+ if (l<j) qsort(l,j);
+ if (i<r) qsort(i,r);
+}
diff --git a/bcc/misc/test/stdio.t b/bcc/misc/test/stdio.t
new file mode 100644
index 0000000..e7e174d
--- /dev/null
+++ b/bcc/misc/test/stdio.t
@@ -0,0 +1,87 @@
+/* stdio.h */
+
+#asm
+
+#define BUFSIZ 512
+#define _NFILE 20
+
+#define _IOREAD 1
+#define _IOWRITE 2
+#define _IODIRTY 4
+#define _IOEOF 8
+#define _IOERR 16
+#define _IOMYBUF 32 /* says if stream routines allocated buffer */
+#define _IOUNBUF 64
+
+#define EOF (-1)
+#define NULL 0
+
+#endasm
+
+#define stdin (&_iob[0])
+#define stdout (&_iob[1])
+#define stderr (&_iob[2])
+
+#define FILE struct _iobuf
+
+struct _iobuf
+{
+ char *_ptr;
+ char *_base;
+ char *_rtop;
+ char *_wtop;
+ char _flags;
+ char _fd;
+}
+ _iob[_NFILE];
+
+#define clearerr(fp) ((fp)->flags&=~_IOERR)
+#define getchar() getc(stdin)
+#define feof(fp) ((fp)->_flags&_IOEOF)
+#define ferror(fp) ((fp)->_flags&_IOERR)
+#define fileno(fp) ((fp)->_fd)
+#define putchar(c) putc((c),stdout)
+
+#define void int
+
+FILE *fdopen();
+char *fgets();
+FILE *fopen();
+FILE *freopen();
+long ftell();
+
+long lseek();
+unsigned read();
+unsigned write();
+
+char *malloc();
+char *realloc();
+char *sbrk();
+
+char *index();
+char *rindex();
+char *strcat();
+char *strcpy();
+char *strncat();
+char *strncpy();
+
+#asm
+
+BLANK EQU 32
+COEOL EQU 10
+EOL EQU 13
+MAXCONTROL EQU 31
+
+* struct _iobuf translated into offsets
+
+ BLOCK 0
+PTR RMB 2
+BASE RMB 2
+RTOP RMB 2
+WTOP RMB 2
+FLAGS RMB 1
+FD RMB 1
+IOB.SIZE
+ ENDB
+
+#endasm
diff --git a/bcc/os.h b/bcc/os.h
new file mode 100644
index 0000000..71dfcef
--- /dev/null
+++ b/bcc/os.h
@@ -0,0 +1,78 @@
+/* os.h - source/target operating system dependencies for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ must have unix-near-compatible creat, open, read, write and close
+
+ source O/S's supported:
+ default:
+ *IX
+ special:
+ EDOS (#define SOS_EDOS if required)
+ MSDOS (#define SOS_MSDOS)
+ target O/S's supported:
+ default:
+ *IX
+ MSDOS
+ special:
+ EDOS (#define TOS_EDOS)
+*/
+
+/* defaults */
+
+#define CREATPERMS 0666 /* permissions for creat */
+#define EOL 10 /* source newline */
+#define EOLTO 10 /* target newline */
+#define DIRCHAR '/'
+#define DIRSTRING "/"
+#define isabspath(fnameptr, tempcptr) \
+ ((*(tempcptr) = *(fnameptr)) == DIRCHAR)
+
+/* special */
+
+#ifdef SOS_EDOS
+# undef DEFAULT_INCLUDE_DIR
+# define DEFAULT_INCLUDE_DIR "3"
+# undef DIRCHAR
+# define DIRCHAR ':'
+# undef DIRSTRING
+# define DIRSTRING ":"
+# define AS09
+# undef EOL
+# define EOL 13
+# undef isabspath
+# define isabspath(fnameptr, tempcptr) \
+ ((*(tempcptr) = *(fnameptr)) >= '0' && *(tempcptr) <= '9' && \
+ (fnameptr)[1] == DIRCHAR)
+#endif
+
+#ifdef SOS_MSDOS
+# define COEOL 10
+# undef DEFAULT_INCLUDE_DIR
+# define DEFAULT_INCLUDE_DIR "\\usr\\include"
+# undef DIRCHAR
+# define DIRCHAR '\\'
+# undef DIRSTRING
+# define DIRSTRING "\\"
+# undef EOL
+# define EOL 13
+/*
+ Problems with newline on MSDOS (as usual).
+ Defining EOL as 10 (LF) handles LF-terminated lines as well as
+ CRLF-terminated lines, but escaped CRLF's do not work. The compiler
+ should handle the escapes better. (Perhaps it does now.)
+ Defining EOL as 13 (CR) handles CRLF-terminated lines but fails on
+ LF-terminated lines.
+*/
+#endif
+
+#ifdef TOS_EDOS
+# undef EOLTO
+# define EOLTO 13
+#endif
+
+/* don't let names dealt with here affect anything outside this file */
+
+#undef SOS_EDOS
+#undef SOS_MSDOS
diff --git a/bcc/output.c b/bcc/output.c
new file mode 100644
index 0000000..c44ea3f
--- /dev/null
+++ b/bcc/output.c
@@ -0,0 +1,813 @@
+/* output.c - output and error handling for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "sizes.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "output.h"
+
+#ifdef XENIX_AS
+# define HEXSTARTCHAR '/'
+#else
+# define HEXSTARTCHAR '$'
+#endif
+#define OUTBUFSIZE 2048
+#define opcodeleadin() /* outtab() for fussy assemblers */
+
+PRIVATE unsigned errcount; /* # errors in compilation */
+ /* depends on zero init */
+PRIVATE char hexdigits[] = "0123456789ABCDEF";
+PRIVATE char *outbuf;
+EXTERN char *outbufend; /* end of pair of output buffers */
+PRIVATE char *outbufmid;
+PRIVATE fd_t output;
+PRIVATE fastin_t outstage; /* depends on zero init */
+
+FORWARD void errorsummary P((void));
+FORWARD void errsum1 P((void));
+#ifdef MC6809
+#ifdef DEBUG
+FORWARD void outvaldigs P((uvalue_t num));
+#endif
+#endif
+
+PUBLIC void bugerror(message)
+char *message;
+{
+ error2error("compiler bug - ", message);
+}
+
+PUBLIC void closeout()
+{
+ char *saveoutptr;
+
+ if (outstage == 3)
+ {
+ saveoutptr = outbufptr;
+ flushout(); /* buffer from last stage */
+ outbufptr = saveoutptr;
+ }
+ outstage = 0; /* flush from top to current ptr */
+ flushout();
+ close(output);
+}
+
+/* error handler */
+
+PUBLIC void error(message)
+char *message;
+{
+ error2error(message, "");
+}
+
+/* error handler - concatenate 2 messages */
+
+PUBLIC void error2error(message1, message2)
+char *message1;
+char *message2;
+{
+ char *warning;
+
+ if (message1[0] == '%' && message1[1] == 'w')
+ {
+ message1 += 2;
+ warning = "warning: ";
+ }
+ else
+ {
+ ++errcount;
+ warning = "error: ";
+ }
+ if (output != 1)
+ {
+ char *old_outbuf;
+ char *old_outbufptr;
+ char *old_outbuftop;
+ fd_t old_output;
+ fastin_t old_outstage;
+ char smallbuf[81]; /* don't use heap - might be full or busy */
+
+ old_outbuf = outbuf;
+ old_outbufptr = outbufptr;
+ old_outbuftop = outbuftop;
+ old_output = output;
+ old_outstage = outstage;
+
+ outbufptr = outbuf = &smallbuf[0];
+ outbuftop = &smallbuf[sizeof smallbuf];
+ output = 1;
+ outstage = 0;
+ errorloc();
+ outstr(warning);
+ outstr(message1);
+ outstr(message2);
+ outnl();
+ flushout();
+
+ outbuf = old_outbuf;
+ outbufptr = old_outbufptr;
+ outbuftop = old_outbuftop;
+ output = old_output;
+ outstage = old_outstage;
+ }
+ comment();
+ errorloc();
+ outstr(warning);
+ outstr(message1);
+ outstr(message2);
+ outnl();
+}
+
+/* summarise errors */
+
+PRIVATE void errorsummary()
+{
+ if (errcount != 0)
+ {
+ outfail();
+ errsum1();
+ }
+ outnl();
+ comment();
+ errsum1();
+}
+
+PRIVATE void errsum1()
+{
+ outudec(errcount);
+ outnstr(" errors detected");
+}
+
+/* fatal error, exit early */
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ error(message);
+ finishup();
+}
+
+/* finish up compile */
+
+PUBLIC void finishup()
+{
+ if (!cppmode)
+ {
+ if (watchlc)
+ {
+ cseg();
+ outop0str("if *-.program.start-");
+ outnhex(getlc());
+ outfail();
+ outnstr("phase error");
+ outop0str("endif\n");
+ }
+#ifdef HOLDSTRINGS
+ dumpstrings();
+#endif
+ dumpglbs();
+ errorsummary();
+ }
+ closein();
+ closeout();
+ exit(errcount == 0 ? 0 : 1);
+}
+
+/* flush output file */
+
+PUBLIC void flushout()
+{
+ unsigned nbytes;
+
+ switch (outstage)
+ {
+ case 0:
+ nbytes = (unsigned) (outbufptr - outbuf);
+ outbufptr = outbuf;
+ break;
+ case 2:
+ nbytes = OUTBUFSIZE;
+ outbufptr = outbuf;
+ outbuftop = outbufmid;
+ outstage = 3;
+ break;
+ default:
+ nbytes = OUTBUFSIZE;
+ if (outstage == 1)
+ nbytes = 0;
+ outbufptr = outbufmid;
+ outbuftop = outbufend;
+ outstage = 2;
+ break;
+ }
+ if (nbytes != 0)
+ {
+ if (!orig_cppmode)
+ clearlabels(outbufptr, outbufptr + nbytes);
+ if (write(output, outbufptr, nbytes) != nbytes)
+ {
+ write(2, "output file error\n", 18);
+ closein();
+ close(output);
+ exit(1);
+ }
+ }
+}
+
+PUBLIC void initout()
+{
+ static char smallbuf[1];
+
+ outbufend = outbuftop = (outbuf = outbufptr = smallbuf) + sizeof smallbuf;
+ output = 1; /* standard output */
+}
+
+PUBLIC void limiterror(message)
+char *message;
+{
+ error2error("compiler limit exceeded - ", message);
+ finishup();
+}
+
+PUBLIC void openout(oname)
+char *oname;
+{
+ if (output != 1)
+ fatalerror("more than one output file");
+ if ((output = creat(oname, CREATPERMS)) < 0)
+ {
+ output = 1;
+ fatalerror("cannot open output");
+ }
+}
+
+/* print character */
+
+PUBLIC void outbyte(c)
+int c;
+{
+#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1
+ register char *outp;
+
+ outp = outbufptr;
+ *outp++ = c;
+ outbufptr = outp;
+ if (outp >= outbuftop)
+ flushout();
+#else /* !C_CODE etc */
+
+#if __AS09__
+# asm
+ TFR X,D
+ LDX _outbufptr,PC
+ STB ,X+
+ STX _outbufptr,PC
+ CMPX _outbuftop,PC
+ LBHS CALL.FLUSHOUT
+# endasm
+#endif /* __AS09__ */
+
+#if __AS386_16__
+# asm
+# if !__FIRST_ARG_IN_AX__
+ pop dx
+ pop ax
+ dec sp
+ dec sp
+# else
+# if ARGREG != DREG
+ xchg ax,bx
+# endif
+# endif
+ mov bx,[_outbufptr]
+ mov [bx],al
+ inc bx
+ mov [_outbufptr],bx
+ cmp bx,[_outbuftop]
+ jae OUTBYTE.FLUSH
+# if !__FIRST_ARG_IN_AX__
+ jmp dx
+# else
+ ret
+# endif
+
+OUTBYTE.FLUSH:
+# if !__FIRST_ARG_IN_AX__
+ push dx
+# endif
+ br _flushout
+# endasm
+#endif /* __AS386_16__ */
+
+#if __AS386_32__
+# asm
+# if !__FIRST_ARG_IN_AX__
+ mov eax,_outbyte.c[esp]
+# else
+# if ARGREG != DREG
+ xchg eax,ebx
+# endif
+# endif
+ mov ecx,[_outbufptr]
+ mov [ecx],al
+ inc ecx
+ mov [_outbufptr],ecx
+ cmp ecx,[_outbuftop]
+ jae OUTBYTE.FLUSH
+ ret
+
+OUTBYTE.FLUSH:
+ br _flushout
+# endasm
+#endif /* __AS386_32__ */
+#endif /* C_CODE etc */
+}
+
+/* print comma */
+
+PUBLIC void outcomma()
+{
+ outbyte(',');
+}
+
+/* print line number in format ("# %u \"%s\"%s", nr, fname, str) */
+
+PUBLIC void outcpplinenumber(nr, fname, str)
+unsigned nr;
+char *fname;
+char *str;
+{
+ outstr("# ");
+ outudec(nr);
+ outstr(" \"");
+ outstr(fname);
+ outstr("\"");
+ outnstr(str);
+}
+
+/* print unsigned offset, hex format */
+
+PUBLIC void outhex(num)
+uoffset_t num;
+{
+#ifdef HEXSTARTCHAR
+ if (num >= 10)
+ outbyte(HEXSTARTCHAR);
+#endif
+ outhexdigs(num);
+#ifdef HEXENDCHAR
+ if (num >= 10)
+ outbyte(HEXENDCHAR);
+#endif
+}
+
+/* print unsigned offset, hex format with digits only (no hex designator) */
+
+PUBLIC void outhexdigs(num)
+register uoffset_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ outbyte(hexdigits[(int) num]);
+}
+
+/* print string terminated by EOL */
+
+PUBLIC void outline(s)
+char *s;
+{
+ register char *outp;
+ register char *rs;
+
+ outp = outbufptr;
+ rs = s;
+#ifdef COEOL
+ if (*rs == COEOL)
+ ++rs;
+#endif
+ do
+ {
+ *outp++ = *rs;
+ if (outp >= outbuftop)
+ {
+ outbufptr = outp;
+ flushout();
+ outp = outbufptr;
+ }
+ }
+ while (*rs++ != EOL);
+ outbufptr = outp;
+#ifdef COEOL
+ if (*rs == COEOL)
+ outbyte(COEOL);
+#endif
+}
+
+/* print minus sign */
+
+PUBLIC void outminus()
+{
+ outbyte('-');
+}
+
+/* print character, then newline */
+
+PUBLIC void outnbyte(byte)
+int byte;
+{
+ outbyte(byte);
+ outnl();
+}
+
+/* print unsigned offset, hex format, then newline */
+
+PUBLIC void outnhex(num)
+uoffset_t num;
+{
+ outhex(num);
+ outnl();
+}
+
+/* print newline */
+
+PUBLIC void outnl()
+{
+ if (watchlc)
+ {
+ outtab();
+ comment();
+ outhex(getlc());
+ }
+ outbyte('\n');
+}
+
+/* print opcode and newline, bump lc by 1 */
+
+PUBLIC void outnop1str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc();
+ outnl();
+}
+
+/* print opcode and newline, bump lc by 2 */
+
+PUBLIC void outnop2str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc2();
+ outnl();
+}
+
+/* print string, then newline */
+
+PUBLIC void outnstr(s)
+char *s;
+{
+ outstr(s);
+ outnl();
+}
+
+/* print opcode */
+
+PUBLIC void outop0str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+}
+
+/* print opcode, bump lc by 1 */
+
+PUBLIC void outop1str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc();
+}
+
+/* print opcode, bump lc by 2 */
+
+PUBLIC void outop2str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc2();
+}
+
+/* print opcode, bump lc by 3 */
+
+PUBLIC void outop3str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc3();
+}
+
+/* print plus sign */
+
+PUBLIC void outplus()
+{
+ outbyte('+');
+}
+
+/* print signed offset, hex format */
+
+PUBLIC void outshex(num)
+offset_t num;
+{
+ if (num >= -(maxoffsetto + 1))
+ {
+ outminus();
+ num = -num;
+ }
+ outhex((uoffset_t) num);
+}
+
+/* print string */
+
+PUBLIC void outstr(s)
+char *s;
+{
+#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1
+ register char *outp;
+ register char *rs;
+
+ outp = outbufptr;
+ rs = s;
+ while (*rs)
+ {
+ *outp++ = *rs++;
+ if (outp >= outbuftop)
+ {
+ outbufptr = outp;
+ flushout();
+ outp = outbufptr;
+ }
+ }
+ outbufptr = outp;
+#else /* !C_CODE etc */
+
+#if __AS09__
+# asm
+ LEAU ,X
+ LDX _outbuftop,PC
+ PSHS X
+ LDX _outbufptr,PC
+ BRA OUTSTR.NEXT
+
+CALL.FLUSHOUT
+ PSHS U,B
+ STX _outbufptr,PC
+ LBSR _flushout
+ LDX _outbufptr,PC
+ LDY _outbuftop,PC
+ PULS B,U,PC
+
+OUTSTR.LOOP
+ STB ,X+
+ CMPX ,S
+ BLO OUTSTR.NEXT
+ BSR CALL.FLUSHOUT
+ STY ,S
+OUTSTR.NEXT
+ LDB ,U+
+ BNE OUTSTR.LOOP
+ STX _outbufptr,PC
+ LEAS 2,S
+# endasm
+#endif /* __AS09__ */
+
+#if __AS386_16__
+# asm
+# if !__CALLER_SAVES__
+ mov dx,di
+ mov cx,si
+# endif
+# if !__FIRST_ARG_IN_AX__
+ pop ax
+ pop si
+ dec sp
+ dec sp
+ push ax
+# else
+# if ARGREG == DREG
+ xchg si,ax
+# else
+ mov si,bx
+# endif
+# endif
+ mov di,[_outbufptr]
+ mov bx,[_outbuftop]
+ br OUTSTR.NEXT
+
+CALL.FLUSHOUT:
+ push si
+# if !__CALLER_SAVES__
+ push dx
+ push cx
+# endif
+ push ax
+ mov [_outbufptr],di
+ call _flushout
+ mov di,[_outbufptr]
+ mov bx,[_outbuftop]
+ pop ax
+# if !__CALLER_SAVES__
+ pop cx
+ pop dx
+#endif
+ pop si
+ ret
+
+OUTSTR.LOOP:
+ stosb
+ cmp di,bx
+ jb OUTSTR.NEXT
+ call CALL.FLUSHOUT
+OUTSTR.NEXT:
+ lodsb
+ test al,al
+ jne OUTSTR.LOOP
+ mov [_outbufptr],di
+# if !__CALLER_SAVES__
+ mov si,cx
+ mov di,dx
+# endif
+# endasm
+#endif /* __AS386_16__ */
+
+#if __AS386_32__
+# asm
+# if !__CALLER_SAVES__
+ mov edx,edi
+ push esi
+# define TEMPS 4
+# else
+# define TEMPS 0
+# endif
+# if !__FIRST_ARG_IN_AX__
+ mov esi,TEMPS+_outstr.s[esp]
+# else
+# if ARGREG == DREG
+ xchg esi,eax
+# else
+ mov esi,ebx
+# endif
+# endif
+ mov edi,[_outbufptr]
+ mov ecx,[_outbuftop]
+ br OUTSTR.NEXT
+
+CALL.FLUSHOUT:
+ push esi
+# if !__CALLER_SAVES__
+ push edx
+# endif
+ push eax
+ mov [_outbufptr],edi
+ call _flushout
+ mov edi,[_outbufptr]
+ mov ecx,[_outbuftop]
+ pop eax
+# if !__CALLER_SAVES__
+ pop edx
+# endif
+ pop esi
+ ret
+
+OUTSTR.LOOP:
+ stosb
+ cmp edi,ecx
+ jb OUTSTR.NEXT
+ call CALL.FLUSHOUT
+OUTSTR.NEXT:
+ lodsb
+ test al,al
+ jne OUTSTR.LOOP
+ mov [_outbufptr],edi
+# if !__CALLER_SAVES__
+ pop esi
+ mov edi,edx
+# endif
+# endasm
+#endif /* __AS386_32__ */
+#endif /* C_CODE etc */
+}
+
+/* print tab */
+
+PUBLIC void outtab()
+{
+ outbyte('\t');
+}
+
+/* print unsigned, decimal format */
+
+PUBLIC void outudec(num)
+unsigned num;
+{
+ char str[10 + 1];
+
+ str[sizeof str - 1] = 0;
+ outstr(pushudec(str + sizeof str - 1, num));
+}
+
+#ifdef MC6809
+#ifdef DEBUG
+
+/* print unsigned value, hex format (like outhex except value_t is larger) */
+
+PUBLIC void outuvalue(num)
+uvalue_t num;
+{
+#ifdef HEXSTARTCHAR
+ if (num >= 10)
+ outbyte(HEXSTARTCHAR);
+#endif
+ outvaldigs(num);
+#ifdef HEXENDCHAR
+ if (num >= 10)
+ outbyte(HEXENDCHAR);
+#endif
+}
+
+/* print unsigned value, hex format with digits only (no hex designator) */
+
+PRIVATE void outvaldigs(num)
+register uvalue_t num;
+{
+ if (num >= 0x10)
+ {
+ outvaldigs(num / 0x10);
+ num %= 0x10;
+ }
+ outbyte(hexdigits[(fastin_t) num]);
+}
+
+/* print signed value, hex format (like outshex except value_t is larger) */
+
+PUBLIC void outvalue(num)
+register value_t num;
+{
+ if (num < 0)
+ {
+ outminus();
+ num = -num;
+ }
+ outuvalue((uoffset_t) num);
+}
+
+#endif /* DEBUG */
+#endif /* MC6809 */
+
+/* push decimal digits of an unsigned onto a stack of chars */
+
+PUBLIC char *pushudec(s, num)
+register char *s;
+register unsigned num;
+{
+ register unsigned reduction;
+
+ while (num >= 10)
+ {
+ reduction = num / 10;
+ *--s = num - 10 * reduction + '0';
+ num = reduction;
+ }
+ *--s = num + '0';
+ return s;
+}
+
+PUBLIC void setoutbufs()
+{
+ if (!isatty(output))
+ {
+ outbufptr = outbuf = ourmalloc(2 * OUTBUFSIZE);
+#ifdef TS
+ts_s_outputbuf += 2 * OUTBUFSIZE;
+#endif
+ outbufmid = outbuftop = outbufptr + OUTBUFSIZE;
+ outbufend = outbufmid + OUTBUFSIZE;
+ outstage = 1;
+ }
+ if (watchlc)
+ outnstr(".program.start:\n"); /* kludge temp label */
+}
diff --git a/bcc/output.h b/bcc/output.h
new file mode 100644
index 0000000..6dc9cf1
--- /dev/null
+++ b/bcc/output.h
@@ -0,0 +1,14 @@
+/* output.h - output for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define OUTBYTE(ch) \
+ do {register char *outp = outbufptr; *outp++ = (ch); \
+ outbufptr = outp; if (outp >= outbuftop) flushout(); } while (0)
+
+EXTERN bool_t ctext; /* nonzero to intermix C source */
+ /* depends on zero init */
+EXTERN char *outbufptr; /* current spot in output buffer */
+EXTERN char *outbuftop; /* top of current output buffer */
+EXTERN bool_t watchlc; /* nonzero to print lc after every line */
+ /* depends on zero init */
diff --git a/bcc/parse.h b/bcc/parse.h
new file mode 100644
index 0000000..ab67f6c
--- /dev/null
+++ b/bcc/parse.h
@@ -0,0 +1,19 @@
+/* parse.h - parser for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* possible scope levels */
+
+#define ARGLEVEL 1
+#define GLBLEVEL 0
+#define MAXLEVEL 125
+#define MINLOCLEVEL 1
+
+/* possible node flags */
+
+#define LVALUE (1 << 0)
+
+EXTERN struct nodestruct *etptr; /* ptr to next entry in expression tree */
+EXTERN struct symstruct *gvarsymptr; /* gsymptr for last identifier declared */
+EXTERN scopelev_t level; /* scope level */
+ /* depends on zero init */
diff --git a/bcc/preproc.c b/bcc/preproc.c
new file mode 100644
index 0000000..90f5a8c
--- /dev/null
+++ b/bcc/preproc.c
@@ -0,0 +1,944 @@
+/* preprocessor routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "output.h"
+#include "parse.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+#include "type.h"
+
+#define MAX_IF 32
+#define MAX__LINE__ 10 /* enough for 32-bit source unsigneds */
+#define MAX_MACRO 32
+#define MAX_PARAM 127 /* max char with no sign on all machines */
+
+/* Definition types. These are kept in the 'storage' member of struct
+ * symstruct and must be distinct from 'LOCAL' because dumplocs() doesn't
+ * check.
+ */
+enum
+{
+ DEF_LINE, /* __LINE__ keyword */
+ DEF_NONE /* nothing special */
+};
+
+struct ifstruct
+{
+ bool_t elseflag;
+ bool_t ifflag;
+};
+
+struct macroposition
+{
+ char *maclineptr;
+ char **paramlist;
+ char *paramspot;
+ bool_t inparam;
+ indn_t nparam;
+};
+
+PRIVATE char dummyparam[] = { EOL, 0 };
+PRIVATE fastin_t iflevel; /* depends on zero init */
+PRIVATE struct ifstruct ifstate;
+ /* elseflag depends on zero init */
+PRIVATE struct ifstruct ifstack[MAX_IF];
+
+PRIVATE struct macroposition macrostack[MAX_MACRO];
+
+FORWARD void asmcontrol P((void));
+FORWARD void control P((void));
+FORWARD void defineorundefinestring P((char *str, bool_pt defineflag));
+FORWARD void elsecontrol P((void));
+FORWARD void endif P((void));
+FORWARD fastin_pt getparnames P((void));
+FORWARD void ifcontrol P((sym_pt ifcase));
+FORWARD void undef P((void));
+
+/* asmcontrol() - process #asm */
+
+PRIVATE void asmcontrol()
+{
+ char treasure; /* to save at least one leading blank */
+
+ asmmode = TRUE;
+ if (orig_cppmode)
+ outstr("#asm\n");
+ else
+ dumplocs();
+ while (TRUE)
+ {
+ skipline();
+ skipeol();
+ if (eof)
+ {
+ eofin("#asm");
+ break;
+ }
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ specialchar();
+ treasure = 0;
+ if (SYMOFCHAR(ch) == WHITESPACE)
+ treasure = ch;
+ blanks();
+ if (ch == '#')
+ {
+ if (ctext)
+ {
+ register char *lptr;
+
+ comment();
+ if (treasure != 0)
+ outbyte(treasure);
+ lptr = lineptr;
+ while (*lptr++ != EOL) /* XXX - handle COEOL too */
+ outbyte(ch);
+ outnl();
+ }
+ gch1();
+ docontrol();
+ if (!asmmode)
+ break;
+ }
+ else
+ {
+ if (treasure != 0)
+ outbyte(treasure);
+ while (ch != EOL) /* XXX - handle COEOL too */
+ {
+ outbyte(ch);
+ gch1();
+ }
+ outnl();
+ }
+ }
+ if (orig_cppmode)
+ outstr("#endasm"); /* nl is done by skipeol */
+}
+
+/* blanksident() - return nonzero if at blanks followed by an identifier */
+
+PUBLIC bool_pt blanksident()
+{
+ blanks();
+ return isident();
+}
+
+PUBLIC void checknotinif()
+{
+ while (iflevel != 0)
+ {
+ if (ifstate.ifflag)
+ eofin("true #conditional");
+ else
+ eofin("false #conditional");
+ endif();
+ }
+}
+
+/* control() - select and switch to control statement */
+
+PRIVATE void control()
+{
+ char sname[NAMESIZE + 1];
+ sym_t ctlcase;
+ struct symstruct *symptr;
+
+ sname[0] = '#'; /* prepare for bad control */
+ sname[1] = 0;
+ while (blanksident())
+ {
+ if ((gsymptr = findlorg(gsname)) == NULL ||
+ gsymptr->flags != DEFINITION)
+ {
+ strcat(sname, gsname);
+ break;
+ }
+ entermac();
+ }
+ if (sname[1] == 0 && ch == EOL)
+ return;
+ if (SYMOFCHAR(ch) == INTCONST)
+ { linecontol(); return; }
+ if ((symptr = findlorg(sname)) == NULL)
+ {
+ if (ifstate.ifflag)
+ error(" bad control");
+ return;
+ }
+ ctlcase = symptr->offset.offsym;
+ if (ifstate.ifflag == FALSE &&
+ (ctlcase < ELSECNTL || ctlcase > IFNDEFCNTL))
+ return;
+ switch (ctlcase)
+ {
+ case ASMCNTL:
+ asmcontrol();
+ break;
+ case DEFINECNTL:
+ define();
+ break;
+ case ELSECNTL:
+ elsecontrol();
+ break;
+ case ENDASMCNTL:
+ asmmode = FALSE;
+ break;
+ case ENDIFCNTL:
+ endif();
+ break;
+ case IFCNTL:
+ case IFDEFCNTL:
+ case IFNDEFCNTL:
+ ifcontrol(symptr->offset.offsym);
+ break;
+ case INCLUDECNTL:
+ include();
+ break;
+ case LINECNTL:
+ { linecontol(); break; }
+ case UNDEFCNTL:
+ undef();
+ break;
+ }
+}
+
+/* define() - process #define */
+
+/*
+ MACRO storage.
+ A symbol recording the macro name is added to the symbol table.
+ This overrides all current scopes of the name (put at head of hash chain).
+ The flags are set to DEFINITION.
+ The indcount is 0 if no parameters, else 1 + number of parameters.
+ The offset field points to the macro string.
+ The macro string is null-terminated but EOL-sentineled.
+ It consists of EOL-terminated substrings followed by parameter numbers,
+ e.g., junk(x,y)=-x+y is stored as '-', EOL, 1, '+', EOL, 2, EOL, 0.
+ Here 1 is for the 1st parameter (start at 1 so 0 can terminate).
+ EOL acts as a sentinel for the scanner.
+ This choice works well because EOL cannot occur in a macro string.
+*/
+
+PUBLIC void define()
+{
+ char sname[NAMESIZE];
+ char quote;
+ struct symstruct **hashptr;
+ struct symstruct *locmark = NULL; /* for -Wall */
+ char *macstring;
+ fastin_t nparnames;
+ char *oldstring;
+ struct symstruct *symptr;
+
+ if (!blanksident())
+ {
+ error("illegal macro name");
+ return;
+ }
+ strcpy(sname, gsname); /* will overwrite gsname if parameters */
+ if (ch == '(')
+ {
+ locmark = locptr;
+ newlevel(); /* temp storage for parameter names */
+ nparnames = getparnames() + 1;
+ }
+ else
+ nparnames = 0;
+ blanks();
+ macstring = charptr;
+ quote = 0;
+ while (ch != EOL)
+ {
+ if (charptr >= char1top) /* check room for char and end of string */
+ macstring = growobject(macstring, 2);
+ if (nparnames && isident())
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->level == level)
+ {
+#ifdef TS
+++ts_n_macstring_param;
+ts_s_macstring += 2;
+#endif
+ *charptr++ = EOL; /* end current string */
+ *charptr++ = symptr->indcount; /* param to insert */
+ }
+ else
+ {
+ if (charptr + strlen(gsname) >= chartop) /* null too */
+ macstring = growobject(macstring, strlen(gsname) + 1);
+#ifdef TS
+++ts_n_macstring_ident;
+ts_s_macstring += strlen(gsname);;
+#endif
+ strcpy(charptr, gsname);
+ charptr += strlen(gsname); /* discard null */
+ }
+ continue;
+ }
+ if (ch == '\\')
+ {
+ gch1();
+ *charptr = '\\';
+ *(charptr + 1) = ch;
+#ifdef TS
+++ts_n_macstring_quoted;
+ts_s_macstring += 2;
+#endif
+ charptr += 2;
+ gch1();
+ continue;
+ }
+ if (quote)
+ {
+ if (ch == quote)
+ quote = 0;
+ }
+ else if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '/')
+ {
+ if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR)
+ {
+ gch1();
+ ch = *--lineptr = '/'; /* pushback */
+ }
+ if (*(lineptr + 1) == '*')
+ {
+ gch1();
+ skipcomment();
+ ch = *--lineptr = ' '; /* comment is space in modern cpp's */
+ }
+ }
+#ifdef TS
+++ts_n_macstring_ordinary;
+++ts_s_macstring;
+#endif
+ *charptr++ = ch;
+ gch1();
+ }
+ {
+ register char *rcp;
+
+ /* strip trailing blanks, but watch out for parameters */
+ for (rcp = charptr;
+ rcp > macstring && SYMOFCHAR(*(rcp - 1)) == WHITESPACE
+ && (--rcp == macstring || *(rcp - 1) != EOL); )
+ charptr = rcp;
+ }
+ if (charptr >= char1top)
+ macstring = growobject(macstring, 2);
+#ifdef TS
+++ts_n_macstring_term;
+ts_s_macstring += 2;
+#endif
+ *charptr++ = EOL;
+ *charptr++ = 0;
+ if (nparnames)
+ {
+ oldlevel();
+ locptr = locmark;
+ }
+ if (asmmode)
+ equ(sname, macstring);
+
+ if ((symptr = findlorg(sname)) != NULL && symptr->flags == DEFINITION)
+ {
+ if (strcmp(macstring, oldstring = symptr->offset.offp) != 0)
+ error("%wredefined macro");
+ if (strlen(macstring) > strlen(oldstring = symptr->offset.offp))
+ symptr->offset.offp = macstring;
+ else
+ {
+ strcpy(oldstring, macstring); /* copy if == to avoid test */
+ charptr = macstring;
+ }
+ return;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(sname));
+#ifdef TS
+++ts_n_defines;
+ts_s_defines += sizeof (struct symstruct) + strlen(sname);
+#endif
+ addsym(sname, vtype, symptr);
+ symptr->storage = DEF_NONE;
+ symptr->indcount = nparnames;
+ symptr->flags = DEFINITION;
+ symptr->level = GLBLEVEL;
+ symptr->offset.offp = macstring;
+ if (*(hashptr = gethashptr(sname)) != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+}
+
+PRIVATE void defineorundefinestring(str, defineflag)
+char *str; /* "name[=def]" or "name def" */
+bool_pt defineflag;
+{
+ char *fakeline;
+ unsigned len;
+ bool_t old_eof;
+
+ len = strlen(str);
+ strcpy(fakeline = (char *) ourmalloc(3 + len + 2 + 2) + 3, str);
+ /* 3 pushback, 2 + 2 guards */
+#ifdef TS
+ts_s_fakeline += 3 + len + 2 + 2;
+ts_s_fakeline_tot += 3 + len + 2 + 2;
+#endif
+ {
+ register char *endfakeline;
+
+ endfakeline = fakeline + len;
+ endfakeline[0] = EOL; /* guards any trailing backslash */
+ endfakeline[1] = EOL; /* line ends here or before */
+ }
+ old_eof = eof;
+ eof = TRUE; /* valid after first EOL */
+ ch = *(lineptr = fakeline);
+ if (defineflag)
+ {
+ if (blanksident()) /* if not, let define() produce error */
+ {
+ blanks();
+ if (ch == '=')
+ *lineptr = ' ';
+ else if (ch == EOL)
+ {
+ register char *lptr;
+
+ lptr = lineptr;
+ lptr[0] = ' ';
+ lptr[1] = '1'; /* 2 extra were allocated for this & EOL */
+ lptr[2] = EOL;
+ }
+ }
+ ch = *(lineptr = fakeline);
+ define();
+ }
+ else
+ undef();
+ eof = old_eof;
+#ifdef TS
+ts_s_fakeline_tot -= len + 2 + 2;
+#endif
+ ourfree(fakeline - 3);
+}
+
+PUBLIC void definestring(str)
+char *str; /* "name[=def]" or "name def" */
+{
+ defineorundefinestring(str, TRUE);
+}
+
+/* docontrol() - process control statement, loop till "#if" is true */
+
+PUBLIC void docontrol()
+{
+ while (TRUE)
+ {
+ control();
+ skipline();
+ if (ifstate.ifflag)
+ return;
+ while (TRUE)
+ {
+ skipeol();
+ if (eof)
+ return;
+ blanks();
+ if (ch == '#')
+ {
+ gch1();
+ break;
+ }
+ skipline();
+ }
+ }
+}
+
+/* elsecontrol() - process #else */
+
+PRIVATE void elsecontrol()
+{
+ if (iflevel == 0)
+ {
+ error("else without if");
+ return;
+ }
+ ifstate.ifflag = ifstate.elseflag;
+ ifstate.elseflag = FALSE;
+}
+
+/* endif() - process #endif */
+
+PRIVATE void endif()
+{
+ if (iflevel == 0)
+ {
+ error("endif without if");
+ return;
+ }
+ {
+ register struct ifstruct *ifptr;
+
+ ifptr = &ifstack[(int)--iflevel];
+ ifstate.elseflag = ifptr->elseflag;
+ ifstate.ifflag = ifptr->ifflag;
+ }
+}
+
+/* entermac() - switch line ptr to macro string */
+
+PUBLIC void entermac()
+{
+ char quote;
+ struct symstruct *symptr;
+ char **paramhead;
+ char **paramlist;
+ int ngoodparams;
+ int nparleft;
+ int lpcount;
+
+ if (maclevel >= MAX_MACRO)
+ {
+ limiterror("macros nested too deeply (33 levels)");
+ return;
+ }
+ symptr = gsymptr;
+ ngoodparams = 0;
+ paramhead = NULL;
+ if (symptr->indcount != 0)
+ {
+ nparleft = symptr->indcount - 1;
+ if (nparleft == 0)
+ paramhead = NULL;
+ else
+ paramhead = ourmalloc(sizeof *paramlist * nparleft);
+ paramlist = paramhead;
+#ifdef TS
+++ts_n_macparam;
+ts_s_macparam += sizeof *paramlist * nparleft;
+ts_s_macparam_tot += sizeof *paramlist * nparleft;
+#endif
+ blanks();
+ while (ch == EOL && !eof)
+ {
+ skipeol();
+ blanks();
+ }
+ if (ch != '(')
+ error("missing '('");
+ else
+ {
+ gch1();
+ while (nparleft)
+ {
+ --nparleft;
+ ++ngoodparams;
+ *(paramlist++) = charptr;
+ quote = 0;
+ lpcount = 1;
+ while (TRUE)
+ {
+ if (ch == '\\')
+ {
+ gch1();
+ if (charptr >= char1top)
+ *(paramlist - 1) = growobject(*(paramlist - 1), 2);
+#ifdef TS
+++ts_n_macparam_string_quoted;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = '\\';
+ }
+ else if (quote)
+ {
+ if (ch == quote)
+ quote = 0;
+ }
+ else if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '/')
+ {
+ if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR)
+ {
+ gch1();
+ ch = *--lineptr = '/'; /* pushback */
+ }
+ if (*(lineptr + 1) == '*')
+ {
+ gch1();
+ skipcomment();
+ ch = *--lineptr = ' '; /* pushback */
+ }
+ }
+ else if (ch == '(')
+ ++lpcount;
+ else if ((ch == ')' && --lpcount == 0) ||
+ (ch == ',' && lpcount == 1))
+ break;
+ if (ch == EOL)
+ ch = ' ';
+ if (charptr >= char1top)
+ *(paramlist - 1) = growobject(*(paramlist - 1), 2);
+#ifdef TS
+++ts_n_macparam_string_ordinary;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = ch;
+ if (*lineptr == EOL)
+ {
+ skipeol(); /* macro case disposed of already */
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ specialchar();
+ if (eof)
+ break;
+ }
+ else
+ gch1();
+ }
+#ifdef TS
+++ts_n_macparam_string_term;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = EOL;
+ {
+ register char *newparam;
+ register char *oldparam;
+ unsigned size;
+
+ oldparam = *(paramlist - 1);
+ size = (/* size_t */ unsigned) (charptr - oldparam);
+ newparam = ourmalloc(size);
+#ifdef TS
+ts_s_macparam_string_alloced += size;
+ts_s_macparam_string_alloced_tot += size;
+#endif
+ memcpy(newparam, oldparam, size);
+ *(paramlist - 1) = newparam;
+#ifdef TS
+ts_s_macparam_string_tot -= charptr - oldparam;
+#endif
+ charptr = oldparam;
+ }
+ if (ch == ',')
+ gch1();
+ else
+ break;
+ }
+ }
+ blanks();
+ while (ch == EOL && !eof)
+ {
+ skipeol();
+ blanks();
+ }
+ if (eof)
+ eofin("macro parameter expansion");
+ if (nparleft)
+ {
+ error("too few macro parameters");
+ do
+ *(paramlist++) = dummyparam;
+ while (--nparleft);
+ }
+ if (ch == ')')
+ gch1();
+ else if (ch == ',')
+ {
+ error("too many macro parameters");
+
+ /* XXX - should read and discard extra parameters. Also check
+ * for eof at end.
+ */
+ while (ch != ')')
+ {
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ break;
+ continue;
+ }
+ gch1();
+ }
+ }
+ else
+ error("missing ')'");
+ }
+
+ if (symptr->storage == DEF_LINE)
+ {
+ char *str;
+
+ str = pushudec(symptr->offset.offp + MAX__LINE__, input.linenumber);
+ memcpy(symptr->offset.offp, str, /* size_t */
+ (unsigned) (symptr->offset.offp + MAX__LINE__ + 1 + 1 - str));
+ }
+
+ {
+ register struct macroposition *mpptr;
+
+ mpptr = &macrostack[maclevel];
+ mpptr->paramlist = paramhead;
+ mpptr->maclineptr = lineptr;
+ ch = *(lineptr = symptr->offset.offp);
+ mpptr->inparam = FALSE;
+ mpptr->nparam = ngoodparams;
+ ++maclevel;
+ }
+/*
+ comment();
+ outstr("MACRO (level ");
+ outudec((unsigned) maclevel);
+ outstr(") ");
+ outline(lineptr);
+*/
+}
+
+/* getparnames() - get parameter names during macro definition, return count */
+
+PRIVATE fastin_pt getparnames()
+{
+ fastin_t nparnames;
+ struct symstruct *symptr;
+
+ nparnames = 0;
+ gch1();
+ while (blanksident())
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->level == level)
+ error("repeated parameter");
+ symptr = addloc(gsname, itype);
+ if (nparnames >= MAX_PARAM)
+ limiterror("too many macro parameters (128)");
+ else
+ ++nparnames; /* number params from 1 */
+ symptr->indcount = nparnames; /* param number */
+ blanks();
+ if (ch == ',')
+ gch1();
+ }
+ if (ch != ')')
+ error("missing ')'");
+ else
+ gch1();
+ return nparnames;
+}
+
+/* ifcontrol - process #if, #ifdef, #ifndef */
+
+PRIVATE void ifcontrol(ifcase)
+sym_pt ifcase;
+{
+ bool_t iftrue;
+ struct symstruct *symptr;
+
+ if (iflevel >= MAX_IF)
+ {
+ limiterror("#if's nested too deeply (33 levels)");
+ return;
+ }
+ {
+ register struct ifstruct *ifptr;
+
+ ifptr = &ifstack[(int)iflevel++];
+ ifptr->elseflag = ifstate.elseflag;
+ ifptr->ifflag = ifstate.ifflag;
+ ifstate.elseflag = FALSE; /* prepare for !(if now)||(if future)*/
+ }
+ if (ifstate.ifflag)
+ {
+ if ((sym_t) ifcase != IFCNTL)
+ {
+ iftrue = FALSE;
+ if (blanksident() && (symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ iftrue = TRUE;
+ }
+ else
+ {
+ incppexpr = TRUE;
+ nextsym();
+ iftrue = constexpression() != 0;
+ incppexpr = FALSE;
+ }
+ if ((!iftrue && (sym_t) ifcase != IFNDEFCNTL) ||
+ (iftrue && (sym_t) ifcase == IFNDEFCNTL))
+ {
+ ifstate.elseflag = TRUE;
+ ifstate.ifflag = FALSE;
+ }
+ }
+}
+
+/* ifinit() - initialise if state */
+
+PUBLIC void ifinit()
+{
+ ifstate.ifflag = TRUE;
+}
+
+/* leavemac() - leave current and further macro substrings till not at end */
+
+PUBLIC void leavemac()
+{
+ register struct macroposition *mpptr;
+
+ do
+ {
+ mpptr = &macrostack[maclevel - 1];
+ if (mpptr->inparam)
+ {
+ lineptr = ++mpptr->paramspot;
+ mpptr->inparam = FALSE;
+ }
+ else
+ {
+ ch = *++lineptr; /* gch1() would mess up next param == EOL-1 */
+ if (ch != 0)
+ {
+ mpptr->paramspot = lineptr;
+ lineptr = mpptr->paramlist[ch - 1];
+ mpptr->inparam = TRUE;
+ }
+ else
+ {
+ lineptr = mpptr->maclineptr;
+ if (mpptr->nparam != 0)
+ {
+ register char **paramlist;
+
+#ifdef TS
+ts_s_macparam_tot -= sizeof *paramlist * mpptr->nparam;
+#endif
+ paramlist = mpptr->paramlist;
+ do
+{
+#ifdef TS
+ts_s_macparam_string_alloced_tot -= strchr(*paramlist, EOL) - *paramlist + 1;
+#endif
+ ourfree(*paramlist++);
+}
+ while (--mpptr->nparam != 0);
+ ourfree(mpptr->paramlist);
+ }
+ --maclevel;
+ }
+ }
+ }
+ while ((ch = *lineptr) == EOL && maclevel != 0);
+}
+
+PUBLIC void predefine()
+{
+ definestring("__BCC__ 1");
+ definestring("__LINE__ 0123456789"); /* MAX__LINE__ digits */
+ findlorg("__LINE__")->storage = DEF_LINE;
+}
+
+PUBLIC char *savedlineptr()
+{
+ return macrostack[0].maclineptr;
+}
+
+PUBLIC void skipcomment()
+{
+/* Skip current char, then everything up to '*' '/' or eof. */
+
+ gch1();
+ do
+ {
+ while (TRUE)
+ {
+ {
+ register char *reglineptr;
+
+ reglineptr = lineptr;
+ symofchar['*'] = SPECIALCHAR;
+ while (SYMOFCHAR(*reglineptr) != SPECIALCHAR)
+ ++reglineptr;
+ symofchar['*'] = STAR;
+ lineptr = reglineptr;
+ if (*reglineptr == '*')
+ break;
+ ch = *reglineptr;
+ }
+ specialchar();
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ break;
+ }
+ else if (ch != '*')
+ gch1();
+ }
+ gch1();
+ if (eof)
+ {
+ eofin("comment");
+ return;
+ }
+ }
+ while (ch != '/');
+ gch1();
+}
+
+/* skipline() - skip rest of line */
+
+PUBLIC void skipline()
+{
+ while (TRUE)
+ {
+ blanks();
+ if (ch == EOL)
+ return;
+ if (ch == '\\')
+ {
+ gch1();
+ if (ch == EOL) /* XXX - I think blanks() eats \EOL */
+ return;
+ gch1(); /* XXX - escape() better? */
+ }
+ else if (ch == '"' || ch == '\'')
+ {
+ stringorcharconst();
+ charptr = constant.value.s;
+ }
+ else
+ gch1();
+ }
+}
+
+/* undef() - process #undef */
+
+PRIVATE void undef()
+{
+ struct symstruct *symptr;
+
+ if (blanksident() && (symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ delsym(symptr);
+}
+
+PUBLIC void undefinestring(str)
+char *str;
+{
+ defineorundefinestring(str, FALSE);
+}
diff --git a/bcc/preserve.c b/bcc/preserve.c
new file mode 100644
index 0000000..74b0f34
--- /dev/null
+++ b/bcc/preserve.c
@@ -0,0 +1,216 @@
+/* preserve.c - preserve opererands or registers in use for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "type.h"
+
+/* change stack ptr without changing condition codes */
+
+PUBLIC void changesp(newsp, absflag)
+offset_t newsp;
+bool_pt absflag;
+{
+ if (newsp != sp || ((bool_t) absflag && switchnow != NULL))
+ {
+#ifdef FRAMEPOINTER
+ if (newsp != framep || (!(bool_t) absflag && switchnow != NULL))
+ {
+ outleasp();
+ if (!(bool_t) absflag && switchnow != NULL)
+ outswoffset(newsp);
+ else
+ outoffset(newsp - framep);
+ outindframereg();
+ outnl();
+ }
+ else
+ regtransfer(FRAMEREG, STACKREG);
+ sp = newsp;
+ if (framep == 0)
+ bugerror("no frame pointer");
+#else
+# ifdef I8088
+ outleasp();
+ outoffset(newsp - sp);
+ outindstackreg();
+ outnl();
+# else
+ modstk(newsp); /* this should preserve CC */
+# endif
+#endif /* FRAMEPOINTER */
+ }
+}
+
+/* load source to any while preserving target */
+
+PUBLIC void loadpres(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+
+ if (target->storage & ALLDATREGS)
+ {
+ if (source->type->scalar & CHAR)
+ {
+ push(target);
+ load(source, DREG);
+ }
+ else
+ load(source, getindexreg());
+ }
+ else
+ {
+ regmark = reguse;
+ reguse |= target->storage;
+ loadany(source);
+ reguse = regmark;
+ }
+}
+
+/* change stack ptr */
+
+PUBLIC void modstk(newsp)
+offset_t newsp;
+{
+ if (newsp != sp)
+ {
+#ifdef FRAMEPOINTER
+ if (newsp != framep || framep == 0 || switchnow != NULL)
+ addconst(newsp - sp, STACKREG);
+ else
+ regtransfer(FRAMEREG, STACKREG);
+#else
+# ifdef I8088
+ addconst(newsp - sp, STACKREG);
+# else
+ outleasp();
+ outoffset(newsp - sp);
+ outncspregname();
+# endif
+#endif
+ sp = newsp;
+ }
+}
+
+/* preserve target without changing source */
+
+PUBLIC void pres2(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ if (target->storage & allregs)
+ {
+ if (target->storage & (allregs - allindregs) /* XXX */ ||
+ (target->indcount == 0 &&
+ target->type->scalar & (DLONG | RSCALAR)))
+ push(target); /* XXX - perhaps not float */
+ else if (((target->storage | reguse) & allindregs) == allindregs)
+ {
+ loadpres(target, source);
+ push(target);
+ }
+ else
+ reguse |= target->storage;
+ }
+}
+
+/* preserve source */
+
+PUBLIC void preserve(source)
+struct symstruct *source;
+{
+ if (source->storage & allregs)
+ {
+ if (source->storage & (allregs - allindregs) /* XXX */ ||
+ ((source->storage | reguse) & allindregs) == allindregs)
+ push(source);
+ else
+ reguse |= source->storage;
+ }
+}
+
+/* preserve lvalue target without changing source or target */
+
+PUBLIC store_pt preslval(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regpushed;
+
+ if (target->indcount == 0)
+ reguse &= ~target->storage;
+ else
+ reguse = (target->storage | reguse) & allindregs;
+ if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR))
+ || reguse != allindregs)
+ return 0; /* XXX - perhaps not float */
+ reguse = source->storage | target->storage; /* free one other than s/t */
+ pushreg(regpushed = getindexreg());
+ reguse = ~(store_t) regpushed & allindregs;
+ return regpushed;
+}
+
+PUBLIC void recovlist(reglist)
+store_pt reglist;
+{
+ poplist(reglist);
+ reguse |= (store_t) reglist;
+}
+
+#ifdef I8088
+PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5};
+ /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */
+ /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */
+#endif
+#ifdef MC6809
+PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2};
+ /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */
+#endif
+
+PUBLIC void savereturn(savelist, saveoffset)
+store_pt savelist;
+offset_t saveoffset;
+{
+ store_t reg;
+ smalin_t *regoffptr;
+ offset_t spoffset;
+
+ if (savelist == 0)
+ return;
+#ifdef MC6809 /* must check this */
+ if (savelist == XREG || savelist == INDREG1)
+ saveoffset -= accregsize; /* patch for DREG/YREG not saved */
+#endif
+ for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1)
+ if (reg & savelist)
+ {
+ outstore();
+ spoffset = saveoffset + *regoffptr * maxregsize;
+#ifdef I8088
+# ifdef FRAMEPOINTER
+ if (switchnow != NULL)
+ outswoffset(spoffset);
+ else
+ outoffset(spoffset - framep);
+ outindframereg();
+# else
+ outoffset(spoffset - sp);
+ outindstackreg();
+# endif
+ outncregname(reg);
+#endif
+#ifdef MC6809
+ if (reg == YREG)
+ bumplc();
+ outregname(reg);
+ outtab();
+ outoffset(spoffset - sp);
+ outncspregname();
+#endif
+ }
+}
diff --git a/bcc/proto.h b/bcc/proto.h
new file mode 100644
index 0000000..0c04044
--- /dev/null
+++ b/bcc/proto.h
@@ -0,0 +1,397 @@
+/* proto.h - extern functions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#include <malloc.h>
+
+/* assign.c */
+void assign P((struct symstruct *source, struct symstruct *target));
+void cast P((struct typestruct *type, struct symstruct *target));
+void extend P((struct symstruct *target));
+
+/* codefrag.c */
+void adjsp P((label_t label));
+void clrBreg P((void));
+void comment P((void));
+void ctoi P((void));
+void defbyte P((void));
+void deflong P((uoffset_t value));
+void defword P((void));
+void defdword P((void));
+void even P((void));
+void negDreg P((void));
+void comDreg P((void));
+void outadd P((void));
+void outaddsp P((void));
+void outcalladr P((void));
+void outcmp P((void));
+void outdec P((void));
+void outdword P((void));
+void outfail P((void));
+void outinc P((void));
+void outindleft P((void));
+void outindright P((void));
+void outindstackreg P((void));
+void outldaccum P((void));
+void outldmulreg P((void));
+void outlea P((void));
+void outleasp P((void));
+void outload P((void));
+void outmulmulreg P((void));
+void outopsep P((void));
+void outpshs P((void));
+void outpuls P((void));
+void outreturn P((void));
+void outstore P((void));
+void outsub P((void));
+void outtest P((void));
+void outword P((void));
+void sctoi P((void));
+void stoi P((void));
+void ustoi P((void));
+void outABX P((void));
+void outdirectpage P((void));
+void outextended P((void));
+void outncspregname P((void));
+void outindframereg P((void));
+void adc0 P((void));
+void addconst P((offset_t offset, store_pt reg));
+void adjlc P((offset_t offset, store_pt reg));
+void andconst P((offset_t offset));
+void bssseg P((void));
+label_t casejump P((void));
+void common P((char *name));
+void cseg P((void));
+void defnulls P((uoffset_t nullcount));
+label_t defstr P((char *sptr, char *stop, bool_pt dataflag));
+bool_pt diveasy P((value_t divisor, bool_pt uflag));
+void dpseg P((void));
+void dseg P((void));
+void equ P((char *name, char *string));
+void equlab P((label_t label, offset_t offset));
+void globl P((char *name));
+void import P((char *name));
+void itol P((store_pt reg));
+void lcommlab P((label_t label));
+void lcommon P((char *name));
+void lea P((offset_t offset, store_pt sourcereg, store_pt targreg));
+void loadconst P((offset_t offset, store_pt reg));
+int lslconst P((value_t shift, store_pt reg));
+int lsrconst P((value_t shift, store_pt reg, bool_pt uflag));
+bool_pt modeasy P((value_t divisor, bool_pt uflag));
+bool_pt muleasy P((uvalue_t factor, store_pt reg));
+void negreg P((store_pt reg));
+char *opstring P((op_pt op));
+void outccname P((char *name));
+void outhiaccum P((void));
+void outimmadr P((offset_t offset));
+void outimadj P((offset_t offset, store_pt targreg));
+void outimmed P((void));
+void outjumpstring P((void));
+void outnccname P((char *name));
+void outncimmadr P((offset_t offset));
+void outoffset P((offset_t offset));
+void public P((char *name));
+void private P((char *name));
+void regexchange P((store_pt sourcereg, store_pt targreg));
+void regtransfer P((store_pt sourcereg, store_pt targreg));
+void sbc0 P((void));
+void set P((char *name, offset_t value));
+void sl1 P((store_pt reg));
+void slconst P((value_t shift, store_pt reg));
+void srconst P((value_t shift, bool_pt uflag));
+void uitol P((store_pt reg));
+void restoreopreg P((void));
+void saveopreg P((void));
+
+/* debug.c */
+void dbitem P((struct symstruct *item));
+void dbtype P((struct typestruct *type));
+void debug P((struct nodestruct *exp));
+void debugswap P((void));
+
+/* declare.c */
+void colon P((void));
+void decllist P((void));
+void lparen P((void));
+void needvarname P((void));
+void program P((void));
+void rbrace P((void));
+void rbracket P((void));
+void rparen P((void));
+void semicolon P((void));
+struct typestruct *typename P((void));
+
+/* express.c */
+struct nodestruct *assignment_exp P((void));
+struct nodestruct *expression P((void));
+
+/* exptree.c */
+struct nodestruct *castnode P((struct typestruct *type,
+ struct nodestruct *nodeptr));
+void etreeinit P((void));
+struct nodestruct *leafnode P((struct symstruct *source));
+struct nodestruct *node P((op_pt t, struct nodestruct *p1,
+ struct nodestruct *p2));
+
+/* floatop.c */
+bool_pt f_indirect P((struct symstruct *target));
+void float1op P((op_pt op, struct symstruct *source));
+void floatop P((op_pt op, struct symstruct *source, struct symstruct *target));
+void fpush P((struct symstruct *source));
+void justpushed P((struct symstruct *target));
+
+/* function.c */
+void call P((char *name));
+void function P((struct symstruct *source));
+void ldregargs P((void));
+void loadretexpression P((void));
+void listo P((struct symstruct *target, offset_t lastargsp));
+void listroot P((struct symstruct *target));
+void popframe P((void));
+void reslocals P((void));
+void ret P((void));
+
+/* gencode.c */
+void bileaf P((struct nodestruct *exp));
+fastin_pt bitcount P((uvalue_t number));
+void codeinit P((void));
+fastin_pt highbit P((uvalue_t number));
+void makeleaf P((struct nodestruct *exp));
+
+/* genloads.c */
+void addoffset P((struct symstruct *source));
+void address P((struct symstruct *source));
+void exchange P((struct symstruct *source, struct symstruct *target));
+store_pt getindexreg P((void));
+void indexadr P((struct symstruct *source, struct symstruct *target));
+void indirec P((struct symstruct *source));
+void load P((struct symstruct *source, store_pt targreg));
+void loadany P((struct symstruct *source));
+void loadreg P((struct symstruct *source, store_pt targreg));
+void makelessindirect P((struct symstruct *source));
+void movereg P((struct symstruct *source, store_pt targreg));
+void onstack P((struct symstruct *target));
+void outadr P((struct symstruct *adr));
+void outcregname P((store_pt reg));
+void outncregname P((store_pt reg));
+void outnregname P((store_pt reg));
+void outregname P((store_pt reg));
+void outshortregname P((store_pt reg));
+void pointat P((struct symstruct *target));
+void poplist P((store_pt reglist));
+void push P((struct symstruct *source));
+void pushlist P((store_pt reglist));
+void pushreg P((store_pt reg));
+void storereg P((store_pt sourcereg, struct symstruct *target));
+void struc P((struct symstruct *source, struct symstruct *target));
+void transfer P((struct symstruct *source, store_pt targreg));
+
+/* glogcode.c */
+void cmp P((struct symstruct *source, struct symstruct *target,
+ ccode_t *pcondtrue));
+void condop P((struct nodestruct *exp));
+void jumpfalse P((struct nodestruct *exp, label_t label));
+void jumptrue P((struct nodestruct *exp, label_t label));
+void logop P((struct nodestruct *exp));
+
+/* hardop.c */
+void add P((struct symstruct *source, struct symstruct *target));
+void incdec P((op_pt op, struct symstruct *source));
+void neg P((struct symstruct *target));
+void not P((struct symstruct *target));
+void op1 P((op_pt op, struct symstruct *source, struct symstruct *target));
+void ptrsub P((struct symstruct *source, struct symstruct *target));
+void sub P((struct symstruct *source, struct symstruct *target));
+
+/* input.c */
+void closein P((void));
+void errorloc P((void));
+void gch1 P((void));
+void include P((void));
+void openio P((int argc, char **argv));
+void skipeol P((void));
+void specialchar P((void));
+
+/* label.c */
+void bumplc P((void));
+void bumplc2 P((void));
+void bumplc3 P((void));
+void clearfunclabels P((void));
+void clearlabels P((char *patchbuf, char *patchtop));
+void clearswitchlabels P((void));
+uoffset_t getlc P((void));
+void deflabel P((label_t label));
+label_t gethighlabel P((void));
+label_t getlabel P((void));
+void jump P((label_t label));
+void lbranch P((ccode_pt cond, label_t label));
+struct symstruct *namedlabel P((void));
+void outcond P((ccode_pt cond));
+void outlabel P((label_t label));
+void outnlabel P((label_t label));
+void sbranch P((ccode_pt cond, label_t label));
+void unbumplc P((void));
+
+/* loadexp.c */
+value_t constexpression P((void));
+void initexpression P((struct typestruct *type));
+struct typestruct *loadexpression P((store_pt targreg,
+ struct typestruct *targtype));
+
+/* longop.c */
+void longop P((op_pt op, struct symstruct *source, struct symstruct *target));
+void long1op P((op_pt op, struct symstruct *target));
+void outlongendian P((void));
+
+/* output.c */
+void bugerror P((char *message));
+void closeout P((void));
+void error P((char *message));
+void error2error P((char *message1, char *message2));
+void fatalerror P((char *message));
+void finishup P((void));
+void flushout P((void));
+void limiterror P((char *message));
+void initout P((void));
+void openout P((char *oname));
+void outbyte P((int ch));
+void outcomma P((void));
+void outcpplinenumber P((unsigned nr, char *fname, char *str));
+void outhex P((uoffset_t num));
+void outhexdigs P((uoffset_t num));
+void outline P((char *s));
+void outminus P((void));
+void outnl P((void));
+void outnbyte P((int byte));
+void outnhex P((uoffset_t num));
+void outnop1str P((char *s));
+void outnop2str P((char *s));
+void outnstr P((char *s));
+void outop0str P((char *s));
+void outop1str P((char *s));
+void outop2str P((char *s));
+void outop3str P((char *s));
+void outplus P((void));
+void outshex P((offset_t num));
+void outstr P((char *s));
+void outtab P((void));
+void outudec P((unsigned num));
+void outuvalue P((uvalue_t num));
+void outvalue P((value_t num));
+char *pushudec P((char *s, unsigned num));
+void setoutbufs P((void));
+
+/* preproc.c */
+void blanks P((void));
+bool_pt blanksident P((void));
+void checknotinif P((void));
+void define P((void));
+void definestring P((char *str));
+void docontrol P((void));
+void entermac P((void));
+void ifinit P((void));
+void leavemac P((void));
+void predefine P((void));
+char *savedlineptr P((void));
+void skipcomment P((void));
+void skipline P((void));
+void undefinestring P((char *str));
+
+/* preserve.c */
+void changesp P((offset_t newsp, bool_pt absflag));
+void loadpres P((struct symstruct *source, struct symstruct *target));
+void modstk P((offset_t newsp));
+void pres2 P((struct symstruct *source, struct symstruct *target));
+void preserve P((struct symstruct *source));
+store_pt preslval P((struct symstruct *source, struct symstruct *target));
+void recovlist P((store_pt reglist));
+void savereturn P((store_pt savelist, offset_t saveoffset));
+
+/* sc.c */
+int main P((int argc, char **argv));
+
+/* scan.c */
+void cppscan P((void));
+void eofin P((char *message));
+bool_pt isident P((void));
+void nextsym P((void));
+void stringorcharconst P((void));
+
+/* softop.c */
+void softop P((op_pt op, struct symstruct *source, struct symstruct *target));
+
+/* state.c */
+void compound P((void));
+void outswoffset P((offset_t offset));
+void outswstacklab P((void));
+
+/* table.c */
+struct symstruct *addglb P((char *name, struct typestruct *type));
+struct symstruct *addloc P((char *name, struct typestruct *type));
+struct symstruct *addlorg P((char *name, struct typestruct *type));
+void addsym P((char *name, struct typestruct *type,
+ struct symstruct *symptr));
+struct symstruct *constsym P((value_t intconst));
+void delsym P((struct symstruct *symptr));
+void dumpglbs P((void));
+void dumplocs P((void));
+void dumpstrings P((void));
+struct symstruct *exprsym P((struct symstruct *symptr));
+struct symstruct *findlorg P((char *name));
+struct symstruct *findstruct P((char *name));
+struct symstruct **gethashptr P((char *sname));
+void growheap P((unsigned size));
+void *growobject P((void *object, unsigned extra));
+label_t holdstr P((char *sptr, char *stop));
+void newlevel P((void));
+void oldlevel P((void));
+void ourfree P((void *ptr));
+void *ourmalloc P((unsigned nbytes));
+void outofmemoryerror P((char *message));
+void *qmalloc P((unsigned size));
+void swapsym P((struct symstruct *sym1, struct symstruct *sym2));
+void syminit P((void));
+
+/* type.c */
+struct typestruct *addstruct P((char *structname));
+struct typestruct *iscalartotype P((scalar_pt scalar));
+struct typestruct *newtype P((void));
+void outntypechar P((struct typestruct *type));
+struct typestruct *pointype P((struct typestruct *type));
+struct typestruct *prefix P((constr_pt constructor, uoffset_t size,
+ struct typestruct *type));
+struct typestruct *promote P((struct typestruct *type));
+struct typestruct *tounsigned P((struct typestruct *type));
+void typeinit P((void));
+
+/* library - fcntl.h */
+int creat P((const char *_path, int _mode));
+int open P((const char *_path, int _oflag, ...));
+
+/* library - stdlib.h */
+double atof P((const char *_str));
+void exit P((int _status));
+
+/* library - string.h */
+void *memcpy P((void *_t, const void *_s, unsigned _length));
+void *memset P((void *_s, int _c, unsigned _nbytes));
+char *strcat P((char *_target, const char *_source));
+char *strchr P((const char *_s, int _ch));
+int strcmp P((const char *_s1, const char *_s2));
+char *strcpy P((char *_target, const char *_source));
+unsigned strlen P((const char *_s));
+char *strncpy P((char *_target, const char *_source, unsigned _maxlength));
+char *strrchr P((const char *_s, int _ch));
+
+/* library - unistd.h */
+int close P((int _fd));
+int isatty P((int _fd));
+long lseek P((int _fd, long _offset, int _whence));
+int read P((int _fd, char *_buf, unsigned _nbytes));
+int write P((int _fd, char *_buf, unsigned _nbytes));
diff --git a/bcc/reg.h b/bcc/reg.h
new file mode 100644
index 0000000..822bda7
--- /dev/null
+++ b/bcc/reg.h
@@ -0,0 +1,139 @@
+/* reg.h - registers for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ The compiler generates "addresses" of the form
+ indirect(indcount) (rx + offset)
+ where
+ rx is a machine register (possibly null)
+ n is the indirection count (possibly 0)
+ offset is a constant.
+ It does not support more complicated formats like
+ indirect(indcount) (rx + index * scale + offset).
+
+ The register is coded as bit flag in the storage component of
+ the symbol structure. This allows groups of registers to be tested
+ using bitwise "&". Throughout the compiler, the group of these bit
+ flags has the type reg_t. If there are only a few registers, reg_t
+ can be an unsigned char. It must be unsigned if the high bit is
+ used, to avoid sign extension problems. For bootstrapping the compiler
+ from a compiler with no unsigned char, the unsigned type should be
+ used instead (with a signifigant waste of storage).
+
+ The bit flags should really be defined as ((reg_t) whatever) but
+ then they would not (necessarily) be constant expressions and couldn't
+ be used in switch selectors or (worse) preprocessor expressions.
+
+ The CONSTANT and GLOBAL (non-) register bits are almost
+ equivalent. A constant with nonzero indirection is marked as a
+ GLOBAL and not a CONSTANT. This makes it easier to test for a constant
+ CONSTANT. Globals which are formed in this way are converted to
+ constants if their indirection count is reset to 0 (by & operator).
+*/
+
+/* register bit flags */
+
+#define NOSTORAGE 0x000 /* structure/union member offsets */
+#define CONSTANT 0x001 /* offsets are values */
+#define BREG 0x002
+#define DREG 0x004
+#define INDREG0 0x008
+#define INDREG1 0x010
+#define INDREG2 0x020
+#define LOCAL 0x040
+#define GLOBAL 0x080 /* offsets from storage name or 0 */
+#define CCREG CONSTANT /* arg to PSHS/PULS functions only */
+#ifdef I8088
+# ifdef FRAMEPOINTER
+# define FRAMEREG LOCAL
+# endif
+# define STACKREG 0x100
+# define DATREG1 0x200
+# define DATREG2 0x400
+# define DATREG1B 0x800
+#endif
+#ifdef MC6809
+# define DPREG LOCAL /* arg to PSHS/PULS functions only */
+# define PCREG GLOBAL /* arg to PSHS/PULS functions only */
+#endif
+
+/* data for pushing and pulling registers */
+
+#define MINREGCHAR 'A'
+#ifdef I8088
+# define FLAGSREGCHAR 'f'
+# define pushchar() pushlist(AXREG)
+#endif
+#ifdef MC6809
+# define pushchar() pushlist(BREG)
+#endif
+
+/* special registers */
+
+#ifdef I8088
+# define ALREG BREG
+# define AXREG DREG
+# define DXREG DATREG2
+# define MULREG DATREG1B
+# define SHIFTREG DATREG1B
+#endif
+#ifdef MC6809
+# define XREG INDREG0 /* XREG is special for ABX in index & switch */
+# define YREG INDREG2 /* XREG and YREG allow LEA (Z test) in cmp() */
+#endif
+
+/* groups of registers */
+
+#define ALLDATREGS (BREG|DREG)
+#define CHARREGS BREG
+#define MAXREGS 1 /* number of data registers */
+#define WORKDATREGS (BREG|DREG)
+
+/* function call and return registers */
+
+#define ARGREG RETURNREG /* for (1st) argument */
+#define LONGARGREGS LONGRETURNREGS /* for long or float arg */
+#define LONGRETURNREGS (INDREG0|LONGREG2)
+#define LONGREG2 DREG
+#ifdef I8088
+# define LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+# define RETURNREG DREG
+#endif
+#ifdef MC6809
+# define RETURNREG INDREG0
+#endif
+
+/* registers which can be pulled as a group with the program counter */
+/* to perform an efficient function return */
+
+#ifdef MC6809
+#define JUNK1REGS BREG /* 1 bytes locals to discard */
+#define JUNK2REGS INDREG2
+#define JUNK3REGS (BREG|INDREG2)
+#define JUNK4REGS (INDREG1|INDREG2)
+#endif
+
+/* registers which can be pushed as a group with the first argument */
+/* to perform an efficient function startup */
+
+#ifdef MC6809
+# define LOC1REGS CCREG /* 1 bytes local to allocate */
+# define LOC2REGS DREG
+# define LOC3REGS (CCREG|DREG)
+# define LOC4REGS (CCREG|DREG|DPREG)
+# endif
+
+/* registers to be used by software operations */
+
+#define OPREG INDREG0 /* 2nd reg for software ops (1st is DREG) */
+#define OPWORKREG INDREG2 /* 3rd register for software ops */
+
+/* maximum indirection count for 1 instruction */
+
+#ifdef I8088
+# define MAXINDIRECT 1
+#endif
+#ifdef MC6809
+# define MAXINDIRECT 2
+#endif
diff --git a/bcc/sc.h b/bcc/sc.h
new file mode 100644
index 0000000..c17536a
--- /dev/null
+++ b/bcc/sc.h
@@ -0,0 +1,27 @@
+/* sc.h - storage classes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef MC6809
+#define DIRECTPAGE 0x01 /* modifier on global to show in dpseg */
+#endif
+#define EXTERNAL 0x02 /* external */
+#define STATIC 0x04
+
+/* symbols with flags above the 1st initialised value are not to be dumped */
+
+#define MAXDUMPFLAG 0x07
+#define INITIALIZED 0x08 /* modifier on global to show initialized */
+#define LABELLED 0x10 /* modifier on static to show labelled */
+ /* and on STRING to show labelled */
+
+/* remaining "flags" are numbers, not flags */
+/* they are disjoint from all combinations of flags above */
+/* except STRING => LABELLED (and no other flags) */
+
+#define DEFINITION 0x20 /* #defined name */
+#define KEYWORD 0x40 /* reserved word for C */
+#define STRUCTNAME 0x60 /* struct/union name or member name */
+#define REGVAR 0x80 /* register variable */
+#define TEMP 0xa0 /* temporary on stack expression eval */
+#define STRING 0xc0 /* string constant (=> LABELLED) */
diff --git a/bcc/scan.c b/bcc/scan.c
new file mode 100644
index 0000000..0baecf8
--- /dev/null
+++ b/bcc/scan.c
@@ -0,0 +1,806 @@
+/* scan.c - lexical analyser for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define GCH1() do { if (SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) specialchar(); } while (0)
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "output.h"
+#include "sc.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "scan.h"
+
+PUBLIC sym_t symofchar[256] =
+{
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR,
+ WHITESPACE, SPECIALCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ WHITESPACE, LOGNOTOP, STRINGCONST, CONTROL, /* !"# */
+ BADCHAR, MODOP, AMPERSAND, CHARCONST, /* $%&' */
+ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */
+ COMMA, HYPHEN, FLOATCONST, SLASH, /* ,-./ */
+
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */
+ INTCONST, INTCONST, COLON, SEMICOLON, /* 89:; */
+ LTOP, ASSIGNOP, GTOP, CONDOP, /* <=>? */
+
+ BADCHAR, IDENT, IDENT, IDENT, /* @ABC */
+ IDENT, IDENT, IDENT, IDENT, /* DEFG */
+ IDENT, IDENT, IDENT, IDENT, /* HIJK */
+ IDENT, IDENT, IDENT, IDENT, /* LMNO */
+ IDENT, IDENT, IDENT, IDENT, /* PQRS */
+ IDENT, IDENT, IDENT, IDENT, /* TUVW */
+ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */
+ SPECIALCHAR, RBRACKET, EOROP, IDENT, /* \]^_ */
+
+ BADCHAR, IDENT, IDENT, IDENT, /* `abc */
+ IDENT, IDENT, IDENT, IDENT, /* defg */
+ IDENT, IDENT, IDENT, IDENT, /* hijk */
+ IDENT, IDENT, IDENT, IDENT, /* lmno */
+ IDENT, IDENT, IDENT, IDENT, /* pqrs */
+ IDENT, IDENT, IDENT, IDENT, /* tuvw */
+ IDENT, IDENT, IDENT, LBRACE, /* xyz{ */
+ OROP, RBRACE, NOTOP, BADCHAR, /* |}~ */
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR
+};
+
+FORWARD void getident P((void));
+FORWARD void intconst P((void));
+FORWARD void ppnumber P((void));
+PRIVATE void newstringorcharconst P((void));
+
+/* skip white space up to end of line (skip EOL's if in comments) */
+
+PUBLIC void blanks()
+{
+ register char *reglineptr;
+
+ while (TRUE)
+ {
+ reglineptr = lineptr;
+ while (SYMOFCHAR(*reglineptr) == WHITESPACE)
+ ++reglineptr;
+ lineptr = reglineptr;
+ if (SYMOFCHAR(ch = *reglineptr) == SPECIALCHAR)
+ {
+ specialchar();
+ if (ch == EOL)
+ return;
+ if (SYMOFCHAR(ch) == WHITESPACE)
+ continue;
+ reglineptr = lineptr;
+ }
+ if (*reglineptr != '/')
+ return;
+ if (SYMOFCHAR(*(reglineptr + 1)) == SPECIALCHAR)
+ {
+ ch = *(lineptr = reglineptr + 1);
+ specialchar();
+ ch = *(reglineptr = --lineptr) = '/'; /* pushback */
+ }
+ if (*(reglineptr + 1) != '*')
+ return;
+ gch1();
+ skipcomment();
+ }
+}
+
+PUBLIC void cppscan()
+{
+ while (TRUE)
+ {
+ switch (SYMOFCHAR(ch))
+ {
+ case CHARCONST:
+ case STRINGCONST:
+ stringorcharconst();
+ *charptr = 0; /* room reserved */
+ outstr(constant.value.s); /* XXX - embedded null would kill it */
+ charptr = constant.value.s;
+ break;
+ case CONTROL:
+ gch1();
+ if (maclevel != 0)
+ {
+ error("# in a macro: not preprocessed"); /* XXX? */
+ break;
+ }
+ else
+ {
+ cppmode = FALSE;
+ docontrol();
+ cppmode = TRUE;
+ break;
+ }
+ case SLASH:
+ gch1();
+ if (ch == '*')
+ {
+ skipcomment();
+ break;
+ }
+ outbyte('/');
+ break;
+ case FLOATCONST:
+ gch1();
+ if (SYMOFCHAR(ch) == INTCONST)
+ {
+ --lineptr;
+ ch = '.'; /* pushback */
+ ppnumber();
+ outstr(constant.value.s);
+ charptr = constant.value.s;
+ }
+ else
+ outbyte('.');
+ break;
+ case IDENT:
+ getident();
+ if ((gsymptr = findlorg(gsname)) != NULL)
+ {
+ if (gsymptr->flags == DEFINITION)
+ {
+ entermac();
+ break;
+ }
+ }
+ outstr(gsname);
+ break;
+ case INTCONST:
+ ppnumber();
+ outstr(constant.value.s);
+ charptr = constant.value.s;
+ break;
+ case SPECIALCHAR:
+ specialchar(); /* XXX - this is necessary because entermac
+ * and skipeol can leave lineptr at a special
+ * char although GCH1 cannot. entermac would
+ * be easy to fix, but too many places already
+ * have to handle the extra work after skipeol
+ * for other reasons.
+ */
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ return;
+ break;
+ }
+#ifdef COEOL
+ if (ch == COEOL)
+ {
+ gch1();
+ break;
+ }
+#endif
+ if (SYMOFCHAR(ch) != SPECIALCHAR)
+ break; /* specialchar advanced the input */
+ /* must be '\\' */
+ default:
+ OUTBYTE(ch);
+ GCH1();
+ break;
+ }
+ }
+}
+
+PUBLIC void eofin(message)
+char *message;
+{
+ error2error("end of file in ", message);
+}
+
+/* get identifier in gsname == gs2name + 2 */
+
+PRIVATE void getident()
+{
+ register int c;
+ register char *idptr;
+ register int length;
+ register char *reglineptr;
+
+ idptr = gsname;
+ length = NAMESIZE;
+ reglineptr = lineptr;
+ c = ch;
+more:
+ do
+ {
+ *idptr++ = c;
+ c = (unsigned char) *++reglineptr;
+ }
+ while (symofchar[c] <= MAXIDSYM && --length != 0);
+ ch = c;
+ *idptr = 0;
+ lineptr = reglineptr;
+ if (symofchar[c] == SPECIALCHAR)
+ {
+ specialchar();
+ if (SYMOFCHAR(ch) <= MAXIDSYM && length != 0)
+ {
+ reglineptr = lineptr;
+ c = ch;
+ goto more;
+ }
+ }
+}
+
+/* return nonzero if at an identifier */
+
+PUBLIC bool_pt isident()
+{
+ if (SYMOFCHAR(ch) != IDENT)
+ return FALSE;
+ getident();
+ return TRUE;
+}
+
+PRIVATE void intconst()
+{
+ fastin_t base;
+ fastin_t digit;
+ register char *digptr;
+ fastin_t lcount;
+ fastin_t ucount;
+ bool_t dflag;
+
+ ppnumber();
+ digptr = charptr = constant.value.s;
+ if (*digptr == '0')
+ {
+ if (digptr[1] != 'x' && digptr[1] != 'X')
+ base = 8;
+ else
+ {
+ base = 16;
+ digptr += 2;
+ }
+ }
+ else
+ base = 10;
+ dflag = FALSE;
+ if (*digptr == 0)
+ error("constant has no digits");
+ if (base != 16)
+ {
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ if (*digptr == '.')
+ {
+ dflag = TRUE;
+ ++digptr;
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ }
+ if (*digptr == 'E' || *digptr == 'e')
+ {
+ dflag = TRUE;
+ ++digptr;
+ if (*digptr == '+' || *digptr == '-')
+ ++digptr;
+ if (SYMOFCHAR(*digptr) != INTCONST)
+ error("exponent has no digits");
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ }
+ }
+ if (dflag)
+ {
+ constant.type = dtype;
+ digit = *digptr;
+ *digptr = 0;
+ constant.value.d = atof(constant.value.s);
+ *digptr = digit;
+ if (digit == 'F' || digit == 'f')
+ {
+ ++digptr;
+ constant.type = fltype;
+ constant.value.d = (float) constant.value.d;
+ }
+ sym = FLOATCONST;
+ if (*digptr != 0)
+ error("junk at end of floating point constant");
+ return;
+ }
+ if (base != 16)
+ digptr = constant.value.s;
+ constant.value.v = 0;
+ while (*digptr >= '0')
+ {
+ digit = *digptr;
+ if (digit > '9')
+ {
+ if (base != 16)
+ break;
+ if (digit >= 'a' && digit <= 'f')
+ digit = digit + (-'a' + '0' + 10);
+ else if (digit >= 'A' && digit <= 'F')
+ digit = digit + (-'A' + '0' + 10);
+ else
+ break;
+ }
+ constant.value.v = base * constant.value.v + (digit - '0');
+ ++digptr;
+ }
+ ucount = lcount = 0;
+ while (TRUE)
+ {
+ if (*digptr == 'L' || *digptr == 'l')
+ ++lcount;
+ else if (*digptr == 'U' || *digptr == 'u')
+ ++ucount;
+ else
+ break;
+ ++digptr;
+ }
+ if (lcount > 1)
+ error("more than one 'L' in integer constant");
+ if (ucount > 1)
+ error("more than one 'U' in integer constant");
+ if (constant.value.v <= maxintto && lcount == 0 && ucount == 0)
+ constant.type = itype;
+ else if (constant.value.v <= maxuintto && lcount == 0
+ && (base != 10 || ucount != 0))
+ constant.type = uitype;
+ else if (constant.value.v <= maxlongto && ucount == 0)
+ constant.type = ltype;
+ else
+ constant.type = ultype;
+ if (*digptr != 0)
+ error("junk at end of integer constant");
+}
+
+PUBLIC void nextsym()
+{
+ static char lastch;
+ register char *reglineptr;
+
+ while (TRUE) /* exit with short, fast returns */
+ {
+ reglineptr = lineptr;
+ while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE)
+ ++reglineptr;
+ lastch = *reglineptr;
+ if (SYMOFCHAR(ch = *(lineptr = reglineptr + 1)) == SPECIALCHAR
+ && sym != SPECIALCHAR)
+ specialchar();
+ switch (sym)
+ {
+ case CHARCONST:
+ --lineptr;
+ ch = lastch; /* pushback */
+ stringorcharconst();
+ newstringorcharconst();
+ if (charptr == constant.value.s)
+ {
+ charptr = constant.value.s;
+ error("empty character constant");
+ constant.value.v = 0;
+ }
+ else
+ {
+ if (charptr != constant.value.s + 1)
+ error("character constant too long");
+ charptr = constant.value.s;
+ constant.value.v = *constant.value.s & CHMASKTO;
+ }
+ constant.type = itype;
+ return;
+ case CONTROL:
+ if (maclevel != 0)
+ {
+ error("# in a macro: not preprocessed"); /* XXX? */
+ return;
+ }
+ else
+ {
+ docontrol();
+ break;
+ }
+ case FLOATCONST:
+ if (SYMOFCHAR(ch) == INTCONST)
+ {
+ --lineptr;
+ ch = lastch;
+ intconst();
+ }
+ else
+ sym = STRUCELTOP;
+ return;
+ case IDENT:
+ --lineptr;
+ ch = lastch;
+ getident();
+ if ((gsymptr = findlorg(gsname)) != NULL)
+ {
+ if (gsymptr->flags == DEFINITION)
+ {
+ entermac();
+ break;
+ }
+ if (gsymptr->flags == KEYWORD)
+ sym = gsymptr->offset.offsym;
+ }
+ return;
+ case INTCONST:
+ --lineptr;
+ ch = lastch;
+ intconst();
+ return;
+ case SPECIALCHAR:
+ ch = *(lineptr = reglineptr);
+ specialchar();
+ if (ch == EOL)
+ {
+ if (incppexpr)
+ {
+ sym = SEMICOLON;
+ return;
+ }
+ skipeol();
+ if (eof)
+ {
+ sym = EOFSYM;
+ return;
+ }
+ break;
+ }
+ if (SYMOFCHAR(ch) != SPECIALCHAR)
+ break;
+ gch1();
+ /* fall through to BADCHAR case */
+ case BADCHAR:
+ error("illegal character");
+ break;
+ case STRINGCONST:
+ --lineptr;
+ ch = lastch; /* pushback */
+ stringorcharconst();
+ newstringorcharconst();
+#ifdef TS
+ ts_n_string += charptr - constant.value.s;
+#endif
+ return;
+ case COLON: /* could be COLONOP or in label */
+ case COMMA: /* could be COMMAOP or in list */
+ case CONDOP:
+ case LBRACE:
+ case LBRACKET:
+ case LPAREN:
+ case NOTOP:
+ case RBRACE:
+ case RBRACKET:
+ case RPAREN:
+ case SEMICOLON:
+ return;
+ case ASSIGNOP:
+ if (ch == '=')
+ {
+ sym = EQOP;
+ gch1();
+ }
+ return;
+ case ADDOP:
+ if (ch == '+')
+ {
+ sym = INCSYM; /* PREINCOP or POSINCOP */
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ADDABOP;
+ gch1();
+ }
+ return;
+ case HYPHEN: /* NEGOP or SUBOP or decoded below */
+ if (ch == '-')
+ {
+ sym = DECSYM; /* PREDECOP or POSTDECOP */
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = SUBABOP;
+ gch1();
+ }
+ else if (ch == '>')
+ {
+ sym = STRUCPTROP;
+ gch1();
+ }
+ return;
+ case STAR: /* INDIRECTOP or MULOP or as below */
+ if (ch == '=')
+ {
+ sym = MULABOP;
+ gch1();
+ }
+ return;
+ case SLASH:
+ if (ch == '*')
+ {
+ skipcomment();
+ break;
+ }
+ if (ch == '=')
+ {
+ sym = DIVABOP;
+ gch1();
+ }
+ else
+ sym = DIVOP;
+ return;
+ case MODOP:
+ if (ch == '=')
+ {
+ sym = MODABOP;
+ gch1();
+ }
+ return;
+ case LTOP:
+ if (ch == '=')
+ {
+ sym = LEOP;
+ gch1();
+ }
+ else if (ch == '<')
+ {
+ gch1();
+ if (ch == '=')
+ {
+ sym = SLABOP;
+ gch1();
+ }
+ else
+ {
+ sym = SLOP;
+ }
+ }
+ return;
+ case GTOP:
+ if (ch == '=')
+ {
+ sym = GEOP;
+ gch1();
+ }
+ else if (ch == '>')
+ {
+ gch1();
+ if (ch == '=')
+ {
+ sym = SRABOP;
+ gch1();
+ }
+ else
+ {
+ sym = SROP;
+ }
+ }
+ return;
+ case AMPERSAND: /* ADDRESSOP or ANDOP or as below */
+ if (ch == '&')
+ {
+ sym = LOGANDOP;
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ANDABOP;
+ gch1();
+ }
+ return;
+ case EOROP:
+ if (ch == '=')
+ {
+ sym = EORABOP;
+ gch1();
+ }
+ return;
+ case OROP:
+ if (ch == '|')
+ {
+ sym = LOGOROP;
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ORABOP;
+ gch1();
+ }
+ return;
+ case LOGNOTOP:
+ if (ch == '=')
+ {
+ sym = NEOP;
+ gch1();
+ }
+ return;
+ }
+ }
+}
+
+PRIVATE void ppnumber()
+{
+ constant.value.s = charptr;
+ while (TRUE)
+ {
+ if (charptr >= char1top)
+ constant.value.s = growobject(constant.value.s, 2);
+ *charptr++ = ch;
+ if (ch == 'E' || ch == 'e')
+ {
+ gch1();
+ if (ch == '+' || ch == '-')
+ continue;
+ }
+ else
+ GCH1();
+ if (SYMOFCHAR(ch) > MAXPPNUMSYM)
+ break;
+ }
+ *charptr = 0;
+}
+
+PUBLIC void stringorcharconst()
+{
+ char terminator;
+
+ constant.value.s = charptr;
+ terminator = ch;
+ while (TRUE)
+ {
+ if (charptr >= char3top)
+ constant.value.s = growobject(constant.value.s, 4);
+ *charptr++ = ch;
+ if (ch == '\\')
+ {
+ gch1();
+ if (ch == EOL)
+ {
+ if (!orig_cppmode)
+ eofin("escape sequence");
+ break;
+ }
+ *charptr++ = ch;
+ }
+ GCH1();
+ if (ch == EOL)
+ {
+ if (!orig_cppmode)
+ error(terminator == '"' ? "end of line in string constant"
+ : "end of line in character constant");
+ break;
+ }
+ if (ch == terminator)
+ {
+ *charptr++ = terminator;
+ gch1();
+ break;
+ }
+ }
+}
+
+PRIVATE void newstringorcharconst()
+{
+ char *endinptr;
+ int escvalue;
+ fastin_t maxdigits;
+ register char *inptr;
+ register char *outptr;
+
+ outptr = constant.value.s;
+ inptr = charptr - 1;
+ if (inptr == outptr || *inptr != *outptr)
+ endinptr = charptr; /* not properly terminated */
+ else
+ endinptr = inptr;
+ inptr = outptr + 1;
+ while (inptr != endinptr)
+ {
+ if (*inptr == '\\')
+ {
+ if (++inptr == endinptr)
+ break; /* error reported already */
+ if (*inptr >= '0' && *inptr < '8')
+ {
+ escvalue = 0;
+ maxdigits = 3;
+ do
+ {
+ escvalue = 8 * escvalue + *inptr - '0';
+ ++inptr;
+ }
+ while (--maxdigits != 0 && *inptr >= '0' && *inptr < '8');
+ --inptr;
+ *outptr++ = escvalue;
+ }
+ else switch (*inptr)
+ {
+ case '"':
+ case '\'':
+ case '\\':
+ *outptr++ = *inptr;
+ break;
+ case 'a':
+ *outptr++ = 7;
+ break;
+ case 'b':
+ *outptr++ = 8;
+ break;
+ case 'f':
+ *outptr++ = 12;
+ break;
+ case 'n':
+ *outptr++ = EOLTO;
+ break;
+ case 'r':
+ *outptr++ = 13;
+ break;
+ case 't':
+ *outptr++ = 9;
+ break;
+ case 'v':
+ *outptr++ = 11;
+ break;
+ default:
+ error("%wnonstandard escape sequence");
+ *outptr++ = *inptr;
+ break;
+ }
+ }
+ else
+ *outptr++ = *inptr;
+ ++inptr;
+ }
+ charptr = outptr;
+}
diff --git a/bcc/scan.h b/bcc/scan.h
new file mode 100644
index 0000000..5333e96
--- /dev/null
+++ b/bcc/scan.h
@@ -0,0 +1,201 @@
+/* scan.h - scanner for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define NAMESIZE 64 /* limit on identifier lengths */
+#define SYMOFCHAR(ch) (symofchar[(unsigned char) (ch)])
+
+/* scanner codes */
+
+enum
+{
+/* The first group of entries consists of all the values that occur in the
+ switch for cppscan().
+*/
+ IDENT,
+ INTCONST,
+#define MAXIDSYM INTCONST /* IDENT and INTCONST must be the only
+ * symofchar[] entries below this */
+ FLOATCONST,
+#define MAXPPNUMSYM FLOATCONST /* IDENT, INTCONST and FLOATCONST must be the
+ * only symofchar[] entries below this */
+ CHARCONST,
+ CONTROL,
+ SLASH,
+ SPECIALCHAR,
+ STRINGCONST,
+
+/* The next group of entries are all the rest of the values that occur in
+ symofchar[] and so in the switch for nextsym().
+*/
+ AMPERSAND, /* ADDRESSOP or ANDOP */
+ BADCHAR,
+ COLON, /* also COLONOP */
+ COMMA, /* also COMMAOP */
+ DECSYM, /* PREDECOP or POSTDECOP */
+ EOFSYM,
+ HYPHEN, /* NEGOP or SUBOP */
+ INCSYM, /* PREINCOP or POSTINCOP */
+ LBRACE,
+ LBRACKET,
+ LPAREN,
+ RBRACE,
+ RBRACKET,
+ RPAREN,
+ SEMICOLON,
+ STAR, /* INDIRECTOP or MULOP */
+ WHITESPACE,
+
+/* The next group of entries consists of all operator codes. These codes must
+ be contiguous so they can be used as (offsetted) array indexes. The group
+ is ordered by operator-precedence (this is not necessary). The first part
+ of it overlaps the previous group.
+*/
+
+/* Assign-abops (level 1) belong here but are at end to improve switch. */
+
+#define FIRSTOP CONDOP
+ CONDOP, /* level 2 */
+
+ OROP, /* level 5 */
+
+ EOROP, /* level 6 */
+
+ ANDOP, /* level 7 */
+
+ GTOP, /* level 9 */
+ LTOP,
+
+ ADDOP, /* level 11 */
+
+ DIVOP, /* level 12 */
+ MODOP,
+
+ LOGNOTOP, /* level 13 */
+ NOTOP,
+
+ STRUCELTOP, /* level 14 */
+ STRUCPTROP,
+
+/* End of symbols that appear in symofchar[]. */
+
+ ASSIGNOP, /* level 1 - assign ops must be contiguous */
+ ADDABOP,
+ ANDABOP,
+ DIVABOP,
+ EORABOP,
+ MODABOP,
+ MULABOP,
+ ORABOP,
+ SLABOP,
+ SRABOP,
+ SUBABOP,
+
+ COMMAOP, /* level 0 */
+
+ COLONOP, /* level 2 */
+
+ LOGOROP, /* level 3 */
+
+ LOGANDOP, /* level 4 */
+
+ EQOP, /* level 8 */
+ NEOP,
+
+ GEOP, /* level 9 */
+ LEOP,
+
+ SLOP, /* level 10 */
+ SROP,
+
+ SUBOP, /* level 11 */
+
+ MULOP, /* level 12 */
+
+ ADDRESSOP, /* level 13 */
+ CASTOP,
+ INDIRECTOP,
+ NEGOP,
+ PREDECOP,
+ PREINCOP,
+ POSTDECOP,
+ POSTINCOP,
+
+ FUNCOP, /* level 14 */
+ LISTOP,
+ ROOTLISTOP,
+
+ LEAF, /* special */
+ PTRADDABOP,
+ PTRADDOP,
+ PTRSUBOP,
+
+/* end of operator codes (they must stay contiguous) */
+
+#define LASTOP PTRSUBOP
+
+ ENUMDECL,
+ NULLDECL,
+ STRUCTDECL,
+ TYPEDECL,
+ TYPEDEFNAME,
+ UNIONDECL,
+ UNSIGNDECL,
+
+ AUTODECL,
+ EXTERNDECL,
+ REGDECL,
+ STATICDECL,
+ TYPEDEFDECL,
+
+ BREAKSYM,
+ CASESYM,
+ CONTSYM,
+ DEFAULTSYM,
+ DEFINEDSYM,
+ DOSYM,
+ ELSESYM,
+ FORSYM,
+ GOTOSYM,
+ IFSYM,
+ RETURNSYM,
+ SIZEOFSYM,
+ SWITCHSYM,
+ WHILESYM,
+
+ ASMCNTL,
+ DEFINECNTL,
+ ENDASMCNTL,
+ INCLUDECNTL,
+ LINECNTL,
+ UNDEFCNTL,
+
+ ELIFCNTL, /* "IF" controls must be contiguous */
+ ELSECNTL,
+ ENDIFCNTL,
+ IFCNTL,
+ IFDEFCNTL,
+ IFNDEFCNTL
+};
+
+EXTERN op_pt arg1op; /* LISTOP, or ROOTLISTOP if arg1inreg */
+EXTERN struct
+{
+ union
+ {
+ char *s;
+ value_t v;
+ double d;
+ }
+ value;
+ struct typestruct *type;
+}
+ constant; /* value of last constant scanned */
+ /* sym tells type */
+EXTERN char funcname[NAMESIZE]; /* name of current function for unique labels */
+EXTERN char gs2name[2 + NAMESIZE]; /* 2 reserved for namespace keys */
+#define gsname (gs2name + 2) /* before last identifier */
+EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */
+EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */
+EXTERN sym_t sym; /* current symbol */
+extern sym_t symofchar[]; /* table to convert chars to their symbols */
diff --git a/bcc/sizes.h b/bcc/sizes.h
new file mode 100644
index 0000000..df0d141
--- /dev/null
+++ b/bcc/sizes.h
@@ -0,0 +1,50 @@
+/* sizes.h - target scalar type sizes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ the compiler is not very portable in this area
+ it only directly supports I8088-I80386 and MC6809
+ it assumes
+ sizeof(source long) >= sizeof(target long)
+ usual register size = int
+ long = 2 int sizes
+*/
+
+#define CHBITSTO 8 /* bits in a character */
+#define CHMASKTO 0xFF /* mask to reduce SOURCE int to TARGET uchar */
+#define INT16BITSTO 16 /* not accessed in non-16 bit case */
+#define INT32BITSTO 32 /* not accessed in non-32 bit case */
+#define MAXINTBITSTO 32 /* max bits in an integer (var processors) */
+#define MAXSCHTO 127 /* maximum signed character */
+#define MAXUCHTO 255 /* maximum unsigned character */
+#define MINSCHTO (-128) /* minimum signed character */
+
+#ifdef MC6809
+# define is5bitoffset(n) ((uoffset_t) (n) + 0x10 < 0x20)
+#endif
+#define isbyteoffset(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO)
+#define ischarconst(n) ((uvalue_t) (n) <= MAXUCHTO)
+#define isnegbyteoffset(n) ((uvalue_t) (n) + MAXSCHTO <= MAXSCHTO - MINSCHTO)
+#define isshortbranch(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO)
+
+#ifdef MC6809
+/* Hack to reduce number of direct page variables. */
+#define intmaskto ((uvalue_t) 0xFFFFL)
+#define maxintto ((uvalue_t) 0x7FFFL)
+#define maxlongto ((uvalue_t) 0x7FFFFFFFL)
+#define maxoffsetto ((uvalue_t) 0x7FFFL)
+#define maxshortto ((uvalue_t) 0x7FFFL)
+#define maxuintto ((uvalue_t) 0xFFFFL)
+#define maxushortto ((uvalue_t) 0xFFFFL)
+#define shortmaskto ((uvalue_t) 0xFFFFL)
+#else
+extern uvalue_t intmaskto; /* mask for ints */
+extern uvalue_t maxintto; /* maximum int */
+extern uvalue_t maxlongto; /* maximum long */
+extern uvalue_t maxoffsetto; /* maximum offset */
+extern uvalue_t maxshortto; /* maximum short */
+extern uvalue_t maxuintto; /* maximum unsigned */
+extern uvalue_t maxushortto; /* maximum unsigned short */
+extern uvalue_t shortmaskto; /* mask for shorts */
+#endif
diff --git a/bcc/softop.c b/bcc/softop.c
new file mode 100644
index 0000000..369ad96
--- /dev/null
+++ b/bcc/softop.c
@@ -0,0 +1,225 @@
+/* softop.c - software operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ softop(operation code, source leaf, target leaf)
+ handles binary operations which are not done in hardware
+ if the result type is (unsigned) long, float or double, all the work
+ is immediately passed on to routines in other files. Otherwise:
+ source and target may be either char, int or unsigned int
+ they are not cast to ints or unsigneds before they get here
+ considerable effort goes into avoiding unnecessary pushes
+-----------------------------------------------------------------------------*/
+
+PUBLIC void softop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regpushed;
+ store_t regmark;
+ scalar_t resultscalar;
+ scalar_t sscalar;
+ scalar_t tscalar;
+ value_t sourceval;
+ bool_t uflag;
+ store_t workreg;
+
+ if ((tscalar = target->type->scalar) & DLONG)
+ {
+ longop(op, source, target);
+ return;
+ }
+ if (tscalar & RSCALAR)
+ {
+ floatop(op, source, target);
+ return;
+ }
+ sscalar = source->type->scalar;
+ resultscalar = tscalar;
+ uflag = tscalar & UNSIGNED;
+ if (op != SLOP && op != SROP)
+ {
+ resultscalar |= sscalar;
+ uflag |= sscalar & UNSIGNED;
+ }
+#ifdef MC6809
+ if ((op_t) op == MULOP && sscalar & CHAR && tscalar & CHAR &&
+ (source->storage != CONSTANT || (uvalue_t) source->offset.offv > 2))
+ {
+ if (source->storage & WORKDATREGS)
+ push(source);
+ load(target, DREG);
+ outldmulreg();
+ outadr(source);
+ outmulmulreg();
+ target->storage = DREG;
+ target->type = iscalartotype(resultscalar);
+ return;
+ }
+#endif
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+#ifdef I8088
+ if (op == MULOP || op == SLOP)
+ loadany(target);
+ else
+#endif
+ load(target, DREG);
+ target->type = iscalartotype(resultscalar);
+ sourceval = source->offset.offv;
+ switch ((op_t) op)
+ {
+ case DIVOP:
+ if (diveasy(sourceval, uflag))
+ return;
+ break;
+ case MODOP:
+ if (modeasy(sourceval, uflag))
+ {
+ if ((uvalue_t) sourceval <= MAXUCHTO + 1)
+ {
+ target->storage = BREG;
+ target->type = ctype;
+ if (uflag)
+ target->type = uctype;
+ }
+ return;
+ }
+ break;
+ case MULOP:
+ if (muleasy((uvalue_t) sourceval, target->storage))
+ return;
+ load(target, DREG);
+ break;
+ case SLOP:
+ slconst(sourceval, target->storage);
+ return;
+ case SROP:
+ srconst(sourceval, uflag);
+ return;
+ }
+ sscalar = (source->type = iscalartotype(resultscalar))->scalar;
+ }
+
+/* to load source first if it is CHAR: */
+/* need work register if target is in WORKDATREGS */
+/* use OPREG unless it will become overloaded later */
+
+/* to preserve source while target is loaded: */
+/* if source is in WORKDATREGS, put it in OPREG, */
+/* unless target is OPREG-indirect */
+/* otherwise, if source is in WORKDATREGS, put it in work reg not OPREG */
+/* also assign a work reg if source is already in OPREG and target needs one */
+
+ regpushed = (regmark = reguse) & OPREG;
+ workreg = OPREG;
+ if ((sscalar & CHAR && target->storage & WORKDATREGS &&
+ source->storage == OPREG && source->indcount != 0) ||
+ ((sscalar & CHAR || source->storage & WORKDATREGS) &&
+ target->storage == OPREG && target->indcount != 0) ||
+#ifdef MC6809 /* for -Wall */
+ (
+#endif
+ (source->storage == OPREG &&
+ target->storage == GLOBAL && target->indcount == 0)
+#ifdef MC6809
+ && posindependent)
+#endif
+ )
+ {
+ if ((regmark | OPREG) == allindregs)
+ regpushed |= (workreg = OPWORKREG);
+ else
+ {
+ reguse |= OPREG;
+ workreg = getindexreg();
+ }
+ }
+ pushlist(regpushed); /* no more pushes */
+ reguse = allindregs; /* error if another reg unexpectedly needed */
+
+ if (sscalar & CHAR)
+ {
+ if (target->storage & WORKDATREGS)
+ {
+ extend(target);
+ if (source->storage == workreg)
+ exchange(source, target);
+ else
+ transfer(target, workreg);
+ }
+ extend(source);
+ if (target->storage != OPREG &&
+ (target->storage != GLOBAL || target->indcount != 0
+#ifdef MC6809
+ || !posindependent
+#endif
+ ))
+ workreg = OPREG;
+ }
+ if (source->storage & WORKDATREGS)
+ {
+ if (target->storage == OPREG && target->indcount == 0)
+ exchange(source, target);
+ else
+ {
+ transfer(source, workreg);
+ workreg = OPREG;
+ }
+ }
+ if (target->storage == GLOBAL && target->indcount == 0
+#ifdef MC6809
+ && posindependent
+#endif
+ )
+ load(target, workreg);
+
+/* source and target now in position to be loaded without any more registers */
+
+ extend(target);
+ load(target, DREG);
+ load(source, OPREG);
+ switch ((op_t) op)
+ {
+ case DIVOP:
+#ifdef I8088
+ call("idiv_");
+#else
+ call("idiv");
+#endif
+ break;
+ case MODOP:
+ call("imod");
+ break;
+ case MULOP:
+#ifdef I8088
+ call("imul_");
+#else
+ call("imul");
+#endif
+ break;
+ case SLOP:
+ call("isl");
+ break;
+ case SROP:
+ call("isr");
+ break;
+ }
+ if (uflag)
+ outbyte('u');
+ outnl();
+ target->type = iscalartotype(resultscalar);
+ poplist(regpushed);
+ reguse = regmark;
+}
diff --git a/bcc/state.c b/bcc/state.c
new file mode 100644
index 0000000..cc821e3
--- /dev/null
+++ b/bcc/state.c
@@ -0,0 +1,793 @@
+/* state.c - statement routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "input.h" /* just for ch and eof for label check */
+#include "label.h"
+#include "os.h" /* just for EOL */
+#include "parse.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#define COLONCHAR ':' /* for label */
+#define GROWCASES 64 /* extra cases for growth of switch struct */
+#define INITIALCASES 16 /* initial cases in switch structure */
+
+struct loopstruct
+{
+ label_t breaklab; /* destination for break */
+ label_t contlab; /* destination for continue */
+ struct nodestruct *etmark; /* expression tree built during loop */
+ struct symstruct *exprmark; /* expression symbols built during loop */
+ struct symstruct *locmark; /* local variables built during loop */
+ struct loopstruct *prevloop; /* previous active for, switch or while */
+ offset_t spmark; /* stack value for continue and break */
+};
+
+struct switchstruct
+{
+ struct casestruct *caseptr; /* current spot in caselist */
+ struct casestruct *casetop; /* last in caselist + 1 */
+ bool_t charselector; /* tells if case selector is char */
+ label_t dfaultlab; /* destination for default case (0 if none) */
+ struct switchstruct *prevswitch; /* previous active switch */
+ struct casestruct
+ {
+ value_t casevalue; /* value giving this case */
+ label_t caselabel; /* corresponding label */
+ }
+ caselist[INITIALCASES]; /* perhaps larger */
+};
+
+PRIVATE struct loopstruct *loopnow; /* currently active for/switch/while */
+ /* depends on NULL init */
+PRIVATE bool_t returnflag; /* set if last effective statement */
+ /* was a return */
+PRIVATE label_t swstacklab; /* label giving stack for switch statement */
+
+FORWARD void addloop P((struct loopstruct *newloop));
+FORWARD void badloop P((void));
+FORWARD void deleteloop P((void));
+FORWARD void evalexpression P((struct nodestruct *exp));
+FORWARD void exprstatement P((void));
+FORWARD bool_pt isforever P((struct nodestruct *exp));
+FORWARD void sort P((struct casestruct *caselist, int count));
+FORWARD void dobreak P((void));
+FORWARD void docase P((void));
+FORWARD void docont P((void));
+FORWARD void dodefault P((void));
+FORWARD void dodowhile P((void));
+FORWARD void dofor P((void));
+FORWARD void dogoto P((void));
+FORWARD void doif P((void));
+FORWARD void doreturn P((void));
+FORWARD void doswitch P((void));
+FORWARD void dowhile P((void));
+FORWARD void jumptocases P((void));
+FORWARD void statement P((void));
+
+/* --- utility routines --- */
+
+PRIVATE void addloop(newloop)
+struct loopstruct *newloop;
+{
+ newloop->breaklab = getlabel();
+ newloop->contlab = getlabel();
+ newloop->etmark = etptr;
+ newloop->exprmark = exprptr;
+ newloop->locmark = locptr;
+ newloop->prevloop = loopnow;
+ newloop->spmark = sp;
+ loopnow = newloop;
+}
+
+PRIVATE void badloop()
+{
+ error(" no active fors, switches or whiles");
+}
+
+PRIVATE void deleteloop()
+{
+ etptr = loopnow->etmark;
+ exprptr = loopnow->exprmark;
+ locptr = loopnow->locmark;
+ loopnow = loopnow->prevloop;
+}
+
+PRIVATE void evalexpression(exp)
+struct nodestruct *exp;
+{
+ offset_t spmark;
+
+ spmark = sp;
+ makeleaf(exp);
+ modstk(spmark);
+}
+
+PRIVATE void exprstatement()
+{
+ struct nodestruct *etmark;
+ struct symstruct *exprmark;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ evalexpression(expression());
+ etptr = etmark;
+ exprptr = exprmark;
+}
+
+PRIVATE bool_pt isforever(exp)
+register struct nodestruct *exp;
+{
+ return exp == NULL ||
+ (exp->tag == LEAF && exp->left.symptr->storage == CONSTANT &&
+ exp->left.symptr->offset.offv != 0);
+}
+
+PRIVATE void sort(caselist, count) /* shell sort */
+struct casestruct *caselist;
+int count;
+{
+ register int gap;
+ register int i;
+ int j;
+ struct casestruct swaptemp;
+
+ gap = 1;
+ do
+ gap = 3 * gap + 1;
+ while (gap <= count);
+ while (gap != 1)
+ {
+ gap /= 3;
+ for (j = gap; j < count; ++j)
+ for (i = j - gap;
+ i >= 0 && caselist[i].casevalue > caselist[i + gap].casevalue;
+ i -= gap)
+ {
+ swaptemp = caselist[i];
+ caselist[i] = caselist[i + gap];
+ caselist[i + gap] = swaptemp;
+ }
+ }
+}
+
+/* --- syntax routines --- */
+
+/* ----------------------------------------------------------------------------
+ compound-statement:
+ "{" <declaration-list> <statement-list> "}"
+---------------------------------------------------------------------------- */
+
+PUBLIC void compound() /* have just seen "{" */
+{
+ struct symstruct *locmark;
+ store_t regmark;
+#ifdef FRAMEPOINTER
+ offset_t framepmark;
+ offset_t softspmark;
+#else
+ /* softsp == sp here unless level == ARGLEVEL so mark is unnec */
+ /* this is also true if funcsaveregsize != 0 but the tests are too messy */
+#endif
+ offset_t spmark;
+
+ locmark = locptr;
+ regmark = reguse;
+#ifdef FRAMEPOINTER
+ softspmark = softsp;
+ framepmark = framep;
+#endif
+ spmark = sp;
+ newlevel();
+ decllist();
+ softsp &= alignmask;
+ if (sym != RBRACE) /* no need for locals if empty compound */
+ reslocals();
+ returnflag = FALSE;
+ while (sym != RBRACE && sym != EOFSYM)
+ statement();
+ oldlevel();
+ if (!returnflag)
+ {
+ if (level != ARGLEVEL)
+ {
+ if (switchnow == NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (framep != 0)
+ {
+ /* some args or locals, maybe at lower levels */
+ modstk(softspmark);
+ if (framep != framepmark)
+ /* frame was just set up */
+ popframe();
+ }
+#else
+ modstk(spmark);
+#endif
+ }
+ }
+ else
+ ret();
+ }
+#ifdef FRAMEPOINTER
+ framep = framepmark;
+ sp = spmark;
+ softsp = softspmark;
+#else
+ softsp = sp = spmark;
+#endif
+ reguse = regmark;
+ locptr = locmark;
+ rbrace();
+}
+
+PRIVATE void dobreak()
+{
+ offset_t spmark;
+
+ if (loopnow == NULL)
+ badloop();
+ else
+ {
+ if (switchnow == NULL)
+ {
+ spmark = sp;
+ modstk(loopnow->spmark);
+ sp = spmark;
+ }
+ jump(loopnow->breaklab);
+ }
+}
+
+PRIVATE void docase()
+{
+ value_t caseval;
+
+ caseval = constexpression() & intmaskto; /* FIXME: warn overflow */
+ if (caseval > maxintto)
+ caseval -= (maxuintto + 1);
+ colon();
+ if (switchnow == NULL)
+ error("case not in switch");
+ else
+ {
+ if (switchnow->charselector && (caseval < 0 || caseval > 255))
+ error("%wcase cannot be reached with char switch");
+ else
+ {
+ if (switchnow->caseptr >= switchnow->casetop)
+ {
+ int ncases;
+
+ ncases = (/* ptrdiff_t */ int)
+ (switchnow->caseptr - &switchnow->caselist[0]);
+ switchnow = realloc(switchnow,
+ (/* size_t */ unsigned)
+ ((char *) switchnow->caseptr
+ - (char *) switchnow)
+ + GROWCASES * sizeof (struct casestruct));
+#ifdef TS
+++ts_n_case_realloc;
+ts_s_case += GROWCASES * sizeof (struct casestruct);
+ts_s_case_tot += GROWCASES * sizeof (struct casestruct);
+#endif
+ if (switchnow == NULL)
+ outofmemoryerror("");
+ switchnow->caseptr = &switchnow->caselist[ncases];
+ switchnow->casetop = switchnow->caseptr + GROWCASES;
+ }
+ switchnow->caseptr->casevalue = caseval;
+ deflabel(switchnow->caseptr->caselabel = getlabel());
+ ++switchnow->caseptr;
+ }
+ }
+}
+
+PRIVATE void docont()
+{
+ struct loopstruct *contloop;
+ offset_t spmark;
+ struct switchstruct *switchthen;
+
+ for (contloop = loopnow, switchthen = switchnow; ;
+ contloop = contloop->prevloop, switchthen = switchthen->prevswitch)
+ {
+ if (contloop == NULL)
+ {
+ badloop();
+ return;
+ }
+ if (contloop->contlab != 0)
+ break;
+ }
+ if (switchnow == NULL)
+ {
+ spmark = sp;
+ modstk(contloop->spmark);
+ sp = spmark;
+ }
+ else if (switchthen == NULL)
+ {
+ outaddsp();
+ outshex(contloop->spmark);
+ outminus();
+ outswstacklab();
+#ifdef MC6809
+ outcregname(LOCAL);
+#endif
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ outnl();
+ }
+ jump(contloop->contlab);
+}
+
+PRIVATE void dodefault()
+{
+ colon();
+ if (switchnow == NULL)
+ error("default not in switch");
+ else if (switchnow->dfaultlab != 0)
+ error("multiple defaults");
+ else
+ deflabel(switchnow->dfaultlab = getlabel());
+}
+
+PRIVATE void dodowhile()
+{
+ struct loopstruct dwhileloop;
+ label_t dolab;
+
+ addloop(&dwhileloop);
+ deflabel(dolab = getlabel());
+ statement();
+ if (sym == WHILESYM)
+ nextsym();
+ else
+ error("missing while at end of do-while");
+ deflabel(dwhileloop.contlab);
+ lparen();
+ jumptrue(expression(), dolab);
+ rparen();
+ semicolon();
+ deflabel(dwhileloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void dofor()
+{
+ struct loopstruct forloop;
+ label_t forstatlab;
+ label_t fortestlab = 0; /* for -Wall */
+ struct nodestruct *testexp;
+ struct nodestruct *loopexp;
+
+ lparen();
+ if (sym != SEMICOLON)
+ exprstatement();
+ semicolon();
+ addloop(&forloop);
+ if (sym == SEMICOLON)
+ testexp = NULL;
+ else
+ testexp = expression(); /* remember test expression */
+ semicolon();
+ if (sym == RPAREN)
+ loopexp = NULL;
+ else
+ loopexp = expression(); /* remember loop expression */
+ rparen();
+ if (!isforever(testexp))
+ jump(fortestlab = getlabel()); /* test at bottom */
+ deflabel(forstatlab = getlabel()); /* back here if test succeeds */
+ statement();
+ deflabel(forloop.contlab);
+ if (loopexp != NULL)
+ evalexpression(loopexp);
+ if (isforever(testexp))
+ jump(forstatlab);
+ else
+ {
+ deflabel(fortestlab); /* test label */
+ jumptrue(testexp, forstatlab);
+ }
+ deflabel(forloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void dogoto()
+{
+ struct symstruct *symptr;
+
+ if (sym == IDENT || sym == TYPEDEFNAME)
+ {
+ symptr = namedlabel();
+/*
+ if (symptr->indcount == 4)
+ modstk(
+ else
+*/
+ adjsp(symptr->offset.offlabel);
+ jump(symptr->offset.offlabel);
+ nextsym();
+ }
+ else
+ error("need identifier");
+}
+
+PRIVATE void doif()
+{
+ struct nodestruct *etmark;
+ label_t elselab;
+ label_t exitlab;
+ struct symstruct *exprmark;
+
+ lparen();
+ etmark = etptr;
+ exprmark = exprptr;
+ jumpfalse(expression(), elselab = getlabel());
+ etptr = etmark;
+ exprptr = exprmark;
+ rparen();
+ statement(); /* true, do a statement */
+ if (sym == ELSESYM) /* "if .. else" statement */
+ {
+ nextsym();
+ jump(exitlab = getlabel()); /* over "else" label and code */
+ deflabel(elselab);
+ statement();
+ deflabel(exitlab);
+ }
+ else
+ deflabel(elselab);
+}
+
+PRIVATE void doreturn()
+{
+ offset_t spmark;
+
+ spmark = sp;
+ if (sym != SEMICOLON) /* returning expression */
+ loadretexpression();
+ ret(); /* clean up stack and return */
+ sp = spmark; /* restore stack for rest of function */
+}
+
+PRIVATE void doswitch()
+{
+ struct switchstruct *sw;
+ struct loopstruct switchloop;
+ offset_t spmark = 0; /* for -Wall */
+ label_t sdecidelab;
+
+ sw = (struct switchstruct *) ourmalloc(sizeof *sw);
+#ifdef TS
+++ts_n_case;
+ts_s_case += sizeof *sw;
+ts_s_case_tot += sizeof *sw;
+#endif
+ lparen();
+ sw->charselector = loadexpression(DREG, NULLTYPE)->scalar & CHAR;
+ rparen();
+ if (switchnow == NULL)
+ spmark = lowsp = sp;
+ addloop(&switchloop);
+ sw->dfaultlab = switchloop.contlab = 0; /* kill to show this is a switch */
+ sw->casetop = (sw->caseptr = sw->caselist) + INITIALCASES;
+ sw->prevswitch = switchnow;
+ jump(sdecidelab = getlabel()); /* to case decision label */
+ if (switchnow == NULL)
+ swstacklab = gethighlabel();
+ switchnow = sw;
+ statement(); /* cases */
+ sw = switchnow;
+ jump(switchloop.breaklab); /* over case decision to break label */
+ deflabel(sdecidelab);
+ if (sw->prevswitch == NULL)
+ modstk(lowsp);
+ jumptocases();
+ deflabel(switchloop.breaklab);
+ if ((switchnow = sw->prevswitch) == NULL)
+ {
+ equlab(swstacklab, lowsp);
+ clearswitchlabels();
+ modstk(spmark);
+ }
+ deleteloop();
+#ifdef TS
+ts_s_case_tot -= (char *) sw->casetop - (char *) sw;
+#endif
+ ourfree(sw);
+}
+
+PRIVATE void dowhile()
+{
+ struct loopstruct whileloop;
+ struct nodestruct *testexp;
+ label_t wstatlab;
+
+ lparen();
+ addloop(&whileloop);
+ testexp = expression();
+ rparen();
+ if (!isforever(testexp))
+ jump(whileloop.contlab); /* test at bottom */
+ deflabel(wstatlab = getlabel()); /* back here if test succeeds */
+ statement();
+ deflabel(whileloop.contlab);
+ jumptrue(testexp, wstatlab);
+ deflabel(whileloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void jumptocases()
+{
+ value_t basevalue;
+ struct casestruct *case1ptr;
+ struct casestruct *caseptr;
+ struct casestruct *casetop;
+ value_t caseval;
+ bool_t charselector;
+ bool_t dfaultflag;
+ label_t dfaultlab;
+ label_t jtablelab;
+ ccode_t lowcondition;
+ store_pt targreg;
+ label_t zjtablelab;
+
+ caseptr = switchnow->caselist;
+ casetop = switchnow->caseptr;
+ sort(caseptr, (/* ptrdiff_t */ int) (casetop - caseptr));
+ basevalue = 0;
+ if ((charselector = switchnow->charselector) != 0)
+ {
+ targreg = BREG;
+ lowcondition = LO;
+ }
+ else
+ {
+ targreg = DREG;
+ lowcondition = LT;
+ }
+ dfaultflag = TRUE;
+ if ((dfaultlab = switchnow->dfaultlab) == 0)
+ {
+ dfaultflag = FALSE;
+ dfaultlab = loopnow->breaklab;
+ }
+ --casetop;
+ for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr)
+ if (case1ptr->casevalue == (case1ptr + 1)->casevalue)
+ error("duplicate case in switch");
+ while (caseptr <= casetop)
+ {
+ outsub();
+ outimadj((offset_t) (caseptr->casevalue - basevalue), targreg);
+ basevalue = caseptr->casevalue;
+ for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr)
+ if (case1ptr->casevalue < (case1ptr + 1)->casevalue - 10)
+ break;
+ if (case1ptr < caseptr + 5)
+ {
+ lbranch(EQ, caseptr->caselabel);
+ ++caseptr;
+ }
+ else
+ {
+ lbranch(lowcondition, dfaultlab);
+ outcmp();
+ outimadj((offset_t) (case1ptr->casevalue - basevalue), targreg);
+ lbranch(HI, zjtablelab = getlabel());
+ if (charselector)
+ ctoi();
+#ifdef MC6809
+ else
+ bumplc(); /* extra for CMPD */
+#endif
+ slconst((value_t) (ptypesize / 2), DREG);
+ /* really log ptypesize */
+ deflabel(jtablelab = casejump());
+#ifdef I8088
+ jtablelab = jtablelab; /* not used, allocated for regress */
+#endif
+ for (caseval = caseptr->casevalue; caseval <= case1ptr->casevalue;
+ ++caseval)
+ {
+#ifdef I8088
+ if (ptypesize > 2)
+ defdword();
+ else
+#endif
+ defword();
+ if (caseval != caseptr->casevalue)
+ outlabel(dfaultlab);
+ else
+ {
+ outlabel(caseptr->caselabel);
+ ++caseptr;
+ }
+#ifdef MC6809
+ if (posindependent)
+ {
+ outminus();
+ outlabel(jtablelab);
+ }
+#endif
+ bumplc2();
+#ifdef I8088
+ if (ptypesize > 2)
+ bumplc2();
+#endif
+ outnl();
+ }
+ deflabel(zjtablelab);
+ }
+ lowcondition = LO; /* 1st subtraction makes rest unsigned */
+ }
+ if (dfaultflag)
+ jump(dfaultlab);
+}
+
+PUBLIC void outswoffset (offset)
+offset_t offset;
+{
+#ifdef FRAMEPOINTER
+ outoffset(offset - softsp - framep);
+#else
+ outoffset(offset - softsp - sp);
+#endif
+ outplus();
+ outswstacklab();
+#ifdef I8088
+ bumplc();
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+PUBLIC void outswstacklab()
+{
+ outbyte(LOCALSTARTCHAR);
+ outlabel(swstacklab);
+}
+
+/* ----------------------------------------------------------------------------
+ statement:
+ <compound-statement>
+ <if-statement>
+ <while-statement>
+ <do-statement>
+ <for-statement>
+ <switch-statement>
+ <case-statement>
+ <default-statement>
+ <break-statement>
+ <continue-statement>
+ <return-statement>
+ <goto-statement>
+ <labelled-statement>
+ <null-statement>
+ <expression> ;
+---------------------------------------------------------------------------- */
+
+PRIVATE void statement()
+{
+#if 1
+ struct symstruct *symptr;
+#endif
+
+more:
+ switch (sym)
+ {
+ case LBRACE:
+ nextsym();
+ compound();
+ return;
+ case IFSYM:
+ nextsym();
+ doif();
+ break;
+ case WHILESYM:
+ nextsym();
+ dowhile();
+ break;
+ case FORSYM:
+ nextsym();
+ dofor();
+ break;
+ case RETURNSYM:
+ nextsym();
+ doreturn();
+ semicolon();
+ returnflag = TRUE;
+ return;
+ case SWITCHSYM:
+ nextsym();
+ doswitch();
+ break;
+ case BREAKSYM:
+ nextsym();
+ dobreak();
+ semicolon();
+ break;
+ case CASESYM:
+ nextsym();
+ docase();
+ goto more;
+ case DEFAULTSYM:
+ nextsym();
+ dodefault();
+ goto more;
+ case DOSYM:
+ nextsym();
+ dodowhile();
+ break;
+ case CONTSYM:
+ nextsym();
+ docont();
+ semicolon();
+ break;
+ case GOTOSYM:
+ nextsym();
+ dogoto();
+ semicolon();
+ break;
+ case SEMICOLON:
+ nextsym();
+ return;
+ case IDENT:
+ case TYPEDEFNAME:
+ blanks(); /* cannot afford nextsym() */
+ while (ch == EOL && !eof)
+ {
+ /* this now fails only on #controls and macros giving ':' */
+ skipeol();
+ blanks();
+ }
+ if (ch == COLONCHAR)
+ {
+#if 0
+ struct symstruct *symptr;
+#endif
+ symptr = namedlabel();
+ if (symptr->indcount != 2)
+ error("redefined label");
+ else
+ {
+ deflabel(symptr->offset.offlabel);
+ if (switchnow != NULL)
+ symptr->indcount = 3;
+ else
+ {
+ symptr->indcount = 4;
+ outbyte(LOCALSTARTCHAR);
+ outlabel(symptr->offset.offlabel);
+ outop0str("\t=\t");
+ outshex(sp);
+ outnl();
+ }
+ }
+ nextsym();
+ nextsym();
+ goto more;
+ }
+ /* else fall into default */
+ default:
+ exprstatement();
+ semicolon();
+ break;
+ }
+ returnflag = FALSE;
+}
diff --git a/bcc/table.c b/bcc/table.c
new file mode 100644
index 0000000..5a5c34e
--- /dev/null
+++ b/bcc/table.c
@@ -0,0 +1,668 @@
+/* table.c - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must
+ * usually be set to some level different from OFFKLUDGELEVEL.
+ */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h"
+#include "os.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "table.h"
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+#define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */
+#define MAXEXPR 500
+#define MAXLOCAL 100
+#define NKEYWORDS 34
+#define NSCALTYPES 12
+#define STACKSPACE 256 /* punt for normal recursions - switch extra */
+
+struct keywordstruct
+{
+ char *kwname;
+ sym_t kwcode;
+};
+
+#ifdef HOLDSTRINGS
+struct string
+{
+ struct string *snext;
+ char *sptr;
+ char *stop;
+ label_t slabel;
+};
+#endif
+
+struct typedatastruct
+{
+ char *tdname;
+ bool_t tdkeyscalar;
+ scalar_t tdscalar;
+ smalin_t tdsize;
+ struct typestruct **tdtypeptr;
+};
+
+PRIVATE struct symstruct exprsyms[MAXEXPR];
+PRIVATE struct symstruct *hashtab[HASHTABSIZE];
+ /* depends on zero init */
+#ifdef HOLDSTRINGS
+PRIVATE struct string *laststring; /* last in list of strings */
+ /* depends on NULL init */
+#endif
+PUBLIC struct symstruct locsyms[MAXLOCAL];
+
+PRIVATE struct symstruct constemplate =
+{
+ CONSTANT, /* storage */
+ 0, /* indcount */
+ 0, /* flags */
+ EXPRLEVEL, /* level */
+ NULL, /* next */
+ NULL, /* prev */
+ NULL, /* type, init later to itype */
+ /* offset is a union, set every time constemplate is used */
+ /* name is a union, namea member is constant "\0" */
+};
+
+PRIVATE struct keywordstruct keywords[NKEYWORDS] =
+{
+ { "enum", ENUMDECL, },
+ { "struct", STRUCTDECL, },
+ { "union", UNIONDECL, },
+ { "unsigned", UNSIGNDECL, },
+
+ { "auto", AUTODECL, },
+ { "extern", EXTERNDECL, },
+ { "register", REGDECL, },
+ { "static", STATICDECL, },
+
+ { "typedef", TYPEDEFDECL, },
+
+ { "break", BREAKSYM, },
+ { "case", CASESYM, },
+ { "continue", CONTSYM, },
+ { "default", DEFAULTSYM, },
+ { "do", DOSYM, },
+ { "else", ELSESYM, },
+ { "for", FORSYM, },
+ { "goto", GOTOSYM, },
+ { "if", IFSYM, },
+ { "return", RETURNSYM, },
+ { "sizeof", SIZEOFSYM, },
+ { "switch", SWITCHSYM, },
+ { "while", WHILESYM, },
+
+ { "#asm", ASMCNTL, },
+ { "#define", DEFINECNTL, },
+ { "#else", ELSECNTL, },
+ { "#endasm", ENDASMCNTL, },
+ { "#endif", ENDIFCNTL, },
+ { "#if", IFCNTL, },
+ { "#ifdef", IFDEFCNTL, },
+ { "#include", INCLUDECNTL, },
+ { "#ifndef", IFNDEFCNTL, },
+ { "#line", LINECNTL, },
+ { "#undef", UNDEFCNTL, },
+
+ { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */
+};
+
+PRIVATE struct typedatastruct scaltypes[NSCALTYPES] =
+{
+ { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */
+ { "char", TRUE, CHAR, 1, &ctype, },
+ { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, },
+ { "char", FALSE, CHAR, 1, &sctype, },
+ { "short", TRUE, SHORT, 2, &stype, },
+ { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, },
+ { "int", TRUE, INT, 2, &itype, },
+ { "int", FALSE, UNSIGNED | INT, 2, &uitype, },
+ { "long", TRUE, LONG | DLONG, 4, &ltype, },
+ { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, },
+ { "float", TRUE, FLOAT, 4, &fltype, },
+ { "double", TRUE, DOUBLE, 8, &dtype, },
+};
+
+FORWARD struct symstruct *addkeyword P((char *name, sym_pt code));
+FORWARD void heapcorrupterror P((void));
+
+PUBLIC struct symstruct *addglb(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr = NULL; /* for -Wall */
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(name));
+#ifdef TS
+++ts_n_global;
+ts_size_global += sizeof (struct symstruct) + strlen(name);
+#endif
+ addsym(name, type, symptr);
+ symptr->storage = GLOBAL;
+ symptr->level = GLBLEVEL;
+ if (*hashptr == NULL)
+ {
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ }
+ else
+ {
+ oldsymptr->next = symptr;
+ symptr->prev = &oldsymptr->next;
+ }
+ return symptr;
+}
+
+PRIVATE struct symstruct *addkeyword(name, code)
+char *name;
+sym_pt code;
+{
+ struct symstruct *symptr;
+
+ (symptr = addglb(name, vtype))->flags = KEYWORD;
+ symptr->offset.offsym = code;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addloc(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ symptr = symptr->next;
+ symptr = locptr;
+ locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]);
+ if (locptr >= &locsyms[MAXLOCAL])
+ limiterror("too many local symbols (101)");
+ addsym(name, type, symptr);
+ if (type->constructor == FUNCTION)
+ symptr->storage = GLOBAL;
+ else
+ symptr->storage = LOCAL;
+ symptr->level = level;
+ if (*hashptr != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addlorg(name, type)
+char *name;
+struct typestruct *type;
+{
+ if (level != GLBLEVEL)
+ return addloc(name, type);
+ return addglb(name, type);
+}
+
+PUBLIC void addsym(name, type, symptr)
+char *name;
+struct typestruct *type;
+register struct symstruct *symptr;
+{
+ if (type->constructor & (ARRAY | FUNCTION))
+ symptr->indcount = 0;
+ else
+ symptr->indcount = 1;
+ symptr->flags = 0;
+ symptr->next = NULL;
+ symptr->type = type;
+ symptr->offset.offi = 0;
+ strcpy(symptr->name.namea, name);
+}
+
+PUBLIC struct symstruct *constsym(longconst)
+value_t longconst;
+{
+ register struct symstruct *symptr;
+
+ symptr = exprsym(&constemplate);
+ symptr->offset.offv = longconst;
+ return symptr;
+}
+
+PUBLIC void delsym(symptr)
+register struct symstruct *symptr;
+{
+ if ((*(symptr->prev) = symptr->next) != NULL)
+ symptr->next->prev = symptr->prev;
+}
+
+/* dumpglbs() - define locations of globals and reserve space for them */
+
+PUBLIC void dumpglbs()
+{
+ int i;
+ register struct symstruct *symptr;
+ register struct typestruct *type;
+
+#ifdef TS
+extern char *brksize;
+struct ts
+{
+ char *what;
+ uvalue_t *where;
+};
+static struct ts ts[] =
+{
+ "ts_n_newtypelist ", &ts_n_newtypelist,
+ "ts_s_newtypelist ", &ts_s_newtypelist,
+ "ts_n_filename_term ", &ts_n_filename_term,
+ "ts_s_filename_term ", &ts_s_filename_term,
+ "ts_n_filename ", &ts_n_filename,
+ "ts_s_filename ", &ts_s_filename,
+ "ts_s_filename_tot ", &ts_s_filename_tot,
+ "ts_n_pathname ", &ts_n_pathname,
+ "ts_s_pathname ", &ts_s_pathname,
+ "ts_s_pathname_tot ", &ts_s_pathname_tot,
+ "ts_n_inputbuf ", &ts_n_inputbuf,
+ "ts_s_inputbuf ", &ts_s_inputbuf,
+ "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot,
+ "ts_n_includelist ", &ts_n_includelist,
+ "ts_s_includelist ", &ts_s_includelist,
+ "ts_s_outputbuf ", &ts_s_outputbuf,
+ "ts_n_macstring_ident ", &ts_n_macstring_ident,
+ "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary,
+ "ts_n_macstring_param ", &ts_n_macstring_param,
+ "ts_n_macstring_quoted ", &ts_n_macstring_quoted,
+ "ts_n_macstring_term ", &ts_n_macstring_term,
+ "ts_s_macstring ", &ts_s_macstring,
+ "ts_n_defines ", &ts_n_defines,
+ "ts_s_defines ", &ts_s_defines,
+ "ts_n_macparam ", &ts_n_macparam,
+ "ts_s_macparam ", &ts_s_macparam,
+ "ts_s_macparam_tot ", &ts_s_macparam_tot,
+ "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary,
+ "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted,
+ "ts_n_macparam_string_term ", &ts_n_macparam_string_term,
+ "ts_s_macparam_string ", &ts_s_macparam_string,
+ "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot,
+ "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced,
+ "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot,
+ "ts_s_fakeline ", &ts_s_fakeline,
+ "ts_s_fakeline_tot ", &ts_s_fakeline_tot,
+ "ts_n_string ", &ts_n_string,
+ "ts_n_case ", &ts_n_case,
+ "ts_n_case_realloc ", &ts_n_case_realloc,
+ "ts_s_case ", &ts_s_case,
+ "ts_s_case_tot ", &ts_s_case_tot,
+ "ts_n_structname ", &ts_n_structname,
+ "ts_s_structname ", &ts_s_structname,
+ "ts_n_type ", &ts_n_type,
+ "ts_s_type ", &ts_s_type,
+ "ts_n_global ", &ts_n_global,
+ "ts_size_global ", &ts_size_global,
+ "ts_n_holdstr ", &ts_n_holdstr,
+ "ts_size_holdstr ", &ts_size_holdstr,
+ "ts_n_growobj ", &ts_n_growobj,
+ "ts_size_growobj_wasted ", &ts_size_growobj_wasted,
+ "ts_n_growheap ", &ts_n_growheap,
+ "ts_s_growheap ", &ts_s_growheap,
+};
+struct ts *tp;
+
+for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp)
+{
+ comment();
+ outstr(tp->what);
+ outstr("");
+ outuvalue(*tp->where);
+ outnl();
+}
+comment();
+outstr("brksize ");
+outhex((uvalue_t) brksize);
+outnl();
+#endif
+
+#ifndef DIRECTPAGE
+ bssseg();
+#endif
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL)
+ && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG
+ /* Don't access type unless flags <= MAXDUMPFLAG, because
+ * type is punned to a symbol pointer for the label chain
+ * and might be null.
+ */
+ && symptr->type->constructor != FUNCTION)
+ {
+#ifdef DIRECTPAGE
+ if (symptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ type = symptr->type;
+ if (symptr->flags & STATIC)
+ lcommon(symptr->name.namea);
+ else
+ common(symptr->name.namea);
+ outnhex(type->typesize);
+ }
+ if (printf_fp)
+ globl("__xfpcvt");
+ if (scanf_fp)
+ globl("__xfptvc");
+}
+
+/* dumplocs() - define offsets of current locals */
+
+PUBLIC void dumplocs()
+{
+ register struct symstruct *symptr;
+ int i;
+
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == LOCAL)
+ set(symptr->name.namea, symptr->offset.offi - sp);
+}
+
+#ifdef HOLDSTRINGS
+
+/* dumpstrings() - dump held-up strings */
+
+PUBLIC void dumpstrings()
+{
+ struct string *stringp;
+
+ dseg();
+ for (stringp = laststring; stringp != NULL; stringp = stringp->snext)
+ {
+ outnlabel(stringp->slabel);
+ defstr(stringp->sptr, stringp->stop, TRUE);
+ dataoffset += stringp->stop - stringp->sptr + 1;
+ }
+}
+
+#endif
+
+PUBLIC struct symstruct *exprsym(symptr)
+struct symstruct *symptr;
+{
+ register struct symstruct *newsymptr;
+
+ newsymptr = exprptr++;
+ if (exprptr >= &exprsyms[MAXEXPR])
+ limiterror("expression too complex (501 symbols)");
+ *newsymptr = *symptr;
+ newsymptr->level = EXPRLEVEL;
+ newsymptr->name.namep = symptr->name.namea;
+ return newsymptr;
+}
+
+PUBLIC struct symstruct *findlorg(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 ||
+ symptr->flags == STRUCTNAME))
+ symptr = symptr->next;
+ return symptr;
+}
+
+PUBLIC struct symstruct *findstruct(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (symptr->flags != STRUCTNAME ||
+ strcmp(symptr->name.namea, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PUBLIC struct symstruct **gethashptr(sname)
+char *sname;
+{
+ register int hashval;
+ register char *rsname;
+
+ hashval = 0;
+ rsname = sname;
+#if 1
+ while (*rsname)
+ hashval = hashval * 2 + *rsname++;
+#else
+ hashval = rsname[0];
+ if (rsname[1] != 0)
+ hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1);
+ else
+ hashval = rsname[0];
+#endif
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+}
+
+PRIVATE void heapcorrupterror()
+{
+ outofmemoryerror(" (heap corrupt - stack overflow?)");
+}
+
+#ifdef HOLDSTRINGS
+
+/* hold string for dumping at end, to avoid mixing it with other data */
+
+PUBLIC label_t holdstr(sptr, stop)
+char *sptr;
+char *stop;
+{
+ register struct string *stringp;
+
+ stringp = qmalloc(sizeof *stringp);
+#ifdef TS
+++ts_n_holdstr;
+ts_size_holdstr += sizeof *stringp;
+#endif
+ stringp->snext = laststring;
+ stringp->sptr = sptr;
+ stringp->stop = stop;
+ laststring = stringp;
+ return stringp->slabel = getlabel();
+}
+
+#endif /* HOLDSTRINGS */
+
+PUBLIC void newlevel()
+{
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level >= MAXLEVEL)
+ limiterror("compound statements nested too deeply (126 levels)");
+ else
+ ++level;
+}
+
+PUBLIC void oldlevel()
+{
+ register struct symstruct *symptr;
+
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level == 0)
+ bugerror("not in a compound statement");
+ else
+ --level;
+ for (symptr = &locsyms[0]; symptr < locptr;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ if (symptr->level > level)
+ delsym(symptr);
+}
+
+PUBLIC void ourfree(ptr)
+void *ptr;
+{
+ free(ptr);
+}
+
+PUBLIC void *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ void *ptr;
+
+ if ((ptr = malloc(nbytes)) == NULL)
+ outofmemoryerror("");
+ return ptr;
+}
+
+PUBLIC void outofmemoryerror(message)
+char *message;
+{
+ error2error("compiler out of memory", message);
+
+#if defined(DEBUG) && 0
+ {
+ unsigned size;
+ char *ptr;
+
+ for (size = 0x1000; size != 0; --size)
+ if ((ptr = malloc(size)) != NULL)
+ {
+ outstr("found free memory at ");
+ outuvalue((uvalue_t) ptr);
+ outstr(" size ");
+ outuvalue((uvalue_t) size);
+ outnl();
+ }
+ }
+#endif
+
+ finishup();
+}
+
+PUBLIC void *growobject(object, extra)
+void *object;
+unsigned extra;
+{
+ /* size_t */ unsigned oblength;
+
+ /* It would be nice to realloc the previous memory if it can be left in
+ * the same place. Since a realloc that moves the memory can almost be
+ * relied on to mess up pointers before *obptr, and since malloc(extra)
+ * would be unlikely to produce memory adjoining chartop, it is not
+ * clear how to do this.
+ */
+#ifdef TS
+ts_size_growobj_wasted += chartop - (char *) object;
+#endif
+ oblength = (/* size_t */ unsigned) (charptr - (char *) object);
+ growheap(oblength + extra);
+#ifdef TS
+++ts_n_growobj;
+#endif
+ memcpy(charptr, object, oblength);
+ object = charptr;
+ charptr += oblength;
+ return object;
+}
+
+#define ALLOC_UNIT ((unsigned) 0x400)
+#ifdef S_ALIGNMENT
+#define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned))
+#else
+#define ALLOC_OVERHEAD (sizeof (unsigned))
+#endif
+
+PUBLIC void growheap(size)
+unsigned size;
+{
+ register char *newptr;
+
+ if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL
+ && (newptr = malloc(size -= ALLOC_UNIT)) == NULL)
+ outofmemoryerror("");
+#ifdef TS
+++ts_n_growheap;
+ts_s_growheap += size;
+#endif
+ charptr = newptr;
+ newptr = (char *) align(newptr + size - ALLOC_OVERHEAD);
+ chartop = newptr;
+ char1top = newptr - 1;
+ char3top = newptr - 3;
+ *(unsigned *) newptr = MARKER;
+}
+
+PUBLIC void *qmalloc(size)
+unsigned size;
+{
+ register char *ptr;
+
+ if ((charptr = (char *) align(charptr)) + size > chartop)
+ growheap(size);
+ ptr = charptr;
+ charptr += size;
+ return ptr;
+}
+
+PUBLIC void swapsym(sym1, sym2)
+struct symstruct *sym1;
+struct symstruct *sym2;
+{
+ struct symstruct swaptemp;
+
+ swaptemp = *sym1;
+ *sym1 = *sym2;
+ *sym2 = swaptemp;
+}
+
+PUBLIC void syminit()
+{
+ struct keywordstruct *kwptr;
+ struct typedatastruct *tdptr;
+ struct typestruct *type;
+
+ exprptr = exprsyms;
+ locptr = locsyms;
+ for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr)
+ {
+ (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar;
+ type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) |
+ alignmask;
+ type->tname = tdptr->tdname;
+ if (tdptr->tdkeyscalar)
+ addkeyword(tdptr->tdname, TYPEDECL)->type = type;
+ }
+ for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr)
+ addkeyword(kwptr->kwname, kwptr->kwcode);
+ constemplate.type = itype;
+}
diff --git a/bcc/table.h b/bcc/table.h
new file mode 100644
index 0000000..f9b2f38
--- /dev/null
+++ b/bcc/table.h
@@ -0,0 +1,71 @@
+/* table.h - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+EXTERN char *charptr; /* next free spot in catchall table */
+EXTERN char *chartop; /* spot after last in table */
+EXTERN char *char1top; /* last character spot in table */
+EXTERN char *char3top; /* third last character spot in table */
+EXTERN struct symstruct *exprptr;
+ /* next entry in expression symbol table */
+EXTERN struct symstruct *locptr;
+ /* next entry in local symbol table */
+extern struct symstruct locsyms[];
+ /* local symbol table */
+
+#define TS1
+#ifdef TS
+uvalue_t ts_n_newtypelist;
+uvalue_t ts_s_newtypelist;
+uvalue_t ts_n_filename_term;
+uvalue_t ts_s_filename_term;
+uvalue_t ts_n_filename;
+uvalue_t ts_s_filename;
+uvalue_t ts_s_filename_tot;
+uvalue_t ts_n_pathname;
+uvalue_t ts_s_pathname;
+uvalue_t ts_s_pathname_tot;
+uvalue_t ts_n_inputbuf;
+uvalue_t ts_s_inputbuf;
+uvalue_t ts_s_inputbuf_tot;
+uvalue_t ts_n_includelist;
+uvalue_t ts_s_includelist;
+uvalue_t ts_s_outputbuf;
+uvalue_t ts_n_macstring_ident;
+uvalue_t ts_n_macstring_ordinary;
+uvalue_t ts_n_macstring_param;
+uvalue_t ts_n_macstring_quoted;
+uvalue_t ts_n_macstring_term;
+uvalue_t ts_s_macstring;
+uvalue_t ts_n_defines;
+uvalue_t ts_s_defines;
+uvalue_t ts_n_macparam;
+uvalue_t ts_s_macparam;
+uvalue_t ts_s_macparam_tot;
+uvalue_t ts_n_macparam_string_ordinary;
+uvalue_t ts_n_macparam_string_quoted;
+uvalue_t ts_n_macparam_string_term;
+uvalue_t ts_s_macparam_string;
+uvalue_t ts_s_macparam_string_tot;
+uvalue_t ts_s_macparam_string_alloced;
+uvalue_t ts_s_macparam_string_alloced_tot;
+uvalue_t ts_s_fakeline;
+uvalue_t ts_s_fakeline_tot;
+uvalue_t ts_n_string;
+uvalue_t ts_n_case;
+uvalue_t ts_n_case_realloc;
+uvalue_t ts_s_case;
+uvalue_t ts_s_case_tot;
+uvalue_t ts_n_structname;
+uvalue_t ts_s_structname;
+uvalue_t ts_n_type;
+uvalue_t ts_s_type;
+uvalue_t ts_n_global;
+uvalue_t ts_size_global;
+uvalue_t ts_n_holdstr;
+uvalue_t ts_size_holdstr;
+uvalue_t ts_n_growobj;
+uvalue_t ts_size_growobj_wasted;
+uvalue_t ts_n_growheap;
+uvalue_t ts_s_growheap;
+#endif
diff --git a/bcc/tags b/bcc/tags
new file mode 100644
index 0000000..c0babfc
--- /dev/null
+++ b/bcc/tags
@@ -0,0 +1,341 @@
+adc0 codefrag.c /^PUBLIC void adc0()$/
+add hardop.c /^PUBLIC void add(source, target)$/
+addconst codefrag.c /^PUBLIC void addconst(offset, reg)$/
+addglb table.c /^PUBLIC struct symstruct *addglb(name, type)$/
+addloc table.c /^PUBLIC struct symstruct *addloc(name, type)$/
+addlorg table.c /^PUBLIC struct symstruct *addlorg(name, type)$/
+addoffset genloads.c /^PUBLIC void addoffset(source)$/
+address genloads.c /^PUBLIC void address(source)$/
+addstruct type.c /^PUBLIC struct typestruct *addstruct(structname)$/
+addsym table.c /^PUBLIC void addsym(name, type, symptr)$/
+adjlc codefrag.c /^PUBLIC void adjlc(offset, reg)$/
+adjsp codefrag.c /^PUBLIC void adjsp(label)$/
+andconst codefrag.c /^PUBLIC void andconst(offset)$/
+assign assign.c /^PUBLIC void assign(source, target)$/
+assignment_exp express.c /^PUBLIC struct nodestruct *assignment_exp()$/
+bileaf gencode.c /^PUBLIC void bileaf(exp)$/
+bitcount gencode.c /^PUBLIC fastin_pt bitcount(number)$/
+blanks scan.c /^PUBLIC void blanks()$/
+blanksident preproc.c /^PUBLIC bool_pt blanksident()$/
+bssseg codefrag.c /^PUBLIC void bssseg()$/
+bugerror output.c /^PUBLIC void bugerror(message)$/
+bumplc label.c /^PUBLIC void bumplc()$/
+bumplc2 label.c /^PUBLIC void bumplc2()$/
+bumplc3 label.c /^PUBLIC void bumplc3()$/
+call function.c /^PUBLIC void call(name)$/
+casejump codefrag.c /^PUBLIC label_t casejump()$/
+cast assign.c /^PUBLIC void cast(type, target)$/
+castnode exptree.c /^PUBLIC struct nodestruct *castnode(type, nodeptr)$/
+changesp preserve.c /^PUBLIC void changesp(newsp, absflag)$/
+checknotinif preproc.c /^PUBLIC void checknotinif()$/
+clearfunclabels label.c /^PUBLIC void clearfunclabels()$/
+clearlabels label.c /^PUBLIC void clearlabels(patchbuf, patchtop)$/
+clearswitchlabels label.c /^PUBLIC void clearswitchlabels()$/
+closein input.c /^PUBLIC void closein()$/
+closeout output.c /^PUBLIC void closeout()$/
+clrBreg codefrag.c /^PUBLIC void clrBreg()$/
+clrBreg codefrag.c /^PUBLIC void clrBreg()$/
+cmp glogcode.c /^PUBLIC void cmp(source, target, pcondtrue)$/
+codeinit gencode.c /^PUBLIC void codeinit()$/
+colon declare.c /^PUBLIC void colon()$/
+comDreg codefrag.c /^PUBLIC void comDreg()$/
+comDreg codefrag.c /^PUBLIC void comDreg()$/
+comment codefrag.c /^PUBLIC void comment()$/
+comment codefrag.c /^PUBLIC void comment()$/
+common codefrag.c /^PUBLIC void common(name)$/
+compound state.c /^PUBLIC void compound() /* have just seen "{" */$/
+condop glogcode.c /^PUBLIC void condop(exp)$/
+constexpression loadexp.c /^PUBLIC value_t constexpression()$/
+constsym table.c /^PUBLIC struct symstruct *constsym(longconst)$/
+cppscan scan.c /^PUBLIC void cppscan()$/
+cseg codefrag.c /^PUBLIC void cseg()$/
+ctoi codefrag.c /^PUBLIC void ctoi()$/
+ctoi codefrag.c /^PUBLIC void ctoi()$/
+dbitem debug.c /^PUBLIC void dbitem(item)$/
+dbtype debug.c /^PUBLIC void dbtype(type)$/
+debug debug.c /^PUBLIC void debug(exp) /* sub-nodes must be leaves */$/
+debugswap debug.c /^PUBLIC void debugswap()$/
+decllist declare.c /^PUBLIC void decllist()$/
+defbyte codefrag.c /^PUBLIC void defbyte()$/
+defbyte codefrag.c /^PUBLIC void defbyte()$/
+defdword codefrag.c /^PUBLIC void defdword()$/
+define preproc.c /^PUBLIC void define()$/
+definestring preproc.c /^PUBLIC void definestring(str)$/
+deflabel label.c /^PUBLIC void deflabel(label)$/
+deflong codefrag.c /^PUBLIC void deflong(value)$/
+defnulls codefrag.c /^PUBLIC void defnulls(nullcount)$/
+defstr codefrag.c /^PUBLIC label_t defstr(sptr, stop, dataflag)$/
+defword codefrag.c /^PUBLIC void defword()$/
+defword codefrag.c /^PUBLIC void defword()$/
+defword codefrag.c /^PUBLIC void defword()$/
+delsym table.c /^PUBLIC void delsym(symptr)$/
+diveasy codefrag.c /^PUBLIC bool_pt diveasy(divisor, uflag)$/
+docontrol preproc.c /^PUBLIC void docontrol()$/
+dpseg codefrag.c /^PUBLIC void dpseg()$/
+dseg codefrag.c /^PUBLIC void dseg()$/
+dumpglbs table.c /^PUBLIC void dumpglbs()$/
+dumplocs table.c /^PUBLIC void dumplocs()$/
+dumpstrings table.c /^PUBLIC void dumpstrings()$/
+entermac preproc.c /^PUBLIC void entermac()$/
+eofin scan.c /^PUBLIC void eofin(message)$/
+equ codefrag.c /^PUBLIC void equ(name, string)$/
+equlab codefrag.c /^PUBLIC void equlab(label, offset)$/
+error output.c /^PUBLIC void error(message)$/
+error2error output.c /^PUBLIC void error2error(message1, message2)$/
+errorloc input.c /^PUBLIC void errorloc()$/
+etreeinit exptree.c /^PUBLIC void etreeinit()$/
+even codefrag.c /^PUBLIC void even()$/
+exchange genloads.c /^PUBLIC void exchange(source, target)$/
+expression express.c /^PUBLIC struct nodestruct *expression()$/
+exprsym table.c /^PUBLIC struct symstruct *exprsym(symptr)$/
+extend assign.c /^PUBLIC void extend(target)$/
+f_indirect floatop.c /^PUBLIC bool_pt f_indirect(target)$/
+fatalerror output.c /^PUBLIC void fatalerror(message)$/
+findlorg table.c /^PUBLIC struct symstruct *findlorg(name)$/
+findstruct table.c /^PUBLIC struct symstruct *findstruct(name)$/
+finishup output.c /^PUBLIC void finishup()$/
+float1op floatop.c /^PUBLIC void float1op(op, source)$/
+floatop floatop.c /^PUBLIC void floatop(op, source, target)$/
+flushout output.c /^PUBLIC void flushout()$/
+for table.c /^ for (i = 0; i < HASHTABSIZE; ++i)$/
+for table.c /^for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp)$/
+fpush floatop.c /^PUBLIC void fpush(source)$/
+function function.c /^PUBLIC void function(source)$/
+gch1 input.c /^PUBLIC void gch1()$/
+gethashptr table.c /^PUBLIC struct symstruct **gethashptr(sname)$/
+gethighlabel label.c /^PUBLIC label_t gethighlabel()$/
+getindexreg genloads.c /^PUBLIC store_pt getindexreg()$/
+getlabel label.c /^PUBLIC label_t getlabel()$/
+getlc label.c /^PUBLIC uoffset_t getlc()$/
+globl codefrag.c /^PUBLIC void globl(name)$/
+growheap table.c /^PUBLIC void growheap(size)$/
+growobject table.c /^PUBLIC void *growobject(object, extra)$/
+highbit gencode.c /^PUBLIC fastin_pt highbit(number)$/
+holdstr table.c /^PUBLIC label_t holdstr(sptr, stop)$/
+ifinit preproc.c /^PUBLIC void ifinit()$/
+import codefrag.c /^PUBLIC void import(name)$/
+incdec hardop.c /^PUBLIC void incdec(op, source)$/
+include input.c /^PUBLIC void include()$/
+indexadr genloads.c /^PUBLIC void indexadr(source, target)$/
+indirec genloads.c /^PUBLIC void indirec(source)$/
+initexpression loadexp.c /^PUBLIC void initexpression(type)$/
+initout output.c /^PUBLIC void initout()$/
+iscalartotype type.c /^PUBLIC struct typestruct *iscalartotype(scalar)$/
+isident scan.c /^PUBLIC bool_pt isident()$/
+itol codefrag.c /^PUBLIC void itol(reg)$/
+jump label.c /^PUBLIC void jump(label)$/
+jumpfalse glogcode.c /^PUBLIC void jumpfalse(exp, label)$/
+jumptrue glogcode.c /^PUBLIC void jumptrue(exp, label)$/
+justpushed floatop.c /^PUBLIC void justpushed(target)$/
+lbranch label.c /^PUBLIC void lbranch(cond, label)$/
+lcommlab codefrag.c /^PUBLIC void lcommlab(label)$/
+lcommon codefrag.c /^PUBLIC void lcommon(name)$/
+ldregargs function.c /^PUBLIC void ldregargs()$/
+lea codefrag.c /^PUBLIC void lea(offset, sourcereg, targreg)$/
+leafnode exptree.c /^PUBLIC struct nodestruct *leafnode(source)$/
+leavemac preproc.c /^PUBLIC void leavemac()$/
+limiterror output.c /^PUBLIC void limiterror(message)$/
+listo function.c /^PUBLIC void listo(target, lastargsp)$/
+listroot function.c /^PUBLIC void listroot(target)$/
+load genloads.c /^PUBLIC void load(source, targreg)$/
+loadany genloads.c /^PUBLIC void loadany(source)$/
+loadconst codefrag.c /^PUBLIC void loadconst(offset, reg)$/
+loadexpression loadexp.c /^PUBLIC struct typestruct *loadexpression(targreg, targtype)$/
+loadpres preserve.c /^PUBLIC void loadpres(source, target)$/
+loadreg genloads.c /^PUBLIC void loadreg(source, targreg)$/
+loadretexpression function.c /^PUBLIC void loadretexpression()$/
+logop glogcode.c /^PUBLIC void logop(exp)$/
+long1op longop.c /^PUBLIC void long1op(op, target)$/
+longop longop.c /^PUBLIC void longop(op, source, target)$/
+lparen declare.c /^PUBLIC void lparen()$/
+lslconst codefrag.c /^PUBLIC int lslconst(shift, reg)$/
+lsrconst codefrag.c /^PUBLIC int lsrconst(shift, reg, uflag)$/
+main bcc-cc1.c /^PUBLIC int main(argc, argv)$/
+main bcc.c /^PUBLIC int main(argc, argv)$/
+makeleaf gencode.c /^PUBLIC void makeleaf(exp)$/
+makelessindirect genloads.c /^PUBLIC void makelessindirect(source)$/
+modeasy codefrag.c /^PUBLIC bool_pt modeasy(divisor, uflag)$/
+modstk preserve.c /^PUBLIC void modstk(newsp)$/
+movereg genloads.c /^PUBLIC void movereg(source, targreg)$/
+muleasy codefrag.c /^PUBLIC bool_pt muleasy(factor, reg)$/
+namedlabel label.c /^PUBLIC struct symstruct *namedlabel()$/
+needvarname declare.c /^PUBLIC void needvarname()$/
+neg hardop.c /^PUBLIC void neg(target)$/
+negDreg codefrag.c /^PUBLIC void negDreg()$/
+negDreg codefrag.c /^PUBLIC void negDreg()$/
+negreg codefrag.c /^PUBLIC void negreg(reg)$/
+newlevel table.c /^PUBLIC void newlevel()$/
+newtype type.c /^PUBLIC struct typestruct *newtype()$/
+nextsym scan.c /^PUBLIC void nextsym()$/
+node exptree.c /^PUBLIC struct nodestruct *node(t, p1, p2)$/
+not hardop.c /^PUBLIC void not(target)$/
+oldlevel table.c /^PUBLIC void oldlevel()$/
+onstack genloads.c /^PUBLIC void onstack(target)$/
+op1 hardop.c /^PUBLIC void op1(op, source, target)$/
+openio input.c /^PUBLIC void openio(argc, argv)$/
+openout output.c /^PUBLIC void openout(oname)$/
+opstring codefrag.c /^PUBLIC char *opstring(op)$/
+ourfree table.c /^PUBLIC void ourfree(ptr)$/
+ourmalloc table.c /^PUBLIC void *ourmalloc(nbytes)$/
+outABX codefrag.c /^PUBLIC void outABX()$/
+outadd codefrag.c /^PUBLIC void outadd()$/
+outadd codefrag.c /^PUBLIC void outadd()$/
+outaddsp codefrag.c /^PUBLIC void outaddsp()$/
+outaddsp codefrag.c /^PUBLIC void outaddsp()$/
+outadr genloads.c /^PUBLIC void outadr(adr)$/
+outbyte output.c /^PUBLIC void outbyte(c)$/
+outcalladr codefrag.c /^PUBLIC void outcalladr()$/
+outcalladr codefrag.c /^PUBLIC void outcalladr()$/
+outcalladr codefrag.c /^PUBLIC void outcalladr()$/
+outccname codefrag.c /^PUBLIC void outccname(name)$/
+outcmp codefrag.c /^PUBLIC void outcmp()$/
+outcmp codefrag.c /^PUBLIC void outcmp()$/
+outcomma output.c /^PUBLIC void outcomma()$/
+outcond label.c /^PUBLIC void outcond(cond)$/
+outcpplinenumber output.c /^PUBLIC void outcpplinenumber(nr, fname, str)$/
+outcregname genloads.c /^PUBLIC void outcregname(reg)$/
+outdec codefrag.c /^PUBLIC void outdec()$/
+outdec codefrag.c /^PUBLIC void outdec()$/
+outdirectpage codefrag.c /^PUBLIC void outdirectpage()$/
+outdword codefrag.c /^PUBLIC void outdword()$/
+outextended codefrag.c /^PUBLIC void outextended()$/
+outfail codefrag.c /^PUBLIC void outfail()$/
+outfail codefrag.c /^PUBLIC void outfail()$/
+outhex output.c /^PUBLIC void outhex(num)$/
+outhexdigs output.c /^PUBLIC void outhexdigs(num)$/
+outhiaccum codefrag.c /^PUBLIC void outhiaccum()$/
+outimadj codefrag.c /^PUBLIC void outimadj(offset, targreg)$/
+outimmadr codefrag.c /^PUBLIC void outimmadr(offset)$/
+outimmed codefrag.c /^PUBLIC void outimmed()$/
+outinc codefrag.c /^PUBLIC void outinc()$/
+outinc codefrag.c /^PUBLIC void outinc()$/
+outindframereg codefrag.c /^PUBLIC void outindframereg()$/
+outindleft codefrag.c /^PUBLIC void outindleft()$/
+outindleft codefrag.c /^PUBLIC void outindleft()$/
+outindleft codefrag.c /^PUBLIC void outindleft()$/
+outindright codefrag.c /^PUBLIC void outindright()$/
+outindright codefrag.c /^PUBLIC void outindright()$/
+outindright codefrag.c /^PUBLIC void outindright()$/
+outindstackreg codefrag.c /^PUBLIC void outindstackreg()$/
+outjumpstring codefrag.c /^PUBLIC void outjumpstring()$/
+outlabel label.c /^PUBLIC void outlabel(label)$/
+outldaccum codefrag.c /^PUBLIC void outldaccum()$/
+outldaccum codefrag.c /^PUBLIC void outldaccum()$/
+outldmulreg codefrag.c /^PUBLIC void outldmulreg()$/
+outldmulreg codefrag.c /^PUBLIC void outldmulreg()$/
+outlea codefrag.c /^PUBLIC void outlea()$/
+outlea codefrag.c /^PUBLIC void outlea()$/
+outleasp codefrag.c /^PUBLIC void outleasp()$/
+outleasp codefrag.c /^PUBLIC void outleasp()$/
+outline output.c /^PUBLIC void outline(s)$/
+outload codefrag.c /^PUBLIC void outload()$/
+outload codefrag.c /^PUBLIC void outload()$/
+outlongendian longop.c /^PUBLIC void outlongendian()$/
+outminus output.c /^PUBLIC void outminus()$/
+outmulmulreg codefrag.c /^PUBLIC void outmulmulreg()$/
+outmulmulreg codefrag.c /^PUBLIC void outmulmulreg()$/
+outnbyte output.c /^PUBLIC void outnbyte(byte)$/
+outnccname codefrag.c /^PUBLIC void outnccname(name)$/
+outncimmadr codefrag.c /^PUBLIC void outncimmadr(offset)$/
+outncregname genloads.c /^PUBLIC void outncregname(reg)$/
+outncspregname codefrag.c /^PUBLIC void outncspregname()$/
+outnhex output.c /^PUBLIC void outnhex(num)$/
+outnl output.c /^PUBLIC void outnl()$/
+outnlabel label.c /^PUBLIC void outnlabel(label)$/
+outnop1str output.c /^PUBLIC void outnop1str(s)$/
+outnop2str output.c /^PUBLIC void outnop2str(s)$/
+outnregname genloads.c /^PUBLIC void outnregname(reg)$/
+outnstr output.c /^PUBLIC void outnstr(s)$/
+outntypechar type.c /^PUBLIC void outntypechar(type)$/
+outoffset codefrag.c /^PUBLIC void outoffset(offset)$/
+outofmemoryerror table.c /^PUBLIC void outofmemoryerror(message)$/
+outop0str output.c /^PUBLIC void outop0str(s)$/
+outop1str output.c /^PUBLIC void outop1str(s)$/
+outop2str output.c /^PUBLIC void outop2str(s)$/
+outop3str output.c /^PUBLIC void outop3str(s)$/
+outopsep codefrag.c /^PUBLIC void outopsep()$/
+outopsep codefrag.c /^PUBLIC void outopsep()$/
+outplus output.c /^PUBLIC void outplus()$/
+outpshs codefrag.c /^PUBLIC void outpshs()$/
+outpshs codefrag.c /^PUBLIC void outpshs()$/
+outpuls codefrag.c /^PUBLIC void outpuls()$/
+outpuls codefrag.c /^PUBLIC void outpuls()$/
+outregname genloads.c /^PUBLIC void outregname(reg)$/
+outreturn codefrag.c /^PUBLIC void outreturn()$/
+outreturn codefrag.c /^PUBLIC void outreturn()$/
+outshex output.c /^PUBLIC void outshex(num)$/
+outshortregname genloads.c /^PUBLIC void outshortregname(reg)$/
+outstore codefrag.c /^PUBLIC void outstore()$/
+outstore codefrag.c /^PUBLIC void outstore()$/
+outstr output.c /^PUBLIC void outstr(s)$/
+outsub codefrag.c /^PUBLIC void outsub()$/
+outsub codefrag.c /^PUBLIC void outsub()$/
+outswoffset state.c /^PUBLIC void outswoffset (offset)$/
+outswstacklab state.c /^PUBLIC void outswstacklab()$/
+outtab output.c /^PUBLIC void outtab()$/
+outtest codefrag.c /^PUBLIC void outtest()$/
+outtest codefrag.c /^PUBLIC void outtest()$/
+outudec output.c /^PUBLIC void outudec(num)$/
+outuvalue output.c /^PUBLIC void outuvalue(num)$/
+outvalue output.c /^PUBLIC void outvalue(num)$/
+outword codefrag.c /^PUBLIC void outword()$/
+pointat genloads.c /^PUBLIC void pointat(target)$/
+pointype type.c /^PUBLIC struct typestruct *pointype(type)$/
+popframe function.c /^PUBLIC void popframe()$/
+poplist genloads.c /^PUBLIC void poplist(reglist)$/
+predefine preproc.c /^PUBLIC void predefine()$/
+prefix type.c /^PUBLIC struct typestruct *prefix(constructor, size, type)$/
+pres2 preserve.c /^PUBLIC void pres2(source, target)$/
+preserve preserve.c /^PUBLIC void preserve(source)$/
+preslval preserve.c /^PUBLIC store_pt preslval(source, target)$/
+program declare.c /^PUBLIC void program()$/
+promote type.c /^PUBLIC struct typestruct *promote(type)$/
+ptrsub hardop.c /^PUBLIC void ptrsub(source, target)$/
+public codefrag.c /^PUBLIC void public(name)$/
+push genloads.c /^PUBLIC void push(source)$/
+pushlist genloads.c /^PUBLIC void pushlist(reglist)$/
+pushreg genloads.c /^PUBLIC void pushreg(reg)$/
+pushudec output.c /^PUBLIC char *pushudec(s, num)$/
+qmalloc table.c /^PUBLIC void *qmalloc(size)$/
+rbrace declare.c /^PUBLIC void rbrace()$/
+rbracket declare.c /^PUBLIC void rbracket()$/
+recovlist preserve.c /^PUBLIC void recovlist(reglist)$/
+regexchange codefrag.c /^PUBLIC void regexchange(sourcereg, targreg)$/
+regtransfer codefrag.c /^PUBLIC void regtransfer(sourcereg, targreg)$/
+reslocals function.c /^PUBLIC void reslocals()$/
+restoreopreg codefrag.c /^PUBLIC void restoreopreg()$/
+ret function.c /^PUBLIC void ret()$/
+rparen declare.c /^PUBLIC void rparen()$/
+savedlineptr preproc.c /^PUBLIC char *savedlineptr()$/
+saveopreg codefrag.c /^PUBLIC void saveopreg()$/
+savereturn preserve.c /^PUBLIC void savereturn(savelist, saveoffset)$/
+sbc0 codefrag.c /^PUBLIC void sbc0()$/
+sbranch label.c /^PUBLIC void sbranch(cond, label)$/
+sctoi codefrag.c /^PUBLIC void sctoi()$/
+sctoi codefrag.c /^PUBLIC void sctoi()$/
+semicolon declare.c /^PUBLIC void semicolon()$/
+set codefrag.c /^PUBLIC void set(name, value)$/
+setoutbufs output.c /^PUBLIC void setoutbufs()$/
+skipcomment preproc.c /^PUBLIC void skipcomment()$/
+skipeol input.c /^PUBLIC void skipeol()$/
+skipline preproc.c /^PUBLIC void skipline()$/
+sl1 codefrag.c /^PUBLIC void sl1(reg)$/
+slconst codefrag.c /^PUBLIC void slconst(shift, reg)$/
+softop softop.c /^PUBLIC void softop(op, source, target)$/
+specialchar input.c /^PUBLIC void specialchar()$/
+srconst codefrag.c /^PUBLIC void srconst(shift, uflag)$/
+stoi codefrag.c /^PUBLIC void stoi()$/
+storereg genloads.c /^PUBLIC void storereg(sourcereg, target)$/
+stringorcharconst scan.c /^PUBLIC void stringorcharconst()$/
+struc genloads.c /^PUBLIC void struc(source, target)$/
+sub hardop.c /^PUBLIC void sub(source, target)$/
+swapsym table.c /^PUBLIC void swapsym(sym1, sym2)$/
+syminit table.c /^PUBLIC void syminit()$/
+tounsigned type.c /^PUBLIC struct typestruct *tounsigned(type)$/
+transfer genloads.c /^PUBLIC void transfer(source, targreg)$/
+typeinit type.c /^PUBLIC void typeinit()$/
+typename declare.c /^PUBLIC struct typestruct *typename()$/
+uitol codefrag.c /^PUBLIC void uitol(reg)$/
+unbumplc label.c /^PUBLIC void unbumplc()$/
+undefinestring preproc.c /^PUBLIC void undefinestring(str)$/
+ustoi codefrag.c /^PUBLIC void ustoi()$/
diff --git a/bcc/type.c b/bcc/type.c
new file mode 100644
index 0000000..4852c9d
--- /dev/null
+++ b/bcc/type.c
@@ -0,0 +1,203 @@
+/* type.c - type and storage-class routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h" /* s.b. switches.h */
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "type.h"
+
+PUBLIC uoffset_t ctypesize = 1;
+PUBLIC uoffset_t dtypesize = 8;
+PUBLIC uoffset_t ftypesize = 0;
+PUBLIC uoffset_t itypesize = 2;
+PUBLIC uoffset_t ptypesize = 2;
+PUBLIC uoffset_t stypesize = 2;
+
+PRIVATE char skey0;
+PRIVATE char skey1;
+
+PUBLIC struct typestruct *addstruct(structname)
+char *structname;
+{
+ unsigned namelength;
+ struct symstruct *symptr;
+ struct typestruct *structype;
+
+ (structype = newtype())->constructor = STRUCTU;
+ structype->alignmask = ctype->alignmask;
+ if (++skey1 == 0)
+ {
+ ++skey1; /* must be nonzero or key string would end */
+ ++skey0; /* will never reach 'A' to be an identifier */
+ }
+ structype->structkey[0] = skey0;
+ structype->structkey[1] = skey1;
+ if (*structname != 0)
+ {
+ symptr = addlorg(structname, structype);
+ symptr->storage = 0;
+ symptr->flags = STRUCTNAME;
+ if (charptr + (namelength = strlen(structname)) >= chartop)
+ growheap(namelength + 1);
+#ifdef TS
+++ts_n_structname;
+ts_s_structname += namelength + 1;
+#endif
+ structype->tname = strcpy(charptr, structname);
+ charptr += namelength + 1;
+ }
+ return structype;
+}
+
+PUBLIC struct typestruct *iscalartotype(scalar)
+scalar_pt scalar;
+{
+ if (scalar & LONG)
+ {
+ if (scalar & UNSIGNED)
+ return ultype;
+ return ltype;
+ }
+ if (scalar & UNSIGNED)
+ return uitype;
+ return itype;
+}
+
+PUBLIC struct typestruct *newtype()
+{
+ register struct typestruct *type;
+
+ type = qmalloc(sizeof *type);
+#ifdef TS
+++ts_n_type;
+ts_s_type += sizeof *type;
+#endif
+ type->typesize = /* (uoffset_t) */
+ type->scalar = /* (scalar_t) */
+ type->constructor = /* (constr_t) */
+ type->structkey[0] = 0;
+ type->nexttype =
+ type->prevtype =
+ type->sidetype = NULL;
+ type->listtype = NULL;
+ type->tname = "";
+ return type;
+}
+
+PUBLIC void outntypechar(type)
+struct typestruct *type;
+{
+ outnbyte(*type->tname);
+}
+
+PUBLIC struct typestruct *pointype(type)
+struct typestruct *type;
+{
+ return prefix(POINTER, ptypesize, type);
+}
+
+PUBLIC struct typestruct *prefix(constructor, size, type)
+constr_pt constructor;
+uoffset_t size;
+struct typestruct *type;
+{
+ register struct typestruct *searchtype;
+
+ for (searchtype = type->prevtype; searchtype != NULL;
+ searchtype = searchtype->sidetype)
+ if (searchtype->constructor == (constr_t) constructor &&
+ searchtype->typesize == size)
+ return searchtype;
+ switch ((searchtype = newtype())->constructor = constructor)
+ {
+ case ARRAY:
+ searchtype->alignmask = type->alignmask;
+ break;
+ case FUNCTION:
+ searchtype->alignmask = ~(uoffset_t) 0;
+ break;
+ case POINTER:
+ searchtype->alignmask = ~(ptypesize - 1) | alignmask;
+ break;
+ case STRUCTU:
+ bugerror("prefixing structure/union");
+ searchtype->alignmask = alignmask;
+ break;
+ }
+ searchtype->typesize = size;
+ searchtype->nexttype = type;
+ searchtype->sidetype = type->prevtype;
+ return type->prevtype = searchtype;
+}
+
+PUBLIC struct typestruct *promote(type)
+struct typestruct *type;
+{
+ scalar_t scalar;
+
+ if ((scalar = type->scalar) & (CHAR | SHORT))
+ {
+ if (scalar & UNSIGNED)
+ return uitype;
+ return itype;
+ }
+ if (scalar & FLOAT)
+ return dtype;
+ if (type->constructor & ARRAY)
+ return pointype(type->nexttype);
+ if (type->constructor & FUNCTION)
+ return pointype(type);
+ return type;
+}
+
+PUBLIC struct typestruct *tounsigned(type)
+struct typestruct *type;
+{
+ switch (type->scalar & ~(UNSIGNED | DLONG))
+ {
+ case CHAR:
+ return uctype;
+ case SHORT:
+ return ustype;
+ case INT:
+ return uitype;
+ case LONG:
+ return ultype;
+ default:
+ error("unsigned only applies to integral types");
+ return type;
+ }
+}
+
+PUBLIC void typeinit()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ uitype->typesize =
+ itype->typesize =
+ ptypesize =
+ itypesize = 4;
+ dtype->alignmask =
+ fltype->alignmask =
+ uitype->alignmask =
+ ltype->alignmask =
+ ultype->alignmask =
+ itype->alignmask = ~(uoffset_t) (4 - 1);
+ ltype->scalar = LONG; /* not DLONG */
+ ultype->scalar = UNSIGNED | LONG;
+ }
+#endif
+ fitype = prefix(FUNCTION, ftypesize, itype);
+ pctype = pointype(ctype);
+ skey0 = 1;
+ vtype->constructor = VOID;
+}
diff --git a/bcc/type.h b/bcc/type.h
new file mode 100644
index 0000000..c451283
--- /dev/null
+++ b/bcc/type.h
@@ -0,0 +1,98 @@
+/* type.h - types for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ A type is essentially a "constructor", a size, and a list of pointers
+ leading to a scalar type.
+ The type constructors are codes for the scalar types and (), [], *,
+ struct and union.
+ The scalar types are char, short, int, long, float and double.
+ The type lists are triply linked.
+
+ Part of the type structure might look like
+
+ int (int)
+ =
+ func <-------> int (int ())
+ | =
+ --> ptr <--> int (int *)
+
+ (the exact structure depends on the order of declarations).
+ This layout results from the pre-declared (int) and (int ()) followed by
+ a declaration using (int *).
+ The sideways link (from func to ptr here) allows all types leading to a
+ given type to be found.
+ This allows different declarations of (int *) to be recognised as the same.
+ Type equivalence is equality of type pointers.
+*/
+
+/*
+ flags for scalar types
+ up to 3 of the flags may be set (none for constructed types)
+ the 2nd and third flags can only be UNSIGNED or DLONG
+ UNSIGNED only applies to integral types
+ DLONG only applies to long and unsigned long types and says that these
+ are actually longer than an int
+*/
+
+#define CHAR 0x01
+#define SHORT 0x02
+#define INT 0x04
+#define LONG 0x08
+#define FLOAT 0x10
+#define DOUBLE 0x20
+#define UNSIGNED 0x40
+#define DLONG 0x80
+
+#define ISCALAR (CHAR | SHORT | INT | LONG)
+#define RSCALAR (FLOAT | DOUBLE)
+
+/*
+ flags for type constructor
+ at most 1 of the flags may be set (none for scalar types)
+ flags are used for fast testing for array/pointer
+*/
+
+#define ARRAY 1
+#define FUNCTION 2
+#define POINTER 4
+#define STRUCTU 8
+#define VOID 0x10
+
+/* type sizes */
+/* default sizes and long and float sizes are hard-coded into type data */
+
+extern uoffset_t ctypesize;
+extern uoffset_t dtypesize;
+extern uoffset_t ftypesize;
+extern uoffset_t itypesize;
+extern uoffset_t ptypesize;
+extern uoffset_t stypesize;
+
+/* basic scalar types */
+
+EXTERN struct typestruct *dtype;
+EXTERN struct typestruct *fltype;
+EXTERN struct typestruct *itype;
+EXTERN struct typestruct *ltype;
+EXTERN struct typestruct *sctype;
+EXTERN struct typestruct *stype;
+EXTERN struct typestruct *uctype;
+EXTERN struct typestruct *uitype;
+EXTERN struct typestruct *ultype;
+EXTERN struct typestruct *ustype;
+EXTERN struct typestruct *vtype;
+
+/* working type */
+
+EXTERN struct typestruct *ctype;
+
+/* constructed types */
+
+EXTERN struct typestruct *fitype;
+EXTERN struct typestruct *pctype;
+
+/* return type of current function */
+
+EXTERN struct typestruct *returntype;
diff --git a/bcc/types.h b/bcc/types.h
new file mode 100644
index 0000000..755b8b1
--- /dev/null
+++ b/bcc/types.h
@@ -0,0 +1,206 @@
+/* types.h - type definitions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ source types big enough to handle target quantities
+ these have to be match the source compiler and target machine
+ this is impossible if the source long type is too small
+*/
+
+typedef unsigned char char_t; /* target char */
+typedef long value_t; /* target ints, longs and offsets */
+typedef unsigned long uvalue_t; /* target unsigned ints, longs and offsets */
+
+#ifdef I8088
+typedef long offset_t; /* target machine offset */
+typedef unsigned long uoffset_t; /* target unsigned machine offset */
+#define outuvalue outhex
+#define outvalue outshex
+#endif
+#ifdef MC6809
+typedef int offset_t;
+typedef unsigned uoffset_t;
+#endif
+
+
+/*
+ storage class type must hold all the flags defined elsewhere
+ it must have a few more bits than the target has registers
+*/
+
+#ifdef I8088
+typedef unsigned store_pt; /* promoted store_t */
+typedef unsigned store_t; /* storage class flags */
+#endif
+#ifdef MC6809
+#ifdef __STDC__
+typedef int store_pt;
+# else
+typedef unsigned store_pt;
+# endif
+typedef unsigned char store_t;
+#endif
+
+
+/*
+ types for library routines
+*/
+
+typedef int fd_t; /* file descriptor */
+
+
+/*
+ basic scalar types - may be tuned to suit machine
+*/
+
+typedef int fastin_pt; /* promoted fastin_t */
+ /* always an int - use to show that the */
+ /* value may be accessed as a fastin_t */
+typedef char fastin_t; /* fast int - a small integer value */
+ /* on some machines, chars can be accessed */
+ /* more efficiently than ints for arithmetic */
+ /* such as comparing and masking which */
+ /* does not requiring promotion */
+ /* change to int if chars are inefficient */
+ /* or if char has < 8 bits */
+typedef int smalin_pt; /* promoted smalin_t */
+typedef char smalin_t; /* small int - a small integer value */
+ /* on most machines, chars are stored in */
+ /* less space than any other type */
+ /* change to fastin_t if this is not true */
+ /* or if char has < 8 bits */
+ /* or if space is not a limiting factor */
+#ifdef __STDC__
+typedef int smalu_pt;
+#else
+typedef unsigned smalu_pt;
+#endif
+typedef unsigned char smalu_t;
+
+
+/*
+ derived scalar types
+ the types containing bit flags fit in an 8 bit smalin_t
+*/
+
+typedef fastin_pt bool_pt; /* promoted bool_t */
+typedef fastin_t bool_t; /* boolean: TRUE if nonzero */
+typedef fastin_pt ccode_pt; /* promoted ccode_t */
+typedef fastin_t ccode_t; /* condition code code */
+typedef smalu_pt constr_pt; /* promoted constr_t */
+typedef smalu_t constr_t; /* type constructor flags */
+typedef smalu_pt indn_pt; /* promoted indn_t */
+typedef smalu_t indn_t; /* storage indirection count */
+typedef unsigned label_t; /* label number */
+typedef smalu_t maclev_t; /* macro expansion level */
+typedef smalin_pt op_pt; /* promoted op_t */
+typedef smalin_t op_t; /* operator code */
+typedef smalu_t sc_t; /* storage class flags */
+typedef smalu_pt scalar_pt; /* promoted scalar_t */
+typedef smalu_t scalar_t; /* type scalar flags */
+typedef smalu_t scopelev_t; /* scope level */
+typedef fastin_pt sym_pt; /* promoted sym_t */
+typedef fastin_t sym_t; /* symbol code from scanner */
+typedef smalu_t weight_t; /* expression tree node weight */
+
+
+/*
+ derived structure types
+ the fields are ordered in a way that is most space-efficient
+ when smalin_t is char and smalu_t is unsigned char
+ the first element of the structures is the one most frequently accessed
+*/
+
+/*
+ expression table entry format
+*/
+
+struct nodestruct
+{
+ op_t tag;
+ weight_t weight;
+ smalu_t flags;
+ struct typestruct *nodetype;
+ union nodeunion
+ {
+ struct nodestruct *nodeptr;
+ struct symstruct *symptr;
+ } left;
+ struct nodestruct *right;
+};
+
+/*
+ symbol table entry format
+*/
+
+struct symstruct
+{
+ store_t storage;
+ indn_t indcount;
+ sc_t flags;
+ scopelev_t level;
+ struct symstruct *next;
+ struct symstruct **prev;
+ struct typestruct *type;
+ union
+ {
+ double *offd; /* value for double constants */
+ offset_t offi; /* offset for register or global storage */
+ label_t offlabel; /* label number for strings */
+ char *offp; /* to string for macro definitions */
+ sym_pt offsym; /* symbol code for keywords */
+ value_t offv; /* value for integral constants */
+ }
+ offset;
+ union
+ {
+ label_t label; /* label number for strings */
+ char namea[1]; /* variable length array for declarations */
+ char *namep; /* to constant storage for exprs */
+ }
+ name;
+};
+
+/*
+ type table entry format
+*/
+
+struct typestruct
+{
+ scalar_t scalar; /* scalar type flags u d f l i s c */
+ constr_t constructor; /* constructed type flags a f p s/u */
+ char structkey[2]; /* unique prefix for member names */
+ /* ranges from "\001\001" to "@\377" */
+ /* avoiding nulls */
+ uoffset_t alignmask; /* alignment mask, typesize - 1 for scalars */
+ uoffset_t typesize; /* size of this type */
+ char *tname; /* name of scalar type or constructor */
+ struct typelist *listtype; /* list of member types */
+ struct typestruct *nexttype;
+ /* next in list */
+ struct typestruct *prevtype;
+ /* previous in list */
+ struct typestruct *sidetype;
+ /* next in sideways list */
+};
+
+/*
+ list of type structures
+*/
+
+struct typelist
+{
+ struct typelist *tlnext;
+ struct typestruct *tltype;
+};
+
+
+/*
+ definitions to avoid passing raw NULLs to functions
+*/
+
+#define NULLNODE ((struct nodestruct *) NULL)
+#define NULLTYPE ((struct typestruct *) NULL)
+
+#include "proto.h"