/* ****************************************************************************** */
/* *										* */
/* *										* */
/* *	##    ##   ######    ######   ##    ##	##    ##  ######    #######	* */
/* *	###  ###  ########  ########  ##   ##	##    ##  #######   ########	* */
/* *	########  ##	    ##	  ##  ##  ##	##    ##  ##	##  ##	  ##	* */
/* *	## ## ##  #######    ######   ####	########  ##	##  ########	* */
/* *	##    ##  ##	##  ##	  ##  ## ##	##    ##  ##	##  #######	* */
/* *	##    ##  ##	##  ##	  ##  ##  ##	##    ##  ##	##  ##	##	* */
/* *	##    ##   ######   ########  ##   ##	##    ##  #######   ##	 ##	* */
/* *	##    ##    ####     ######   ##   ##	##    ##  ######    ##	  ##	* */
/* *										* */
/* *										* */
/* ****************************************************************************** */
/* ****************************************************************************** */
/* *										* */
/* *  There are certain portions of the code which are dependent to particular	* */
/* *  machines and operating systems, and these are surrounded by conditional	* */
/* *  compilation tags. 							* */
/* *										* */
/* *	      TAG	 Computer				   O/S		* */
/* *	      ---	 --------				   ---		* */
/* *										* */
/* *	      68K	 Sage IV MC68000 computer		   (TRIPOS)	* */
/* *	      U42	 Sun MC68000 computer			   (UNIX 4.2)	* */
/* *	      AMI	 Amiga 68000				   (AMIGADOS)	* */
/* *										* */
/* ****************************************************************************** */
/* *  P J Floyd (from an original BCPL verion by I D Wilson)			* */
/* *										* */
/* *  Last Modified:	11-APR-85    (PJF)					* */
/* ****************************************************************************** */

#include <stdio.h>
#include <sys/file.h>

/* local kludges: need close comment Neil */
#define setjmp	_setjmp
#define longjmp	_longjmp

/*  Global variables */
/*  ================ */

