[comp.sources.amiga] v89i028: zc - c compiler, Part01/04

page@swan.ulowell.edu (Bob Page) (03/08/89)

Submitted-by: monty@brahms.Berkeley.EDU (Joe Montgomery)
Posting-number: Volume 89, Issue 28
Archive-name: languages/zc.1

This is zc, a modified version of hcc (the Sozobon-C compiler by
Johann Ruegg) from Fred Fish disk 171.  I have made some minor
modifications to get it to work with A68K and Blink.  Also included is
zcc, a unix-style front end for zc/a68k/blink.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	bstok.h
#	cookie.h
#	flags.h
#	gen.h
#	nodes.h
#	ops.h
#	param.h
#	sttok.h
#	tok.h
#	tytok.h
#	zc.doc
#	zcc.doc
#	zc.readme
#	zcc.readme
#	makefile
#	zcc.c
# This archive created: Tue Mar  7 21:51:16 1989
cat << \SHAR_EOF > bstok.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	bstok.h
 *
 *	basic token values
 *	(some compilers cant do enums, so use defines)
 */

#ifndef ENUMS
#define BADTOK	0
#define ID	1
#define ICON	2
#define FCON	3
#define SCON	4
#define DPARAM	6	/* parameter to #define */
#define EOFTOK	7
#define POSTINC 8	/* DOUBLE '+' is pre-inc */
#define POSTDEC 9	/* DOUBLE '-' is pre-dec */
#define TCONV	10	/* coertion */
#define TSIZEOF 11	/* sizeof(type expr) */
#define NL	12
#define WS	13	/* white space */
#define SCON2	14	/* <string> */
#define PTRDIFF 0x18
#define PTRADD	0x19
#define PTRSUB	0x1a
#define ARROW	0x1b
#define LTEQ	0x1c
#define GTEQ	0x1d
#define NOTEQ	0x1e
#else
enum {
	BADTOK, ID, ICON, FCON, SCON, DPARAM, EOFTOK,
	POSTINC, POSTDEC, TCONV, TSIZEOF, NL, WS, SCON2,
	PTRDIFF, PTRADD, PTRSUB, ARROW, LTEQ, GTEQ, NOTEQ
};
#endif

#define ASSIGN	0x100+	/* add to char of op */
#define DOUBLE	0x80+
#define UNARY	0x200+

#define STAR	(UNARY '*')	/* used a lot */

#define isassign(x)	(x >= 0x100)
SHAR_EOF
cat << \SHAR_EOF > cookie.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	cookie.h
 */

/* restrictions on type */

#define R_INTEGRAL	1
#define R_FLOATING	2
#define R_POINTER	4
#define R_STRUCT	8
#define R_ARITH		(R_INTEGRAL|R_FLOATING)
#define R_SCALAR	(R_ARITH|R_POINTER)
#define R_ASSN		(R_SCALAR|R_STRUCT)

/* cookies */
#define FORSIDE		1
#define FORPUSH		2
#define FORCC		3
#define FORIMA		4
#define FORADR		5
#define FORINIT		6
#define IND0		7
#define RETSTRU		8

/* eval flags derived from cookie */
#define NOVAL_OK	1	/* value is optional */
#define CC_OK		2	/* just setting cond. codes okay */
#define IMMA_OK		4	/* immediate OREG is okay */
SHAR_EOF
cat << \SHAR_EOF > flags.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	flags.h
 *
 *	token or e_flags flags
 */

#define CAN_U	2	/* can be unary op */
#define CAN_AS	4	/* can be op-assign */
#define SPECIAL 8	/* special token beginner ("'/*) */
#define SEE_U	0x10	/* for ICON */
#define SEE_L	0x20	/* for ICON */
#define C_NOT_A 0x40	/* commutative but not associative */
#define C_AND_A 0x80	/* commutative and associative */
#define IMMEDID	0x100	/* Ptr to XXX ID which is really
				Array of XXX or Fun ret XXX */
#define CHILDNM	0x200	/* my name is my (left) child's name */
#define SIDE_CC 0x400	/* cc set as side effect of op. */
#define RCHILDNM 0x800	/* my name is my (right) child's name */
SHAR_EOF
cat << \SHAR_EOF > gen.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	gen.h
 */

#include "cookie.h"

/* parameters for case */
#define C_SIMPLE	8	/* use simple if n <= this */
#define C_RATIO		3	/* use table if max-min/n <= this */

/* branch types */
/* designed so that pairs (i,i+1) with odd i represent opposites */
#define B_EQ	1
#define B_NE	2
#define B_LT	3
#define B_GE	4
#define B_LE	5
#define B_GT	6
#define B_YES	7
#define B_NO	8
#define B_ULT	9
#define B_UGE	10
#define B_ULE	11
#define B_UGT	12

