

 The last installment for the DOS library ( for now anyway ). This month I
intend to cover the remaining routines that deal with file handaling. These
are all straight forward to use and can be included in a larger program.

 Deleteing a File
------------------

 You are about to discover how inventive the Commodore programming team was
when it came to naming these routines, to delete a file use use the function

 DeleteFile ( name )

where name is the address of a 0 terminated text string that specifies the
file. This address should be in register D1. For instsance, to delete a file
in ram: called 'letter.doc', you could use the following:

		move.l		#Filename,d1	d1=addr of filename
		CALLDOS		DeleteFile	and kill it


Filename	dc.b		'ram:letter.doc',0
		even

 Of course the dos.library must be open before calling this ( or any of the
following ) functions. Here is the complete example :

; DOS_eg1.s

; Example of DeleteFile () usage.

; M.Meany, April 1991

			Include		exec/exec_lib.i
			Include		libraries/dos_lib.i

;--------------	Open DOS library

		lea		dosname,a1	a1-> lib name
		moveq.l		#0,d0		any version
		CALLEXEC	OpenLibrary	and attempt open
		move.l		d0,_DOSBase	save lib base ptr
		beq		error		quit if error

;--------------	Delete the file

		move.l		#filename,d1	d1=addr of file
		CALLDOS		DeleteFile	and kill it

;--------------	Close DOS library

		move.l		_DOSBase,a1	a1->lib base
		CALLEXEC	CloseLibrary	and close it

;--------------	Finish

error		rts

;------
;--------------	DATA
;------

dosname		'dos.library',0
		even

_DOSBase	dc.l		0

filename	dc.b		'ram:letter.doc',0
		even


 Create a file in ram: called letter.doc, assemble and then run this program.
Hey presto ! ram:letter.doc is no more.

 Renaming a file
-----------------

 Well to rename a file, use

Rename ( oldname, newname )

 where oldname specifies the file to be renamed and newname is its new title.
Going back to our friend ram:letter.doc, suppose a text editor your are
writing has the option to back up a file before saving a newer version. So
ram:letter.doc would become ram:letter.bak ( sound familiar ). To do this
then:

		move.l		#oldname,d1
		move.l		#newname,d2
		CALLDOS		Rename


oldname		dc.b		'ram:letter.doc',0
		even
newname		dc.b		'ram:letter.bak',0
		even

 It is important to specify the same path for each file, any differences
will cause the rename to fail. Here is the complete example:



; DOS_eg2.s

; Example of Rename () usage.

; M.Meany, April 1991

		Incdir		sys:Include/
		Include		exec/exec_lib.i
		Include		libraries/dos_lib.i

;--------------	Open DOS library

		lea		dosname,a1	a1-> lib name
		moveq.l		#0,d0		any version
		CALLEXEC	OpenLibrary	and attempt open
		move.l		d0,_DOSBase	save lib base ptr
		beq		error		quit if error

;--------------	Rename the file

		move.l		#oldname,d1	d1=addr of filename
		move.l		#newname,d2	d2=addr of new name
		CALLDOS		Rename		and rename it

;--------------	Close DOS library

		move.l		_DOSBase,a1	a1->lib base
		CALLEXEC	CloseLibrary	and close it

;--------------	Finish

error		rts

;------
;--------------	DATA
;------

dosname		dc.b		'dos.library',0
		even

_DOSBase	dc.l		0

oldname		dc.b		'ram:letter.doc',0
		even

newname		dc.b		'ram:letter.bak',0
		even

 To Create a Directory on a Disc
---------------------------------

 As you have probably guessed, this function is called CreateDir. Call it
with the address of the text string that specifies the directory you wish
to create in register D1. For Example :


		move.l		#mydir,d1
		CALLDOS		CreateDir


mydir		dc.b		'ram:MarksDirectory',0
		even


 The function returns a value in register D0, this is the 'key' to the
directory created. This key locks the directory for exclusive use by your
program. In order to free the directory so that the system and other tasks
can access it, we must UnLock it. This is done by calling UnLock with the
key in register D1. If CreateDir returns a value 0 in D0, then the directory
could not be created. Here is how you would create and then unlock a
directory :


		move.l		#mydir,d1	d1=addr of dir name
		CALLDOS		CreateDir	create it
		move.l		d0,dir_key	save key
		beq		error_NO_KEY	quit if no key

		move.l		dir_key,d1	d1=key
		CALLDOS		UnLock		and unlock the directory


