dos_compilers/Digital Research PLI-86 v1/BLOKCOPY.PLI

322 lines
11 KiB
Plaintext
Raw Normal View History

2024-06-30 21:01:25 +02:00
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;