dos_compilers/Digital Research PLI-86 v1/BLOKCOPY.PLI
2024-06-30 12:01:25 -07:00

322 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diocopy: procedure options(main);
/*****************************************************************************
* *
* I B M D O S D i r e c t F u n c t i o n C a l l s *
* *
******************************************************************************
******************************************************************************
* *
* This program tests many of the IBM DOS direct function calls. The tests *
* are not particularly complicated, but they do serve as examples for using *
* direct DOS function calls from PL/I-86. *
* *
******************************************************************************
* *
* NOTE! YOU SHOULD STUDY THE IBM DOS DOCUMENTATION FOR MORE COMPLETE *
* INFORMATION BEFORE USING ANY OF THESE FUNCTIONS IN YOUR PROGRAMS. *
* *
* *
******************************************************************************
* To use this program, enter the command: *
* *
* A>blokcopy filename.typ newname.typ *
*****************************************************************************/
/* DIOMOD.DCL contains the declarations for the DOS functions */
%include 'diomod.dcl';
%replace
true by '1'b,
false by '0'b;
declare
(tempsrc,tempdest) char(14) var,
(dest_space(37),src_space(37)) bit(8),
borrow bit(1),
ret_code fixed(7),
(actual,i,num_buffs) fixed(15),
(hi_word,lo_word,num_recs) bit(16),
memory (0:0) bit(16) based(memptr());
declare /* source file FCB */
srcfcb_ptr ptr,
1 source_file based(srcfcb_ptr),
2 drive fixed(7),
2 name character(8),
2 type character(3),
2 current_block bit(16),
2 record_size bit(16),
2 file_size(2) bit(16),
2 date bit(16),
2 reserved(10) bit(8),
2 current_rec bit(8),
2 rand_rec_no(2) bit(16);
declare /* destination file FCB */
destfcb_ptr pointer,
1 dest_file based(destfcb_ptr),
2 drive fixed(7),
2 name character(8),
2 type character(3),
2 current_block bit(16),
2 record_size bit(16),
2 file_size(2) bit(16),
2 date bit(16),
2 reserved(10) bit(8),
2 current_rec bit(8),
2 rand_rec_no(2) bit(16);
/*****************************************************************************/
/* M a i n P r o g r a m */
/*****************************************************************************/
/* Initialize Source & Destination FCBs */
/* The file I/O used later will require the full 4-byte random record field,
so we'll need the 37-byte FCB. The default FCBs will not be big enough,
hence the array of 37 bytes for space. */
srcfcb_ptr = addr(src_space);
destfcb_ptr = addr(dest_space);
/* set drives for both files to be default; OPEN will possibly change this */
source_file.drive = 0;
dest_file.drive = 0;
/* get the filenames from the command line */
call get_names(tempsrc,tempdest);
/* split up name & type; make sure they're the right length, padded with
trailing blanks if necessary */
i = index(tempsrc,'.');
source_file.name = substr(tempsrc,1,i-1) || ' ';
source_file.name = substr(source_file.name,1,8);
source_file.type = substr(tempsrc,i+1) || ' ';
source_file.type = substr(source_file.type,1,3);
/* do the same for the destination name */
i = index(tempdest,'.');
/* the following PUT EDIT statements are needed to make the register
allocator work right */
PUT SKIP EDIT('1.DEST_FILE.NAME=',DEST_FILE.NAME,'<--') (A,A,A);
dest_file.name = substr(tempdest,1,i-1) || ' ';
PUT SKIP EDIT('2.DEST_FILE.NAME=',DEST_FILE.NAME,'<--') (A,A,A);
dest_file.name = substr(dest_file.name,1,8);
PUT SKIP EDIT('3.DEST_FILE.NAME=',DEST_FILE.NAME,'<--') (A,A,A);
dest_file.type = substr(tempdest,i+1,3) || ' ';
PUT SKIP EDIT('1.DEST_FILE.TYPE=',DEST_FILE.TYPE,'<--') (A,A,A);
dest_file.type = substr(dest_file.type,1,3);
PUT SKIP EDIT('2.DEST_FILE.TYPE=',DEST_FILE.TYPE,'<--') (A,A,A);
/* open the source file, if possible */
if open(addr(source_file)) = -1 then do;
put skip list('No Source File');
call reboot();
end;
/* create the destination file */
if make(addr(dest_file)) = -1 then do;
put skip list('No Directory Space');
call reboot();
end;
/************************************************************************
* Use Random Block Read & Write to read/write an exact number of bytes. *
* To simplify things, read in terms of a single byte record size. That *
* way, records read/written = bytes read/written. *
************************************************************************/
/* set the source file random record field */
call setrec(srcfcb_ptr);
/* set the source file record size to 1 byte */
source_file.record_size = '0001'b4;
/* get both words of source file size (in bytes) */
lo_word = source_file.file_size(1);
hi_word = source_file.file_size(2);
/* set the DMA address */
call setdma(addr(memory(0)));
/* READ-- if file size > 64k, read it in FE00h-byte chunks */
do while(hi_word ^= '0000'b4);
num_recs = 'FE00'b4; /* number of bytes to read */
call blockrd(addr(source_file),num_recs,addr(actual),addr(ret_code));
if ret_code ^= 0 then do;
put skip list('ERROR: Source file > 64k. BLOCKRD returned ',
ret_code);
call reboot();
end;
borrow = less_than(lo_word,num_recs);
lo_word = sub(lo_word,num_recs);
if borrow then hi_word = sub(hi_word,'0001'b4);
end;
/* read the less-than-64k chunk */
call blockrd(addr(source_file),lo_word,addr(actual),addr(ret_code));
if ret_code ^= 0 then do;
put skip list('ERROR: BLOCKRD returned ',ret_code);
call reboot();
end;
/* now reverse the above process to write to the destination file */
/* set the destination file random record field */
call setrec(addr(dest_file));
/* set the destination file record size to 1 byte */
dest_file.record_size = '0001'b4;
/* get source file size (in bytes) so we know how much to write */
lo_word = source_file.file_size(1);
hi_word = source_file.file_size(2);
/* WRITE-- if file size > 64k, write it in FE00h-byte chunks */
do while(hi_word ^= '0000'b4);
num_recs = 'FE00'b4; /* number of bytes to write */
call blockwr(addr(dest_file),num_recs,addr(actual),addr(ret_code));
if ret_code ^= 0 then do;
put skip list('ERROR: Source file > 64k. BLOCKWR returned ',
ret_code);
call reboot();
end;
borrow = less_than(lo_word,num_recs);
lo_word = sub(lo_word,num_recs);
if borrow then hi_word = sub(hi_word,'0001'b4);
end;
/* write the less-than-64k chunk */
call blockwr(addr(dest_file),lo_word,addr(actual),addr(ret_code));
if ret_code ^= 0 then do;
put skip list('ERROR: BLOCKRD returned ',ret_code);
call reboot();
end;
/* close destination file */
if close(addr(dest_file)) = -1 then do;
put skip list('Disk is Read Only');
call reboot();
end;
/* all done! */
put skip list('File Copied');
call reboot();
/****************************************************************************/
/* P r o c e d u r e s */
/****************************************************************************/
get_names: procedure(src,dest);
/* get the filenames from the command line */
declare
(src,dest) char(14) var, /* file names */
buffptr pointer,
cmdline char(127) var based(buffptr),
indx fixed;
buffptr = dbuff();
/* delete any leading blanks */
do while(substr(cmdline,1,1) = ' ');
cmdline = substr(cmdline,2);
end;
/* find the break between the two filenames */
indx = index(cmdline,' ');
/* the following statement is needed to make the register allocator
work right */
PUT SKIP LIST('INDX=',INDX);
/* get the source filename */
src = substr(cmdline,1,indx-1);
cmdline = substr(cmdline,indx+1);
/* delete any intervening blanks */
do while(substr(cmdline,1,1) = ' ');
cmdline = substr(cmdline,2);
end;
/* put the rest of the command line in destination filename */
dest = substr(cmdline,1,14);
end get_names;
/*****************************************************************************/
/* U n s i g n e d A r i t h m e t i c P r o c e d u r e s */
/*****************************************************************************/
complement: procedure((x)) returns(bit(16));
/* two's complement */
declare
x bit(16);
x = xor(x,'FFFF'b4);
x = add(x,'0001'b4);
return(x);
end;
add: procedure((x),(y)) returns(bit(16));
/* 16 bit unsigned add */
declare
(x,y,z) bit(16),
(xp,yp,zp) ptr,
su bit(16),
sv bit(16),
sw bit(16),
u fixed bin(15) based(xp),
v fixed bin(15) based(yp),
w fixed bin(15) based(zp);
xp = addr(x);
yp = addr(y);
zp = addr(z);
/* get sign bits of u and v */
su = x & '8000'b4;
sv = y & '8000'b4;
/* zero sign bits of x and y */
x = x & '7FFF'b4;
y = y & '7FFF'b4;
w = u + v;
sw = z & '8000'b4;
/* get sign bit of z */
z = z & '7FFF'b4;
/* XOR of su, sv, sw */
sw = xor(xor(su,sv),sw);
/* put in sign bit of z */
z = z | sw;
return(z);
end add;
sub: /* unsigned substract */
procedure((x),(y)) returns(bit(16));
declare
(x,y) bit(16);
return(add(x,complement(y)));
end sub;
xor: procedure(x,y) returns(bit(16));
/* 16 bit logical exclusive or */
declare
(x,y) bit(16);
return(bool(x,y,'0110'b));
end xor;
less_than: procedure((x),(y)) returns(bit(1));
/* returns '1'b if x < y, '0'b otherwise */
/* 3 possibilities:
1. hi order bit of x = 1; hi order bit of y = 0 ==> '0'b
2. hi order bit of x = 0; hi order bit of y = 1 ==> '1'b
3. hi order bit of x = hi order bit of y.
In this case, set the hi order bit to 0 and compare x
and y as fixed bin(15) numbers. */
declare
(x,y) bit(16),
(xptr,yptr) pointer,
xval fixed bin(15) based(xptr),
yval fixed bin(15) based(yptr);
xptr = addr(x);
yptr = addr(y);
/* case 1: */
if substr(x,1,1) & ^(substr(y,1,1)) then return('0'b);
/* case 2: */
if ^(substr(x,1,1)) & substr(y,1,1) then return('1'b);
/* case 3: */
substr(x,1,1) = '0'b;
substr(y,1,1) = '0'b;
if xval < yval then return('1'b);
else return('0'b);
end less_than;
end diocopy;