mydir		dc.b		'ram:MarksDirectory',0
		even

dir_key		dc.l		0

 Here is a complete example that creates a directory in ram. I leave it for
you to verify the directory exsists !



; DOS_eg3.s

; Example of CreateDir () usage.

; M.Meany, April 1991

		Incdir		sys:Include/
		Include		exec/exec_lib.i
		Include		libraries/dos_lib.i

;--------------	Open DOS library

		lea		dosname,a1	a1-> lib name
		moveq.l		#0,d0		any version
		CALLEXEC	OpenLibrary	and attempt open
		move.l		d0,_DOSBase	save lib base ptr
		beq		error		quit if error

;--------------	Create the directory

		move.l		#mydir,d1	d1=addr of dir name
		CALLDOS		CreateDir	and create it
		move.l		d0,dir_lock	save returned key
		beq		error1		quit if error

;--------------	Unlock the directory so system can access it

		move.l		dir_lock,d1	d1=key for the dir
		CALLDOS		UnLock		and release it

;--------------	Close DOS library

error1		move.l		_DOSBase,a1	a1->lib base
		CALLEXEC	CloseLibrary	and close it

;--------------	Finish

error		rts

;------
;--------------	DATA
;------

dosname		dc.b		'dos.library',0
		even

_DOSBase	dc.l		0

mydir		dc.b		'ram:MarksDirectory',0
		even

dir_lock	dc.l		0

 Adding A Comment to a File
----------------------------

 You should be aware that every file can have a comment attached to it. To
add a comment to a file using DOS we use the SetComment () function, this
requires two parameters. The address of the file name should be in register
D1 and the address of the comment in register D2. For example :

		move.l		#filename,d1
		move.l		#comment,d2
		CALLDOS		SetComment

filename	dc.b		'ram:letter.doc',0
		even

comment		dc.b		"Any old Iron",0
		even

 This will add the comment ' Any old Iron ' to the file ram:letter.doc.
Again a full example is given:


; DOS_eg4.s

; Example of SetComment () usage.

; M.Meany, April 1991

		Incdir		sys:Include/
		Include		exec/exec_lib.i
		Include		libraries/dos_lib.i

;--------------	Open DOS library

		lea		dosname,a1	a1-> lib name
		moveq.l		#0,d0		any version
		CALLEXEC	OpenLibrary	and attempt open
		move.l		d0,_DOSBase	save lib base ptr
		beq		error		quit if error

;--------------	Comment the file

		move.l		#filename,d1	d1=addr of file
		move.l		#comment,d2	d2=addr of file comment
		CALLDOS		SetComment	and add comment

;--------------	Close DOS library

		move.l		_DOSBase,a1	a1->lib base
		CALLEXEC	CloseLibrary	and close it

;--------------	Finish

error		rts

;------
;--------------	DATA
;------

dosname		dc.b		'dos.library',0
		even

_DOSBase	dc.l		0

filename	dc.b		'ram:letter.doc',0
		even

comment		dc.b		"This wasn't here before",0
		even

 Before you assemble and run this, make sure the file ram:letter.doc exsists.
Type 

list ram:

	from the CLI to see any comments currently attached to this file ( do
not be supprised if there is no comment ). After assembling and running this
example, enter the same command from the CLI, you should see the comment
appear after the file this time.

 Setting A Files Protection Bits
---------------------------------
 
 DOS attaches a number of protection flags to every file. You should already
be familiar with these ( read the manual that was supplied with your Amy if
not ).

 To alter the condition of these flags using DOS you set the appropriate BIT
to ZERO ( 0 ) in a flag long word. The most common bits are rwed, these
occupy the lowest four bits of the long word as shown below:

Bit Position:	xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
Flag	    :	-------- -------- -------- ----rwed

 I am not sure on the convention here, but I always CLEAR all other flags
in the long word ( upward compatability and all that ! ). To clear all the
flags, a value of -1 is used ( $FFFFFFFF ), it is then possible to SET the
bits you require. For instance, suppose you wish to make a file READABLE
only. You require a flag value of :

		-------- -------- -------- ----rwed
		11111111 11111111 11111111 11110111

 Only the r ( read ) flag is SET ( 0 ).

 Well thats the theory, here is how it is accomplished. The function