int  aborted;		  /*   Logical */
int  abscodewords;	  /*   Integer (16 bit) */
int  absrp16;		  /*   Integer (16 bit) */
int  absrp32;		  /*   Integer (16 bit) */
int  asmlabel;		  /*   Integer (16 bit) */
long *bavec;		  /*   Base addresses (32 bit) */
int  bracount;		  /*   Integer (16 bit) */
int  bsswords;		  /*   Integer (16 bit) */
int  bytesonline;	  /*   Integer (8 bit) */
int  ch; 		  /*   character */
int  charpos;		  /*   Integer (8 bit) */
int  charsperline;	  /*   Integer (8 bit) */
int  *codebuff;		  /*   Buffer to store code generated for a line */
int  codentimes; 	  /*   Integer (16 bit) */
SCBPTR codestream;	  /*   scb ptr */
string codevec;		  /*   Vector of bytes	*/
int  codewords;		  /*   Integer (16 bit) */
int  commentline;	  /*   Logical */
int  crossreference;	  /*   Logical */
string *cvecs;		  /*   Vector of ptrs to code buffers */
int  dataptr;		  /*   Integer */
VAR16BIT *datavector;	  /*   Vector of 16 bit values */
string datestring;	  /*   String */
int  dest_ea;		  /*   Integer (16 bit) */
int  directive;		  /*   Integer (8 bit) */
int  dumpsymbols;	  /*   Logical */
int  ended;		  /*   Logical */
struct XDEFNODE *entrysymbols;	/*   List pointer */
int  error_found;	  /*   Logical */
int  errormessages;	  /*   Logical */
int  errors;		  /*   Integer (8 bit) */
int  *errorvec;		  /*   Vector of integers */
long exp;		  /*   Integer (32 bit) */
int  exptype;		  /*   Integer (16 bit) */
int  *expvec;		  /*   Pointer */
int  *expvecp;		  /*   Pointer */
int  extrnref;		  /*   Logical */
struct SYMNODE *extrnlsymb;	/*   Ptr to structure */
struct XREFNODE *extrnsymbols;	/*   List ptr */
int  failed;		  /*   Logical */
jmp_buf fatalerrorp;	  /*   Label */
int  fwdref;		  /*   Logical */
int  fwdreftype; 	  /*   Integer (8 bit) */
int  getlevel;		  /*   Integer (8 bit) */
int  getlocallabel;	  /*   Logical */
int  in_movem;		  /*   Logical */
int  inmacro;		  /*   Logical */
string inputbuff;	  /*   Vector */
int  instr_mask; 	  /*   Integer (16 bit) */
int  inst_masktype;	  /*   Integer (8 bit) */
int  instr_size; 	  /*   Integer (8 bit) */
int  labelset;		  /*   Logical */
string labelvec; 	  /*   String */
int  length;		  /*   Integer (8 bit) */
int  linepos;		  /*   Integer (16 bit) */
int  linesperpage;	  /*   Integer (8 bit) */
int  listed;		  /*   Logical */
int  listing;		  /*   Logical */
int  listlinenumber;	  /*   Integer (16 bit) */
SCBPTR liststream;	  /*   scb ptr */
int  llenfixed;		  /*   Logical */
int  locallabel; 	  /*   Logical */
int  loclabelset;	  /*   Logical */
long location;		  /*   Integer (32 bit) */
int  locmode;		      /*   Integer (8 bit) */
struct MACRONODE *macrobase;   /*   Pointer to structure */
int macrodepth;		      /*   Integer (8 bit) */
struct MACRONODE *macroend;    /*   Pointer to structure */
string macroname;	  /*   String */
long maxloc;		  /*   Integer (32 bit) */
long minloc;		  /*   Integer (32 bit) */
int  maxextlength;	  /*   Integer (8 bit) */
int  maxsectnumber;	  /*   Integer (8 bits) */
string name_hdrfile;	  /*   String */
int  nargs;		  /*   Integer (8 bit) */
struct REFNODE *nargstack; /*   Pointer */
int  nitems;		  /*   Integer (16 bit) */
int  noobj;		  /*   Logical */
long number;		  /*   Integer (32 bit) */
int  objectmodule;	  /*   Integer (8 bit) */
int  onpage;		  /*   Integer (16 bit) */
int  op_ea;		  /*   Integer (16 bit) */
int  op1_ea;		  /*   Integer (16 bit) */
long op1_exp;		  /*   Integer (32 bit) */
int  op1exptype; 	  /*   Integer (8 bit) */
int  op1_extrnref;	  /*   Logical */
struct SYMNODE *op1extrnlsymb;	   /*	Ptr to structure */
struct EXPRESSNODE *op1_registers;  /*	Pointer */
int  op1_relocation_needed;	   /*	Logical */
int  op1reloc_wrt;	  /*   integer (8 bits) */
string outbuff;		  /*   String */
int  pagenumber; 	  /*   Integer */
int  paging;		  /*   Logical */
int  parmlisting;	  /*   Logical */
int  pass1;		  /*   Logical */
int  pass2;		  /*   Logical */
int  plenfixed;		  /*   Logical */
string PUname;		  /*   String */
jmp_buf rdsymlevel;	  /*   C stack pointer */
jmp_buf recoverlevel;	  /*   C stack pointer */
struct EXPRESSNODE  *registers;	/*   Pointer */
int  regnum;		  /*   Integer (8 bits) */
int  release;		  /*   Integer (8 bits) */
struct RELOCNODE *reloc16info;	 /*   List pointer */
struct RELOCNODE *reloc32info;	 /*   List pointer */
int  reloc_16count;	  /*   Integer (16 bits) */
int  reloc_32count;	  /*   Integer (16 bits) */
int  relcodewords;	  /*   Integer (16 bit) */
int  relocation_needed;	  /*   Logical */
int  reloc_wrt;		  /*   Integer (8 bit) */
int  relrp16;		  /*   Integer (16 bit) */
int  relrp32;		  /*   Integer (16 bit) */
struct SECTNODE *sectionlist;	 /*   List pointer */
int  sectnumber; 	  /*   Integer (8 bits) */
struct SECTNODE *sectptr;  /*   Vector */
int  secttype;		  /*   Integer (8 bits) */
int  skiplevel;		  /*   Integer (8 bit) */
int  skipping;		  /*   Logical */
int  source_ea;		  /*   Integer (16 bit) */
int  sourcelinenumber;	  /*   Integer (16 bit) */
FILE *sourcestream;	  /*   scb pointer */
struct NEWVECNODE *stvec;  /*   Result of GETVEC */
struct NEWVECNODE *stvecp; /*   Result of GETVEC */
int  stvecupb;		  /*   Workspace size */
int  symb;		  /*   Integer (16 bit) */
struct SYMNODE *symbtype;  /*   Pointer to structure */
SCBPTR sysout;		  /*   scb pointer */
int  systemwords;	  /*   Logical */
int  symbcount;		  /*   Integer (16 bit) */
int  tagsize_given;	  /*   Logical */
struct SYMNODE **tagtable; /*   Vector */
string tagv;		  /*   String */
string timestring;	  /*   String */
string titlevec; 	  /*   String */
int  totalwords; 	  /*   Integer (16 bit) */
int  ts_default; 	  /*   Integer (8 bit) */
int  *typevec;		  /*   Vector */
int  undefined;		  /*   Logical */
long value;		  /*   Integer (32 bit) */
int  version;		  /*   Integer (8 bit) */
SCBPTR verstream;	  /*   scb pointer */
int  (*wrchsave)();	  /*   Pointer to WRCH */
struct CROSSREFNODE *xreftable;	    /*	 Pointer */
int  xref;		  /*   Logical */
int  UCflag;		  /*   Logical */
struct DIRNODE *dir_incl;  /*   Pointer to linked list */
int no_labels;		  /*   Logical */
string name_sourcestream;  /*   String  */
struct FNAMENODE *current_filename;  /*   String  */
int warnings;              /*   Integer */
int output_local_labels;   /*   Logical */
string name_codestream;    /*   String  */
struct FNAMENODE *current_directory;  /*   Hold for includes */

