[comp.sources.amiga] v89i016: fixfd - make asm include file from a .fd file

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

Submitted-by: rick@QUCDNAST.BITNET
Posting-number: Volume 89, Issue 16
Archive-name: util/fixfd.1

#	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:
#	ReadMe
#	FixFD.asm
#	FixFD.docs
#	FixFD.link
#	FixFD.uu
#	Std_Start.uu
# This archive created: Mon Jan 30 18:53:00 1989
cat << \SHAR_EOF > ReadMe

 To : Aspiring M68000 Programmers
 
From: Peter Wyspianski

Date: 01 Jan 89


As I was getting ready to archive my 'FixFD' utility, it occured to me that
some aspects of programming the Amiga would have been a LOT easier to learn if
I just had a few examples to look over.

I came to the Amiga programming enviroment from the MacIntosh.  So I was no
stranger to the M68000 or the sort of things you have to do with it in such a
complex enviroment.  Still, it has been a struggle.  While writing this utility
I had to learn how to detect the user hitting 'ctrl-c' to abort the program. 
No big deal, but I wasted a couple hours looking in the wrong places for the
information (the AmigaDOS manual and some magazines).  Turns out it is not
really documented anywhere, at least not specifically.

But I wonder where I would be now if I was a complete novice M68000 programmer?
It's not like the 6502 days when you could just drop into a machine language
monitor and hand-code some instructions to see what they do (that is how I
first learned ML).

I have decided to include the source code for the main program.  You may study
it, and even use the routines if you like.  I just hope you learn something.

I have NOT included my 'Std_Macs68k' file.  This file just contains a bunch of
macros that match my programming style.  For example, if I am testing a
register for zero, I like to be able to code 'bz.s xxx' rather then the more
ambiguous 'beq.s xxx'.  So in my macro file I have a macro called 'bz'.

I have also not included the 'dos_lib.i' file.  This file can be created by
using FixFD like so:

>FixFD dos_lib.fd dos_lib.i

in my case, I then edited the dos_lib.i file to add a 'PREASM' option and ran
it through the assembler (CAPE68k from Inovatronics).  This feature of CAPE
lets it inhale the 'INCLUDE' file without pausing to assemble it.  A real
timesaver in larger projects.  This step is entirely optional.

Finally, the code must be linked with Std_Startup.obj.  This file is my
customized version of AStartup.obj.  I have included 'Std_Startup.obj' but not
the source code for it.  If you want to play around with FixFD, you could link
with AStartup.obj instead.  Here is how you get the link to work:

>BLink with FixFD.link

if you don't happen to have the freely-redistributable 'BLink' then substitute
the name of your linker (probably 'ALink').  The file 'FixFD.link' is also
included.  Take a look at it, because it expects to find everything in 'RAM:'.

Good luck!  Remember to read the docs.  And if you have any questions or
comments then please send me a postcard (my address is in the docs).

-Peter W.SHAR_EOF
cat << \SHAR_EOF > FixFD.asm
; file:FixFD.asm
;-----------------------------
;          Fix FD
;-----------------------------
; A utility to convert FD files to EQU files.
;
; Copyright (c) 1988 by Peter Wyspianski
;
; Revision History
; ----------------
; 30 Dec 88  created
; 01 Jan 89  changed to use the 'dos_lib.i' file

;----------------------------------------
; Constants

null	equ     $00
bs	equ	$08
tab	equ	$09
lf	equ     $0a ; amiga eoln
cr	equ     $0d ; CR only
esc	equ	$1b
csi	equ	$9b ; control sequence introducer

; DOS Constants:

MODE_OLDFILE	equ 1005
MODE_NEWFILE	equ 1006

SIGBREAKB_CTRL_C	EQU	$0C
SIGBREAKB_CTRL_D	EQU	$0D
SIGBREAKB_CTRL_E	EQU	$0E
SIGBREAKB_CTRL_F	EQU	$0F

SIGBREAKF_CTRL_C	EQU	$1000
SIGBREAKF_CTRL_D	EQU	$2000
SIGBREAKF_CTRL_E	EQU	$4000
SIGBREAKF_CTRL_F	EQU	$8000

;**SIGBREAK_ANY		equ	$F000
SIGBREAK_ANY		equ	$1000

; Exec Base Offsets:

ThisTask	EQU	$114

; Task Control Structure Offsets:

TC_SIGRECVD	EQU	$1A
TC_SIGALLOC	EQU	$12

;----------------------------------------
; Includes

	MACFILE "RAM:Std_Macs68k"
	INCLUDE "RAM:dos_lib.i"

;----------------------------------------
; Publics

	XDEF    _main
	XDEF	Exit
	
;----------------------------------------
; Externals:

; from std.startup:

	XREF	_exit
	XREF	_stdin,_stdout,_SysBase,_DOSBase

;----------------------------------------
; The beginning

	SECTION Main,CODE

; just a little something to brighten some file-zapper's day:

	dc.b	'Be Happy!',null
	cnop	0,2