SetProtection () will attach the long word value in register D2 to the
flags attached to the file specified at the address held in register D1.
For example, to make the file ram:letter.doc readable only ( r flag=0 ):

		moveq.l		#-1,d2		clear all flags
		move.l		#%0111,d2	set only the r bit
		move.l		#filename,d1	d1=addr of filename
		CALLDOS		SetProtection	and protect file


filename	dc.b		'ram:letter.doc',0
		even

 A full example is given below. I reccomend you play with it and try setting
and clearing various bits in the flag field. You can see the condition of
the flags attached to a file by again using the List command from the CLI as
you did for the files comment. Here is the example :



; DOS_eg5.s

; Example of SetProtection () usage.

; M.Meany, April 1991

		Incdir		sys:Include/
		Include		exec/exec_lib.i
		Include		libraries/dos_lib.i

;--------------	Open DOS library

		lea		dosname,a1	a1-> lib name
		moveq.l		#0,d0		any version
		CALLEXEC	OpenLibrary	and attempt open
		move.l		d0,_DOSBase	save lib base ptr
		beq		error		quit if error

;--------------	Delete the file

		move.l		#filename,d1	d1=addr of file
		moveq.l		#-1,d2		clear all flags
		move.l		#%0001,d2	d2= rwe-
		CALLDOS		SetProtection	and protect

;--------------	Close DOS library

		move.l		_DOSBase,a1	a1->lib base
		CALLEXEC	CloseLibrary	and close it

;--------------	Finish

error		rts

;------
;--------------	DATA
;------

dosname		dc.b		'dos.library',0
		even

_DOSBase	dc.l		0

filename	dc.b		'ram:letter.doc',0
		even


 Calling Other Tasks From Disc
-------------------------------

 This function could have been so useful if not for the minor bugs, still I
will let you find these for yourself ( as I did while writing the A68K front
end ).

 Suppose you were writing a program similar to SID ( what ? never heard of
SID ! You poor person. Send a disc to me for instant remedy and thank Simon
Knipe for introducing SID to me later ). One of the options you want to make
available is calling a text editor from your program. How ?

 The DOS function Execute () will let you run a program from within your own
program. It requires THREE parameters, in register d1 should be a text line 
identical to that used from the CLI to invoke the program you are calling (
this should include any specific parameters ). In register d2 should be the
handle of the input file, set this to 0 if you wish the program to use the
same CLI window as your program. In register d3 should be the handle of the 
output file the program will use. A simple example, calling dir :

		move.l		#filename,d1
		moveq.l		#0,d2
		move.l		d2,d3
		CALLDOS		Execute


filename	dc.b		'dir ram: opt a',0
		even

 This will produce a full directory listing of the ram disc in the CLI
window which spawned the original program.

 Here is an example of invoking a text editor from within a program, it
is also a good oppurtunity to sprad a good text editor, TXED PLUS. When
you assemble and run this, be sure to have disc 11 nearby, you will be
asked to insert it so that TXED+ can be loaded.



; DOS_eg6.s

; Example of Execute () usage.

; You will need Disc 11 handy when you run this !

; M.Meany, April 1991

		Incdir		sys:Include/
		Include		exec/exec_lib.i
		Include		libraries/dos_lib.i

;--------------	Open DOS library

		lea		dosname,a1	a1-> lib name
		moveq.l		#0,d0		any version
		CALLEXEC	OpenLibrary	and attempt open
		move.l		d0,_DOSBase	save lib base ptr
		beq		error		quit if error

;--------------	Run text editor

		move.l		#editor,d1	d1=addr of file
		moveq.l		#0,d2		CLI input
		move.l		d2,d3		CLI output
		CALLDOS		Execute		and run it

;--------------	Close DOS library

		move.l		_DOSBase,a1	a1->lib base
		CALLEXEC	CloseLibrary	and close it

;--------------	Finish

error		rts

;------
;--------------	DATA
;------

dosname		dc.b		'dos.library',0
		even

_DOSBase	dc.l		0

editor		dc.b		'club11:utils/txed+',0
		even


 Well that just about wraps up this months episode. Last month I did say
