Google
 

Trailing-Edge - PDP-10 Archives - DEC_CMS-20_V1.0_SRC - cms/sources/replac.bli
There are no other files named replac.bli in the archive.
MODULE REPLACE	(
		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:
!
!	Compare a master file with a variation file and generate an updated
!	master file showing all of the corrections or changes implied by the
!	variation.
!
! ENVIRONMENT:	VAX/VMS, DS-20
!
! AUTHOR: D. Knight , CREATION DATE: 10-Nov-78
!
!--
!
! TABLE OF CONTENTS
!

FORWARD ROUTINE
	REPLACE,			!Basic REPLACE algorithm
	CHKOPN,
	DELFIL;

!
! INCLUDE FILES:
!

%if %bliss(bliss32) %then
    library 'sys$library:starlet';
%else
    require 'jsys:';
%fi

LIBRARY 'XPORT:';			!XPORT I/O macros

REQUIRE 'SCONFG:';			!CMS configuration options

REQUIRE 'BLISSX:';

REQUIRE 'COMUSR:';

REQUIRE 'HOSUSR:';

REQUIRE 'LOGUSR:';

REQUIRE 'RESV:';

REQUIRE 'SHRUSR:';

!
! MACROS:
!

!
! EQUATED SYMBOLS:
!

!
! OWN STORAGE:
!

OWN
    	KEEP,				!/KEEP SPECIFIED
	HOLD,				!/RESERVE (UPDATE)
	RESRGEN : VECTOR[CH$ALLOCATION(GEN_SIZE)];

GLOBAL
	CHANGES,			!TRUE if changes seen in file replaced
	USE_NOTES,			!Process notes if true, don't if false
	RESRPTR,			!Pointer to reserved generation
	RESRSIZ,			!Size of reserved generation string
	USR_REM : REF DESC_BLOCK,
	VARIANT;			!Variant to be generated, 0 if none.

!
! EXTERNAL REFERENCES:
!

external literal
	s_errfile,			!file is missing or invalid
	s_gencreate,			!generation created
	s_gecreres,			!generation created and reserved
	s_nochanges,			!no changes
	s_noelem,			!no such element exists in directory
	s_nofile,			!file does not exist
	s_notyours;			!element not reserved by you

EXTERNAL
	GEN_BUF,
	GEN_LGT,
	res_head;			!pointer to reservation text area

EXTERNAL ROUTINE
	badlib,
	BEGTRN,				!Mark start of transaction
	BUG,				!bug in CMS
	CANTRN,				!Cancel transaction
	CHKRES,				!Check file reservation
	COMAND,
	DELRES,				!Delete old reservation file
	DELVRS,				!Delete multiple versions of file
	DONLIB,				!Unlock library
	ENDTRN,				!Mark end of transaction
	ERS,				!User error
	ERSXPO,				!Error with xport message
	exits,				!exit silently
	FILTYP,				!Check for correct record attributes
	GETACT,				!Get user account name
	GETELM,				!Process element list
	GET_LXM,
        get_stg_ct,
	LOGTRN,				! write log record(IOLOG)
	REMRES,				!Remove file reservation
	REPFIL,				!Do the actual replace
	REPREP,				!Report replacements
	REPRES,				!Report reservations
	sysmsg,
	SAFLIB,				!Lock library
        trnlog,				!translate a logical name
	UPDRES,				!Update reservation
	YES;
GLOBAL ROUTINE REPLACE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	The REPLACE algorithm is used to generate a new master file
!	using the information from the old master and the modified
!	working file.
!
!	Initialize the tables, get the command line, then call REPLACE proper.
!
! FORMAL PARAMETERS:
!
!	NONE.
!
! IMPLICIT INPUTS:
!
!	NONE.
!
! IMPLICIT OUTPUTS:
!
!	NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    BEGIN

    LOCAL
	CMD,
	F_UNUSUAL,			! set when unusual occurance
	LIST_PTR: REF BLOCK FIELD(RES_FLD),	!Cell used to store reservation list pointer
	LIST_SAV,
	PAR: REF PARAMETER_BLOCK,
	P_QUAL : REF QUALIFIER_BLOCK,
	QUAL : REF QUALIFIER_BLOCK,
	REP_PTR,
	REP_CNT,
	RES_CNT,
	RES_OK,
	RESULT,				!Result of GETELM call
	SUB_CMD;

    ! initialize flag
    F_UNUSUAL = FALSE ;
    CHANGES=FALSE;
    KEEP = FALSE ;
    HOLD = FALSE ;
    USE_NOTES=TRUE;

    !Parse the command line
    IF
	NOT COMAND(CMD,SUB_CMD,QUAL,PAR,USR_REM)
    THEN
	RETURN K_SILENT_ERROR;

    !Initialize qualifiers
    VARIANT=0;

    !Check parameter qualifier /VARIANT
    P_QUAL=.PAR[PAR_A_QUAL];
    WHILE
	.P_QUAL NEQ K_NULL
    DO
	BEGIN
	SELECTONE .P_QUAL[QUA_CODE] OF
	    SET
	    [K_VARIANT_QUAL]: VARIANT=CH$RCHAR(.P_QUAL[QUA_VALUE_PTR]);

	    [K_NOVARIANT_QUAL]: VARIANT = 0;
	    TES;

	P_QUAL=.P_QUAL[QUA_A_NEXT];
	END;

    !Set up command qualifiers, if any
    WHILE
	.QUAL NEQ K_NULL
    DO
	BEGIN
	SELECTONE .QUAL[QUA_CODE] OF
	    SET

	    [K_RESERVE_QUAL]:
    		HOLD = TRUE ;

	    [K_KEEP_QUAL]:
    		KEEP = TRUE ;

	    [K_NORESERVE_QUAL]:
    		HOLD = FALSE;

	    [K_NOKEEP_QUAL]:
    		KEEP = FALSE;

	    TES;

	QUAL=.QUAL[QUA_A_NEXT]

	END;

    !Set count of number of reservations seen to start and
    !reservation OK to failure
    REP_CNT=0;
    RES_CNT=0;
    RES_OK=FALSE;

    !Lock the library
    IF
	NOT SAFLIB(K_UPDATE_LIB)
    THEN
	RETURN K_SILENT_SEVERE ;

    !Make sure element is already reserved by caller
    IF
	CHKRES(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],LIST_PTR)
    THEN
	!Make sure reservation belongs to this user
	BEGIN

	LOCAL
	    RES_NM : VECTOR[CH$ALLOCATION(gen_size)],
	    RES_LN,
	    RES_PT,
	    U_NAME : VECTOR[CH$ALLOCATION(40)], !Save user's name here
	    U_NAM_LGT;			!Length of user's name

	LIST_SAV=.LIST_PTR;

	!Pick up name of user who is running this routine
	U_NAM_LGT=GETACT(U_NAME);

	!See if user is among the reservers
	REPEAT
	    BEGIN

	    LOCAL
		RES_NAM : VECTOR[CH$ALLOCATION(40)],
		RES_N_LGT,
		RES_PTR,
		STG_LGT,
		STG_PTR;

	    IF
		.LIST_PTR[CUR_RES] AND
		NOT .LIST_PTR[REP_MKR]
	    THEN
		BEGIN
		!Length of this reservation line
		STG_LGT=.LIST_PTR[STG_SIZ] ;
		!String pointer to the line
		STG_PTR=ch$plus(.res_head,.LIST_PTR[STG_ADR]);

		!Advance over known element name
		STG_PTR=CH$PLUS(.STG_PTR,.PAR[PAR_TEXT_LEN]+2);
		STG_LGT=.STG_LGT-.PAR[PAR_TEXT_LEN]-2;

		!Pick up generation reserved..
		RES_PT=CH$PTR(RES_NM);
		RES_LN=GET_LXM(STG_PTR,%C' ',.STG_LGT,RES_PT);
		if
		    .res_ln gtr gen_size
		then
		    badlib(lit('Generation field too large in reservation file'));
		STG_LGT=.STG_LGT-.RES_LN-1;
		RES_PT=CH$PTR(RES_NM);

		!Pick up reserver's name
		RES_PTR=CH$PTR(RES_NAM);
		RES_N_LGT=GET_LXM(STG_PTR,%C' ',.STG_LGT,RES_PTR);
		if
		    .res_n_lgt gtr 40
		then
		    badlib(lit('Username field in reservation file is too large.'));
		STG_LGT=.STG_LGT-.RES_N_LGT-1;

		RES_CNT=.RES_CNT+1;

		!Compare the two names
		IF
		    CH$EQL(.U_NAM_LGT,CH$PTR(U_NAME),.RES_N_LGT,CH$PTR(RES_NAM))
		THEN
		    !We have the reservation, remember it
		    BEGIN
		    RESRSIZ=.RES_LN;
		    RESRPTR=CH$PTR(RESRGEN);
		    CH$MOVE(.RESRSIZ,CH$PTR(RES_NM),.RESRPTR);
		    LIST_PTR[REM_FLG]=TRUE;
		    REP_PTR=.LIST_PTR;
		    RES_OK=TRUE;

		    !Find the qualifier field, if any
		    UNTIL
			.STG_LGT LEQ 0
		    DO
			BEGIN

			LOCAL
			    CHAR;

			CHAR=CH$RCHAR_A(STG_PTR);
			STG_LGT=.STG_LGT-1;

			!This assumes for now that /NONOTES is the last qualifier
			!on the line
			IF
			    .CHAR EQL %C'/' AND
			    CH$EQL(.STG_LGT,.STG_PTR,7,CH$PTR(UPLIT('NONOTES')))
			THEN
			    BEGIN
			    USE_NOTES=FALSE;
			    EXITLOOP
			    END
			END
		    END
		END;

	    !Keep track of nested replaces as well
	    IF
		.RES_OK AND
		.LIST_PTR[REP_MKR]
	    THEN
		REP_CNT=.REP_CNT+1;

	    !Advance to the next element in the list
	    LIST_PTR=.LIST_PTR[LINK_ADR];

	    !Have we reached the end of the list?
	    IF
		.LIST_PTR EQL 0
	    THEN
		!Someone else owns it (also?)
		BEGIN

		IF
		    NOT .RES_OK
		THEN
		    BEGIN
		    ERS(s_notyours,CAT(('Element '),
			PAR[PAR_TEXT],(' is not reserved by you')));
		    DONLIB();
		    RETURN K_SILENT_ERROR
		    END
		ELSE
		    EXITLOOP
		END
	    END
	END
    ELSE
	!The element is not reserved, therefore it cannot be replaced.
	BEGIN
	!See if it doesn't exist
	IF
	    GETELM(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],0)
		EQL G_NO_ELM
	THEN
 	    BEGIN
 	    local
 		d_log_nam : $str_desc(),
 		d_log_trn : $str_desc(),
 		log_trn_buf : vector[ch$allocation(log_nam_value_size)];
 	    $str_desc_init(descriptor = d_log_nam,
 			   string=(len_comma_ptr(lib)));
 	    $str_desc_init(descriptor = d_log_trn,
 			   string=(log_nam_value_size,ch$ptr(log_trn_buf)));
 	    trnlog(d_log_nam,d_log_trn);
	    ERS(s_noelem,CAT(('Element '),PAR[PAR_TEXT],
		(' does not exist in the CMS library '),d_log_trn));
    	    END
	ELSE
	    ERS(s_notyours,CAT(('Element '),
		PAR[PAR_TEXT],(' is not reserved by you')));
	DONLIB();
	RETURN K_SILENT_ERROR
	END;

    !Check for multiple reservations
    IF
	.RES_CNT GTR 1 OR
	.REP_CNT GTR 0
    THEN
	BEGIN
	!Report reservations
	IF
	    .RES_CNT GTR 1
	THEN
	    REPRES(.LIST_SAV,.REP_PTR);

	!Report replacements
	IF
	    .REP_CNT GTR 0
	THEN
	    REPREP(.REP_PTR);

	!Ask him if he wishes to continue
	IF
	    NOT YES(LIT('Proceed'))
	THEN
	    BEGIN
	    DONLIB();
	    RETURN K_SILENT_ERROR;
	    END;

	! set flag for logging
	F_UNUSUAL = TRUE ;

	END;

    !Make sure the files for the element exist
    RESULT=GETELM(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],CHKOPN);

    IF
	.RESULT EQL G_NO_ELM
    THEN
	BEGIN
 	local
 	    d_log_nam : $str_desc(),
 	    d_log_trn : $str_desc(),
 	    log_trn_buf : vector[ch$allocation(log_nam_value_size)];
 	$str_desc_init(descriptor = d_log_nam,
 		       string=(len_comma_ptr(lib)));
 	$str_desc_init(descriptor = d_log_trn,
 		       string=(log_nam_value_size,ch$ptr(log_trn_buf)));
 	trnlog(d_log_nam,d_log_trn);
	ERS(s_noelem,CAT(('Element '),PAR[PAR_TEXT],(' does not exist in the CMS library '),d_log_trn));
	END
    ELSE
    IF
	.RESULT EQL G_ERMSG
    THEN
	BEGIN
	DONLIB();
	RETURN K_SILENT_ERROR
	END
    ELSE
    IF
	.RESULT NEQ G_OK
    THEN
	BUG(LIT('Error in element processing (REPLACE)'));

    !Start critical part of transaction
    BEGTRN();

    !Process the element list
    RESULT=GETELM(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],REPFIL);

    !Check for success
    IF
	.RESULT EQL G_OK
    THEN
	BEGIN
	!Mark element unreserved
	IF
	    .HOLD
	THEN
	    BEGIN
	    IF
		.USE_NOTES
	    THEN
		UPDRES(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],
		    CH$PTR(GEN_BUF),.GEN_LGT,.USR_REM[DESC_PTR],
		    .USR_REM[DESC_LEN],0,0)
	    ELSE
		UPDRES(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],
		    CH$PTR(GEN_BUF),.GEN_LGT,.USR_REM[DESC_PTR],
		    .USR_REM[DESC_LEN],CH$PTR(UPLIT('/NONOTES')),8)
	    END
	ELSE
	    REMRES(REPL,.USR_REM[DESC_PTR],.USR_REM[DESC_LEN])
	END
    ELSE
    !Something other than success was found
    IF
	.RESULT EQL G_NO_ELM
    THEN
	BUG(CAT(('Element '),PAR[PAR_TEXT],(' does not exist')))
    ELSE
    IF
	.RESULT EQL G_ERMSG
    THEN
	BEGIN
	CANTRN();
	DONLIB();
	RETURN K_SILENT_ERROR
	END
    ELSE
	!Disastrous error
	BUG(LIT('Error in element processing (REPLACE)'));

    ! log this transaction
    IF
	.F_UNUSUAL
    THEN
	BEGIN	! log it as unusual

	IF
	    NOT LOGTRN(K_UNUSUAL_LOG,.GEN_LGT,CH$PTR(GEN_BUF))
	THEN
	    BUG(CAT('Unable to write unusual log record. error occurred ',
		    'in routine REPLACE of module REPLAC.')) ;

	END	! log it as unusual
    ELSE
	BEGIN	! write normal log record

	IF
	    NOT LOGTRN(K_NORMAL_LOG,.GEN_LGT,CH$PTR(GEN_BUF))
	THEN
	    BUG(CAT('Unable to write log record. error occurred in ',
		    'routine REPLACE of module REPLAC.')) ;

	END ;	! write normal log record
    
    ENDTRN();

    !Remove old reservation file
    DELRES();

    !Now delete the old files from the work and/or library area
    GETELM(.PAR[PAR_TEXT_PTR],.PAR[PAR_TEXT_LEN],DELFIL);

    !We are done with the library
    DONLIB();

    !Tell user if no changes were recorded
    IF
	NOT .CHANGES
    THEN
	sysmsg(s_nochanges,LIT('No changes'),0);

    IF .HOLD
    THEN
	begin
        sysmsg(s_gecreres,CAT(('Element '),PAR[PAR_TEXT],(', Generation '),
        (.GEN_LGT,CH$PTR(GEN_BUF)),(' created and reserved')),0);
	exits(s_gecreres)
	end
    ELSE
	!Tell user which generation was created
	begin
	sysmsg(s_gencreate,
	    CAT(('Element '),PAR[PAR_TEXT],(', Generation '),
	    (.GEN_LGT,CH$PTR(GEN_BUF)),(' created')),0);
	exits(s_gencreate)
	end

    END;				!End of REPLACE