/* derived nodes */
/* re-use stmt keywords for now */
#ifndef ENUMS
#define ONAME	'a'
#define OREG	'b'
#define REGVAR	'c'
#define PUSHER	'd'
#define CMPBR	'e'
#define FIELDAS	'f'
#else
enum {
	ONAME = 'a', OREG, REGVAR, PUSHER, CMPBR, FIELDAS
};
#endif

#define BR_TOK	'i'

/* evaluation order values */
#define EV_NONE		0
#define EV_LEFT		1
#define EV_RIGHT	2
#define EV_LR		3
#define EV_RL		4
#define EV_LRSEP	5	/* left then right, but seperate */
SHAR_EOF
cat << \SHAR_EOF > nodes.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	nodes.h
 */

/*
 *	stuff common to all nodes
 */
#define COMMON	int cflags;	\
		int fill;	\
		union node *left;	\
		union node *right;	\
		union node *tptr;	\
		union node *nm_ext;	\
		char cname[NMSIZE]

#define n_flags e.cflags
#define n_left	e.left
#define n_next	e.left
#define n_right e.right
#define n_tptr	e.tptr
#define n_nmx	e.nm_ext
#define n_name	e.cname

/*
 *	expression (and symbol table) node
 */
struct enode {
	COMMON;
	int	token;		/* must be same place as tnode */
	int	eflags;
	char	etype;		/* type of node */
	char	sc;
	char	eprec;
	char	rno;
	union {
		long	vival;
		long	voffs;
		double	vfval;
	} vu;
	char	fldw, fldof;		/* use if cant do fields */
/*	unsigned	fldw:6, fldof:6;	/* use fields just so
						we know fields work */
};

#define e_token e.token
#define e_flags e.eflags
#define e_prec	e.eprec
#define e_rno	e.rno
#define e_type	e.etype
#define e_ival	e.vu.vival
#define e_offs	e.vu.voffs
#define e_fval	e.vu.vfval
#define e_sc	e.sc
#define e_fldw	e.fldw
#define e_fldo	e.fldof

/* for e_flags values, see tok.h */

/* values for e_type */

#define E_LEAF	0	/* no descendants */
#define E_UNARY 1	/* left node is expr, no right node */
#define E_BIN	2	/* left and right are expr */
#define E_SPEC	3	/* special '(', '[', '.', '->', ... */

/*
 * code generation node
 */
struct gnode {
	COMMON;
	int	token;
	int	eflags;
	char	etype;
	char	sc;
/* all of above fields must match first fields in enode! */

	char	needs;		/* registers needed */
	char	grno;		/* register used in ret value */
	char	basety; 	/* type FLOAT, UNS, INT or AGREG */
	char	basesz; 	/* size 1,2,4 or 3 -> see bsize */
	char	gr1, gr2;
	char	*betwc; 	/* code for between L and R */
	long	goffs;		/* offsets for OREG, ONAME */
	union gu {
		long	bsize;		/* AGREG size or misc. */
		struct {
/*			int	gfldw:6, gfldo:6;	/* field info */
			char	gfldw, gfldo;	/* use if no fields */
		} gfl;
	} gu;
};

#define g_token g.token
#define g_flags g.eflags
#define g_type	g.etype
#define g_sc	g.sc
#define g_needs g.needs
#define g_rno	g.grno
#define g_offs	g.goffs
#define g_betw	g.betwc
#define g_ty	g.basety
#define g_sz	g.basesz
#define g_code	g.tptr
#define g_bsize g.gu.bsize
#define g_fldw	g.gu.gfl.gfldw
#define g_fldo	g.gu.gfl.gfldo
#define g_r1	g.gr1
#define g_r2	g.gr2

/* types of operands -- ordered in cast strength order */
#define ET_S	1	/* signed integer */
#define ET_U	2	/* unsigned integer */
#define ET_F	3	/* float or double */
#define ET_A	4	/* aggregate */

/*
 *	type list node
 */
struct tnode {
	COMMON;
	int	token;		/* must be same place as enode */
	int	tflags;
	char	aln;		/* alignment needed */
	long	tsize;
};

#define t_token t.token
#define t_flags t.tflags
#define t_size	t.tsize
#define t_aln	t.aln

/*
 *	name extension node
 */
struct nmext {
	COMMON;
	char nmx[NMXSIZE-NMSIZE];	/* name extension (with name)*/
};

#define x_nm	x.nmx

/*
 *	block info node
 */
struct bnode {
	COMMON;
	union node *syms;
	union node *tags;
	int	regs;		/* reg alloc mask */
	long	lsize;		/* size of locals */
	int	tmsize; 	/* max tmps used for 1 expr */
};

#define b_syms	b.syms
#define b_tags	b.tags
#define b_regs	b.regs
#define b_size	b.lsize
#define b_tsize b.tmsize

/*
 *	node to hold case for switch generation
 */