I would show you how to determine the length of a file on disc. Well, those
of you who were wide awake will remember I had already shown this on an
earlier disc and gave a subroutine that could be included into other proggys
to determine the length of any file.


 OK, you missed it, so here it is again :

 Every file saved on a disc using DOS has a FileInfoBlock attached to it.
This block keeps a record of information refering to the file ( see below ).
To read the fileinfoblock into memory the DOS library function Examine is 
used. Once the block is in memory it is simple to extract the information
required from it. Here is the file info blocks structure:

 Offset		Reference Name	Size	Discription
 --------------------------------------------------------------
  0		DiskKey		LONG	Disk Number.
  4		DirEntryType	LONG	File Type ( + for a directory,
  						    - for a file ).
  8		FileName	108	The files name.
  116		Protection	LONG	File Protection Bits.
  120		EntryType	LONG	Entry Type.
  124		Size		LONG	The files length, in bytes.
  128		NumBlocks	LONG	The number of disc blocks occupied.
  132		Days		LONG	Day of Creation.
  136		Minute		LONG	Time of creation ( mins ).
  140		Tick		LONG	Time of Creation ( secs ).
  144		Comment		116	Any attached comment.
  
  This subroutine is only interested in the files size, so the FileInfoBlock
is read into memory, then the long word starting 124 bytes from the start of
the block is read. This is the files length in bytes.

 Here is a run through of the subroutine :
 
 Note that offsets for the FileInfoBlock can be found in the dos.i file 
supplied with DevpacII.

 Some memory is reserved for the FileInfoBlock ( FIB from now on ! ), as
there is no reason for this to be in CHIP ram PUBLIC memory is asked for
( asking for PUBLIC memory will cause AllocMem to first try and get FAST ram,
if none or not enough is available then CHIP ram is used ). The pointer to
the memory block is stored in file_info for later use. If the memory was not
allocated the program branches to error1 and again finishes.

 It's time to hunt the file down on the disc. The DOS function Lock is used
for this purpose. This function also locks the file for our explicit use, so
it is important to save the key value, returned in d0, so the file can be
unlocked when we have finished with the file. If the file ( or directory )
specified cannot be found, the Lock function returns 0 in d0. If this is the
case the program again aborts. Here are the parameters required by the Lock
function :

  In d1 :  The address of the file ( or directory ) name, 0 terminated.
     d2 :  The access mode required, either READ or WRITE.
     
 The value returned in d0 is the lock key if the file was found, or 0 other-
wise.

 Once the file has been found and locked we can load it's FIB using the DOS
function Examine. This function requires the following parameters :

  In d1 :  The Key value returned by the Lock function
     d2 :  The address where the FIB should be written.
     
 With the FIB now in memory, we can now look at the files size. The address
of the start of the FIB is put into a0 and a 16 bit displacement value (
fib_Size, defined in dos.i as explained earlier ) is used to form the address
of the files size. This value is copied into file_len. This program does 
nothing with this information, it was written as an learning experiment for
myself.

 At the end of the subroutine the value in file_len is copied into d0. All
being well, this will be the files length, else it will be zero.




; Subroutine that returns the length of a file in bytes.

; Entry		a0 = address of file name

; Exit		d0 = length of file in bytes or 0 if any error occurred

; Corrupted	a0

; M.Meany, Feb 91


; Save register values

FileLen		movem.l		d1-d4/a1-a4,-(sp)

; Save address of filename and clear file length

		move.l		a0,RFfile_name
		move.l		#0,RFfile_len

; Allocate some memory for the File Info block

		move.l		#fib_SIZEOF,d0
		move.l		#MEMF_PUBLIC,d1
		CALLEXEC	AllocMem
		move.l		d0,RFfile_info
		beq		error1
		
; Lock the file
		
		move.l		RFfile_name,d1
		move.l		#ACCESS_READ,d2
		CALLDOS		Lock
		move.l		d0,RFfile_lock
		beq		error2

; Use Examine to load the File Info block

		move.l		d0,d1
		move.l		RFfile_info,d2
		CALLDOS		Examine

; Copy the length of the file into RFfile_len

		move.l		RFfile_info,a0
		move.l		fib_Size(a0),RFfile_len

; Release the file

		move.l		RFfile_lock,d1
		CALLDOS		UnLock

; Release allocated memory

error2		move.l		RFfile_info,a1
		move.l		#fib_SIZEOF,d0
		CALLEXEC	FreeMem


