Trailing-Edge
-
PDP-10 Archives
-
DEC_CMS-20_V1.0_SRC
-
cms/sources/fixup.bli
There are no other files named fixup.bli in the archive.
module fixup (! Fix the ills of a library.
ident = '1',
%if
%bliss(bliss32)
%then
language(bliss32),
addressing_mode(external=long_relative,
nonexternal=long_relative)
%else
language(bliss36)
%fi
) =
begin
!
! COPYRIGHT (C) 1982 BY
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
! ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
! INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
! COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
! OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
! TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!
!++
! Facility: CMS Library Processor
!
! Abstract:
!
! This module contains the routines for doing the VERIFY/REPAIR
! basic functions
!
! Environment: VAX/VMS
!
! Author: Dave Knight
!
!--
!
! Table of Contents:
!
forward routine
fixcrc, !Fix a file CRC
fixhdr; !Fix up the file header
!
!
!
%if %bliss(bliss32) %then
library 'SYS$LIBRARY:STARLET' ;
%else
require 'tendef:';
undeclare
%quote $chlfd, ! name conflicts between monsym and tendef
%quote $chcrt; ! monsym required in jsys:
require 'jsys:';
%fi
library 'XPORT:' ;
require 'BLISSX:' ;
require 'SCONFG:' ;
require 'HOSUSR:' ;
require 'timusr:' ;
require 'filusr:';
require 'rbusr:';
!
! Macros:
!
%if Tops20 %then
macro
at_eof (jfn) =
begin
local status;
gtsts ((jfn); status);
.pointr (status,gs_eof)
end %;
%fi
!
! Equated Symbols:
!
literal
debug = false;
!
! Own Storage:
!
global
have_repaired;
global literal
k_expand_file_size = extended_file_spec + 5,
k_size_stack = 40;
!
! External References:
!
external literal
s_inoopen, !can not open input file
s_onoopen, !can not open output file
s_oanoopen, !can not open output file for append
s_nosetrev, !cannot set revision mark for filespec
s_repairfai, !cannot repair file
s_timenoset; !cannot set the time for filespec
external routine
bug : novalue, ! Report a bug.
bugsts : novalue, ! Report a bug involving a status code.
crccalc, ! Calculate the CRC of a line
crctable : novalue, ! Set up polynomial table
%if %bliss(bliss36) %then
cvtas0, ! Convert desc to ASCIZ
freas0, ! Return dynamic memory allocated by cvtas0
jfn_truncate, ! truncate a file (filops) /TBD/
%fi
dirspc : novalue, ! Find the directory portion of a file spec.
errsts, ! Report an error involving a status code.
erssts, ! Report an error involving a status code.
fresad : novalue, ! Free string allocated by ASK or CAT macro.
hexasz,
say,
timcop,
trnfil,
truncate : novalue; ! truncate a file
global routine fixcrc (a_file_name, crc, a_custom_msg ) =
!++
! Functional Description:
!
! This routine will calculate the summed CRC's of a file
! and write out the result at the end of the file. The
! control line looks like */C: .
!
! TOPS-20: It is assumed that the file is not sequenced and is
! composed of 7 bit ASCII characters. This is true even if XPORT
! has marked the file as containing 36 bit bytes.
!
! Formal Parameters:
!
! a_file_name : address of a descriptor of the file
! to be fixed
! crc : new count to be written at end of the file
! a_custom_msg : k_null or the address of a descriptor for a
! custom message to be printed after successful
! operation.
!
! Implicit Inputs:
!
! The file is closed.
!
! Implicit Outputs:
!
! None.
!
! Routine Value:
! Completion Codes:
!
! TRUE - File CRC corrected
! FALSE - CRC fixup failed
!
! Side Effects:
!
! None.
!
!--
begin
bind
file_name = .a_file_name : desc_block,
d_custom_msg = .a_custom_msg : desc_block;
literal
max_byte_count = 256;
own
$io_block(rd),
$io_block(wrt);
local
f_cksum, !flag to show chksum record fnd
len,
num_buf : vector[ch$allocation(max_num_size+5)], ! Space for new crc
ptr ,
%if VaxVms %then
save_rfa: vector[rab$s_rfa, byte], ! save area for RFA of record
save_rab: ref $rab_decl, ! save area for RAB
%fi
%if Tops20 %then
fbsiz, ! for 20, file byte size
file_z_ptr, ! temp pointer to ASCIZ string
skips, ! number skips taken by jsys
jfn, ! system dependent file handle
byte_size, ! number of bits per byte (or character) for accessing file
err_code, ! TOPS-20 error mnemonic from jsys
upd_count, ! updated count returned by jsys, decremented from original value
upd_ptr, ! updated byte-ptr into string
buf : vector[ch$allocation(max_byte_count)],
%fi
status ;
have_repaired = true; ! set flag that this routine has
! been entered
f_cksum = false; !flag clear when no cksum rec
! encountered
! Make sure filename isn't too long
if .file_name[desc_len] gtr k_expand_file_size
then
bug(cat( file_name, 'is too long for stack (FIXCRC).')) ;
! Open the file
%if Tops20 %then
! prepair for gtjfn call, convert to ASCIZ
cvtas0 (file_name, file_z_ptr);
! get JFN for specified file
skips = gtjfn (gj_sht or gj_old, .file_z_ptr; jfn);
! release dynamic memory allocated by cvtas0
freas0 (.file_z_ptr);
! do error checking
if .skips eql 0
then
begin
erssts(s_inoopen, .jfn,
cat('Cannot open input file ',file_name, ' (FIXCRC)') );
return false;
end;
byte_size = 7;
skips = openf (.jfn, ! open file for READ
fld(.byte_size,of_bsz) or fld(true,of_rd) or fld(true,of_wr);
err_code);
! do error checking
if .skips eql 0
then
begin
erssts(s_inoopen, .err_code,
cat('Cannot open input file ',file_name, ' (FIXCRC)') );
return false;
end;
!+
! Read every record in the file until you get the end of the file
! or until you get to a record containing the checksum data.
!-
repeat
begin
ptr = ch$ptr (buf);
%if debug %then ! debug code
! print out current position in file
skips = rfptr (.jfn; err_code, fbsiz);
$xpo_put_msg (string = $str_concat ('FIXCRC: file-pointer = ',
$str_ascii(.fbsiz) ));
%fi ! end debug code
skips = sin (.jfn, ! job-file-number
.ptr, ! input-buffer pointer
+max_byte_count, ! read n bytes or until NUL
10; ! termination byte = <LF>
err_code, ! return error code
upd_ptr, ! updated version of 2nd param
upd_count); ! updated count
if .skips eql 0 ! check for error during SIN
then
begin
if at_eof (.jfn) ! must do special processing for EOF check
then
exitloop;
bugsts(.err_code,
lit('Unable to do GET operation (FIXCRC)') );
end;
%if debug %then
begin
local length;
length = ch$diff(.upd_ptr,.ptr);
$xpo_put_msg (severity = success,
string = $str_concat ('Length = ', $str_ascii(.length),
' Text = "', (.length,.ptr), '"'));
end;
%fi
! I do not understand why, but SIN is not deleting nulls, i.e. it
! is passing them on as data. NOTE that it is also passing the
! CRLF along as data but this is supposd to happen.
! bypass all nulls in buffer
while ch$rchar(.ptr) eql 0
do
ch$rchar_a(ptr);
if ch$eql( 4, ch$ptr(uplit('*/C:')), 4, .ptr)
then
begin
f_cksum = true;
exitloop ;
end;
end ; !(of REPEAT loop)
!+
! Test to see if checksum was encountered. If so, that checksum
! record must be truncated from the file.
!-
if .f_cksum
then
begin ! checksum found in file
! get position in file
skips = rfptr (.jfn; err_code, fbsiz);
if .skips eql 0
then
bugsts(.err_code,
lit('Unable to get file-pointer from RFPTR jsys (FIXCRC)'));
! adjust fbsiz to reflect previous record
fbsiz = .fbsiz - (max_byte_count-.upd_count);
%if debug %then ! debug code
! print adjusted file position before doing truncate
$xpo_put_msg (string = $str_concat ('FIXCRC: adjusted file-pointer = ',
$str_ascii(.fbsiz) ));
%fi ! end debug code
if not jfn_truncate (.jfn, .byte_size, .fbsiz)
then
begin
geter ($fhslf, err_code);
bugsts (.err_code,
cat('Unable to truncate ', file_name, ' (FIXCRC)'));
end;
end;
skips = closf (.jfn; err_code);
if .skips eql 0
then
bugsts (.err_code,
cat('Unable to close ', file_name, ' (FIXCRC)') );
! release job-file-number
rljfn (.jfn);
%fi
%if VaxVms %then
!+
! This section is not used by TOPS-20 because of XPORT related
! problems. XPORT does some buffering behind the scene so the
! jfn in iob$h_channel can not be used in conjunction with certain
! jsysi, such as rfptr and gtsts.
!-
!+
! Open and scan the file for a checksum record.
!-
! Open the file
if not (status = ($cms_open ( iob = rd_iob, file_spec = file_name,
failure = 0 )) )
then
begin
erssts(s_inoopen,.status, cat('Cannot open input file ',file_name));
return false;
end;
!+
! Read every record in the file until you get the end of the file
! or until you get to a record containing the checksum data.
! The position in the file is saved for the truncation operation.
! NOTE that for VMS the position of a record is saved after the record
! has been read, but for TOPS-20 the position must be saved before
! the read is done.
!-
until
begin
%if Tops20 %then
LOCAL
jfn,
error_code,
ret_code;
! get current file pointer
jfn = .rd_iob[iob$h_channel];
ret_code = rfptr (.jfn; error_code, fbsiz);
if .ret_code eql 0
then
bugsts(.error_code,
lit('Unable to get file-pointer from RFPTR jsys'));
%if debug %then
$xpo_put_msg (string = $str_concat ('FIXCRC: file-pointer = ',
$str_ascii(.fbsiz) ));
%fi
%fi
$step_get (iob = rd_iob ) eql step$_eof
end
do
begin
!Is it the checksum record? If so, set a flag to handle
!the encountered checksum record, define the RAB, and save
!the rfa
if ch$eql( 4, ch$ptr(uplit('*/C:')),4,.rd_iob[iob$a_string])
then
begin
f_cksum = true;
%if %bliss(bliss32) %then
save_rab = .rd_iob[iob$a_rms_rab]; !define the RAB
ch$move(rab$s_rfa,ch$ptr(save_rab[rab$w_rfa]),ch$ptr(save_rfa));
%fi
exitloop ;
end;
end ;
!Test to see if checksum was encountered. If so, that checksum
!record must be truncated from the file.
$cms_close ( iob = rd_iob);
If .f_cksum then
truncate (file_name,
%if VaxVms %then save_rfa %fi %if Tops20 %then fbsiz %fi,
bugsts);
%fi
!+
! The file now has no checksum. A new one must be added to
! the file, and so the crc is set up and appended
!-
! set up the crc that is desired for the now truncated file
ptr = ch$move( 4,ch$ptr(uplit('*/C:')),ch$ptr(num_buf));
len = hexasz(.crc, .ptr, 8) ;
ptr = ch$plus( .ptr, .len);
ch$wchar(%c' ', .ptr);
len = .len + 5;
if not (status = ($cms_open ( iob = wrt_iob, file_spec = file_name,
options = append,failure = 0 )) )
then
begin
erssts(s_oanoopen,.status, cat('Cannot open output file ',
file_name, ' for append'));
return false;
end;
! Register file
trnfil ( wrt_iob) ;
!Append the newly-calculated crc to the file
$step_put ( iob = wrt_iob,
string = (.len, ch$ptr(num_buf)),
failure = 0 );
! Close the file
$cms_close ( iob = wrt_iob );
!+
! The file now has been "fixed", ie, it has had the old checksum
! truncated from it and a new checksum appended to it. It should
! now be correct.
!-
! Inform the user - Check for control files and issue special messages for those
if d_custom_msg eqla k_null
then
fresad(say(cat('***Repaired checksum for file ',file_name)))
else
say(d_custom_msg);
begin
!
! KLUDGE: Routine TRNFIL is a nop unless the file has just been
! created. Since we just appended to a file, TRNFIL did not mark
! it as closed by CMS. Get the official transaction time and
! try to fix the file-header. FIXHDR may have already been called
! once for this file, if so the user will see the "header repaired"
! message twice.
!
external routine
trntim : novalue; ! get official transaction time
local
trnx_time: time_block; ! hold official transaction time
trntim (trnx_time);
fixhdr (file_name, trnx_time);
end;
true
end; !End of routine FIXCRC
global routine fixhdr (r_file_spec,time_val) =
!++
! Functional Description:
!
!
! This routine updates the file as specified with a revision number of
! 2, and the given time. If no time is given, the time that already
! exists is used.
!
! Formal Parameters:
!
! r_file_spec - Address of file descriptor.
! time_val - time to be used to reset time
!
! Implicit Inputs:
!
! The logical name fac_name$LIB is assumed to denote a library.
!
! Implicit Outputs:
!
! None
!
! Routine Value:
! Completion Codes:
!
! TRUE - header fixed up correctly
! FALSE - header fixup failed
!
! Side Effects:
!
! None.
!
!--
begin ! FIXHDR
local
directory : desc_block, ! Directory of expanded specification.
expanded : desc_block; ! Descriptor of expanded specification,
! explained below.
map
r_file_spec : ref desc_block, ! File specification passed
time_val : ref time_block;
%if %bliss(bliss32) %then
local
r_xabrdt : ref $xabrdt_decl,
status ; ! System service status code.
own
expanded_str : vector[ch$allocation(nam$c_maxrss)],
! Expanded file specification returned
! by $PARSE. It fully identifies a
! directory, but the rest of the
! specification has only been checked
! for syntax.
resultant_str : vector[ch$allocation(nam$c_maxrss)],
! Full file specification returned by
! $SEARCH
nam : $nam(esa = expanded_str, ess = nam$c_maxrss,
rsa = resultant_str, rss = nam$c_maxrss),
! Name block for RMS.
xabrdt : $xabrdt(), ! Extended attribute block for RMS.
fab : $fab(fac = put, nam = nam, xab = xabrdt) ;
! File access block pointing to the
! name block and xab block just
! declared.
! Have RMS check the file specification and find the directory.
fab[fab$b_fns] = .r_file_spec[desc_len] ;
fab[fab$l_fna] = .r_file_spec[desc_ptr] ;
if
not (status = $parse(fab = fab))
then
begin
fresad(errsts(s_repairfai,.status, cat('***Cannot repair ',
.r_file_spec)));
return false
end
else
begin ! Search.
! Find the directory portion of the expanded file specification.
$str_desc_init(descriptor = expanded,
string = (.nam[nam$b_esl], .nam[nam$l_esa])) ;
dirspc(expanded, directory) ;
! Process the file
if
not (status = $search(fab = fab))
then
bugsts(.status, cat('FIXHDR cannot search ', directory)) ;
! Get some of the file's characteristics.
fab[fab$v_nam] = 1 ; ! Tell RMS to use the NAM block.
if
not (status = $open(fab = fab))
then
begin
fresad(errsts(s_repairfai,.status, cat('***Cannot repair ',
(.nam[nam$b_rsl], .nam[nam$l_rsa])))) ;
return false
end;
! Set revision number to 2
xabrdt[xab$w_rvn] = 2 ;
! Set the specified time
timcop(.time_val,xabrdt[xab$q_rdt]);
! Close the file
if
not ( status = $close ( fab = fab))
then
BEGIN
IF .status EQL rms$_prv
THEN
BEGIN
fresad(errsts(s_repairfai,.status, cat('***Cannot repair ',
(.nam[nam$b_rsl], .nam[nam$l_rsa]),' ;you must own the file'))) ;
RETURN false;
END
ELSE
bugsts( .status, cat('FIXHDR cannot close ',
(.nam[nam$b_rsl], .nam[nam$l_rsa]))) ;
END;
end ;
%fi
%if %bliss(bliss36) %then
%if %switches(tops20) %then
local
file_z_ptr, ! pointer to asciz string
handle: block[1], ! JFN and flags
next_handle, ! JFN and flags
temp; ! flags
cvtas0( .r_file_spec, file_z_ptr) ;
! get the JFN for the file
temp = gj_sht or gj_old or gj_ifg or gj_flg ;
if
gtjfn( .temp, .file_z_ptr; handle ) neq 1
then
begin
fresad(errsts(s_repairfai,.handle, cat('***Cannot repair ',
.r_file_spec)));
return false
end
else
begin
! Process the file
local
error_num, ! error status
internal_time, ! internal date and time
new_mark, ! JFN and index and update flag
new_time; ! jfn and update flags
! Set the revision mark to 'S'
new_mark = hwf($fbusw, .handle);
if
not chfdb ( .new_mark, -1, %c'S' )
then
begin
geter ( $fhslf ; error_num );
fresad(erssts (s_nosetrev, .error_num,
cat( '***Cannot set the revision mark for ',.r_file_spec))) ;
return false
end ;
timcop (.time_val, internal_time);
! Change the FBD
new_time = hwf($fbwrt, .handle);
if
not chfdb ( .new_time, -1, .internal_time)
then
begin
geter ( $fhslf ; error_num) ;
fresad(erssts (s_timenoset, .error_num,
cat('***Cannot set the time for ',.r_file_spec))) ;
return false
end ;
! release the jfn
rljfn (.handle);
end ;
%else
%error(ds-10 support not implemented)
%fi
%fi
!Give user a message
fresad(SAY(CAT('***Repaired header for file ',.r_file_spec)));
true
end ; ! fixhdr
end ! Module FIXUP
eludom