struct cnode {
	COMMON;
	int	c_value;	/* value for case */
	int	c_label;	/* case label or label label */
	int	c_def;		/* label defined */
};

#define c_defined c.c_def
#define c_casev c.c_value
#define c_casel c.c_label

union node {
	struct enode e;
	struct tnode t;
	struct nmext x;
	struct bnode b;
	struct cnode c;
	struct gnode g;
};

typedef union node NODE;
typedef NODE *NODEP;

/* defines for n_flags */

#define N_BRKPR 1	/* break printnode recursion */
#define N_COPYT 2	/* tptr is a copy */
#define N_ISFREE 4	/* node is on free list (error check) */

NODEP allocnode();
SHAR_EOF
cat << \SHAR_EOF > ops.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	ops.h
 *
 *	defines of allowed operands
 *	'E' means Dreg or OREG or ONAME or (if on left) ICON
 *	'Q' means ICON which is 1 to 8
 *	ONE means ICON which is 1
 */

#define DOPD	1
#define AOPD	2
#define MOPD	4
#define IOPD	8

#define DOPA	0x10
#define AOPA	0x20
#define MOPA	0x40
#define IOPA	0x80

#define DOPM	0x100
#define AOPM	0x200
#define MOPM	0x400
#define IOPM	0x800

#define QOPD	0x1000
#define ONEOPM	0x2000
#define ASSOC	0x4000

#define EOPD	(DOPD|MOPD|IOPD)
#define DOPE	(DOPD|DOPM)
#define IOPE	(IOPD|IOPM)
#define EOPA	(DOPA|MOPA|IOPA)
SHAR_EOF
cat << \SHAR_EOF > param.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	param.h
 *
 *	basic parameters
 */

#ifndef MMCC
#define MMCC	0
#endif

#ifndef CC68
#define CC68	0
#endif

#ifndef dLibs
#define dLibs	0
#endif

#undef NULL
#define NULL 0L

#define ENUMS	1	/* define if host compiler can do enums */
#define DEBUG	1

#define NHASH	32

#define ROPEN	"r"
#define WOPEN	"w"
#define FLTFORM "%.3g"

#define MAXSTR	256
#define MAXINCL 10
#define NMSIZE	12	/* must be at least 12 */
#define NMXSIZE	32

/* sizes of basic types */
#ifndef NOLONGS
#define SIZE_C	1	/* char */
#define SIZE_I	2	/* int */
#define SIZE_S	2	/* short */
#define SIZE_L	4	/* long */
#define SIZE_U	2	/* unsigned */
#define SIZE_F	4	/* float */
#define SIZE_D	4	/* double */
#define SIZE_P	4	/* pointer */
#define MAXINT	0x7fffL
#define MININT	-0x8000
#define MAXUNS	0xffffL
#else
#define SIZE_C	1	/* char */
#define SIZE_I	4	/* int */
#define SIZE_S	2	/* short */
#define SIZE_L	4	/* long */
#define SIZE_U	4	/* unsigned */
#define SIZE_F	4	/* float */
#define SIZE_D	4	/* double */
#define SIZE_P	4	/* pointer */
#define MAXINT	0x7fffffff
#endif

/* alignment requirements */
#define ALN_C	0	/* char */
#define ALN_I	1	/* int */
#define ALN_S	1	/* short */
#define ALN_L	1	/* long */
#define ALN_U	1	/* unsigned */
#define ALN_F	1	/* float */
#define ALN_D	1	/* double */
#define ALN_P	1	/* pointer */

#define STACKALN 1

/* usage for registers */
#define DRV_START	3
#define DRV_END		7
#define AREG		8
#define ARV_START	AREG+3
#define ARV_END		AREG+5

/* definition of stack frame */
#define ARG_BASE	8
#define LOC_BASE	0

/* need for own buffers (ALCYON hack ) ? */
#define NEEDBUF		0

SHAR_EOF
cat << \SHAR_EOF > sttok.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	sttok.h
 *
 *	statement keyword tokens
 */

#ifndef ENUMS
#define K_GOTO		'a'
#define K_RETURN	'b'
#define K_BREAK		'c'
#define K_CONTINUE	'd'

#define K_IF		'e'
#define K_ELSE		'f'
#define K_FOR		'g'
#define K_DO		'h'
#define K_WHILE		'i'
#define K_SWITCH	'j'

#define K_CASE		'k'
#define K_DEFAULT	'l'
#define K_ASM		'm'

#define K_SIZEOF	'n'

#else
enum {
	K_GOTO = 'a', K_RETURN, K_BREAK, K_CONTINUE,
	K_IF, K_ELSE, K_FOR, K_DO, K_WHILE, K_SWITCH,
	K_CASE, K_DEFAULT, K_ASM,
	K_SIZEOF,
};
#endif
SHAR_EOF
cat << \SHAR_EOF > tok.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	tok.h
 *
 *	establish token values
 */