; All done so return

error1		move.l		RFfile_len,d0
		movem.l		(sp)+,d1-d4/a1-a4
		rts

RFfile_name	dc.l		0
RFfile_lock	dc.l		0
RFfile_info	dc.l		0
RFfile_len	dc.l		0


 And finaly, the completed version of UCase. The above subroutine has been
added to the source and the necessary alterations made to make use of it.
An extra error message has also been added incase the files length cannot
be determined for some reason.

 Well you have now been taken through the development of a utility. Feel
free to alter the convert subroutine to produce different results, for 
instance it would be worth adding a further check so that text contained
in quote marks ( single or double ) is not converted. I leave this as an
exersise for the reader.



; DOS_eg7.s

; Here is the program that will convert any file of ANY length
;from upper case to lower case. All you have to do is enter the files name
;as a parameter at the CLI.

; Useful messages are now printed all over the show, taking user-friendlieness
;to the extreme.

; Added a routine to get filename from user.

; Added subroutine to determine length of file to be converted.

;--------------	To start with, the INCLUDE files we require.

		incdir		sys:include/		specify directory
		include		exec/exec_lib.i
		include		exec/exec.i
		include		libraries/dos_lib.i
		include		libraries/dos.i

;--------------	First then, 0 terminate parameter list.

Start		move.b		#0,-1(a0,d0)

;--------------	Now save start of parameter list as filename pointer

		move.l		a0,filename

;--------------	Open the DOS library

		lea		dosname,a1		a1->library name
		moveq.l		#0,d0			d0=0,any version
		CALLEXEC	OpenLibrary		open the library
		move.l		d0,_DOSBase		save base ptr
		beq		error			leave if error

;--------------	Get CLI output handle

		CALLDOS		Output			get handle
		move.l		d0,STD_OUT		save it
		beq		error1		leave if no handle

;--------------	Time for the first message, an introduction to the prog.

		lea		intro_msg,a0		a0=addr of msg
		bsr		PrintMsg		print it


;--------------	Check for usage instructions.

		move.l		filename,a0		a0-->parameter list
		cmpi.b		#'?',(a0)		is 1st param a ?
		bne		.continue		if not branch
		lea		usage,a0		a0=addr of msg
		bsr		PrintMsg		print it
		bra		error1			and quit

;--------------	Check that a file name has been given

.continue	move.l		filename,a0		a0-->parameter list
		tst.b		(a0)			is 1st byte a 0
		bne.s		.ok			if not branch

		bsr		GetFileName	else call subroutine
						;to get a filename from user

		tst.l		d0		does user want to quit?
		beq		error1		if so leave

;--------------	Now display a message telling user what file is bieng
;		converted.

.ok		lea		convrt_msg,a0	a0=addr of msg
		bsr		PrintMsg	print it

		move.l		filename,a0	a0=address of filename
		bsr		PrintMsg	print it

		lea		convrt_msg1,a0	a0=addr of msg
		bsr		PrintMsg	print it

;-------------- Call subroutine to determine length of file

		move.l		filename,a0	a0->the files name
		bsr		FileLen		determine size of file
		move.l		d0,file_len	save length
		bne.s		.cont		branch if all ok

		lea		no_len_msg,a0	a0=addr of error msg
		bsr		PrintMsg	print it
		bra		error1		and quit

;--------------	Allocate memory for our text buffer. D0 already holds the
;		length of the file.

.cont		move.l		#MEMF_PUBLIC!MEMF_CLEAR,d1 d1=requirements
		CALLEXEC	AllocMem		ask for memory
		move.l		d0,buffer		save mem addr
		bne.s		.cont1		branch if all ok

		lea		no_mem_msg,a0	a0=addr of error msg
		bsr		PrintMsg	print it
		bra		error1		leave if error

;--------------	Open file for reading

.cont1		move.l		filename,d1		d1=addr of filename
		move.l		#MODE_OLDFILE,d2	d2=access mode
		CALLDOS		Open			open the file
		move.l		d0,filehd		save handle
		bne.s		.cont2		branch if ok

		lea		no_file_msg,a0	a0=addr of error msg
		bsr		PrintMsg	print it
		bra		error2		leave if error

;--------------	Read data from file into buffer