/*   Basic constants	*/
/*   ===============	*/
#define tagtablesize 500
#define expsize 100
#define titlecharsmax 132
#define codesize 100
#define errorsize 200
#define maxllen 200
#define minllen 60
#define maxplen 200
#define minplen 20
#define tabspace 8
#define maxmacrodepth 10
#define maxgetlevel 10


/*   Symbol types  (for symbol table) */
/*   ================================ */

#define s_abs16  0   /*  Tag with absolute value  (16 bit address) */
#define s_abs32  1   /*  Tag with absolute value  (32 bit address) */
#define s_dir	 2   /*  Assembler directive */
#define s_rel	 3   /*  Relocatable symbols */
#define s_instr  4   /*  Instruction mnemonic */
#define s_new	 5   /*  New entry in the symbol table */
#define s_Dr	 6   /*  Data register */
#define s_Ar	 7   /*  Address register */
#define s_SR	 8   /*  Status Register */
#define s_CCR	 9   /*  Condition Codes Register */
#define s_USP	10   /*  User stack pointer */
#define s_SP	11   /*  SP is equivalent to A7 */
#define s_PC	12   /*  Program Counter */
#define s_macro 13   /*  User defined macro name */
#define s_ext	14   /*  Externally defined symbols */
#define s_reg	15   /*  Symbol defined via REG */

/*   Other symbol types (do not appear in symbol table) */
/*   ================================================== */
#define s_star	   16	/*  Location counter Symbol */
#define s_none	   17	/*  A NULL symbol (space or newline) */
#define s_bra	   18	/*  Left parenthesis */
#define s_number   19	/*  Number (123. or 'e', say) */
#define s_operator 20	/*  Operator */
#define s_slash    21
#define s_hyphen   22	/*  Symbols for MOVEM */

/*   Operators	   */
/*   =========	   */