struct tok {
	char	*name;
	int	tnum;
	long	ival;
	double	fval;
	char	prec;
	int	flags;
};

#include "flags.h"
#include "bstok.h"

#define is_sclass(x)	(x >= K_EXTERN && x <= K_STATIC)
#define is_tadj(x)	(x >= K_LONG && x <= K_UNSIGNED)
#define is_btype(x)	(x >= K_INT && x <= K_VOID)
#define is_tykw(x)	(x >= K_EXTERN && x <= K_STRUCT)

#define is_stkw(x)	(x >= K_GOTO && x <= K_ASM)
#define is_brast(x)	(x >= K_GOTO && x <= K_CONTINUE)
#define is_blkst(x)	(x >= K_IF && x <= K_SWITCH)
#define is_lblst(x)	(x >= K_CASE && x <= K_DEFAULT)

#include "tytok.h"
#include "sttok.h"

/* modifier seen flags */
#define SAW_SHORT	1
#define SAW_LONG	2
#define SAW_UNS		4
SHAR_EOF
cat << \SHAR_EOF > tytok.h
/* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
 *
 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.
 *
 *	tytok.h
 *
 *	keyword token values
 */

#ifndef ENUMS
#define K_EXTERN	'A'
#define K_AUTO		'B'
#define K_REGISTER	'C'
#define K_TYPEDEF	'D'
#define K_STATIC	'E'

#define ENUM_SC		K_STATIC+1	/* storage class for enum item */
#define HERE_SC		K_STATIC+2	/* storage class for glb def */
#define FIRST_SC	K_EXTERN
#define LAST_SC		K_STATIC

#define T_UCHAR		'F'
#define T_ULONG		'G'

#define K_LONG		'H'
#define K_SHORT		'I'
#define K_UNSIGNED	'J'

#define K_INT		'K'
#define K_CHAR		'L'
#define K_FLOAT		'M'
#define K_DOUBLE	'N'
#define K_VOID		'O'

#define FIRST_BAS	T_UCHAR
#define LAST_BAS	K_VOID

#define K_UNION		'P'
#define K_ENUM		'Q'
#define K_STRUCT	'R'
#else
#define FIRST_SC	K_EXTERN
#define LAST_SC		K_STATIC
#define FIRST_BAS	T_UCHAR
#define LAST_BAS	K_VOID
enum {
	K_EXTERN = 'A', K_AUTO, K_REGISTER, K_TYPEDEF, K_STATIC,
	ENUM_SC, HERE_SC,
	T_UCHAR, T_ULONG,
	K_LONG, K_SHORT, K_UNSIGNED,
	K_INT, K_CHAR, K_FLOAT, K_DOUBLE, K_VOID,
	K_UNION, K_ENUM, K_STRUCT
};
#endif
SHAR_EOF
cat << \SHAR_EOF > zc.doc

							    ZC(1)
ZC
NAME
   zc  -Sozobon C compiler ported to the amiga.  Ver 1.01
	by  Johann Ruegg.
	modified by Joe Montgomery Dec 1988.

