www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1998/06/30/09:13:52

Sender: bill AT taniwha DOT tssc DOT co DOT nz
Message-ID: <3598E41B.936A7C26@taniwha.tssc.co.nz>
Date: Wed, 01 Jul 1998 01:11:55 +1200
From: Bill Currie <bill AT taniwha DOT tssc DOT co DOT nz>
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: djasm patches

This is a multi-part message in MIME format.
--------------A470A987EB9B1A7BBE411DB9
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I know DJ said only safe bug fixes, but I want to get this in before I
forget and some of the chages ARE safe bugfixes, or at least fairly well
tested.

Changes include:
 o More instructions and addressing modes
 o Better `.' (PC) support (`.' always points to the beginning
   of the current instruction)
 o `.struct' tweeks
 o Most of the error messages conform to the GNU standard 
   or at least gcc (should be usable with emacs error parsing)
 o Map file output works with include files.
 o Extreamly rudimentary .obj (OMF) output support.
 o Misc bug fixes (eg incorrect relocation mode for pushd)
 o Ported to Linux

Due to DJ's request mestioned above, I don't EXPECT this to get into the
source before 2.02 comes out, but it would be nice as this brings the
official and unofficial versions of djasm into line (I don't do alot of
programming at home at the moment, so the next set of patches could be a
while, but then again...:).

Bill
-- 
Leave others their otherness.
--------------A470A987EB9B1A7BBE411DB9
Content-Type: text/plain; charset=us-ascii; name="djasm.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="djasm.diff"

*** src/stub/djasm.y	Sat May 30 19:44:22 1998
--- /home/bill/src/djasm/djasm.y	Wed Jul  1 00:45:06 1998
***************
*** 1,5 ****
- /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
- /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
  /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  %{
  
--- 1,3 ----
***************
*** 7,22 ****
    
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
- #include "../../include/coff.h"
  #include <fcntl.h>
  #include <time.h>
  #include <ctype.h>
  #include <unistd.h>
- 
  #ifndef O_BINARY
  #define O_BINARY 0
  #endif
  
  #define SMALL_EXE_HEADER 0
  #if SMALL_EXE_HEADER
--- 5,21 ----
    
  #include <stdio.h>
  #include <stdlib.h>
+ #include <stdarg.h>
  #include <string.h>
  #include <fcntl.h>
  #include <time.h>
  #include <ctype.h>
  #include <unistd.h>
  #ifndef O_BINARY
  #define O_BINARY 0
  #endif
+ #undef _POSIX_SOURCE
+ #include "coff.h"
  
  #define SMALL_EXE_HEADER 0
  #if SMALL_EXE_HEADER
***************
*** 32,37 ****
--- 31,37 ----
  #define MAX(a,b) ((a)>(b)?(a):(b))
  #define MIN(a,b) ((a)<(b)?(a):(b))
  
+ void djerror(char *s);
  void yyerror(char *s);
  
  #define OUT_exe 0
***************
*** 41,46 ****
--- 41,47 ----
  #define OUT_inc 4
  #define OUT_s   5
  #define OUT_sys 6
+ #define OUT_obj 7
  
  char *ext_types[] = {
    "exe",
***************
*** 50,55 ****
--- 51,57 ----
    "inc",
    "ah",
    "sys",
+   "obj",
    0
  };
  
***************
*** 77,82 ****
--- 79,85 ----
  typedef struct {
    short line;
    short addr;
+   char *name;
  } lineaddr_s;
  
  lineaddr_s *lineaddr=0;
***************
*** 90,101 ****
  int stack_ptr = 0;
  int start_ptr = 0;
  int movacc = 0;
  
  typedef struct Symbol {
    struct Symbol *next;
    char *name;
    int value;
!   int defined;
    struct Patch *patches;
    int first_used;
    int type;
--- 93,107 ----
  int stack_ptr = 0;
  int start_ptr = 0;
  int movacc = 0;
+ int main_obj = 1;
  
  typedef struct Symbol {
    struct Symbol *next;
    char *name;
    int value;
!   unsigned defined:1;
!   unsigned external:1;
!   unsigned public:1;
    struct Patch *patches;
    int first_used;
    int type;
***************
*** 107,112 ****
--- 113,120 ----
  #define SYM_code	4
  #define SYMTYPES "?ADDTTTT"
  
+ Symbol pc_symbol = {0,".",0,1,0,0,0,0,SYM_code};
+ 
  #define REL_abs		0
  #define REL_abs32	1
  #define REL_16		2
***************
*** 117,122 ****
--- 125,131 ----
    struct Patch *next;
    int location;
    int lineno;
+   char *filename;
    int rel;
  } Patch;
  
***************
*** 124,135 ****
  Symbol *get_symbol(char *name, int create);
  Symbol *set_symbol(Symbol *sym, int value);
  Symbol *zerosym;
  void destroy_symbol(Symbol *sym, int undef_error);
  void destroy_locals(void);
  void add_struct_element(Symbol *s);
  void emit_struct(Symbol *ele, int tp, Symbol *struc);
  void build_struct(Symbol *ele, int tp, Symbol *struc);
- int undefs = 0;
  
  struct {
    int regs;
--- 133,146 ----
  Symbol *get_symbol(char *name, int create);
  Symbol *set_symbol(Symbol *sym, int value);
  Symbol *zerosym;
+ int undefs = 0;
+ 
  void destroy_symbol(Symbol *sym, int undef_error);
  void destroy_locals(void);
  void add_struct_element(Symbol *s);
  void emit_struct(Symbol *ele, int tp, Symbol *struc);
+ void emit_struct_abs(Symbol *ele, int tp, Symbol *struc, int offset);
  void build_struct(Symbol *ele, int tp, Symbol *struc);
  
  struct {
    int regs;
***************
*** 175,180 ****
--- 186,200 ----
  void do_include(char *fname);
  void do_linkcoff(char *fname);
  
+ void write_THEADR(FILE *outfile, char *inname);
+ void write_LNAMES(FILE *outfile, ...);
+ void write_SEGDEF(FILE *outfile, int size, int name, int class, int overlay);
+ void write_EXTDEF(FILE *outfile, Symbol *symtab);
+ void write_PUBDEF(FILE *outfile, Symbol *symtab, int bss_start);
+ void write_LEDATA(FILE *outfile, int segment, unsigned char *outbin, int size,
+ 		  Symbol *symtab);
+ void write_MODEND(FILE *outfile, int main_obj, int start_ptr);
+ 
  %}
  
  %expect 2 /* see regmem */
***************
*** 625,631 ****
  
  lines
  	:
! 	| lines line '\n'		{ lineno++; }
  	| lines INCLUDE STRING '\n'	{ strbuf[strbuflen]=0; do_include(strbuf); }
  	| lines INCLUDE NUMBER '\n'	{ strbuf[strbuflen]=0; do_include(strbuf); }
  	;
--- 645,651 ----
  
  lines
  	:
! 	| lines line '\n'		{ lineno++; pc_symbol.value=pc; }
  	| lines INCLUDE STRING '\n'	{ strbuf[strbuflen]=0; do_include(strbuf); }
  	| lines INCLUDE NUMBER '\n'	{ strbuf[strbuflen]=0; do_include(strbuf); }
  	;
***************
*** 635,642 ****
  
  	| ID ':'			{ set_symbol($1, pc)->type |= (pc?SYM_data:SYM_code); }
  	| ID '=' const			{ set_symbol($1, $3)->type = SYM_abs; }
- 	| ID '=' PC offset		{ set_symbol($1, pc + $4)->type = SYM_abs; }
- 	| ID '=' const '-' PC		{ set_symbol($1, $3 - pc)->type = SYM_abs; }
  	| STRUCT ID '\n'		{ struct_pc=0;
  					  struct_tp=$1;
  					  struct_sym=$2->name;
--- 655,660 ----
***************
*** 650,655 ****
--- 668,674 ----
  					  symtab=$<sym>4;
  	  				}
  	| ID STRUCT ID			{ emit_struct($1,$2,$3); }
+ 	| ID STRUCT ID '(' const ')'	{ emit_struct_abs($1,$2,$3,$5); }
  	| error
  
  	| ONEBYTE			{ emitb($1); }
***************
*** 689,695 ****
  	| ARITH2 regmem ',' REG16	{ emitb($1*8+1); reg($4); }
  	| ARITH2 REG16 ',' regmem	{ emitb($1*8+3); reg($2); }
  
! 	| ARITH2D regmem ',' constID	{ emitb(0x66); emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  	| ARITH2 REG32 ',' constID	{ emitb(0x66);
  					  if ($2) {
  					      int v=$4.ofs+$4.sym->value;
--- 708,714 ----
  	| ARITH2 regmem ',' REG16	{ emitb($1*8+1); reg($4); }
  	| ARITH2 REG16 ',' regmem	{ emitb($1*8+3); reg($2); }
  
! 	| ARITH2D regmem ',' constID	{ emitb(0x66); emitb(0x81); reg($1); emits($4.sym,$4.ofs,REL_abs32); }
  	| ARITH2 REG32 ',' constID	{ emitb(0x66);
  					  if ($2) {
  					      int v=$4.ofs+$4.sym->value;
***************
*** 740,745 ****
--- 759,766 ----
  	| BSR REG32 ',' regmem		{ emitb(0x66); emitb(0x0f); emitb(0xbd); reg($2); }
  
  	| CALL ID			{ emitb(0xe8); emits($2,0,REL_16); $2->type |= SYM_code; }
+ 	| CALL REG16			{ emitb(0xff); modrm(3,2,$2); }
+ 	| CALL regmem			{ emitb(0xff); reg(2); }
  	| CALLF regmem			{ emitb(0xff); reg(3); }
  	| CALLF const ':' constID	{ emitb(0x9a); emits($4.sym,$4.ofs,REL_abs); emitw($2); }
  	| CALLFD const ':' constID	{ emitb(0x66); emitb(0x9a); emits($4.sym,$4.ofs,REL_abs32); emitw($2); }
***************
*** 784,789 ****
--- 805,832 ----
  	| IMUL REG32 ',' REG32		{ emitb(0x66); emitb(0x0f); emitb(0xaf); modrm(3, $2, $4);}
  	| IMUL REG16 ',' regmem		{ emitb(0x0f); emitb(0xaf); reg($2); }
  	| IMUL REG32 ',' regmem		{ emitb(0x66); emitb(0x0f); emitb(0xaf); reg($2); }
+ 	| IMUL REG16 ',' REG16 ',' const { if ($6>=-128 && $6<=127)
+ 					      emitb(0x6b);
+ 					  else
+ 					      emitb(0x69);
+ 					  modrm(3, $2, $4);
+ 					  if ($6>=-128 && $6<=127)
+ 					      emitb($6);
+ 					  else
+ 					      emitw($6);
+ 					}
+ 	| IMUL REG32 ',' REG32 ',' const { emitb(0x66);
+ 					  if ($6>=-128 && $6<=127)
+ 					      emitb(0x6b);
+ 					  else
+ 					      emitb(0x69);
+ 					  modrm(3, $2, $4);
+ 					  if ($6>=-128 && $6<=127)
+ 					      emitb($6&0xff);
+ 					  else
+ 					      emitd($6);
+ 					}
+ 
  	| IMUL REG16 ',' regmem ',' const { if ($6>=-128 && $6<=127)
  					      emitb(0x6b);
  					  else
***************
*** 827,832 ****
--- 870,877 ----
  
  	| JMPW ID			{ emitb(0xe9); emits($2,0,REL_16); $2->type |= SYM_code; }
  	| JMPB ID			{ emitb(0xeb); emits($2,0,REL_8); $2->type |= SYM_code; }
+ 	| JMPB REG16			{ emitb(0xff); modrm(3,4,$2); }
+ 	| JMPB regmem			{ emitb(0xff); reg(4); }
  	| JMPF regmem			{ emitb(0xff); reg(5); }
  	| JMPF const ':' constID	{ emitb(0xea); emits($4.sym,$4.ofs,REL_abs); emitw($2); }
  	| JMPFD const ':' constID	{ emitb(0x66); emitb(0xea); emits($4.sym,$4.ofs,REL_abs32); emitw($2); }
***************
*** 876,883 ****
  					      emitb(0x8b);
  					  reg($2);
  					}
! 	| MOVD regmem ',' constID	{ emitb(0x66); emitb(0xc7); reg(0); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
! 	| MOV REG32 ',' constID		{ emitb(0x66); emitb(0xb8+$2); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  	| MOV REG32 ',' REG32		{ emitb(0x66); emitb(0x89); modrm(3, $4, $2); }
  	| MOV regmem ',' REG32		{ emitb(0x66);
  					  if ($4==0 && _modrm.regs==0)
--- 921,928 ----
  					      emitb(0x8b);
  					  reg($2);
  					}
! 	| MOVD regmem ',' constID	{ emitb(0x66); emitb(0xc7); reg(0); emits($4.sym,$4.ofs,REL_abs32); }
! 	| MOV REG32 ',' constID		{ emitb(0x66); emitb(0xb8+$2); emits($4.sym,$4.ofs,REL_abs32); }
  	| MOV REG32 ',' REG32		{ emitb(0x66); emitb(0x89); modrm(3, $4, $2); }
  	| MOV regmem ',' REG32		{ emitb(0x66);
  					  if ($4==0 && _modrm.regs==0)
***************
*** 913,920 ****
  	| MOVSZXB REG32 ',' regmem	{ emitb(0x66); emitb(0x0f); emitb($1); reg($2); }
  	| MOVSZXW REG32 ',' regmem	{ emitb(0x66); emitb(0x0f); emitb($1+1); reg($2); }
  
! 	| ORG const			{ if (pc > $2) yyerror ("Backwards org directive"); else while (pc < $2) emitb(0x90); }
! 	| ORG const ',' const		{ if (pc > $2) yyerror ("Backwards org directive"); else while (pc < $2) emitb($4); }
  
  	| OUT const ',' REG8		{ emitb(0xe6); emitb($2); }
  	| OUT const ',' REG16		{ emitb(0xe7); emitb($2); }
--- 958,965 ----
  	| MOVSZXB REG32 ',' regmem	{ emitb(0x66); emitb(0x0f); emitb($1); reg($2); }
  	| MOVSZXW REG32 ',' regmem	{ emitb(0x66); emitb(0x0f); emitb($1+1); reg($2); }
  
! 	| ORG const			{ if (pc > $2) djerror ("Backwards org directive"); else while (pc < $2) emitb(0x90); }
! 	| ORG const ',' const		{ if (pc > $2) djerror ("Backwards org directive"); else while (pc < $2) emitb($4); }
  
  	| OUT const ',' REG8		{ emitb(0xe6); emitb($2); }
  	| OUT const ',' REG16		{ emitb(0xe7); emitb($2); }
***************
*** 935,941 ****
  	| PUSHD regmem			{ emitb(0x66); emitb(0xff); reg(6); }
  	| PUSHB const			{ emitb(0x6a); emitb($2); }
  	| PUSHW constID			{ emitb(0x68); emits($2.sym,$2.ofs,REL_abs); }
! 	| PUSHD constID			{ emitb(0x66); emitb(0x68); emits($2.sym,$2.ofs,REL_abs); emitw($2.ofs >> 16); }
  
  	| RET				{ emitb(0xc3); }
  	| RET const			{ emitb(0xc2); emitw($2); }
--- 980,986 ----
  	| PUSHD regmem			{ emitb(0x66); emitb(0xff); reg(6); }
  	| PUSHB const			{ emitb(0x6a); emitb($2); }
  	| PUSHW constID			{ emitb(0x68); emits($2.sym,$2.ofs,REL_abs); }
! 	| PUSHD constID			{ emitb(0x66); emitb(0x68); emits($2.sym,$2.ofs,REL_abs32); }
  
  	| RET				{ emitb(0xc3); }
  	| RET const			{ emitb(0xc2); emitw($2); }
***************
*** 950,969 ****
  	| SETCC regmem			{ emitb(0x0f); emitb(0x90+$1); reg(0); }
  
  	| SHIFT REG8 ',' const		{ emitb($4 == 1 ? 0xd0 : 0xc0); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
! 	| SHIFT REG8 ',' REG8		{ if ($4 != 1) yyerror ("Non-constant shift count must be `cl'"); emitb(0xd2); modrm(3, $1, $2); }
  	| SHIFT REG16 ',' const       	{ emitb($4 == 1 ? 0xd1 : 0xc1); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
! 	| SHIFT REG16 ',' REG8		{ if ($4 != 1) yyerror ("Non-constant shift count must be `cl'"); emitb(0xd3); modrm(3, $1, $2); }
  	| SHIFT REG32 ',' const       	{ emitb(0x66); emitb($4 == 1 ? 0xd1 : 0xc1); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
! 	| SHIFT REG32 ',' REG8		{ if ($4 != 1) yyerror ("Non-constant shift count must be `cl'"); emitb(0x66); emitb(0xd3); modrm(3, $1, $2); }
  
  	| SHLRD REG16 ',' REG16 ',' const
  	  { emitb(0x0f); emitb($1); modrm(3, $4, $2); emitb($6); }
  	| SHLRD REG16 ',' REG16 ',' REG8
! 	  { if ($6 != 1) yyerror ("Non-constant shift count must be `cl'");
  	    emitb(0x0f); emitb($1+1); modrm(3, $4, $2); }
  
  	| STACK				{ stack_ptr = pc; }
! 	| START				{ start_ptr = pc; }
  
  	| TESTB regmem ',' const	{ emitb(0xf6), reg(0); emitb($4); }
  	| TEST REG8 ',' const		{ emitb(0xf6), modrm(3, 0, $2); emitb($4); }
--- 995,1019 ----
  	| SETCC regmem			{ emitb(0x0f); emitb(0x90+$1); reg(0); }
  
  	| SHIFT REG8 ',' const		{ emitb($4 == 1 ? 0xd0 : 0xc0); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
! 	| SHIFT REG8 ',' REG8		{ if ($4 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0xd2); modrm(3, $1, $2); }
  	| SHIFT REG16 ',' const       	{ emitb($4 == 1 ? 0xd1 : 0xc1); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
! 	| SHIFT REG16 ',' REG8		{ if ($4 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0xd3); modrm(3, $1, $2); }
  	| SHIFT REG32 ',' const       	{ emitb(0x66); emitb($4 == 1 ? 0xd1 : 0xc1); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
! 	| SHIFT REG32 ',' REG8		{ if ($4 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0x66); emitb(0xd3); modrm(3, $1, $2); }
  
  	| SHLRD REG16 ',' REG16 ',' const
  	  { emitb(0x0f); emitb($1); modrm(3, $4, $2); emitb($6); }
  	| SHLRD REG16 ',' REG16 ',' REG8
! 	  { if ($6 != 1) djerror ("Non-constant shift count must be `cl'");
  	    emitb(0x0f); emitb($1+1); modrm(3, $4, $2); }
+ 	| SHLRD REG32 ',' REG32 ',' const
+ 	  { emitb(0x66); emitb(0x0f); emitb($1); modrm(3, $4, $2); emitb($6); }
+ 	| SHLRD REG32 ',' REG32 ',' REG8
+ 	  { if ($6 != 1) djerror ("Non-constant shift count must be `cl'");
+ 	    emitb(0x66); emitb(0x0f); emitb($1+1); modrm(3, $4, $2); }
  
  	| STACK				{ stack_ptr = pc; }
! 	| START				{ start_ptr = pc; main_obj=1; }
  
  	| TESTB regmem ',' const	{ emitb(0xf6), reg(0); emitb($4); }
  	| TEST REG8 ',' const		{ emitb(0xf6), modrm(3, 0, $2); emitb($4); }
***************
*** 977,984 ****
  	| TEST regmem ',' REG16		{ emitb(0x85); reg($4); }
  	| TEST REG16 ',' regmem		{ emitb(0x85); reg($2); }
  
! 	| TESTD regmem ',' constID	{ emitb(0x66); emitb(0xf7); reg(0); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
! 	| TEST REG32 ',' constID	{ emitb(0x66); emitb(0xf7); modrm(3, 0, $2); emits($4.sym,$4.ofs,REL_abs); emitw($4.ofs >> 16); }
  	| TEST REG32 ',' REG32		{ emitb(0x66); emitb(0x85); modrm(3, $4, $2); }
  	| TEST regmem ',' REG32		{ emitb(0x66); emitb(0x85); reg($4); }
  	| TEST REG32 ',' regmem		{ emitb(0x66); emitb(0x85); reg($2); }
--- 1027,1034 ----
  	| TEST regmem ',' REG16		{ emitb(0x85); reg($4); }
  	| TEST REG16 ',' regmem		{ emitb(0x85); reg($2); }
  
! 	| TESTD regmem ',' constID	{ emitb(0x66); emitb(0xf7); reg(0); emits($4.sym,$4.ofs,REL_abs32); }
! 	| TEST REG32 ',' constID	{ emitb(0x66); emitb(0xf7); modrm(3, 0, $2); emits($4.sym,$4.ofs,REL_abs32); }
  	| TEST REG32 ',' REG32		{ emitb(0x66); emitb(0x85); modrm(3, $4, $2); }
  	| TEST regmem ',' REG32		{ emitb(0x66); emitb(0x85); reg($4); }
  	| TEST REG32 ',' regmem		{ emitb(0x66); emitb(0x85); reg($2); }
***************
*** 1085,1091 ****
  
  dditem
  	: const				{ emitd($1); }
! 	| UID offset			{ emits($1,$2,REL_abs); emitw(0); }
  	| const DUP const		{ for (i=0; i<$1; i++) emitd($3); }
  	;
  
--- 1135,1141 ----
  
  dditem
  	: const				{ emitd($1); }
! 	| UID offset			{ emits($1,$2,REL_abs32); }
  	| const DUP const		{ for (i=0; i<$1; i++) emitd($3); }
  	;
  
***************
*** 1110,1116 ****
  	: SREG ':' regmemitem		{ emitb(sreg_overrides[$1]); }
  	| REG16				{ if (_modrm.addr32) {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      yyerror("Cannot mix 16 and 32 bit addressing");
  					  } else {
  					      _modrm.regs |= (1<<$1);
  					      _modrm.addr16=1;
--- 1160,1166 ----
  	: SREG ':' regmemitem		{ emitb(sreg_overrides[$1]); }
  	| REG16				{ if (_modrm.addr32) {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      djerror("Cannot mix 16 and 32 bit addressing");
  					  } else {
  					      _modrm.regs |= (1<<$1);
  					      _modrm.addr16=1;
***************
*** 1127,1147 ****
  					      $$ = (1<<($1)) | ($3<<8);
  					  else {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      yyerror("Scale must be 1,2,4 or 8");
  					  }
  					}
  	| const '*' REG32		{ if ($1==1 || $1==2 || $1==4 || $1==8)
  					      $$ = (1<<($3)) | ($1<<8);
  					  else {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      yyerror("Scale must be 1,2,4 or 8");
  					  }
  					}
  	| REG32 OP_SHL const		{ if ($3>=0 && $3<=3)
  					      $$ = (1<<($1)) | (0x100<<$3);
  					  else {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      yyerror("Shift must be 0,1,2 or 3");
  					  }
  					}
  	;
--- 1177,1197 ----
  					      $$ = (1<<($1)) | ($3<<8);
  					  else {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      djerror("Scale must be 1,2,4 or 8");
  					  }
  					}
  	| const '*' REG32		{ if ($1==1 || $1==2 || $1==4 || $1==8)
  					      $$ = (1<<($3)) | ($1<<8);
  					  else {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      djerror("Scale must be 1,2,4 or 8");
  					  }
  					}
  	| REG32 OP_SHL const		{ if ($3>=0 && $3<=3)
  					      $$ = (1<<($1)) | (0x100<<$3);
  					  else {
  					      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
! 					      djerror("Shift must be 0,1,2 or 3");
  					  }
  					}
  	;
***************
*** 1149,1154 ****
--- 1199,1205 ----
  const
  	: NUMBER			{ $$ = $1; }
  	| KID				{ $$ = $1->value; }
+ 	| PC				{ $$ = pc_symbol.value; }
  	| const OP_OR const		{ $$ = $1 || $3; }
  	| const '|' const		{ $$ = $1 | $3; }
  	| const '^' const		{ $$ = $1 ^ $3; }
***************
*** 1227,1232 ****
--- 1278,1284 ----
    int min_uninit;
    time_t now;
    char *outfilename, *leader;
+   char *current_map_file;
  
    /* Sort the opcodes now so that we can use `bsearch' later.  */
    qsort (opcodes,
***************
*** 1264,1272 ****
        symcount++;
      if (!s->defined && s->patches)
      {
-       fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", s->name, s->first_used);
        for (p=s->patches; p; p=p->next)
!         fprintf(stderr,"\treferenced on line %d\n", p->lineno);
        undefs++;
      }
    }
--- 1316,1323 ----
        symcount++;
      if (!s->defined && s->patches)
      {
        for (p=s->patches; p; p=p->next)
! 	fprintf(stderr,"%s:%d: undefined symbol `%s'\n", p->filename, p->lineno, s->name);
        undefs++;
      }
    }
***************
*** 1274,1280 ****
      return 1;
    if (total_errors)
    {
!     fprintf(stderr, "%d errors\n", total_errors);
      return 1;
    }
  
--- 1325,1331 ----
      return 1;
    if (total_errors)
    {
!     fprintf(stderr, "%s: %d errors\n", inname, total_errors);
      return 1;
    }
  
***************
*** 1370,1375 ****
--- 1421,1427 ----
      case OUT_com:
      case OUT_bin:
      case OUT_sys:
+     case OUT_obj:
        outfile = fopen(outfilename, "wb");
        break;
      case OUT_h:
***************
*** 1455,1460 ****
--- 1507,1522 ----
        if (i&15)
          fputc('\n', outfile);
        break;
+     case OUT_obj:
+       write_THEADR(outfile,inname);
+       write_LNAMES(outfile,"","CODE","BSS","TEXT","DATA",0);
+       write_SEGDEF(outfile,bsspc,4,2,1);	/* text and data */
+       write_SEGDEF(outfile,pc-bsspc,5,3,1);	/* .bss */
+       write_EXTDEF(outfile,symtab);
+       write_PUBDEF(outfile,symtab,bsspc);
+       write_LEDATA(outfile,1,outbin,bsspc,symtab);
+       write_MODEND(outfile,main_obj,start_ptr);
+       break;
    }
    fclose(outfile);
    
***************
*** 1476,1484 ****
      for (s = symtab; s; s=s->next)
        if (!istemp(s->name, 0))
          fprintf(mapfile, "0000:%04X  %s (%c)\n", s->value, s->name, SYMTYPES[s->type]);
!     fprintf(mapfile, "\nLine numbers for (%s)\n", argv[1]);
      for (i=0; i<num_lineaddr; i++)
      {
        fprintf(mapfile, "%5d 0000:%04X", lineaddr[i].line, lineaddr[i].addr);
        if ((i & 3) == 3)
          fputc('\n', mapfile);
--- 1538,1556 ----
      for (s = symtab; s; s=s->next)
        if (!istemp(s->name, 0))
          fprintf(mapfile, "0000:%04X  %s (%c)\n", s->value, s->name, SYMTYPES[s->type]);
!     current_map_file = 0;
      for (i=0; i<num_lineaddr; i++)
      {
+       if (current_map_file != lineaddr[i].name)
+       {
+ 	current_map_file = lineaddr[i].name;
+ 	if ((i & 3) != 3)
+ 	  fprintf(mapfile, "\n");
+ 	fprintf(mapfile, "\nLine numbers for (%s)\n", current_map_file);
+ 	num_lineaddr-=i;
+ 	lineaddr+=i;
+ 	i=0;
+       }
        fprintf(mapfile, "%5d 0000:%04X", lineaddr[i].line, lineaddr[i].addr);
        if ((i & 3) == 3)
          fputc('\n', mapfile);
***************
*** 1491,1504 ****
    return 0;
  }
  
! void yyerror(char *s)
  {
    fprintf(stderr, "%s:%d: %s\n", inname, lineno, s);
    strbuf[strbuflen] = 0;
-   fprintf(stderr, "Last token was `%s' (%s)\n", last_token, yytname[(unsigned char)yytranslate[last_tret]]);
    total_errors++;
  }
  
  Symbol *get_symbol(char *name, int create)
  {
    Symbol *s;
--- 1563,1581 ----
    return 0;
  }
  
! void djerror(char *s)
  {
    fprintf(stderr, "%s:%d: %s\n", inname, lineno, s);
    strbuf[strbuflen] = 0;
    total_errors++;
  }
  
+ void yyerror(char *s)
+ {
+   djerror(s);
+   fprintf(stderr, "%s:%d: Last token was `%s' (%s)\n", inname, lineno, last_token, yytname[(unsigned char)yytranslate[last_tret]]);
+ }
+ 
  Symbol *get_symbol(char *name, int create)
  {
    Symbol *s;
***************
*** 1514,1519 ****
--- 1591,1598 ----
    strcpy(s->name, name);
    s->value = 0;
    s->defined = 0;
+   s->external = 0;
+   s->public = 0;
    s->patches = 0;
    s->first_used = lineno;
    s->type = SYM_unknown;
***************
*** 1523,1529 ****
  void add_struct_element(Symbol *s)
  {
    if (islocal(s->name) || istemp(s->name,0)) {
!     yyerror("Cannot have local or temporary labels within a structure");
    } else {
      char *id=alloca(strlen(s->name)+strlen(struct_sym)+2);
      strcpy(id,struct_sym);
--- 1602,1608 ----
  void add_struct_element(Symbol *s)
  {
    if (islocal(s->name) || istemp(s->name,0)) {
!     djerror("Cannot have local or temporary labels within a structure");
    } else {
      char *id=alloca(strlen(s->name)+strlen(struct_sym)+2);
      strcpy(id,struct_sym);
***************
*** 1564,1578 ****
  int set_structure_symbols(Symbol *ele, Symbol *struc, int tp, int base, int type)
  {
    if (tp!='s') {
!     yyerror("must use `.struct' to emit structures or unions");
      return 0;
    }
    if (!struc->defined) {
!     yyerror("undefined symbol used in struct");
      return 0;
    }
    if (!is_structure(struc)) {
!     yyerror("symbol must be a .struct or .union");
      return 0;
    }
    set_symbol(ele,base)->type|=type;
--- 1643,1657 ----
  int set_structure_symbols(Symbol *ele, Symbol *struc, int tp, int base, int type)
  {
    if (tp!='s') {
!     djerror("must use `.struct' to emit structures or unions");
      return 0;
    }
    if (!struc->defined) {
!     djerror("undefined symbol used in struct");
      return 0;
    }
    if (!is_structure(struc)) {
!     djerror("symbol must be a .struct or .union");
      return 0;
    }
    set_symbol(ele,base)->type|=type;
***************
*** 1596,1608 ****
    int i;
  
    if (set_structure_symbols(ele,struc,tp,pc,(pc?SYM_data:SYM_code)))
!     for (i=0; i<struc->value; i++) emitb(0); /* only unitialized structures supported */
  }
  
  void build_struct(Symbol *ele, int tp, Symbol *struc)
  {
    if (ele && (islocal(ele->name) || istemp(ele->name,0))) {
!     yyerror("Cannot have local or temporary labels within a structure");
    } else {
      char *id=alloca((ele?strlen(ele->name):0)+strlen(struct_sym)+2);
      Symbol *sym;
--- 1675,1694 ----
    int i;
  
    if (set_structure_symbols(ele,struc,tp,pc,(pc?SYM_data:SYM_code)))
!     for (i = 0; i < struc->value; i++)
!       emitb(0); /* only unitialized structures supported */
! }
! 
! void emit_struct_abs(Symbol *ele, int tp, Symbol *struc, int offset)
! {
!   /* NOTE: Does not actually emit any bytes! (by design) */
!   set_structure_symbols(ele,struc,tp,offset,(offset?SYM_data:SYM_code));
  }
  
  void build_struct(Symbol *ele, int tp, Symbol *struc)
  {
    if (ele && (islocal(ele->name) || istemp(ele->name,0))) {
!     djerror("Cannot have local or temporary labels within a structure");
    } else {
      char *id=alloca((ele?strlen(ele->name):0)+strlen(struct_sym)+2);
      Symbol *sym;
***************
*** 1620,1626 ****
  	symtab=symtab->next;
  	sym->next=0;
      }
!     set_structure_symbols(sym,struc,tp,(struct_tp=='s')?struct_pc:0,0);
      if (!ele) {
        destroy_symbol(sym,0);
      }
--- 1706,1712 ----
  	symtab=symtab->next;
  	sym->next=0;
      }
!     set_structure_symbols(sym,struc,tp,(struct_tp=='s')?struct_pc:0,SYM_abs);
      if (!ele) {
        destroy_symbol(sym,0);
      }
***************
*** 1638,1644 ****
    if (istemp(s->name, 'b'))
      s->defined = 0;
    if (s->defined)
!     fprintf(stderr,"Warning: symbol %s redefined\n", s->name);
    s->value = value;
    s->defined = 1;
    while (s->patches)
--- 1724,1730 ----
    if (istemp(s->name, 'b'))
      s->defined = 0;
    if (s->defined)
!     fprintf(stderr,"%s:%d: warning: symbol %s redefined\n", inname, lineno, s->name);
    s->value = value;
    s->defined = 1;
    while (s->patches)
***************
*** 1693,1699 ****
  	   So far away from me
  	   You're so far away from me
  	   -- from `So far away' by Mark Knopfler.  */
! 	fprintf(stderr, "%s:%d: 8-bit relocation too big (%d); use long form\n", inname, p->lineno, o);
  	total_errors++;
        }
        cp[0] = o;
--- 1779,1785 ----
  	   So far away from me
  	   You're so far away from me
  	   -- from `So far away' by Mark Knopfler.  */
! 	fprintf(stderr, "%s:%d: 8-bit relocation too big (%d); use long form\n", p->filename, p->lineno, o);
  	total_errors++;
        }
        cp[0] = o;
***************
*** 1717,1725 ****
        if (undef_error && !_s->defined && _s->patches)
        {
  	Patch *p,*_p;
- 	fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", _s->name, _s->first_used);
  	for (p=_s->patches; p; p=_p) {
! 	  fprintf(stderr,"\treferenced on line %d\n", p->lineno);
  	  _p=p->next;
  	  free(p);
  	}
--- 1803,1810 ----
        if (undef_error && !_s->defined && _s->patches)
        {
  	Patch *p,*_p;
  	for (p=_s->patches; p; p=_p) {
! 	  fprintf(stderr,"%s:%d: undefined symbol `%s'\n", p->filename, p->lineno, _s->name);
  	  _p=p->next;
  	  free(p);
  	}
***************
*** 1747,1755 ****
        if (!_s->defined && _s->patches)
        {
  	Patch *p,*_p;
- 	fprintf(stderr, "Undefined symbol `%s', first used on line %d\n", _s->name, _s->first_used);
  	for (p=_s->patches; p; p=_p) {
! 	  fprintf(stderr,"\treferenced on line %d\n", p->lineno);
  	  _p=p->next;
  	  free(p);
  	}
--- 1832,1839 ----
        if (!_s->defined && _s->patches)
        {
  	Patch *p,*_p;
  	for (p=_s->patches; p; p=_p) {
! 	  fprintf(stderr,"%s:%d: undefined symbol `%s'\n", p->filename, p->lineno, _s->name);
  	  _p=p->next;
  	  free(p);
  	}
***************
*** 1856,1861 ****
--- 1940,1946 ----
    s->patches = p;
    p->location = pc;
    p->lineno = lineno;
+   p->filename = inname;
    p->rel = rel;
    switch (rel)
    {
***************
*** 2004,2009 ****
--- 2089,2095 ----
        s->patches = p;
        p->location = pc+1+needsib; /* ALL bytes emitted below, accounts for yet to be emitted mbyte */
        p->lineno = lineno;
+       p->filename = inname;
        p->rel = _modrm.addr32 ? REL_abs32 : REL_abs;
        _modrm.regs=0; /* force offset field to be full size (2/4 bytes rather than 1) */
      }
***************
*** 2063,2069 ****
      }
    }
    if (err) {
!     yyerror(err);
      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
    } else {
      _modrm.regs=-1;
--- 2149,2155 ----
      }
    }
    if (err) {
!     djerror(err);
      _modrm.nsyms = _modrm.addr32 = _modrm.addr16 = _modrm.offset = _modrm.regs = 0;
    } else {
      _modrm.regs=-1;
***************
*** 2107,2113 ****
        {
          FileStack *tmp = file_stack;
          fclose(infile);
!         free(inname);
          lineno = file_stack->line + 1; /* Correct for .include line */
          infile = file_stack->f;
          inname = file_stack->name;
--- 2193,2199 ----
        {
          FileStack *tmp = file_stack;
          fclose(infile);
!         /*free(inname);*/ /* needed by lineaddr_s and Patch */
          lineno = file_stack->line + 1; /* Correct for .include line */
          infile = file_stack->f;
          inname = file_stack->name;
***************
*** 2155,2162 ****
--- 2241,2307 ----
  	}
  
      case '0' ... '9':
+     #ifdef __linux
+       /* fscanf "%i" doesn't work reliably with libc5.4.44 for large hex nubmers */
+       if (c == '0')
+         {
+ 	  /* octal or hex */
+ 	  yylval.i = 0;
+ 	  c = fgetc (infile);
+ 	  if (c == 'x' || c == 'X')
+ 	    {
+ 	      while (1)
+ 		{
+ 		  c = fgetc (infile);
+ 		  if (!isxdigit (c))
+ 		    {
+ 		      ungetc(c, infile);
+ 		      break;
+ 		    }
+ 		  c = toupper (c);
+ 		  if (c > '9')
+ 		    c -= 'A' - '9' - 1;
+ 		  yylval.i *= 16;
+ 		  yylval.i += c - '0';
+ 		}
+ 	    }
+ 	  else if (c >= '0' && c <= '7')
+ 	    {
+ 	      yylval.i = c - '0';
+ 	      while (1)
+ 		{
+ 		  c = fgetc (infile);
+ 		  if (!(c >= '0' && c <= '7'))
+ 		    {
+ 		      ungetc(c, infile);
+ 		      break;
+ 		    }
+ 		  yylval.i *= 8;
+ 		  yylval.i += c - '0';
+ 		}
+ 	    }
+ 	  else
+ 	    ungetc(c, infile);
+ 	}
+       else
+         {
+ 	  yylval.i = c - '0';
+ 	  while (1)
+ 	    {
+ 	      c = fgetc (infile);
+ 	      if (!isdigit (c))
+ 		{
+ 		  ungetc(c, infile);
+ 		  break;
+ 		}
+ 	      yylval.i *= 10;
+ 	      yylval.i += c - '0';
+ 	    }
+         }
+     #else
        ungetc(c, infile);
        fscanf(infile, "%i", &(yylval.i));
+     #endif
        sprintf(last_token, "%d", yylval.i);
        return NUMBER;
        break;
***************
*** 2259,2265 ****
        emitb(0x07);
        break;
      case 1: /* cs */
!       yyerror("Cannot pop CS");
        break;
      case 2: /* ss */
        emitb(0x17);
--- 2404,2410 ----
        emitb(0x07);
        break;
      case 1: /* cs */
!       djerror("Cannot pop CS");
        break;
      case 2: /* ss */
        emitb(0x17);
***************
*** 2321,2326 ****
--- 2466,2472 ----
    }
    lineaddr[num_lineaddr].line = lineno;
    lineaddr[num_lineaddr].addr = pc;
+   lineaddr[num_lineaddr].name = inname;
    num_lineaddr++;
  }
  
***************
*** 2422,2429 ****
    f = fopen(fname, "r");
    if (!f)
    {
!     fprintf(stderr, "Error: cannot open %s\n", fname);
!     perror("The error was");
      return;
    }
    fs = (FileStack *)malloc(sizeof(FileStack));
--- 2568,2575 ----
    f = fopen(fname, "r");
    if (!f)
    {
!     fprintf(stderr, "%s:%d: error openning `%s'", inname, lineno, fname);
!     perror("");
      return;
    }
    fs = (FileStack *)malloc(sizeof(FileStack));
***************
*** 2446,2451 ****
--- 2592,2598 ----
    long len;
    int f;
    char *data, *p;
+   char *coff_filename;
    FILHDR *header;
    SCNHDR *f_thdr;		/* Text section header */
    SCNHDR *f_dhdr;		/* Data section header */
***************
*** 2461,2468 ****
    f = open (filename, O_RDONLY | O_BINARY);
    if (f < 0)
      {
!       fprintf (stderr, "Error: cannot open %s\n", filename);
!       perror("The error was");
        return;
      }
    len = lseek (f, 0L, SEEK_END);
--- 2608,2615 ----
    f = open (filename, O_RDONLY | O_BINARY);
    if (f < 0)
      {
!       fprintf(stderr, "%s:%d: error openning `%s'", inname, lineno, filename);
!       perror("");
        return;
      }
    len = lseek (f, 0L, SEEK_END);
***************
*** 2481,2487 ****
        || strcmp (f_dhdr->s_name, _DATA)
        || strcmp (f_bhdr->s_name, _BSS))
      {
!       fprintf (stderr, "The file %s is not a valid COFF file.\n", filename);
        return;
      }
  
--- 2628,2634 ----
        || strcmp (f_dhdr->s_name, _DATA)
        || strcmp (f_bhdr->s_name, _BSS))
      {
!       fprintf (stderr, "%s:%d: `%s' is not a valid COFF file.\n", inname, lineno, filename);
        return;
      }
  
***************
*** 2501,2506 ****
--- 2648,2654 ----
  
    symbol = (void *) data + header->f_symptr;
    base = (void *) symbol + header->f_nsyms * SYMESZ;
+   coff_filename = strdup (filename);
    for (cnt = header->f_nsyms; cnt > 0; symbol++, cnt--)
      {
        if (symbol->e.e.e_zeroes == 0)
***************
*** 2591,2603 ****
  		  Patch *pat = (Patch *) malloc (sizeof (Patch));
  
  		  if (rp->r_type == RELOC_REL32)
! 		    fprintf (stderr,
  			     "Call from COFF file to (yet) undefined "
! 			     "destination, %s, is not supported.\n", p);
  		  pat->next = s->patches;
  		  s->patches = pat;
  		  pat->location = textbase + rp->r_vaddr;
  		  pat->lineno = -1;
  		  pat->rel = REL_abs32;
  		}
  	    }
--- 2739,2752 ----
  		  Patch *pat = (Patch *) malloc (sizeof (Patch));
  
  		  if (rp->r_type == RELOC_REL32)
! 		    fprintf (stderr,"%s:%d: warning:"
  			     "Call from COFF file to (yet) undefined "
! 			     "destination, %s, is not supported.\n", inname, lineno, p);
  		  pat->next = s->patches;
  		  s->patches = pat;
  		  pat->location = textbase + rp->r_vaddr;
  		  pat->lineno = -1;
+ 		  pat->filename = coff_filename;
  		  pat->rel = REL_abs32;
  		}
  	    }
***************
*** 2617,2626 ****
  		delta = s->value - textbase;
  	      break;
  	    default:
! 	      fprintf (stderr,
! 		       "COFF file %s contains bad relation "
  		       "entry type (0x%02x).\n",
! 		       filename, rp->r_type);
  	      delta = 0;
  	    }
  	  *((int *)(outbin + textbase + rp->r_vaddr)) += delta;
--- 2766,2775 ----
  		delta = s->value - textbase;
  	      break;
  	    default:
! 	      fprintf (stderr, "%s:%d:"
! 		       "COFF file %s contains bad relocation "
  		       "entry type (0x%02x).\n",
! 		       inname, lineno, filename, rp->r_type);
  	      delta = 0;
  	    }
  	  *((int *)(outbin + textbase + rp->r_vaddr)) += delta;
***************
*** 2628,2630 ****
--- 2777,3057 ----
      }
  }
  
+ int write_BYTE(unsigned char byte, FILE *outfile, unsigned char *checksum)
+ {
+   fputc(byte,outfile);
+   *checksum-=byte;
+   return 1;
+ }
+ 
+ int write_WORD(unsigned short word, FILE *outfile, unsigned char *checksum)
+ {
+   return write_BYTE(word&0xff,outfile,checksum) +
+ 	 write_BYTE((word>>8)&0xff,outfile,checksum);
+ }
+ 
+ int write_STRING(char *str, FILE *outfile, unsigned char *checksum)
+ {
+   int length=0;
+   int len=strlen(str);
+ 
+   if (len>254)
+     len=254;
+   length+=write_BYTE(len,outfile,checksum);
+   while (len--)
+     length+=write_BYTE(*str++,outfile,checksum);
+   return length;
+ }
+ 
+ int write_INDEX(int index, FILE *outfile, unsigned char *checksum)
+ {
+   if (index>127)
+     return write_WORD(index+0x8000,outfile,checksum);
+   else
+     return write_BYTE(index,outfile,checksum);
+ }
+ 
+ void write_THEADR(FILE *outfile, char *inname)
+ {
+   unsigned char checksum=0;
+   off_t lptr,cptr;
+   int length;
+ 
+   write_BYTE(0x80,outfile,&checksum);
+   /* reserve space for the length field */
+   lptr=ftell(outfile);
+   write_WORD(0,outfile,&checksum); /* does not change checksum */
+ 
+   length=write_STRING(inname,outfile,&checksum);
+   cptr=ftell(outfile);
+   fseek(outfile,lptr,0/*SEEK_SET*/);
+   write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+   fseek(outfile,cptr,0/*SEEK_SET*/);
+   write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+ }
+ 
+ void write_LNAMES(FILE *outfile, ...)
+ {
+   va_list names;
+   int written=0;
+   int length=0;
+   off_t lenptr=0;
+   unsigned char checksum=0;
+   char *name;
+ 
+   va_start(names,outfile);
+   name=va_arg(names,char*);
+   
+   while (name)
+     {
+       int len=strlen(name);
+       /* truncate names to 254 characters (omf limitation) */
+       if (len>254)
+ 	len=254;
+       /* make sure the record doesn't overflow */
+       if (length+len>1020)
+ 	{
+ 	  off_t cptr=ftell(outfile);
+ 	  fseek(outfile,lenptr,SEEK_SET);
+ 	  write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+ 	  fseek(outfile,cptr,SEEK_SET);
+ 	  write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+ 	  length=0;
+ 	  written=0;
+ 	}
+       if (!written)
+ 	{
+ 	  written=1;
+ 	  write_BYTE(0x96,outfile,&checksum);
+ 	  /* reserve space for the length field */
+ 	  lenptr=ftell(outfile);
+ 	  write_WORD(0,outfile,&checksum); /* does not change checksum */
+ 	}
+       length+=write_STRING(name,outfile,&checksum);
+       name=va_arg(names,char*);
+     }
+   if (written)
+     {
+       off_t cptr=ftell(outfile);
+       fseek(outfile,lenptr,SEEK_SET);
+       write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+       fseek(outfile,cptr,SEEK_SET);
+       write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+     }
+ }
+ 
+ void write_SEGDEF(FILE *outfile, int size, int name, int class, int overlay)
+ {
+   unsigned char checksum=0;
+   write_BYTE(0x98,outfile,&checksum);
+   write_WORD(7+(name>127)+(class>127)+(overlay>127),outfile,&checksum);
+   /* A=2 (word), C=2 (public), B=?, P=0 */
+   write_BYTE(0x48|((size==0x1000)<<1),outfile,&checksum);
+   write_WORD(size,outfile,&checksum);
+   write_INDEX(name,outfile,&checksum);
+   write_INDEX(class,outfile,&checksum);
+   write_INDEX(overlay,outfile,&checksum);
+   write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+ }
+ 
+ void write_EXTDEF(FILE *outfile, Symbol *symtab)
+ {
+   int written=0;
+   int length=0;
+   off_t lenptr=0;
+   unsigned char checksum=0;
+   Symbol *sym=symtab;
+ 
+   while (sym)
+     {
+       if (sym->external)
+         {
+ 	  int len=strlen(sym->name);
+ 	  /* truncate names to 254 characters (omf limitation) */
+ 	  if (len>254)
+ 	    len=254;
+ 	  /* make sure the record doesn't overflow */
+ 	  if (length+len>1020)
+ 	    {
+ 	      off_t cptr=ftell(outfile);
+ 	      fseek(outfile,lenptr,SEEK_SET);
+ 	      write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+ 	      fseek(outfile,cptr,SEEK_SET);
+ 	      write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+ 	      length=0;
+ 	      written=0;
+ 	    }
+ 	  if (!written)
+ 	    {
+ 	      written=1;
+ 	      write_BYTE(0x96,outfile,&checksum);
+ 	      /* reserve space for the length field */
+ 	      lenptr=ftell(outfile);
+ 	      write_WORD(0,outfile,&checksum); /* does not change checksum */
+ 	    }
+ 	  length+=write_STRING(sym->name,outfile,&checksum);
+ 	}
+       sym=sym->next;
+     }
+   if (written)
+     {
+       off_t cptr=ftell(outfile);
+       fseek(outfile,lenptr,SEEK_SET);
+       write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+       fseek(outfile,cptr,SEEK_SET);
+       write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+     }
+ }
+ 
+ void write_PUBDEF(FILE *outfile, Symbol *symtab, int bss_start)
+ {
+   int length=0;
+   off_t lenptr=0,cptr;
+   unsigned char checksum=0;
+   Symbol *sym=symtab;
+ 
+   while (sym)
+     {
+       if (sym->public && sym->defined) /* silently ignore undefined pubdefs */
+         {
+ 	  write_BYTE(0x96,outfile,&checksum);
+ 	  /* reserve space for the length field */
+ 	  lenptr=ftell(outfile);
+ 	  write_WORD(0,outfile,&checksum); /* does not change checksum */
+ 
+ 	  length+=write_INDEX(0,outfile,&checksum); /* group index */
+ 	  if (sym->type&SYM_abs)
+ 	    {
+ 	      length+=write_INDEX(0,outfile,&checksum);
+ 	      length+=write_WORD(0,outfile,&checksum);
+ 	      length+=write_STRING(sym->name,outfile,&checksum);
+ 	    }
+ 	  else
+ 	    {
+ 	      if (sym->value>=bss_start)
+ 		{
+ 		  length+=write_INDEX(5,outfile,&checksum);
+ 		  length+=write_STRING(sym->name,outfile,&checksum);
+ 		  length+=write_WORD(sym->value-bss_start,outfile,&checksum);
+ 		}
+ 	      else
+ 	        {
+ 		  length+=write_INDEX(4,outfile,&checksum);
+ 		  length+=write_STRING(sym->name,outfile,&checksum);
+ 		  length+=write_WORD(sym->value,outfile,&checksum);
+ 		}
+ 	    }
+ 	  write_INDEX(0,outfile,&checksum);
+ 
+ 	  cptr=ftell(outfile);
+ 	  fseek(outfile,lenptr,SEEK_SET);
+ 	  write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+ 	  fseek(outfile,cptr,SEEK_SET);
+ 	  write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+ 	  length=0;
+ 	}
+       sym=sym->next;
+     }
+ }
+ 
+ void write_LEDATA(FILE *outfile, int segment, unsigned char *outbin, int size,
+ 		  Symbol *symtab)
+ {
+   /* does not yet support relocations :( */
+   int len;
+   int maxlen=1020-(segment>127);
+   int offset=0;
+   int length=0;
+   off_t lenptr,cptr;
+   unsigned char checksum=0;
+ 
+   while (size)
+     {
+       len=size;
+       if (len>maxlen)
+ 	len=maxlen;
+       write_BYTE(0xa0,outfile,&checksum);
+       /* reserve space for the length field */
+       lenptr=ftell(outfile);
+       write_WORD(0,outfile,&checksum); /* does not change checksum */
+ 
+       length+=write_INDEX(segment,outfile,&checksum);
+       length+=write_WORD(offset,outfile,&checksum);
+       offset+=len;
+       size-=len;
+       while (len--)
+         length+=write_BYTE(*outbin++,outfile,&checksum);
+       cptr=ftell(outfile);
+       fseek(outfile,lenptr,SEEK_SET);
+       write_WORD(length+1,outfile,&checksum); /* plus 1 for checksum */
+       fseek(outfile,cptr,SEEK_SET);
+       write_BYTE(checksum,outfile,&checksum); /* sets checksum to 0 */
+       length=0;
+       /* !!! write out fixups (none generated yet as extern not yet implemented)
+        * also need to make sure the last bytes of the ledata are not a partial
+        * relocation site.
+        */
+     }
+ }
+ 
+ void write_MODEND(FILE *outfile, int main_obj, int start_ptr)
+ {
+   unsigned char checksum=0;
+ 
+   write_BYTE(0x8a,outfile,&checksum);
+   if (main_obj)
+     {
+       write_WORD(6,outfile,&checksum); /* five bytes plus 1 for checksum */
+       write_BYTE(0xc1,outfile,&checksum); /* main, start, fixup */
+       /* the following is a FIXUPP record for the start address */
+       write_BYTE(0x50,outfile,&checksum);
+       write_INDEX(1,outfile,&checksum);
+       write_WORD(start_ptr,outfile,&checksum);
+     }
+   else
+     {
+       write_WORD(2,outfile,&checksum); /* one byte plus 1 for checksum */
+       write_BYTE(1,outfile,&checksum); /* fixup only (eh? why not 0?) */
+     }
+   write_BYTE(checksum,outfile,&checksum);
+ }

--------------A470A987EB9B1A7BBE411DB9--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019