.cont2		move.l		filehd,d1		d1=file handle
		move.l		buffer,d2		d2=addr of buffer
		move.l		file_len,d3		d3=size of file
		CALLDOS		Read			read data from file

;--------------	Close the file

		move.l		filehd,d1		d1=file handle
		CALLDOS		Close			close the file

;--------------	Call subroutine to do conversion. Note I have used the 
;		routine detailed above, but as a subroutine. If you wanted
;		to process the file in some other way, you just change the
;		subroutine.

		bsr		convert

;--------------	Open the file using MODE_NEWFILE to erase old contents

		move.l		filename,d1		d1=filename
		move.l		#MODE_NEWFILE,d2	d2=access mode
		CALLDOS		Open			and open file
		move.l		d0,filehd		save handle
		bne.s		.cont3		branch if OK

		lea		no_out_file,a0	a0=addr of error msg
		bsr		PrintMsg	print it		
		bra		error2		leave if error

;--------------	Write contents of buffer to the file

.cont3		move.l		filehd,d1		d1=files handle
		move.l		buffer,d2		d2=addr of buffer
		move.l		file_len,d3		d3=size of buffer
		CALLDOS		Write			write buffer

;--------------	Close the file

		move.l		filehd,d1		d1=file handle
		CALLDOS		Close			and close it

;--------------	Release buffer memory

error2		move.l		buffer,a1		a1=addr of buffer
		move.l		file_len,d0		d0=size allocated
		CALLEXEC	FreeMem			and release it

;--------------	Close the DOS library

error1		lea		all_done_msg,a0	a0=addr of message
		bsr		PrintMsg	print it

		move.l		_DOSBase,a1		a1=lib base ptr
		CALLEXEC	CloseLibrary		and close it

error		rts					all done so quit

**************************************************************************

;--------------
;--------------	SUBROUTINE AREA
;--------------

**************************************************************************

;--------------	Subroutine to get a filename from user

;Entry		none

;Exit		d0=0 if user wishes to quit or if no keyboard handle
;		   could be obtained.

;--------------	Get keyboard handle

GetFileName	CALLDOS		Input		get keyboard handle
		move.l		d0,STD_IN	store it
		beq.s		.error		leave if no handle

;--------------	Display a prompt to the user

		lea		get_file,a0	a0=addr of prompt message
		bsr		PrintMsg	print it

;--------------	Get filename

		move.l		STD_IN,d1	d1=handle
		move.l		#key_buffer,d2	d2=addr of buffer
		move.l		#buf_len,d3	d3=max num of chars to read
		CALLDOS		Read		get user input

;--------------	Save addr of filename and 0 terminate it

		lea		key_buffer,a0	a0=addr of filename
		move.l		a0,filename	save addr of filename
		move.b		#0,-1(a0,d0)	0 terminate

;--------------	Get first character of filename into register d0. If this is
;		a 0 byte then the user pressed return and wants to quit. This
;		value will be passed back to the calling program.

		moveq.l		#0,d0		clear d0
		move.b		(a0),d0		get 1st char into d0

;--------------	And return

.error		rts

**************************************************************************

;--------------	Subroutine to display any message in the CLI window

; Entry		a0 must hold address of 0 terminated message.
;		STD_OUT should hold handle of file to be written to.
;		DOS library must be open

PrintMsg	move.l		a0,a1		get a working copy

;--------------	Determine length of message

		moveq.l		#-1,d3		reset counter
.loop		addq.l		#1,d3		bump counter
		tst.b		(a1)+		is this byte a 0
		bne.s		.loop		if not loop back

;--------------	Make sure there was a message

		tst.l		d3		was there a message ?
		beq.s		.error		if not, graceful exit

;--------------	Get handle of output file

		move.l		STD_OUT,d1	d1=file handle
		beq.s		.error		leave if no handle

;--------------	Now print the message
;		At this point, d3 already holds length of message
;		and d1 holds the file handle.

		move.l		a0,d2		d2=address of message
		CALLDOS		Write		and print it

;--------------	All done so finish

.error		rts

**************************************************************************


;-------------- Subroutine to convert chars in buffer from lower case to
;		upper case.

; Initialise the data counter

convert		move.l		file_len,d0	d0 is counter
		subq.l		#1,d0		adjust for dbra
		
; Get address of start of buffer into register a0.

		move.l		buffer,a0	a0=start addr of buffer