SYNOPSIS
   zc  [ options ] [file.c's ]

DESCRIPTION
     Zc is a c compiler for the amiga.	It is as far as
     I know a K & R compatible compiler.  Zc takes <file>.c
     and creates a Motorola compatible assembly source whose
     default name is <file>.s .  include files are looked
     for in the directory specified by the manx environment
     variable INCLUDE.	Simply use the command
     set INCLUDE=includedir
     from the CLI or place it in your startup-sequence.

     Below: are the options available at present.

       -Dxxxx	Define xxxx
		  same as a #define xxxx in the source file
       -Uxxxx	Undefine xxxx
		  same as a #undefine xxxx in the source file
       -Ixxxx	Include Directory = xxxx
       -P	profiler. Places a call to mcount before calling
		  main.  You had better not use this for now.
       -Oxxxx	outputfile name = xxxx
       -V	display compiler version
       -?	Help
       -C	force Data,Bss into Chip memory
       -F	force Data,Bss into Fast memory
       -Exxxx	errorfile. Zc writes the number of errors into
		  this file.  This is used by the compiler front
		  end in order to determine whether to start the
	       assembler a68k.

BUGS

    See zc.readme.


    Joe Montgomery UC Berkeley Math Dept.
    monty@brahms.berkeley.edu


SHAR_EOF
cat << \SHAR_EOF > zcc.doc

							    ZCC(1)
ZCC
NAME
   zcc	A unix style front end for the
	Sozobon C compiler(by Johann Ruegg) ported to the Amiga.  Ver 1.01
	A68K  a Motorola Compatible 68000 Assembler for the Amiga.
	Blink a Software Distillery Linker Ver 6.5 for the Amiga.

SYNOPSIS
   zcc	[ options ] [file.c's ] [files.s] [files.o]

DESCRIPTION
     Zcc is a unix style c front end for the Amiga.
     It will compile all .c files creating .s files,
     assemble all .s files creating .o files and link all
     .o files creating an executable with the same name as
     the first file minus the extension.

     Zcc will call zc to compile all .c files. If an error
     occurs then zcc will abort and will not call the assembler
     A68K or the linker Blink.	If a successful compile is
     done then a68k is called and afterwards the .s file is
     deleted. If all the files have been compiled and/or assembled
     then Blink is called.

     Zcc will call a68k to assemble all .s files. The source will
     not be deleted upon completion.

     Zcc looks to see if the following environment variables
     have been set and if so then uses them otherwise default
     directories will be used.

       Env Var	     Default	      Description
	CCEXEC	      c:	    directory containing zc,a68k,blink
	CCTEMP	      ram:	    location for temporay .s file
				    only used for .c files which
				    will be assembled.
	INCLUDE 		    directory to find the include files
	CCLIB	      lib:	    directory containing BothStartup.obj
				    amiga.lib and any other libraries
				    that will be used

OPTIONS
	     -Dxxxx   define xxxx
	     -Uxxxx   undefine xxxx
	     -C       data->chip
	     -F       data->fast
	     -S       don't use startups
	     -T       don't use amiga.lib
	     -A       don't assemble
	     -c       don't link
	     -Ixxxx   include dir
	     -V       printout actions only
	     -lxxxx   use library  CCLIBxxxx.lib

SEEALSO

   zc.doc

BUGS
    See zc.readme.


    Joe Montgomery UC Berkeley Math Dept.
    monty@brahms.berkeley.edu


SHAR_EOF
cat << \SHAR_EOF > zc.readme
	  zc c - compiler

	   revised by Joe Montgomery dec 1988.
	    (monty@brahms.berkeley.edu)


    This is a modified version of hcc the Sozobon-C compiler by
       Johann Ruegg.  The documentation released with the compiler
       states the following:


 * Permission is granted to anyone to use this software for any purpose
 * on any computer system, and to redistribute it freely, with the
 * following restrictions:
 * 1) No charge may be made other than reasonable charges for reproduction.
 * 2) Modified versions must be clearly marked as such.
 * 3) The authors are not responsible for any harmful consequences
 *    of using this software, even if they result from defects in it.

      I can only add that I can not be held responsible for any
      harmful consequences as well.

     I hope that this goes a long way toward the goal of having a
     freely distributable c compiler for the amiga.  I have modified
     hcc so that it generates code compatible with a68k.  I have
     not been able to test this adequately as I do not have the
     amiga.lib.  However I will get it hopefully within a few weeks
     and then begin to do some more checking.  It does seem to
     to generate assembly language files that a68k does not complain
     about.  There are some problems however:

	One I don't know Motorola 68000 assem or the directives.
	A68k did not have much documentation so I guessed about
	the use of some.  I used XREF for externally defined labels
	XDEF for global defines, and DC,DS for data storage.  I hope
	my usage is correct. Further a68k requires the SECTIONS DATA
	and BSS to be named so I used DATA & BSS for those names.
	This may be a problem or not. I do know that
	hcc doesn't generate a XREF or public direc for functions
	or variables which are external to the file.  It expects
	the assembler to figure this out. a68k does not like this.
	I tried to remedy both these problems to some extent.
	The code has 0 comments and as I do not have a printer, I
	found it difficult to make any major changes, so I caused
	the compiler to generate a XREF label for every function
	call. Not good, hopefully I can get that working latter.
	For the variables, I was able to get it to generate XREF's
	for externally defined global variables, however external
	variables within a function are not declared to be XREF.

	I tried to label most of the changes I made with the
	comment
	  /*  JMM ...

    The following files were modified:

    Revised main.c to use Amiga File System Naming Conventions
       Added ?,C,F,E switches.
			     ? help
			     C force data,bss into Chip memory
			     F force data,bss into Fast memory
			     Exxxx use xxxx as errorfile.
				   writes the number of errors to the
				   file
			     Oxxxx use xxxx as the output file
				   instead of the default file.

    Revised out.c to use MOTOROLA assembly directives in order
       to be compatible with C.Gibbs a68k assembler & blink
       Added END statement
       Changed .comm label,size to label DC.x 0
	       .even	to CNOP 2,0
	       .globl	to XDEF
	       .text	to CODE CODE  [CHIP | FAST]
	       .data	to DATA DATA  [CHIP | FAST]
	       .bss	to BSS BSS
    Revised d2.c so that externs are declared as XREF -----
    Revised g2.c & gen.c to declare all called functions XREF
      (will need to change this to declare only external functions)


     I also wrote a front end called zcc that automatically calls
       a68k if no errors and then blink.
     It is somewhat a unix style front end but I don't know all
       the options available.

     for zcc and zc, if you type zcc ? or zc ? it will list the
       various options.(one exception is that zc doesn't list
			-E as an option.)

     Again, I hope to correct  the above problems as well as adding
     more options.  One not of caution, zc expects all options
     to be upper case. I did not change this as it uses all the
     lower case options for debug purposes.  Perhaps in the future
     I will change this.

     Please let me know of any problems, and I will attempt to fix
     them.


	Thanks, for all the great PD and FD software out there.  Hope
	you can get some use out of this.

		     Thanks again,

		       Joe





SHAR_EOF
cat << \SHAR_EOF > zcc.readme
To create zcc simply compile and link zcc.c.
      Note zcc.c is freely distributable.

	Joe Montgomery
	monty@brahms.berkeley.edu


SHAR_EOF
cat << \SHAR_EOF > makefile
OBJS =	d2.o decl.o expr.o fix.o fun.o g2.o gen.o gsub.o gunk.o \
	main.o md.o nodes.o out.o p2.o pre.o tok.o subs.o

H =	bstok.h cookie.h flags.h gen.h nodes.h ops.h param.h \
	sttok.h tok.h tytok.h

RM =		delete
CFLAGS =	-c
CC =		cc
AFLAGS =	-o
LD =		ln
LDFLAGS =
LIBS =		-lm32 -lc32

.c.o:
	$(CC) $(CFLAGS)   $*.c



Zc :	       $(OBJS)
		$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

$(OBJS) :       $(H)

clean:
		$(RM) *.o

clobber:
		$(RM) *.o



SHAR_EOF
cat << \SHAR_EOF > zcc.c
/*  preprocessor for zc (formerly hcc) , a68k assembler, blink
*/