ROUTINE CHKOPN (FIL_NAM_LGT,FIL_NAM_STR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
!	NONE.
!
! IMPLICIT INPUTS:
!
!	NONE.
!
! IMPLICIT OUTPUTS:
!
!	NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    BEGIN

    LOCAL
	$io_block_decl(OPN),
	STS;

    $IO_BLOCK_INIT(OPN);

    STS=$STEP_OPEN(IOB=OPN_IOB,FILE_SPEC=(.FIL_NAM_LGT,.FIL_NAM_STR),
		    FAILURE=0);

    IF
	NOT .STS
    THEN
	BEGIN
	!Check if file is protected from access
	IF
	    step$_no_access eql .STS
	THEN
	    ERSXPO(s_nofile,.STS,CAT(('File '),(.FIL_NAM_LGT,.FIL_NAM_STR),
	    	(' is protected from access')))

	!Check if file does not exist
	ELSE
	    ERSXPO(s_nofile,.STS,CAT(('File '),(.FIL_NAM_LGT,.FIL_NAM_STR),
	    (' does not exist')));
	RETURN G_ERMSG
	END;

    !Check for correct characteristics
    IF
	NOT FILTYP(OPN_IOB)
    THEN
	BEGIN
	$step_close(IOB=OPN_IOB);
	ERS(s_errfile,CAT(('File '),(.FIL_NAM_LGT,.FIL_NAM_STR),
	    (' has incorrect record format or attributes')));
	RETURN G_ERMSG
	END;

    $step_close(IOB=OPN_IOB);

    G_OK

    END;				!End of CHKOPN
ROUTINE DELFIL (FIL_NAM_LGT,FIL_NAM_STR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
!	FIL_NAM_LGT - length of file
!	FIL_NAM_STR - pointer to file
!
! IMPLICIT INPUTS:
!
!	HOLD - if true, do not delete user files
!
! IMPLICIT OUTPUTS:
!
!	NONE.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    BEGIN

    LOCAL
	FIL : VECTOR[CH$ALLOCATION(EXTENDED_FILE_SPEC)],
	FIL_PTR,
	FIL_SIZ;

    !Delete old files from user area if HOLD is not specified
    IF
	NOT (.HOLD OR .KEEP)
    THEN
	DELVRS(0,.FIL_NAM_LGT,.FIL_NAM_STR);

    !Point to master file of same name in the library
    FIL_PTR=CH$PTR(FIL);
    FIL_PTR=CH$MOVE(%CHARCOUNT(LIB),CH$PTR(UPLIT(LIB)),.FIL_PTR);
    FIL_PTR=CH$MOVE(.FIL_NAM_LGT,.FIL_NAM_STR,.FIL_PTR);
    FIL_SIZ=CH$DIFF(.FIL_PTR,CH$PTR(FIL));

    !Delete all except most recent version(s) of file in library
    DELVRS(FILVRS,.FIL_SIZ,CH$PTR(FIL));

    G_OK

    END;				!End of DELFIL
END				!End of Module REPLACE
ELUDOM