;-------------------------------
; BCD_Left  [18 Nov 88]
;
; - converts hex word to a string of one to five left justified BCD digits
; - string is null terminated
;
; Inputs :  d0.w = hex word
;           a0.l = starting address of string
; Outputs:  all regs preserved
;
; Notes  :  - from 1 to five digits can be returned plus the zero termination
;             for a total of up to six characters
;           - starts by determining number of digits in the string

BCD_Left

	pushm	d0-d3/a0-a1
	
	move.w	#3,d2		; # digits - 2
	lea	LBCDTAB,a1	; point to ten thousands

1$	cmp.w	(a1)+,d0	; determine number of digits in result
	bcc.s	2$		; (ubge) taken if right size
	dbra	d2,1$		; taken for 10K through 10
	bra.s	6$		; we have just a ones digit

2$	subq.l	#2,a1		; compensate for following pre-decrement

3$	move.w	(a1)+,d1	; d1=BCD digit weight
	move.b	#'0',d3		; init digit to ASCII '0'
4$	cmp.w	d1,d0		; digit weight ? remainder
	blt	5$		; taken if done with this digit
	addq.b	#1,d3		; inc BCD digit result
	sub.w	d1,d0		; decrement total
	bnz.s	4$		; go for more
5$	move.b	d3,(a0)+	; stash digit
	dbra	d2,3$		; next digit position
6$	or.b	#'0',d0		; form ones digit
	move.b	d0,(a0)+
	clr.b	(a0)		; form zero terminator

	pullm	d0-d3/a0-a1
	rts

LBCDTAB	dc.w	10000,1000,100,10

;----------------------------------------
; GetDec  [30 Dec 88]
;
; - converts a decimal string to a hex value
;
; Inputs : a0 = ^ string
; Outputs: d0.l = value
;
; Reg Use: d1,a0-a1
;
; Calls  : none
; Uses   : none
;
; Notes  : - Non-numeric input produces garbage (GIGO applies).
;	   - Excessively long strings cause wrap-around.

GetDec:

	clr.l	d0		; result
1$	move.b	(a0)+,d1	; fetch next digit
	bz.s	2$		; if 'digit' is a null then all done

; here the running result is multiplied by ten:

	asl.l	#1,d0		; x2
	move.l	d0,a1		; save the x2 value (a1 = scratch)
	asl.l	#2,d0		; x4 x8
	add.l	a1,d0		; x8 + x2 = x10
	
; the latest 'units' digit is added to the result:

	sub.b	#'0',d1		; force digit to range 0-9
	add.l	d1,d0		; splice into result
	bra.s	1$		; and go for more!

2$	rts

;----------------------------------------
; PrStr   [31 Dec 88] _stdout
; FPrStr  [31 Dec 88] a file
;
; - sends a null terminated string to a file (_stdout)
;
; Inputs : a0 = ^string
;	   a1 = file handle (FPrStr only)
;
; Outputs: none
;
; Calls  : Write    (DOS.Library)
; Uses   : _DOSBase (library base)
;	   _stdout
;
; Notes  : exits via the call to Write

PrStr:
	move.l	_stdout,a1
FPrStr:
	push.l	a1	; save file handle

	move.l	a0,a1	; find the string length
1$	tst.b	(a1)+
	bnz.s	1$	; loop until end of string
	sub.l	a0,a1	; start-end+1 = len+1
	sub.l	#1,a1	; fix the length

	pull.l	d1	; recover file handle
	move.l	a0,d2	; ^buffer
	move.l	a1,d3	; length
	move.l	_DOSBase,a6
	jmp	_LVOWrite(a6)	; exit via this routine

;----------------------------------------
; ReadLn   [31 Dec 88] from _stdin
; FReadLn  [31 Dec 88] from a file
;
; - reads a line from a file (_stdin)
; - terminator (lf) is NOT stored
; - string is returned null-terminated
;
; Inputs : a0 = ^string buffer
;	   a1 = file handle (FReadLn only)
;
; Outputs: d0 = result: 1 = ok, 0 = eof, -1 = error
;
; Reg Use: d0-d3/a0-a2
;
; Calls  : Read    (DOS.Library)
; Uses   : _DOSBase (library base)

ReadLn:
	move.l	_stdin,a1

FReadLn:

	move.l	a0,a2		; keep ^buffer safe
	move.l	a1,a3		; keep file handle safe
	
1$	move.l	a3,d1		; file handle
	move.l	a2,d2		; ^buffer
	move.l	#1,d3		; read one char
	CallDOS	Read
	cmp.l	#1,d0		; what was returned?
	bne.s	2$		; exit if error or eof
	
	move.b	(a2)+,d1	; fetch character and bump ^buffer
	cmp.b	#lf,d1		; end of line?
	bne.s	1$		; taken if not

2$	move.b	#null,-1(a2)	; null terminate the string
	rts			; and exit