#include <stdio.h>

#define toupper( x ) ( x > 'Z' ? x - ('a'-'A'): x )

char *malloc();
extern char *getenv();

	       /* flags if 1 then will allow that operation
		* to be performed on a file		   */
short dozc,doa68k,doblink,dodebug,debug;
short blinkxref,startup,standardblinklib;

doexec( x,errmsg,file )
char x[],*errmsg,*file;
{
if( debug ){
  printf("%s\n",x);
  return(1);
}
if( ! Execute(x,0L,0L) ){
  printf(errmsg,file);
  quit();
}
return(1);
}

char libdir[32];	      /* librarys' dir             */
char cmddir[32];	     /*  zc,a68k,blink 's dir     */
char xrefname[128];	    /* blink xref file output	 */
char blinklibs[128];	   /* blink lib direc		*/
char blinkname[128];	  /* output file from a68k     */
char a68kname[128];	 /* output file from zc       */
char zcopts[128];	/* zc options for each phase */
char a68kopts[128];    /* a68k options		    */
char zctemp[128];     /* CCTEMP dir		   */
char blinkopts[128]; /* blink options		  */
char buf[256];	    /* command line		 */
char buf2[256];    /* scratch buf		*/

/* memory allocation/deallocation routines */
struct mem {
struct mem *prev;
long len;
char *memory;
} *curmem;


char *jmalloc(n)
long n;
{
char *buf;
struct mem *memlist;
buf=(char *)malloc( n+(long )sizeof(struct mem));
if(!buf){
    printf("cc: outofmemory\n");
    quit();
}
memlist=(struct mem *)buf;
memlist->len=n;
memlist->memory=buf+sizeof(struct mem);
memlist->prev=curmem;
curmem=memlist;
return(memlist->memory);
}

quit()
{

  jfree();
  exit(0);
}

jfree(){
struct mem *nxmem;

while(curmem != NULL){
  nxmem=curmem->prev;
  free(curmem);  /* frees all the memory we so graciously gobbled up */
  curmem=nxmem;
}
}/*end of jfree */



/*********************************************************

  Handles file list compiles,assembles,links

**********************************************************/


/* lists of source file names, as well as type of operation */

struct filenm{
  struct filenm *next;
  struct filenm *prev;
  short ab;	 /* abnormal file name */
  short zc;	  /* 1 if .c file */
  short a68k;	  /* 1 if .s file */
  char *name;
}*files,*curfile;


#define copystring( x )  (char *)strcpy( jmalloc( (long )len((char *) x )), x )


/* adds a file to the file list
 *   computes whether an compile and/or assembly will be done
 *   also determines whether this is an abnormal file name.
 *   If so then only a link will be done on the file
 */