#define s_plus	      23
#define s_minus       24
#define s_over	      25
#define s_times       s_star
#define s_logand      26
#define s_logor       27
#define s_lshift      28
#define s_rshift      29
#define s_Ar_indirect 30
#define s_Ar_postincr 31
#define s_Ar_predecr  32
#define s_ket	      33
#define s_literal     34
#define s_colon       35
#define s_monminus    36
#define s_abs	      37
#define s_comma       38
#define s_opapply     39
#define s_not	      40
#define s_desc	      41

/*   A number big enough to mask off 's.xxx' */

#define s_mask 0x3F   /*  (32+16+8+4+2+1 = 63) */

/*   Instruction types	 */
/*   =================	 */

#define i_zop 0x0    /*  No operands for this instruction */
#define i_1op 0x8    /*  One operand for this instruction */
#define i_2op 0x10   /*  Two operands for this instruction */

/*   Possible instruction sizes */
/*   ========================== */

#define size_b 0x1
#define size_w 0x2
#define size_l 0x4
#define size_bw ( size_b + size_w )
#define size_wl ( size_w + size_l )
#define size_bwl ( ( size_b + size_w ) + size_l )
#define size_bl ( size_b + size_l )

/*   Instruction combinations with the Number of operands, and */
/*   the sizes of instructions allowed */

#define ins_zop       ((i_zop << 8) + s_instr)
#define ins_1op       ((i_1op << 8) + s_instr)
#define ins_2op       ((i_2op << 8) + s_instr)
#define ins_1op_b     (((i_1op + size_b)  << 8) + s_instr)
#define ins_1op_w     (((i_1op + size_w)  << 8) + s_instr)
#define ins_1op_l     (((i_1op + size_l)  << 8) + s_instr)
#define ins_1op_bw    (((i_1op + size_bl) << 8) + s_instr)
#define ins_1op_wl    (((i_1op + size_wl) << 8) + s_instr)
#define ins_1op_bwl   (((i_1op + size_bwl) << 8) + s_instr)
#define ins_1op_bl    (((i_1op + size_bl) << 8) + s_instr)
#define ins_2op_b     (((i_2op + size_b)  << 8) + s_instr)
#define ins_2op_w     (((i_2op + size_w)  << 8) + s_instr)
#define ins_2op_l     (((i_2op + size_l)  << 8) + s_instr)
#define ins_2op_bw    (((i_2op + size_bw) << 8) + s_instr)
#define ins_2op_bl    (((i_2op + size_bl) << 8) + s_instr)
#define ins_2op_wl    (((i_2op + size_wl) << 8) + s_instr)
#define ins_2op_bwl   (((i_2op + size_bwl) << 8) + s_instr)

/*   Variants of the 'Special Instructions' */
/*   ====================================== */
#define ins_N 0   /*  The ordinary instruction (e.g. CMP) */
#define ins_A 1   /*  (e.g. CMPA) */
#define ins_I 2   /*  (e.g. CMPI) */
#define ins_M 3   /*  (e.g. CMPM) */
#define ins_Q 4   /*  (e.g. ADDQ) */

/*   Instruction templates */
/*   ===================== */

#define m_ADD  0xD000
#define m_ADDI 0x600
#define m_AND  0xC000
#define m_ANDI 0x200
#define m_CMP  0xB000
#define m_CMPI 0xC00
#define m_CMPM 0xB108
#define m_EOR  0xB100
#define m_EORI 0xA00
#define m_OR   0x8000
#define m_ORI  0x0
#define m_SUB  0x9000
#define m_SUBI 0x400