;----------------------------------------
; FileOpenError  [31 Dec 88]
;
; - calls IoErr to get a specific error number for a failed file open.
; - prints an error message of the form:
;
;   Error #xxx opening file "yyyy".
;
;
; Inputs : a0 = ^filename
; Outputs: none
;
; Reg Use: d0-d1/a0-a1
;
; Calls  : IoErr    (DOS.Library)
;	   BCD_Left
;	   PrStr
; Uses   : _DOSBase (library base)
;	   BCDBuff

FileOpenError:

	push.l	a0		; save ^file name

	CallDOS	IoErr		; must do this FIRST
	push.w	d0		; save the bad news

	lea	BadOpenMsg,a0
	jsr	PrStr

	pull.w	d0		; recover error number
	lea	BCDBuff,a0
	jsr	BCD_Left
	
	lea	BCDBuff,a0
	jsr	PrStr		; show the number
	
	lea	BadOpenMsg1,a0	; second half of error message
	jsr	PrStr
	
	pull.l	a0		; fetch ^file name
	jsr	PrStr
	
	lea	BadOpenMsg2,a0	; third half of error message
	jsr	PrStr
	
	rts

*----------------------------------------
* Main  [30 Dec 88]
*
* here is a picture of the entry stack:
*
*   12  ---        not ours!
*    8  ^argvArray pointer to argvArray
*    4  argc       argument count
* sp 0  RA     our return address

_main:
	clr.l	TheError	; default good return
	
	move.l  sp,savesp	; to ensure that we clean up on exit
	pull.l	ReturnAddr	; just in case we need it...