struct filenm *addfile(name)
char name[];
{
long l;
struct filenm *newfile;
char *filename;

newfile = (struct filenm *)jmalloc(sizeof(struct filenm));
newfile->prev = curfile;
newfile->next = NULL; /* last file so far */
if(curfile)
   curfile->next = newfile;
else
   files = newfile;
curfile = newfile;
filename = (char *) copystring( (char *)name);
curfile->name=filename;    /* contains the new filename */
l=len(filename);

curfile->ab=0; /* assume it is normal until proven otherwise */
curfile->zc=0;
curfile->a68k=0;

if(filename[l-2] == '.'){
  if(filename[l-1]== 'c'){
     curfile->zc = 1;
     curfile->a68k=1;
  }else if (filename[l-1] == 'a' || filename[l-1] == 's'){
     curfile->a68k=1;
  }else if(filename[l-1] != 'o')
     curfile->ab = 1; /* abnormal file name */
}else
  curfile->ab = 1; /* abnormal file name */
}/* end of addfile */



long len(x)
char x[];
{
long i;

for(i=0; x[i] != 0 ; i++);
return(i);
}




char *tofiletype(nm,buffer,ext1,ext2)
char nm[],buffer[],ext1[],ext2;
{
long l;

strcpy(buffer,nm);
l=len(buffer);
if(l < 2 || ( buffer[l-2] != '.') ){
  strcat(buffer,ext1);
  return(buffer);
}
if(ext2)
  buffer[l-1] = ext2;
else
  buffer[l-2] = '\0'; /* must be executable */
return(buffer);
}/*end of tofiletype */

#define toassem( x ) tofiletype( x ,a68kname,".s ",'s')
#define tolink( x ) tofiletype( x ,blinkname,".o ",'o')
#define toexec( x ) tofiletype( x ,blinkname,".lnk ",'\0')

doerrors()
{
FILE *err;
int nmerrors;

  if( (err=fopen("ram:zc.errors","r"))==NULL)
     return();
  nmerrors=0;
  fscanf(err,"%d",&nmerrors);
  close(err);
  if(nmerrors)
     quit();
  return(); /* no errors thank goodness */
}


/* this assembles the file */
assemfile(nm,outnm)
char nm[],outnm[];
{

strcpy(buf,cmddir);
strcat(buf,"a68k <* >* ");
strcat(buf,a68kopts);
strcat(buf,"-o");
strcat(buf,outnm);
strcat(buf," ");
strcat(buf,nm);
Chk_Abort();
doexec(buf,"cc: assemble error: %s\n",nm);
}/*end of assemfile*/

/* compiles and/or assembles the files in the file list */
compilefiles(){
struct filenm *file;
char nm[];

file=files;
while(file){
  toassem(file->name);/* use this as the input to a68k
		       * unless updated below	       */
  if(file->zc && dozc ){
     strcpy(buf,cmddir);
     strcat(buf,"zc >* <* -Eram:zc.errors ");
     strcat(buf,zcopts);
     strcat(buf," ");
     if( (file->a68k && doa68k) || file->ab){
       strcat(buf," -O");
       if(file->a68k && doa68k)
	 strcpy(buf2,zctemp);  /* use temp file if doing an assemble */
       else
	 buf2[0]='\0';
       strcat(buf2,file->name);
       strcat(buf,toassem(buf2));/* use designated outputfile */
     }
     strcat(buf," ");
     strcat(buf,file->name);
     Chk_Abort();
     doexec(buf,"cc: compile error: %s\n",file->name);/* start compiler */
     doerrors(); /* read error file to see if any errors */
  }   /* compiled okay */
  if(file->a68k && doa68k){
     assemfile(a68kname,tolink(file->name)); /* assemble file */
     if(file->zc){ /* if was a c file remove .s file */
       strcpy(buf,"c:delete >* <* ");
       strcat(buf,a68kname);
       Chk_Abort();
       doexec(buf,"cc: delete error: %s\n",a68kname);
     }
  }
  file=file->next;/* get next file */
}/* done with this file, compile & assemble next */
}/* done with files */


linkfiles(){
struct filenm *file;
char nm[];

if(!doblink || files == NULL ) return();/* don't do anything if not supposed to */
file=files;
strcpy(buf,cmddir);
strcat(buf,"blink <* >* ");
if(startup){
  strcat(buf,libdir);
  strcat(buf,"BothStartup.obj ");
}
while(file){
  strcat(buf,tolink(file->name));/* build linker list */
  file = file->next;
  strcat(buf," ");
}
strcat(buf," TO ");
strcat(buf,toexec(files->name));/* use first file name */
strcat(buf," LIB ");
strcat(buf,blinklibs);
if(standardblinklib){
   strcat(buf,libdir);
   strcat(buf,"amiga.lib ");
}
if(!dodebug)
  strcat(buf," NODEBUG ");
if(blinkxref){
  strcat(buf," XREF ");
  strcat(buf,xrefname);
}
Chk_Abort();
doexec(buf,"cc: linker error:\n",NULL);
printf("cc: executable is %s \n",toexec(files->name));
}/* done linking it */