/*   Directives */
/*   ========== */
#define d_equ 0
#define d_equr 1
#define d_set 2
#define d_org 3
#define d_rorg 4
#define d_dc 5
#define d_ds 6
#define d_page 7
#define d_list 8
#define d_nolist 9
#define d_nol 9
#define d_spc 10
#define d_nopage 11
#define d_llen 12
#define d_plen 13
#define d_ttl 14
#define d_noobj 15
#define d_ifeq 17
#define d_ifne 18
#define d_iflt 19
#define d_ifle 20
#define d_ifgt 21
#define d_ifge 22
#define d_endc 23
#define d_macro 24
#define d_endm 25
#define d_mexit 26
#define d_end 27
#define d_fail 28
#define d_get 29
#define d_cnop 30
#define d_extrn 31
#define d_entry 32
#define d_section 33
#define d_offset 34
#define d_mask2 35
#define d_idnt 36
#define d_format 37
#define d_noformat 38
#define d_reg 39
#define d_dcb 40
#define d_text 41
#define d_data 42
#define d_bss 43
#define d_ifc 44
#define d_ifnc 45
#define d_abs 46
#define d_ifd 47
#define d_ifnd 48

/*   Other assorted constants */
/*   ======================== */

#define tagchars 30
#define tagsize ((tagchars/bytesperword) + 1)
#define yes true
#define no false


/*   Symbol table type bits */
/*   ====================== */

#define stb_muldef 0x1
#define stb_setnow 0x2
#define stb_setever 0x4
#define stb_equ 0x8
#define stb_set 0x10
#define st_type_mask 0xF

/*   Special cross-reference values */
/*   ============================== */

#define cr_undefined  - 1
#define cr_multiple   - 2
#define cr_setsymbol  - 3

/*   Address Mode Type Bits */
/*   ====================== */

#define am_Dr 0x1
#define am_Ar 0x2
#define am_Ar_ind 0x4
#define am_Ar_pi 0x8
#define am_Ar_pd 0x10
#define am_Ar_disp 0x20
#define am_Ar_index 0x40
#define am_abs16 0x80
#define am_abs32 0x100
#define am_PC_disp 0x200
#define am_PC_index 0x400
#define am_imm3 0x800
#define am_imm16 0x1000
#define am_imm32 0x2000
#define am_imm 0x3800
#define am_special 0x4000
#define am_all 0x3FFF
#define am_A_all (am_Ar_ind + am_Ar_pi + am_Ar_pd + am_Ar_disp + am_Ar_index)
#define am_data (am_Dr+am_A_all+am_abs16+am_abs32+am_PC_disp+am_PC_index+am_imm)
#define am_mem	(am_A_all+am_abs16+am_abs32+am_PC_disp+am_PC_index+am_imm)
#define am_alt	(am_Dr+am_Ar+am_A_all+am_abs16+am_abs32)
#define am_mem_alt  ( am_mem & am_alt )
#define am_data_alt  ( am_data & am_alt )
#define am_contr  (am_Ar_ind+am_Ar_disp+am_Ar_index+am_abs16+am_abs32+am_PC_disp+am_PC_index)
#define am_contr_alt  ( am_contr & am_alt )

/*   Effective address types */
/*   ======================= */

#define ea_R_disp      1
#define ea_R_index     2
#define ea_exp	       3
#define ea_literal     4

/*   Tag size specifiers */
/*   =================== */

#define ts_byte        1
#define ts_word        2
#define ts_long        3
#define ts_short       4
#define ts_none        0

/*   Object module types available. */
/*   ============================== */

#define o_none	       0
#define o_tripos       1
#define o_motorola     2
#define o_intelhex     3
#define o_unix4_2      4
#define o_amiga        5

/*   Tripos object module identifiers. */
/*   ================================= */

#define t_hunk		1000
#define t_reloc 	1001
#define t_end		1002
#define t_abshunk	1003
#define t_absrel	1004
#define t_symbols	2001
#define t_reloc32	t_reloc
#define t_reloc16	1010
#define t_absrel32	t_absrel
#define t_absrel16	1011
#define t_ext		1005

#define ext_defrel	   1
#define ext_defabs	   2
#define ext_ref 	 129


/*   Unix object module identifiers.   */
/*   ================================= */

#define bytes_per_reloc_symbol	   8
#define bytes_per_symbol	  12