; make a pointer to our TC_SIGRECVD:

	move.l	_SysBase,a0	; base of the Exec library
	move.l	ThisTask(a0),a0	; ^Task Control Structure (that's us!)
	lea	TC_SIGRECVD(a0),a0 ; ^the flags
	move.l	a0,TaskSigs	; save the pointer for later

; and we're off:

	lea	GreetMsg,a0	; say hello
	jsr	PrStr

	pull.l	argc		; argc (argument count)
	pull.l	argv		; ^argv (argument array)
	
	move.l	argc,d0		; argv format: <name> <source> <dest>
	cmp.l	#3,d0		; we need three arguments...
	blt.l	Help		; ...taken if 'confused user' error!

	move.l	argv,a0		; fetch ^argv
	move.l	4(a0),a0	; point to first argument
	move.l	a0,SName	; save ^source file name

	move.l	argv,a0		; fetch ^argv
	move.l	8(a0),a0	; point to second argument
	move.l	a0,DName	; save ^dest file name

; open the input file:

	move.l	SName,d1
	move.l	#MODE_OLDFILE,d2	; must already exist
	CallDOS	Open

	move.l	d0,sfile	; save source file handle
	bnz.s	1$		; taken if ok

; handle problems opening the input file:

	move.l	SName,a0
	jsr	FileOpenError
	move.l	#30,TheError
	bra.l	Exit			; bye!

; open the output file:

1$	move.l	DName,d1
	move.l	#MODE_NEWFILE,d2
	CallDOS	Open

	move.l	d0,dfile	; save dest file handle
	bnz.s	ScanFD		; taken if ok

; handle problems opening the output file:

	move.l	DName,a0
	jsr	FileOpenError
	move.l	#30,TheError
	bra.l	Exit2
	
; read lines of the input file until EOF is true:

ScanFD:

; If the output file is acutally the tube then we don't want
; line numbers cluttering the display:

	move.l	dfile,d1	; output file handle
	CallDOS	IsInteractive
	move.b	d0,TubeOut	; -1 = yeah, 0 = nope
	
	lea	HeaderMsg,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr

	move.l	DName,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr
	
	lea	HeaderMsg1,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr

	tst.b	TubeOut		; skip screen formatting if outfile...
	bnz.s	1$		; ... is connected to the tube.
	
	lea	StatusMsg,a0
	jsr	PrStr

	lea	CursorOff,a0
	jsr	PrStr

1$	move.w	line,d0		; bump line number
	add.w	#1,d0
	move.w	d0,line

	tst.b	TubeOut		; gonna use the tube?
	bnz.s	8$		; taken if not (being used by out file)

	lea	BCDBuff,a0	; convert line number to a dec string
	jsr	BCD_Left

	lea	BCDBuff,a0	; show the line number
	jsr	PrStr

; This gets REAL fancy by adding one 'bs' to StrBuff for every
; non-null char in BCDBuff:

	lea	BCDBuff,a0
	lea	StrBuff,a1
	
2$	move.b	#bs,(a1)+	; put one in there
	tst.b	(a0)+		; check for a null
	bnz.s	2$		; taken if not
	
	move.b	#null,-1(a1)	; kill the last bs and null terminate

	lea	StrBuff,a0	; backup
	jsr	PrStr

8$	move.l	TaskSigs,a0	; see if the user hit ctrl-c thru ctrl-f
	move.l	(a0),d0		; d0 = SigsRecvd
	and.l	#SIGBREAK_ANY,d0	; mask all but ours
	bnz.l	Abort		; taken if we hit

	lea	StrBuff,a0	; fetch a line from the input file
	move.l	sfile,a1
	jsr	FReadLn	

	tst.l	d0		; see what's up!
	
	bz.l	Exit0		; taken if EOF
	bmi.l	Exit0		; taken if error

;----------------------------------------
; determine what sort of line it is here:
;
; 		# = option (process further)
; A-Z,a-z,'_','.' = FD entry (strip)
;
; all others are ignored ('*',';', and anything else)

	move.b	StrBuff,d0	; fetch first char
	
	cmp.b	#'#',d0		; option?
	beq	6$		; taken if so
	
	cmp.b	#'.',d0		; fd entry?
	beq.s	3$		; taken if so
	
	cmp.b	#'_',d0		; fd entry?
	beq.s	3$		; taken if so
	
	cmp.b	#'A',d0		; fd entry?
	blt.l	1$		; taken if NOT (ignore)
	
	or.b	#$20,d0		; force to lowercase
	cmp.b	#'z',d0		; fd entry?
	bgt.l	1$		; taken if NOT (ignore)

;---------------------------------------------------------------
; strip the line (scan for a space, open paren, or end of line)
; there are NO blank lines here (eliminated above):
;

3$	lea	LVOMsg,a0	; prefix the routine name with '_LVO'
	move.l	dfile,a1
	jsr	FPrStr
	
	lea	StrBuff,a0
5$	move.b	(a0)+,d0	; fetch a char and bump pointer
	bz.s	4$		; taken if end of line
	cmp.b	#' ',d0		; space?
	beq.s	4$		; taken if so
	cmp.b	#'(',d0		; open paren?
	bne.s	5$		; taken if so

4$	move.b	#null,-1(a0)	; null-terminate right AT the 1st excess char

	pea	-1(a0)		; save ^end of string (for later)
	
	lea	StrBuff,a0	; show the line
	move.l	dfile,a1	; output file handle
	jsr	FPrStr
	
	lea	StrBuff,a0
	pull.l	d0		; fetch ^end of string
;***	sub.l	a0,d0		; d0 = string len
;***	lea	EQU8Msg,a0	; <tab> <tab> equ <tab>-
;***	cmp.l	#8,d0		; seven chars or less?
;***	blt.s	44$		; taken if so (output extra tab)

	lea	EQUMsg,a0	; <tab> equ <tab>-
44$	move.l	dfile,a1	; output file handle
	jsr	FPrStr
	
	move.w	bias,d0		; convert the bias to a decimal string
	lea	BCDBuff,a0
	jsr	BCD_Left
	
	lea	BCDBuff,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr		; show the bias

	lea	EQUMsg1,a0	; finish the line off
	move.l	dfile,a1	; output file handle
	jsr	FPrStr

	move.w	#6,d0		; bump bias
	add.w	d0,bias

	bra.l	1$		; and go again!

;----------------------------------------
; check for the '##bias' option:

6$	move.l	StrBuff+2,d0	; fetch 4 chars (should be 'bias')
	or.l	#$20202020,d0	; force to lowercase
	cmp.l	#'bias',d0
	bne.l	1$		; ignore if not the option

; scan for a space:

	lea	StrBuff+6,a0	; skip the '##bias'

7$	move.b	(a0)+,d0	; fetch a char and bump pointer
	bz.l	1$		; taken if end of line (ignore)
	cmp.b	#' ',d0		; space?
	bne.s	7$		; taken if not

; fetch and show the bias:

	jsr	GetDec		; a0 should be pointing at the number
	move.w	d0,bias		; save it
	
; show the 'bias = ' message:

	lea	BiasMsg,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr

	move.w	bias,d0		; convert the bias to a decimal string
	lea	BCDBuff,a0
	jsr	BCD_Left
	
	lea	BCDBuff,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr		; show the bias

	lea	BiasMsg1,a0
	move.l	dfile,a1	; output file handle
	jsr	FPrStr
	
	bra.l	1$		; go for another line


;-------------------------------------------
; show the help message and exit:

Help:
	lea	HelpMsg,a0
	jsr	PrStr
	bra.s	Exit

;-------------------------------------------
; show the 'break...' message and exit:

Abort:
	lea	BreakMsg,a0
	jsr	PrStr
	bra.s	ExitA

;-----------------------------
; Exit routines  [30 Dec 88]
;

Exit0:

	lea	DoneMsg,a0
	jsr	PrStr

ExitA:
	lea	CursorOn,a0
	jsr	PrStr

Exit1:
	move.l	dfile,d1	; close the dest file
	CallDOS	Close

Exit2:
	move.l	sfile,d1	; close the source file
	CallDOS	Close

Exit:
	push.l	TheError	; error code
	jsr	_exit		; and wind it up

;----------------------------------------
; constants

	SECTION Constants,DATA

GreetMsg:
	dc.b	lf
	dc.b	csi,'0;33;40m'
	dc.b	' FixFD '
	dc.b	csi,'0;31;40m'
	dc.b	'v1.0 - Copyright ',$a9
	dc.b	' 1988, Peter Wyspianski',lf,lf
	dc.b	null

HelpMsg
	dc.b	' This utility takes an ''.FD'' file and generates a set of',lf
	dc.b	' EQUates that can be used by an assembler.',lf,lf
	dc.b	' Parameters: source_file dest_file.',lf,lf
	dc.b	' See the docs for more info! -PW',lf,lf,null

BadOpenMsg:
	dc.b	csi,'0;33;40m'
	dc.b	' Error '
	dc.b	csi,'0;31;40m'
	dc.b	'#'
	dc.b	null

BadOpenMsg1:
	dc.b	' opening file "',null

BadOpenMsg2:
	dc.b	'"',lf,lf,null

CursorOff
	dc.b	csi
	dc.b	'0 p'
	dc.b	null

CursorOn
	dc.b	csi
	dc.b	' p'
	dc.b	null

StatusMsg:
	dc.b	'   Reading line '
	dc.b	null

DoneMsg
	dc.b	lf,lf
	dc.b	csi,'0;33;40m'
	dc.b	' Finished.'
	dc.b	csi,'0;31;40m'
	dc.b	lf,lf,null

BreakMsg
	dc.b	lf,lf
;***	dc.b	csi,'0;33;40m'
	dc.b	'*** BREAK'
;***	dc.b	csi,'0;31;40m'
	dc.b	lf,lf,null
	
HeaderMsg
	dc.b	'; file:',null

HeaderMsg1
	dc.b	lf
	dc.b	';',lf
	dc.b	'; generated by FixFD v1.0',lf
	dc.b	';',lf
	dc.b	null

BiasMsg
	dc.b	'; Bias = ',null
	
BiasMsg1
	dc.b	lf
	dc.b	';',lf
	dc.b	null

LVOMsg
	dc.b	'_LVO',null
	
EQU8Msg
	dc.b	tab
EQUMsg
	dc.b	tab
	dc.b	'equ -'
	dc.b	null

EQUMsg1
	dc.b	lf
	dc.b	null

;----------------------------------------
; Uninitialized storage

	SECTION Variables,BSS

TaskSigs	ds.l	1	; pointer to our TC_SIGRECVD

TheError	ds.l	1	; error return code

SName		ds.l	1	; ^source file name
DName		ds.l	1	; ^dest file name

sfile		ds.l	1	; source file handle
dfile		ds.l	1	; dest file handle

savesp		ds.l    1	; entry stack pointer

argc		ds.l	1	; argument count
argv		ds.l	1	; argument array pointer

ReturnAddr	ds.l	1	; program return address

bias		ds.w	1	; library entry bias
line		ds.w	1	; current line number

TubeOut		ds.b	1	; -1 = yes, 0 = nope
		ds.b	1	; alignment

BCDBuff		ds.b	6	; bcd string buffer

StrBuff		ds.b	256	; longest possible string

		ENDSHAR_EOF
cat << \SHAR_EOF > FixFD.docs

 FixFD v1.0
 User Manual

Copyright (C) 1988 by Peter Wyspianski

[31 Dec 88]


----------------------
Please Read The Manual
----------------------

The FixFD utility is not complicated, but please take a couple minutes to read
through this manual before you try it.  Thanks!


--------
Abstract
--------

FixFD is a utility for the Amiga series of computers that reads an '.FD' file
to produce an assembler 'include' file.


-----------
Legal Stuff
-----------

Amiga is a trademark of Commodore-Amiga, Inc.
The author is in no way connected with Commodore-Amiga, Inc.

The FixFD utility package, consisting of the program and documentation file, is
copyrighted.  Permission is granted for NON-COMMERCIAL distribution of
UNMODIFIED copies of the entire package.  All other rights are reserved. 
Distribution of separate parts of the package, or of modified copies is
specifically prohibited.  Failure to abide by these rules may result in a fine,
and/or jail term.  Additionally you may get a guilty conscience and I certainly
won't visit you.  Pass the word, pass this program!


-----------------------
Who Needs This Utility?
-----------------------

If you are an Amiga assembly language programmer (or want to be), then read on.
Otherwise, this utility is NOT for you (sorry)!


-----------
The Problem
-----------

When you're programming in assembly language, the most common way to define a
'Library Vector Offset' (LVO) is to use the XLIB macro like so:

	XLIB	Open	; DOS.Library
	XLIB	Close	; DOS.Library
	
where the 'XLIB' macro looks something like this:

XLIB	macro		; <routine name>
	xref	_LVO\1
	endm

so by the time the assembler has sorted out those first couple of definitions
here is what you got:

	xref	_LVOOpen
	xref	_LVOClose
	
Later on in the program you may want to call the 'Open' routine:

	move.l	DOSBase,a6
	jsr	_LVOOpen(a6)

Of course most of us use a macro for those lines.  But here is a question -
just where IS the actual value of the symbol '_LVOOpen' defined?  It is defined
in the scanned library 'Amiga.Lib'!

The problem is that Amiga.Lib is about 80K bytes long, and contains a LOT of
things besides the _LVO definitions.  Having the _LVOs defined in Amiga.Lib
requires that you ALWAYS link your code with Amiga.Lib.  This effectively
neutralizes assemblers that produce loadable object files.  It also makes for
some very long link times.


------------
The Solution
------------

The ideal solution to the problem of having the LVOs defined in Amiga.Lib is to
just equate them to their proper values:

_LVOOpen	EQU	-30
_LVOClose	EQU	-36

Now you don't have to link with Amiga.Lib and the assembler will probably get
done a bit sooner as it doesn't have to do as much work.  To get these equates
you simply use FixFD!


------------
What It Does
------------

The Extras disk includes a drawer called 'FDx.x' (where x.x is the operating
system revision, currently '1.3'.  Within this drawer are a number of files
whose names end with '.FD'.  These '.FD' files all have a standard format. 
They completely define all the LVOs within a particular library.  The '.FD'
files are updated with every new revision of the operating system.

FixFD simply reads an '.FD' format file and cranks out a file that your
assembler can read (using 'INCLUDE').  And thats all there is to it!

You have a lot of choices when it comes to putting the resultant 'include'
files to use.  Adding a bunch of 'INCLUDE' statements is one possibility.  Or
you could merge them into one big include file.  If your assembler supports
'preassembled symbols' then you can preassemble the LVO file(s) for lightning
assembly speed!

I like to have all the LVOs in one big file.  That way I can use the cut-and-
paste features of my text editor to put just the LVOs I need right into the
assembly file I'm working on.

There is probably a utility somewhere out there that does exactly the same
thing as FixFD.  Too bad I haven't seen it (yet)!  So here is my contribution. 
Incidentally, it would have been far quicker to write this in something like
BASIC, but I simply wanted some practice at working with DOS files from
assembly.


-----------
Using FixFD
-----------

From the CLI (Command Line Interpreter) or Shell type:

>fixfc source_file dest_file

where 'source_file' is the name of the '.FD' file you want to read
 and   'dest_file'  is the name of the new file you want to make

You can use an asterix ('*') for the dest file, to send output to the CLI
window.  In that case the fancy line number display is suppressed so it doesn't
tangle up the output.

FixFD can be aborted in the usual way (ctrl-c).  And if you forget one of the
file names (or use '?'), you get a little blurb reminding you what to do.

It DOESN'T work from WorkBench so don't try it (crashes the system).  I could
make it WorkBench compatible but why bother?

Thats about it.  I sure hope you like it!


--------------------
So How Does It Work?
--------------------

[This section is for the curious; it may be safely skipped by others.]


FixFD scans each line of the input file looking for one of the following:

##bias xx

Where xx is a decimal number 0-65535.  Sets the base from which subsequent LVOs
are calculated.  Defaults to zero.  The usual value is 30.

<LVO name> <whatever>

An LVO name is any line that starts with one of these characters:

	a-z, A-Z, period ('.'), underline ('_')
	
When an LVO name is found, the line is scaned for an open paren ('(') or space.
If one is found, the line is chopped from that point on.  In any case, the LVO
name is written to the dest file with the prefix '_LVO'.  Following the name is
a tab, the word 'equ', another tab, and the decimal offset of the LVO.

All other lines (including blank lines, and lines beginning with ';' or '*')
are ignored.


-------------------------
Send Postcards Not Money!
-------------------------

The Author enjoys getting mail.  Especially picture post cards.  If you like
this program, hate it, or want to see some improvements, please send me a
post card:

Peter Wyspianski
5-10A Brock Cres
Kingston, Ont
CANADA  K7K 5K6

Don't bother sending money.  However, all offers of employment will be
seriously considered.


-----------------
End of the Manual
-----------------

Congradulations on having read this far.  Current research indicates that you
are one of only 9.23% of users who bother to read the manual.


-------------------------
Technical Details/Credits
-------------------------

FixFD is written in M68000 Assembly Language.  Total development time was about
eight hours, including writing this doc file.  I had to write most of the DOS
file code from scratch.  I already had the decimal conversion and formatting
routines.

Some of the better products used in the development of this utility include:

CAPE 68010 Assembler (Inovatronics)
BLink (Software Distillery)
Uedit (Rick Stiles)

(The preceeding was an unsolicited endorsement).

Special Thanks: Sharon W.



SHAR_EOF
cat << \SHAR_EOF > FixFD.link

FROM
RAM:Std_Startup.obj
RAM:FixFD.obj

TO
FixFD

SHAR_EOF
cat << \SHAR_EOF > FixFD.uu

begin 644 FixFD
M```#\P`````````&``````````4```!R````#@```&````$G````;````$T`"
M``/I````<B//````'"/`````)"/(````*$*Y````("QX``0CS@````23R4ZN6
M_MHH0$JL`*QG``"P80`!<B!L`*S1R-'((&@`$-'(T<A(YR`P1?D```"`1_D`^
M````=`%P`!`8)LI@`A384<C__$(:(#D````D('D````H$AA3@&\>#`$`(&_T3
M4H(FRF`*$AA3@`P!`"!O!!3!8/)"&F#<0AI"FR`"3-\,!$AY`````"\`+'D`U
M```(3J[_RB/`````$"QY````"$ZN_\0CP````!0CP````!A.N0```1QP`"YY9
M````'$YU80``Q&$``*XCP````"!"IR\`)$`@*@`D9Q`L>0````@@0"(H``!.<
MKO^"(BH`(&<H)#P```/M3J[_XB/`````$"/`````%"/`````&&<*Y8@@0"EH+
M``@`I$ZY```!''``8`0@+P`$+GD````<+P`L>``$(#D````(9P(B0$ZN_F)*C
MN0```"!G#DZN_WPB>0```"!.KOZ&(!].=4CG`08N/``#@`<L>``$3J[_E$S?.
M8(!P9&"R0>P`7$ZN_H!![`!<3J[^C$YU0KD````(0_D````L(#P````B3J[]]
MV"/`````"&>V3G4``````^P````9`````0````(````(````#@```!0````>V
M````:@```'````"L````M@```+P```#&````S````-H```#J````_````1P`G
M``$B```!*````4@```%4```!8@```6X```&H```!K@```;X````#`````@``8
M`$P```!2````I`````(````#````T@```3H````````#\@```^H````.``$`%
M``````````````````````````````````````````````````````!D;W,NT
M;&EB<F%R>0````/R```#ZP```&````/R```#Z0```2="92!(87!P>2$`2.?P*
MP#0\``-#^0```$JP660&4<K_^F`:58DR&18\`#"P06T```A2`Y!!9O00PU'*Y
M_^H````P$,!"$$S?`P].=2<0`^@`9``*0H`2&&<0XX`B0.6`T(D$`0`PT(%@7
M[$YU(GD````4+PDB2$H99OR3R)/\`````2(?)`@F"2QY````"$[N_]`B>0``?
M`!`D2"9)(@LD"B8\`````2QY````"$ZN_]8,@`````%F"!(:#`$`"F;<%7P`X
M`/__3G4O""QY````"$ZN_WP_`$'Y````\TZY````:C`?0?D````N3KD````*!
M0?D````N3KD```!J0?D```$.3KD```!J(%].N0```&I!^0```1Y.N0```&I.;
M=4*Y````!"//````&"/?````)"!Y````!"!H`11!Z``:(\@`````0?D`````&
M3KD```!J(]\````<(]\````@(#D````<#(`````#;0`"TB!Y````("!H``0C>
MR`````@@>0```"`@:``((\@````,(CD````()#P```/M+'D````(3J[_XB/`P
M````$&8:('D````(3KD```#&(_P````>````!&```LXB.0````PD/````^XL3
M>0````A.KO_B(\`````49AH@>0````Q.N0```,8C_````!X````$8``"AB(Y+
M````%"QY````"$ZN_R@3P````"Q!^0```6LB>0```!1.N0```'`@>0````PBV
M>0```!1.N0```'!!^0```7,B>0```!1.N0```'!*.0```"QF&$'Y```!*TZYR
M````:D'Y```!(DZY````:C`Y````*@9```$SP````"I*.0```"QF/D'Y````\
M+DZY````"D'Y````+DZY````:D'Y````+D/Y````-!+\``A*&&;X$WP``/__3
M0?D````T3KD```!J('D`````(!`"@```$`!F``%\0?D````T(GD````03KD`]
M``"62H!G``%R:P`!;A`Y````-`P``"-G``#$#```+F<:#```7V<4#```06T`&
M_UP````@#```>FX`_U!!^0```:$B>0```!1.N0```'!!^0```#00&&<,#```5
M(&<&#```*&;P$7P``/__2&C__T'Y````-")Y````%$ZY````<$'Y````-"`?1
M0?D```&G(GD````43KD```!P,#D````H0?D````N3KD````*0?D````N(GD`5
M```43KD```!P0?D```&N(GD````43KD```!P,#P`!M%Y````*&``_JX@.0``C
M`#8`@"`@("`,@&)I87-F`/Z80?D````Z$!AG`/Z,#```(&;T3KD```!2,\``\
M```H0?D```&3(GD````43KD```!P,#D````H0?D````N3KD````*0?D````N.
M(GD````43KD```!P0?D```&=(GD````43KD```!P8`#^+D'Y````1DZY````W
M:F!&0?D```%=3KD```!J8`Q!^0```3Q.N0```&I!^0```2=.N0```&HB.0``;
M`!0L>0````A.KO_<(CD````0+'D````(3J[_W"\Y````!$ZY```!0@`````#`
M[`````$````````$E@````L````!```!,````)(```"(````I@```,H```&8G
M```!T````@(```1V```$A@```&P````B`````P```!0```#<````Z@```/8`Z
M``$"```!"@```18```%*```!L````>@```(>```",````D(```)6```"8@``<
M`H8```*2```"N````MP```,F```#6````W(```.$```#E@```Z@```/D```#B
M_```!`X```0@```$,@``!$(```10```$7@``!&H````1````!````-8```#\Y
M```!$````40```(2```"-@```E````)<```#&@```V8```.<```#\```!"8`4
M``0\```$2@``!%@```1D````0`````4```#D````\````1X```$D```!*@``:
M`3X```%0```!5@```5P```%L```!=@```7P```&&```!C````:(```&J```!(
MN@```<0```':```!X@```?(```'\```"#````A@```(D```"*@```CP```)(O
M```":````G(```)X```"@````HP```*8```"G@```K(```*^```"T````M8``
M``+L```#(````RP```-,```#4@```UX```-L```#>````WX```.*```#D```0
M`Z(```.R```#O````](```/J```#]@``!`(```0(```$%```!!H```0L```$0
M<```!(````20`````````_(```/J````;`J;,#LS,SLT,&T@1FEX1D0@FS`[/
M,S$[-#!M=C$N,"`M($-O<'ER:6=H=""I(#$Y.#@L(%!E=&5R(%=Y<W!I86YSH
M:VD*"@`@5&AI<R!U=&EL:71Y('1A:V5S(&%N("<N1D0G(&9I;&4@86YD(&=E@
M;F5R871E<R!A('-E="!O9@H@15%5871E<R!T:&%T(&-A;B!B92!U<V5D(&)YL
M(&%N(&%S<V5M8FQE<BX*"B!087)A;65T97)S.B!S;W5R8V5?9FEL92!D97-T]
M7V9I;&4N"@H@4V5E('1H92!D;V-S(&9O<B!M;W)E(&EN9F\A("U05PH*`)LPB
M.S,S.S0P;2!%<G)O<B";,#LS,3LT,&TC`"!O<&5N:6YG(&9I;&4@(@`B"@H`8
MFS`@<`";('``("`@4F5A9&EN9R!L:6YE(``*"ILP.S,S.S0P;2!&:6YI<VAEZ
M9"Z;,#LS,3LT,&T*"@`*"BHJ*B!"4D5!2PH*`#L@9FEL93H`"CL*.R!G96YE%
M<F%T960@8GD@1FEX1D0@=C$N,`H["@`[($)I87,@/2``"CL*`%],5D\`"0EE]
7<74@+0`*`````_(```/K````30```_([=
``
end
size 2948
SHAR_EOF
cat << \SHAR_EOF > Std_Start.uu

begin 644 Std_Startup.obj
M```#YP````````/H`````E-T87)T=7`````#Z0```'(CSP```!PCP````"0C@
MR````"A"N0```"`L>``$(\X````$D\E.KO[:*$!*K`"L9P``L&$``7(@;`"L%
MT<C1R"!H`!#1R-'(2.<@,$7Y````@$?Y`````'0!<``0&";*8`(4V%'(__Q":
M&B`Y````)"!Y````*!(84X!O'@P!`"!O]%*")LI@"A(84X`,`0`@;P04P6#RD
M0AI@W$(:0IL@`DS?#`1(>0`````O`"QY````"$ZN_\HCP````!`L>0````A.^
MKO_$(\`````4(\`````83KD`````<``N>0```!Q.=6$``,1A``"N(\`````@7
M0J<O`"1`("H`)&<0+'D````(($`B*```3J[_@B(J`"!G*"0\```#[4ZN_^(C`
MP````!`CP````!0CP````!AG"N6(($`I:``(`*1.N0````!P`&`$("\`!"YY2
M````'"\`+'@`!"`Y````"&<"(D!.KOYB2KD````@9PY.KO]\(GD````@3J[^_
MAB`?3G5(YP$&+CP``X`'+'@`!$ZN_Y1,WV"`<&1@LD'L`%Q.KOZ`0>P`7$ZNB
M_HQ.=4*Y````"$/Y````+"`\````(DZN_=@CP`````AGMDYU``````/L````!
M&0````$````"````"`````X````4````'@```&H```!P````K````+8```"\<
M````Q@```,P```#:````Z@```/P```$<```!(@```2@```%(```!5````6(`\
M``%N```!J````:X```&^`````P````(```!,````4@```*0````````#[X$``
M``)?;6%I;@````````(```#2```!.@$```)?<W1A<G1U<``````!```"7V5X)
M:70```````%"`````````_(```/J````#@`!````````````````````````1
M````````````````````````````````9&]S+FQI8G)A<GD````#[P$```)?]
M<W1D97)R`````!@!```"7W-T9&]U=``````4`0```E]$3U-"87-E````"`$`1
M``)?<W1D:6X``````!`!```"7V5R<FYO```````,`0```E]3>7-"87-E````#
5!`````````/R```#ZP```&````/R\
``
end
size 876
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.