help()
{

  printf("cc: Version 1.0 Preprocessor for \n%s%s%s%s%s%s%s%s%s%s%s%s%s",
	 "   cc: Sozobon-C compiler, \n",
	 "   as: a68k C.Gibbs Motorola Compatible Assembler, and\n",
	 "   blink:  Software Distillery Linker \n",
	 "           looks for lib:amiga.lib and lib:BothStartup.obj \n",
	 "   Syntax:\n",
	 "           cc [OPTIONS] <files.c> <files.s> <files.o> \n\n",
	 "   Options:\n",
	 "    -Dxxxx   define xxxx,   -Uxxxx undefine xxxx\n",
	 "    -C    data->chip,       -F data->fast\n",
	 "    -S  don't use startups, -T don't use amiga.lib\n",
	 "    -A    don't assemble,   -c don't link\n",
	 "    -Ixxxx  include dir,    -V printout actions only\n",
	 "    -lxxxx  use library  lib:xxxx.lib\n");
}

main(argc,argv)
int argc;
char *argv[];
{
  int i, l;
  char *s;

  printf("cc: \n");
  if(argc < 2 || argv[1][0] == '?'){
     help();
     exit(0);
  }
  startup=standardblinklib=1;/* use BothStartup.obj & amiga.lib */
  blinklibs[0]='\0';       /* blink lib direc           */
  blinkname[0]='\0';      /* output file from a68k     */
  a68kname[0]='\0';      /* output file from zc       */
  zcopts[0]='\0';       /* zc options for each phase */
  a68kopts[0]='\0';    /* a68k options              */
  zctemp[0]='\0';     /* CCTEMP dir                */
  blinkopts[0]='\0'; /* blink options             */
  buf[0]='\0';      /* command line              */
  buf2[0]='\0';    /* scratch buf               */

  dodebug=debug=0;
  dozc=doa68k=doblink=1;/* will compile,assem,link unless told otherwise*/
  curmem=NULL;/* haven't grabbed any memory yet*/
  files=NULL;
  curfile=NULL;
  blinkxref=0;
  strcpy(xrefname," ");

  if( getenv("CCLIB") ){
      strcpy(libdir," ");
      strcat(libdir,getenv("CCLIB")); /* get libdirector */
  }else
      strcpy(libdir," lib:"); /* default directory */
  if( ! getenv("CCEXEC") )
      strcpy(cmddir,"c:");
  else{
      strcpy(cmddir,getenv("CCEXEC")); /*dir for zc,a68k,blink */
  }
  if( getenv("CCTEMP") ){
     strcpy(zctemp,getenv("CCTEMP"));
  }else{
     printf("cc:Warning, environment variable CCTEMP unset\n   Using ram: \n");
     strcpy(zctemp,"ram:");
  }
  if( ! getenv("INCLUDE")){
     printf("cc: Warning, environment variable INCLUDE unset\n");
  }else{
     strcpy(a68kopts," -I");
     strcat(a68kopts,getenv("INCLUDE") );
  }
  for(i = 1; i < argc; i++){/* parse arguments */
     Chk_Abort();  /* Do options */
     if(argv[i][0] == '+'){
	s = argv[i];
	switch(s[1]){
	   default:
	      printf("cc: No + switches allowed\n");
	      break;
	}
      }else if(argv[i][0] == '-' ){
	s = argv[i];
	switch(s[1]){
	   case 'A':
	   case 'a':
	     doblink = doa68k = 0;
	     break;
	   case 'C':  /* force data into chip memory */
	     strcat(zcopts," -C ");
	     break;
	   case 'c':
	     doblink = 0;
	     break;
	   case 'd':
	   case 'D':
	     strcat(zcopts," -D");
	     strcat(zcopts,&s[2]);
	     break;
	   case 'F':
	     strcat(zcopts," -F ");
	     break;
	   case 'i':
	   case 'I':
	     strcat(zcopts," -I");
	     strcat(zcopts,&s[2]);
	     break;
	   case 'l':
	     strcat(blinklibs," -l");
	     strcat(blinklibs,&s[2]);
	     strcat(blinklibs," ");
	     break;
	   case 'T':
	     standardblinklib=0; /* don't use amiga.lib */
	     break;
	   case 'S':
	     startup = 0;/* don't use BothStartup.obj */
	     break;
	   case 'u':
	   case 'U':
	     strcat(zcopts," -U");
	     strcat(zcopts,&s[2]);
	     break;
	   case 'v':
	   case 'V':
	     debug = 1;
	     break;
	   default:
	     printf("bad option: \"%s\"\n", argv[i]);
	     exit(1);
	     break;
	}
     }else  /* argument wasn't an option so must be a file  */
	addfile(argv[i]);/* add filename to list of files */
  }/* done with parsing arguments */
  compilefiles(); /* compile all the files */
  linkfiles();   /*  link all the files */
  quit();/* cleanup mess and go home */
}

SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.