#define omagic			  0x107
#define nmagic			  0x108
#define n_undf			  0x0
#define n_abs			  0x2
#define n_text			  0x4
#define n_data			  0x6
#define n_bss			  0x8
#define n_comm			  0xC
#define n_fn			  0x1F
#define n_ext			  0x1
#define n_other 		  0x0
#define n_desc			  0x0
#define r_pcrel 		  0x80
#define r_length32		  0x40
#define r_length16		  0x20
#define r_length8		  0x0
#define r_extern		  0x10

/*   Amiga object module identifiers. */
/*   ================================= */

#define hunk_unit		   999
#define hunk_name		  1000
#define hunk_code		  1001
#define hunk_data		  1002
#define hunk_bss		  1003
#define hunk_reloc32		  1004
#define hunk_reloc16		  1005
#define hunk_reloc8		  1006
#define hunk_ext		  1007
#define hunk_symbol		  1008
#define hunk_debug		  1009
#define hunk_end		  1010

#define ext_symb		     0
#define ext_def 		     1
#define ext_ref32		   129
#define ext_common		   130
#define ext_ref16		   131
#define ext_ref8		   132

/*   Return codes */
/*   ============ */

#ifdef TRIPOS
#define rc_catastrophic 10
#define rc_aborted 20
#define rc_error_found 10 
#define rc_warning_given 5
#endif

#ifdef U42
#define rc_catastrophic 10
#define rc_aborted 20
#define rc_error_found 10 
#define rc_warning_given 5
#endif

#ifdef AMI
#define rc_catastrophic 10
#define rc_aborted 20
#define rc_error_found 10 
#define rc_warning_given 5
#endif


/* Structures */
/* ========== */


struct REFNODE {
     struct REFNODE *link;
     int    value;
     };


struct SYMNODE {
     struct SYMNODE *st_link;
     struct REFNODE *st_references;
     long  st_value;
     short st_value_low;
     short st_value_high;
     short st_flags;
     short st_definition;
     short st_number;
     short st_type;
     union {
       struct SYMNODE	*st_xref;
       struct MACRONODE *st_macro;
       int st_template;
     } uval;
     string st_name;
   };


struct RELOCNODE {
     struct RELOCNODE *link;
     long   address;
     short  sectno;
     short  wrt;
   };


struct CROSSREFNODE {
     struct SYMNODE *symbol;
     struct CROSSREFNODE *left;
     struct CROSSREFNODE *right;
     };

struct XDEFNODE {
     struct XDEFNODE *link;
     struct SYMNODE *symbol;
     };

struct XREFNODE {
     struct XREFNODE  *e_link;
     struct SYMNODE   *e_symbol;
     struct RELOCNODE *e_refs32;
     struct RELOCNODE *e_refs16;
     struct RELOCNODE *e_refs8;
     int e_count32;
     int e_count16;
     int e_count8;
     };


struct SECTNODE {
     struct SECTNODE *sect_link;
     string sect_name;
     string sect_codevec;
     short sect_type;
     short sect_number;
     long  sect_min;
     long  sect_max;
     long  sect_loc;
     };


struct MACRONODE {
     string lineptr;
     short  length;
     struct MACRONODE *link;
     };


struct EXPRESSNODE {
    int type;
    union {
      struct EXPRESSNODE *eptr;
      long longvalue;
      int  intvalue;
      } uvalleft;
    union {
      struct EXPRESSNODE *eptr;
      int value;
      } uvalright;
   };


struct SVNODE {
   int type;
   int size;
   long value;
   int extref;
   struct SYMNODE *extsymb;
   };


struct DIRNODE {
   struct DIRNODE *link;
   string file;
   };


struct FNAMENODE {
   struct FNAMENODE *link;
   string fname;
   };

struct NEWVECNODE {
   struct NEWVECNODE *link;
   int length;
   };


/* NEWVEC constants */

#define NEWNODEPTRSIZE ((sizeof(struct NEWVECNODE)-1)/BYTESPERWORD + 1)
#define newvecmax ((8<<10)/BYTESPERWORD)
#define newveclimit (newvecmax+NEWNODEPTRSIZE)
#define newvecsize (newveclimit-1)