; Move codes for 'a' and 'z' into data registers. This will speed loop up.

		move.b		#'a',d1		d1=code of char 'a'
		move.b		#'z',d2		d2=code of char 'z'

; If char is less than 'a' it is not lower case, so don't convert it.

char_loop	cmp.b		(a0)+,d1
		bgt.s		not_lower_case

; If char is greater than 'z' it is not lower case, so don't convert it.

		cmp.b		-1(a0),d2
		blt.s		not_lower_case 

; Char must be lower case so convert it.

		sub.b		#$20,-1(a0)	convert byte

; Test for end of data. Loop back if not there yet.

not_lower_case	dbra		d0,char_loop	loop until end of data

		rts

**************************************************************************

; Subroutine that returns the length of a file in bytes.

; Entry		a0 = address of file name

; Exit		d0 = length of file in bytes or 0 if any error occurred

; Corrupted	a0

; M.Meany, Feb 91


; Save register values

FileLen		movem.l		d1-d4/a1-a4,-(sp)

; Save address of filename and clear file length

		move.l		a0,RFfile_name
		move.l		#0,RFfile_len

; Allocate some memory for the File Info block

		move.l		#fib_SIZEOF,d0
		move.l		#MEMF_PUBLIC,d1
		CALLEXEC	AllocMem
		move.l		d0,RFfile_info
		beq		.error1
		
; Lock the file
		
		move.l		RFfile_name,d1
		move.l		#ACCESS_READ,d2
		CALLDOS		Lock
		move.l		d0,RFfile_lock
		beq		.error2

; Use Examine to load the File Info block

		move.l		d0,d1
		move.l		RFfile_info,d2
		CALLDOS		Examine

; Copy the length of the file into RFfile_len

		move.l		RFfile_info,a0
		move.l		fib_Size(a0),RFfile_len

; Release the file

		move.l		RFfile_lock,d1
		CALLDOS		UnLock

; Release allocated memory

.error2		move.l		RFfile_info,a1
		move.l		#fib_SIZEOF,d0
		CALLEXEC	FreeMem


; All done so return

.error1		move.l		RFfile_len,d0
		movem.l		(sp)+,d1-d4/a1-a4
		rts

RFfile_name	dc.l		0
RFfile_lock	dc.l		0
RFfile_info	dc.l		0
RFfile_len	dc.l		0

**************************************************************************


;--------------
;--------------	DATA AREA
;--------------

dosname		dc.b		'dos.library',0
		even
_DOSBase	dc.l		0

STD_OUT		dc.l		0
STD_IN		dc.l		0

filename	dc.l		0
		even
filehd		dc.l		0
buffer		dc.l		0
file_len	dc.l		0

;-------------- Buffer for keyboard entry

key_buffer		ds.b		200
buf_len		equ		*-buffer

;--------------	Messages that will be displayed in CLI window

intro_msg	dc.b		$0a,'Ucase, by M.Meany.',$0a,$0a,0
		even

usage		dc.b		$0a,'UCASE, a utility to convert all characters'
		dc.b		' in a file',$0a,' from lower case to upper case.',$0a,$0a
		dc.b		'From the CLI :',$0a
		dc.b		'              UCASE <filename>',$0a,$0a
		dc.b		'Where <filename> is the name of the file to convert.'
		dc.b		$0a,$0a,'     © M.Meany, March 91',$0a,$0a,0
		even

convrt_msg	dc.b		'Converting file : ',0
		even

convrt_msg1	dc.b		'  to upper case.',$0a,0
		even

no_len_msg	dc.b		"ABORTED......Can't determine files length.",$0a,0
		even

no_mem_msg	dc.b		"ABORTED......Can't allocate memory for buffer.",$0a,0
		even

no_file_msg	dc.b		"ABORTED......Can't open file to read data.",$0a,0
		even

no_out_file	dc.b		"ABORTED......Can't open file to save data.",$0a,0
		even

all_done_msg	dc.b		"Thank you for using this utility. M.Meany.",$0a,$0a,0
		even

get_file	dc.b		"You must specify a file name !",$0a
		dc.b		"Please enter a file name or press return to quit.",$0a
		dc.b		0
		even


 Next month we will be moving on to Intuition, things really start to get
interesting then.

						Mark.
