Google
 

Trailing-Edge - PDP-10 Archives - BB-L054E-RK - apxpat.b36
There are no other files named apxpat.b36 in the archive.
MODULE APXPAT (
		LANGUAGE(BLISS36),
		ENTRY (
			BLD_MAST_PAT_LIST,
			BLD_PAT_LIST,
			BLD_PROD_LIST,
			CHANGE_PS,
			DISP_PAT_LIST,
			DISP_SP_LIST,
			GENCCL,
                        REP_PATCH,      ![115]
			GET_PAT_DIR,
			SEL_PAT
				)
		) =
BEGIN

!
!                      COPYRIGHT (c) 1980 BY
!           Digital Equipment Corporation, Maynard, MA.
!
!   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:
!
!   Autopatch Exec Patch Processing Support Routines
!
! ABSTRACT:
!
!
!
!
! ENVIRONMENT: TOPS-20 / TOPS-10
!
! AUTHOR: Donald R. Brandt, CREATION DATE: 3 May 1980
!
! MODIFIED BY:
!
!	Revision history follows
!
!--

!
! Edit History for APXPAT
!
! PAT001  by DRB on 3-Oct-80
!   Added routine GEN_TRACE to generate  MAKLIB  commands  that
!   would  produce trace block information in the .LOG file for
!   the newest copies of all the product libraries.
!
! PAT002  by DRB on 3-Oct-80
!   Modified  GEN_FIXCMD  routine that produces MAKLIB commands
!   for FIX style edits.
!
! PAT003  by DRB on 22-Oct-80
!   Modified GENCCL  routine  to  compute  checksum  of  MAKLIB
!   command file that is generated.
!
! PAT004  by DRB on 30-Oct-80
!   Changed  last_tape  in  GET_PAT_DIR  to  25.   Thus   patch
!   directory  files  will  only  be  recognized  from  tapes 1
!   through 25.
!
! PAT005  by DRB on 31-Oct-80
!   Added   routines   DISP_SP_LIST   and   DISP_PAT_LIST   for
!   displaying edits.
!
! PAT006  by DRB on 31-Dec-80
!   Changed  messages  in  FMT_PAT_STS  macro  to  more   fully
!   describe patch status.
!
! PAT007  by DRB on 27-Aug-81
!   Changed  temporary storage TABLES rep_list and fix_list
!   from static tables to dynamic tables, thus they could be
!   expanded if necessary.
!
! PAT010  by ESB on 21-Dec-81
!   Add source patching.  See comments in routine GENCCL.
!
! 065 by ESB on 5-Apr-82
!   Remove "to library xxx" from the list of patches displayed by the
!   PEPB INIT command.  This is purely cosmetic.
!
! 075 by TGS on 21-Jan-83
!   Change GEN_SRCCMD to check the output filespec for UPDATE indirect
!   command files and, if a logical name was specified, change it to 
!   PAT: before writing to the .CCL file.  The PDB is not changed, and
!   no change is made to the output spec if no logical name was specified
!   in the PDF/PDB.  This allows PDFs to specify ASL: for NEW,LIB library
!   files and still have TOPS-10 UPDATE processing write output files to
!   PAT:.  Required because INSTALL processing assumes all files are on
!   PAT:.  Has no effect on TOPS-20.
!
! 076 by TGS on 18-Feb-83
!   Modify GEN_SRCCMD to unconditionally change the input logical filespec
!   (if one exists) to ASL: on output to the UPDATE indirect command file.
!   CUR entries in the PDF specifying DIS:filespec will result in a SUP
!   entry PAT:output spec=ASL:input spec,correction filespec.  This allows
!   successive multi-tape updates.
!
! 100 by HAH on 31-MAY-83
!   Implement additional patch type 'REP' (replace). No action is taken
!   in GEN_CCL when this patch type is seen in the DPD file. This patch
!   type is intended for the replacement of modules where no patching
!   is required in the build process.
!
! 114 by RBW on 11-NOV-83
!   
!       GENCCL was rewritten  to handle edit  types that do  not
!   require indirect  command files.   Now, GENMKL,  GENSRC,  or
!   nothing  is  called,  depending  on  the  edit  type.   This
!   accomplishes several  things:  First, the  indirect  command
!   file can  no  longer  contain  BOTH  "maklib"  AND  "update"
!   commands; previously it could.  Second, it should be  easier
!   to implement multiple edit types per product if we decide to
!   do that in some future time.
!
! 115 by RBW on 12-NOV-83
!       REP_PATCH was added in this edit. This routine is called
!   during the batch job to copy PATCH files for REP type edits.
!   
! 122 by RBW on 16-MAR-84
!       Modify REP_PATCH to correctly handle multiple edit types.  It was
!   returning after seeing the first non-REP edit type.  It also wasn't 
!   handling error returns correctly.
!
GLOBAL BIND EDTPAT = %O'122' ;		! Edit level of this module
!
! TABLE OF CONTENTS:
!

FORWARD ROUTINE

    BLD_MAST_PAT_LIST,			!Build master patch list
    BLD_PAT_LIST,			!Build selectable patch list
    BLD_PROD_LIST,			!Build product list for RETRIEVE
    CHANGE_PS,				!Change patch status
    DISP_PAT_LIST,			!Display patch list for product
    DISP_SP_LIST,			!Display selected patch list for
					! a product
    GENCCL,				!Generate patch command file
    GENMKL,                             ![114]...MAKLIB command file
    GENSRC,                             ![114]...UPDATE command file
    REP_PATCH,                          ![115]...copy edit files for REP patch
    DO_COPY,                            ![115]......but copy only once 
    GEN_FIXCMD,				!Generate FIX command line
    GEN_LIBCPY,				!Generate copy library command
    GEN_REPCMD,				!Generate replace REL command
    GEN_SRCCMD,				![010] Generate source patch command line
    GEN_TRACE,				!Generate /TRACE command
    GET_PAT_DIR,			!Get patch directory FILE$$
    SEL_PAT ;				!Select patches for a product


!
! INCLUDE FILES:
!

LIBRARY 'BLI:TENDEF'	;		!PDP-10 Definitions
LIBRARY 'BLI:MONSYM'	;		!TOPS-20 Monitor Symbols
LIBRARY 'APEX'		;		!APEX definitions
LIBRARY 'DEBUG'		;		!Debugging macros


 
!
! EXTERNAL REFERENCES:
!

GLOBAL BIND EDTAPX = APEX_EDT ;		! Edit level of APEX.R36


!
!  The BLISS interface routines to the GALAXY library
!   These are defined in BLSGLX.B36
!
 
EXTERNAL ROUTINE $F_FD	;		!Return FD for a file
EXTERNAL ROUTINE $F$CHKS ;		!Compute checksum of a file
EXTERNAL ROUTINE $K_SOUT ;		!String output routine
EXTERNAL ROUTINE $M_GMEM ;		!Memory allocation routine
EXTERNAL ROUTINE $M_RMEM ;		!Memory deallocation routine
EXTERNAL ROUTINE $FMT$ERR ;		!Format GALAXY error message
EXTERNAL ROUTINE $FMT$FD ;		!Format name from FD for a file
EXTERNAL ROUTINE $FMT$NUM ;		!Format number
EXTERNAL ROUTINE $A$PDFD ;		!Get a patch directory FD
 
!
!  APEX support routines
!

EXTERNAL ROUTINE GET_VALUE ;		!Get item value from TBLUK table
EXTERNAL ROUTINE GET_KEY ;		!Get item key from TBLUK table
EXTERNAL ROUTINE T_DELETE ;		!Delete entry in a table
EXTERNAL ROUTINE T_ENTER ;		!Make entry in a table
EXTERNAL ROUTINE T_LOOKUP ;		!Lookup entry in a table
EXTERNAL ROUTINE A_LOOKUP ;		!Lookup address in a table
EXTERNAL ROUTINE A_ENTER ;		!Enter address/value in a table
 
EXTERNAL ROUTINE BUF_WRITE ;		!Write a buffer of data
EXTERNAL ROUTINE CLOSE ;		!Close a file
EXTERNAL ROUTINE OPEN_I ;		!Open a file for input
EXTERNAL ROUTINE OPEN_O ;		!Open a file for output
EXTERNAL ROUTINE FILE_COPY ;            ![115]copy a file... 

 
!
! MACROS:
!

MACRO
    FMT_PAT_STS(status) =
	SELECTONE status OF
	    SET
	    [ps_ret]:  S('retrieved and ready for processing') ;
	    [ps_sel]:  S('selected to be applied during batch job') ;
	    [ps_exc]:  S('excluded and will not be applied') ;
	    [ps_app]:  S('applied to files in autopatching directory') ;
	    [ps_ins]:  S('installed in all product files') ;
	    [ps_per]:  S('permanently installed in the product') ;
	    [OTHERWISE]:  S('unknown') ;
	    TES % ;

 
!
! EQUATED SYMBOLS:
!

!
! OWN STORAGE:
!

OWN
    REP_LIST:	REF TABLE$$ INITIAL(0),	! Used to keep track of commands
					! generated to replace modules

    FIX_LIST:	REF TABLE$$ INITIAL(0),	! Used to keep track of commands
					! generated for FIX edits

    SRC_LIST:	REF TABLE$$ INITIAL(0),	![010] Used to keep track of commands
					![010] generated for SRC edits.

    COP_LIST:   REF TABLE$$ INITIAL(0); ![115] Used to keep track of straight
                                        !   replacement edits

GLOBAL ROUTINE BLD_MAST_PAT_LIST(prod_list,pat_list) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function  returns  a  list  of  all  patches  for  all
!   products specified.
!
! FORMAL PARAMETERS:
!
!	prod_list:
!		address of TABLE$$ of products
!
!	pat_list:
!		address of TABLE$$ for patches
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN			!Beginning ROUTINE BLD_MAST_PAT_LIST

    LOCAL
	patch:		REF PATCH$$,
	product:	REF PRODUCT$$,
	n,
	nn ;
    MAP
	pat_list:	REF TABLE$$,
	prod_list:	REF TABLE$$ ;
 
    $TRACE('Beginning','BLD_MAST_PAT_LIST') ;
 
    CK_DATATYPE(prod_list,TABLE) ;
    CK_DATATYPE(pat_list,TABLE) ;
    PURGE_TABLE(pat_list) ;
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.prod_list,product) EQL true DO
	BEGIN
	CK_DATATYPE(product,PRODUCT) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.product[PROD_PAT_LIST],patch) EQL true DO
	    BEGIN
	    CK_DATATYPE(patch,PATCH) ;
	    IF NOT T_ENTER(.pat_list,.patch[PAT_NAME],.patch)
	    THEN
		RETURN false
	    END 
	END ;
    true

    END ;				!End of BLD_MAST_PAT_LIST

GLOBAL ROUTINE BLD_PAT_LIST(prod_list,pat_list) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function returns a list of all selectable patches  for
!   all products specified.
!
!   A patch is "selectable" if it  has  one  of  the  following
!   status values:
!
!	retrieved
!	selected
!	excluded
!	applied
!
!
! FORMAL PARAMETERS:
!
!	prod_list:
!		address of TABLE$$ of products
!
!	pat_list:
!		address of TABLE$$ for selected patches
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN				!Beginning ROUTINE BLD_PAT_LIST

    LOCAL
	patch:		REF PATCH$$,
	product:	REF PRODUCT$$,
	n,
	nn ;
    MAP
	pat_list:	REF TABLE$$,
	prod_list:	REF TABLE$$ ;
 
    $TRACE('Beginning','BLD_PAT_LIST') ;
 
    CK_DATATYPE(prod_list,TABLE) ;
    CK_DATATYPE(pat_list,TABLE) ;
    PURGE_TABLE(pat_list) ;
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.prod_list,product) EQL true DO
	BEGIN
	CK_DATATYPE(product,PRODUCT) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.product[PROD_PAT_LIST],patch) EQL true DO
	    BEGIN
	    CK_DATATYPE(patch,PATCH) ;
	    IF ((.patch[PAT_STATUS] EQL ps_ret) OR
		(.patch[PAT_STATUS] EQL ps_sel) OR
		(.patch[PAT_STATUS] EQL ps_exc) OR
		(.patch[PAT_STATUS] EQL ps_app))
	    THEN
		IF NOT T_ENTER(.pat_list,.patch[PAT_NAME],.patch)
		THEN
		    RETURN false
	    END 
	END ;
    true

    END ;				!End of BLD_PAT_LIST

GLOBAL ROUTINE BLD_PROD_LIST(mast_list,sel_list,lev) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This  function  returns  a  list  of products that are at a
!   specified patch level.  The list returned will be a  subset
!   of a specified master list.
!
! FORMAL PARAMETERS:
!
!	mast_list:
!		address of TABLE$$ of products
!
!	sel_list:
!		address of TABLE$$ for selected products
!
!	lev:	the required patch level
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!   The patch count field of the product descriptor will be set
!   to zero for all products selected from the master list.
!
!--


    BEGIN				!Beginning ROUTINE BLD_PROD_LIST

    LOCAL
	product:	REF PRODUCT$$,
	n,
	value ;
    MAP
	mast_list:	REF TABLE$$,
	sel_list:	REF TABLE$$ ;
    OWN
	msg:	INITIAL(S(cr_lf,
      ' (No patches will be processed from this tape for this product)',
		cr_lf,' (Patches retrieved through patch tape ')) ;
 
    $TRACE('Beginning','BLD_PROD_LIST') ;
 
    CK_DATATYPE(mast_list,TABLE) ;
    CK_DATATYPE(sel_list,TABLE) ;
    PURGE_TABLE(sel_list) ;

    value = true ;
    n = 0 ;
    WHILE GET_VALUE((n=.n+1),.mast_list,product) EQL true DO
	BEGIN
	CK_DATATYPE(product,PRODUCT) ;
	IF .product[PROD_PAT_LEVEL] EQL .lev
	THEN
	    BEGIN
	    product[PROD_PAT_COUNT] = 0 ;
	    value = T_ENTER(.sel_list,.product[PROD_NAME],.product) ;
	    END ;
	IF .product[PROD_PAT_LEVEL] LSS .lev
	THEN
	    $ERROR(W$PPM,*,.product[PROD_NAME],.msg,
		    FMT_NUM(.product[PROD_PAT_LEVEL]),S(')')) ;
	END ;

    .value

    END ;				!End of BLD_PROD_LIST

GLOBAL ROUTINE CHANGE_PS(product,old_status,new_status) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   For the specified product, this function changes the status
!   of all patches having a specified status.

    BEGIN				!Beginning ROUTINE CHANGE_PS

    LOCAL
	patch:		REF PATCH$$,
	n ;
    MAP
	product:	REF PRODUCT$$ ;

    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_PAT_LIST],patch) EQL true DO
        BEGIN
        CK_DATATYPE(patch,PATCH) ;
        IF .patch[PAT_STATUS] EQL .old_status
        THEN
	    patch[PAT_STATUS] = .new_status
        END ;

    true
    END ;				!End of CHANGE_PS

GLOBAL ROUTINE DISP_PAT_LIST(product) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function displays the status of all  patches  for  the
!   specified product.
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN				!Beginning ROUTINE DISP_PAT_LIST

    LOCAL
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	patch_found,
	n,
	nn,
	nnn ;
    MAP
	product:	REF PRODUCT$$ ;
 
    $TRACE('Beginning','DISP_PAT_LIST') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    patch_found = false ;
    nn = 0 ;
    WHILE
    GET_VALUE((nn=.nn+1),.product[PROD_PAT_LIST],patch) EQL true DO
        BEGIN
        CK_DATATYPE(patch,PATCH) ;
	patch_found = true ;
        nnn = 0 ;
        WHILE
        GET_VALUE((nnn=.nnn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO
	    BEGIN
	    CK_DATATYPE(edit,EDIT) ;
	    TTY((cr_lf,'   Edit '),.edit[EDIT_NAME],
		 (' to library ')) ;
	    lib = .edit[EDIT_LIB] ;
	    file = .edit[EDIT_FILE] ;
	    CK_DATATYPE(lib,LIBRARY) ;
	    TTY(.lib[LIB_NAME],(' is '),
	      FMT_PAT_STS(.patch[PAT_STATUS])) ;
	    END
        END ;

    IF NOT .patch_found
    THEN
	$ERROR(W$NPR,*,.product[PROD_NAME]) ;
    true

    END ;				!End of DISP_PAT_LIST

GLOBAL ROUTINE DISP_SP_LIST(product) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This  function  displays  all  selected  patches  for   the
!   specified product.
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	SETUP processing must have been previously done.
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!	None
!
!--

    BEGIN				!Beginning ROUTINE DISP_SP_LIST

    LOCAL
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	n,
	nn,
	nnn ;
    MAP
	product:	REF PRODUCT$$ ;
 
    $TRACE('Beginning','DISP_SP_LIST') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    nn = 0 ;
    WHILE
    GET_VALUE((nn=.nn+1),.product[PROD_SP_LIST],patch) EQL true DO
        BEGIN
        CK_DATATYPE(patch,PATCH) ;
        nnn = 0 ;
        WHILE
        GET_VALUE((nnn=.nnn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO
	    BEGIN
	    CK_DATATYPE(edit,EDIT) ;
	    TTY((cr_lf,'   Edit '),.edit[EDIT_NAME]) ;		![065]
![065]	    lib = .edit[EDIT_LIB] ;
	    file = .edit[EDIT_FILE] ;
![065]	    CK_DATATYPE(lib,LIBRARY) ;
	    TTY((' from file '),FMT_FILE(file)) ;		![065]
	    END
        END ;
    true

    END ;				!End of DISP_SP_LIST

%([114] NOTE -- THIS ROUTINE HAS BEEN COMMENTED OUT* * * * * *
GLOBAL ROUTINE GENCCL(product) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function generates an indirect file for  patching  the
!   product  specified in the argument.  The file to be written
!   is specified in the "product command  file"  entry  in  the
!   product  descriptor.  The file will contain MAKLIB commands
!   for applying all 'selected' patches for this product.
!
!   The exact contents of the file for each library will be:
!
!   library copy commands to move the distribution libraries to
!   the patching area.
!
!   a command to apply each edit for all selected patches to
!   that library
!
!   /TRACE commands to print trace block information on the new
!   libraries
!
!   The file ends with a /EXIT
!
![010] Add source patching.  Generate a command file for UPDATE (a piece
![010] of SOUPR) instead of MAKLIB.  Assume that the batch control file
![010] will copy all the needed source and REL files into PAT:.  For source
![010] patching, don't generate trace info, MAKLIB copy commands or /EXIT.
!
! FORMAL PARAMETERS:
!
!	product:
!		the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if 
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN				!Beginning ROUTINE GENCCL

    LITERAL
	byte_size_7 = 7,		! ASCII byte size of CCL file
	byte_size_36 = 36 ;		! Word byte size of CCL file
    LOCAL
	checksum,
	error,
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	n,
	nn,
	ed_type ;			![010] type of patch, REL, FIX, or SRC
    MAP
	product:	REF PRODUCT$$ ;

    CK_DATATYPE(product,PRODUCT) ;

    file = .product[PROD_PCF_FILE] ;
    CK_DATATYPE(file,FILE) ;

    IF .rep_list EQL 0
    THEN
	rep_list = GET_TABLE(30) ;		! Create table
    IF .fix_list EQL 0
    THEN
	fix_list = GET_TABLE(30) ;		! Create table
    IF .src_list EQL 0				![010]
    THEN					![010]
	src_list = GET_TABLE(30) ;		![010] Create table

    PURGE_TABLE(rep_list) ;
    PURGE_TABLE(fix_list) ;
    PURGE_TABLE(src_list) ;			![010]

    IF NOT OPEN_O(.file,byte_size_7)
    THEN
	RETURN false ;

![010]
![010] Determine type of edit.
![010]
    GET_VALUE(1,.product[PROD_SP_LIST],patch) ;	![010]
    GET_VALUE(1,.patch[PAT_EDIT_LIST],edit) ;	![010]
    ed_type = .edit[EDIT_TYPE] ;		![010]

!
! For all product libraries, generate a command
![010] Not for source patching.
!
    IF (.ed_type NEQ et_src) AND (.ed_type NEQ et_rep) THEN	![010][100]
    BEGIN					![010]
	n = 0 ;
	WHILE
	GET_VALUE((n=.n+1),.product[PROD_LIB_LIST],lib) EQL true DO
	    IF NOT GEN_LIBCPY(.file,.lib)
	    THEN
		RETURN false ;
    END ;					![010]
!
! For each selected patch, generate commands for all replacement
! REL type edits.
!
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) EQL true DO
	BEGIN
	CK_DATATYPE(patch,PATCH) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO
	    BEGIN
	    CK_DATATYPE(edit,EDIT) ;
	    IF .edit[EDIT_TYPE] EQL et_rel
	    THEN
		IF NOT GEN_REPCMD(.file,.edit)
		THEN
		    RETURN false ;
	    END ;
	END ;
![010]
![010] For each selected patch, generate commands for all source
![010] type edits.
![010]
    n = 0 ;								![010]
    WHILE								![010]
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) EQL true DO	![010]
	BEGIN								![010]
	CK_DATATYPE(patch,PATCH) ;					![010]
	nn = 0 ;							![010]
	WHILE								![010]
	GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO	![010]
	    BEGIN							![010]
	    CK_DATATYPE(edit,EDIT) ;					![010]
	    IF .edit[EDIT_TYPE] EQL et_src				![010]
	    THEN							![010]
		IF NOT GEN_SRCCMD(.file,.edit)				![010]
		THEN							![010]
		    RETURN false ;					![010]
	    END ;							![010]
	END ;								![010]
!
! For each selected patch, generate commands for all FIX type edits.
!
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) EQL true DO
	BEGIN
	CK_DATATYPE(patch,PATCH) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO
	    BEGIN
	    CK_DATATYPE(edit,EDIT) ;
	    IF .edit[EDIT_TYPE] EQL et_fix
	    THEN
		IF NOT GEN_FIXCMD(.file,.edit)
		THEN
		    RETURN false ;
	    END ;
	END ;
!
! For all product libraries, generate a /TRACE command
![010] No trace info needed for source patches.
!
    IF (.ed_type NEQ et_src) AND (.ed_type NEQ et_rep) THEN	![010][100]
    BEGIN					![010]
	n = 0 ;
	WHILE
	GET_VALUE((n=.n+1),.product[PROD_LIB_LIST],lib) EQL true DO
	    IF NOT GEN_TRACE(.file,.lib)
	    THEN
		RETURN false ;
    END ;					![010]
!
! Terminate file
![010] UPDATE doesn't like /EXIT, so skip this for source patches.
!
    IF (.ed_type NEQ et_src) AND (.ed_type NEQ et_rep) THEN	![010][100]
	OUT(.file,S('/EXIT',cr_lf)) ;

    IF NOT CLOSE(.file)
    THEN
	RETURN false ;
!
! Take checksum of file
!
    IF NOT OPEN_I(.file,byte_size_36)
    THEN
	RETURN false ;

    IF $F$CHKS(.file[FILE_IFN],checksum,error)
    THEN
        BEGIN
        file[FILE_ACT_CKSUM] = .checksum ;
        file[FILE_EXP_CKSUM] = .checksum ;
        END
    ELSE
        BEGIN
        file[FILE_ACT_CKSUM] = 0 ;
        file[FILE_EXP_CKSUM] = 0 ;
        $ERROR(W$CGC,*,FMT_FILE(file),$GERROR(.error)) ;
        END ;

    IF NOT CLOSE(.file)
    THEN
	RETURN false ;

    true
    END ;				!End of GENCCL [114])%

GLOBAL ROUTINE GENCCL(PRODUCT) =        ![114] This routine supercedes the old
!++                                     !GENCCL!
!
! FUNCTIONAL DESCRIPTION:
!
!       Since we  currently  only  support  one  edit  type  per
!   product, this routine checks what type an edit is, and calls
!   routines to "do the right thing" depending on the edit type.
!   If the edit type is ET_FIX or ET_REL, then GENMKL is called.
!   If the edit type is ET_SRC,  then GENSRC is called.  If  the
!   edit type is ET_REP, then we return true.
!
!
! FORMAL PARAMETERS:
!
!	product:
!		the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if 
!
! SIDE EFFECTS:
!
!	None
!
!--
    BEGIN                       !GENCCL
    MAP
	product:	REF PRODUCT$$ ;

    LOCAL
        patch:  REF PATCH$$,
        edit:   REF EDIT$$;

    CK_DATATYPE(product,PRODUCT);

    GET_VALUE(1,.product[PROD_SP_LIST],patch);
    CK_DATATYPE(patch,PATCH);

    GET_VALUE(1,.patch[PAT_EDIT_LIST],edit);
    CK_DATATYPE(edit,EDIT);

    RETURN
        (SELECTONE .edit[EDIT_TYPE] OF
            SET
            [ET_FIX, ET_REL]:   GENMKL(.product);
            [ET_SRC]:           GENSRC(.product);
            [ET_REP]:           true;
            [OTHERWISE]:        false
            TES);

    END;                        !GENCCL
GLOBAL ROUTINE REP_PATCH(product) =    !This routine added in edit 115 
!++
!
! FUNCTIONAL DESCRIPTION:
!   
!       This routine processes replacement  type edits.  In  the
!   case  of  some  products  (DECNET-20  in  particular),   the
!   replacement files are needed  at BUILD time.  This  routine,
!   which is invoked  during BUILD processing  copies the  "edit
!   files" to the  filespec specified as  "newest" in the  "edit
!   library".
!   
!
! FORMAL PARAMETERS:
!
!   PRODUCT: the product data descriptor.
!
!
! IMPLICIT INPUTS:
!
!   None
!
!
! IMPLICIT OUTPUTS:
!
!   None
!
!
! SIDE EFFECTS:
!
!   Files get copied
!
!--

    BEGIN                           !REP_PATCH
    MAP
        product:        REF PRODUCT$$;

    LOCAL
        patch:          REF PATCH$$,
        edit:           REF EDIT$$,
        value,
        n,
        nn;

    CK_DATATYPE(product,PRODUCT);

    IF .cop_list EQL 0
    THEN
        cop_list = GET_TABLE(30);

    PURGE_TABLE(cop_list);

    value = true;
    n = 0;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) DO
        BEGIN
        CK_DATATYPE(patch,PATCH);
        nn = 0;
        WHILE 
        GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) DO
            BEGIN
            CK_DATATYPE(edit,EDIT);
            SELECTONE .edit[EDIT_TYPE] OF
                SET
                [ET_REP]:   IF NOT DO_COPY(.edit)
                            THEN
                                value = false;      ![122]
![122]                          .value = false;
![122]          [OTHERWISE]:RETURN true;
                TES;
            END;
        END;

    RETURN .value;
    END;                            !REP_PATCH

ROUTINE DO_COPY(edit) =           !This routine added in edit 115
    BEGIN                           !DO_COPY
    MAP
        edit:           REF EDIT$$;

    LOCAL
	cur_file:	REF FILE$$,
	new_file:	REF FILE$$,
	pat_file:	REF FILE$$,
	lib:		REF LIBRARY$$,
	tedit:		REF EDIT$$,
	mod_key,
	mod_name,
        value,
	n ;

    MACRO $GEN_RKEY =
	BEGIN
	LOCAL
	    a,
	    l1,
	    l2 ;
	l1 = CH$LEN(.mod_name) ;
	l2 = CH$LEN(FMT_FILE(pat_file)) ;
	$M_GMEM(((.l1+.l2+1-1)/5)+1,a) ;
	CH$COPY(.l1,CH$PTR(.mod_name),
		 .l2,CH$PTR(FMT_FILE(pat_file)),
		 0,
		 (.l1+.l2+1),CH$PTR(.a) ) ;
	.a
	END % ;

    CK_DATATYPE(edit,EDIT) ;

    lib = .edit[EDIT_LIB] ;
    CK_DATATYPE(lib,LIBRARY) ;
    cur_file = .lib[LIB_FILE] ;
    CK_DATATYPE(cur_file,FILE) ;
    new_file = .cur_file[FILE_NEWEST] ;
    CK_DATATYPE(new_file,FILE) ;
    pat_file = .edit[EDIT_FILE] ;
    CK_DATATYPE(pat_file,FILE) ;

    value = true;
    n = 0 ;
    WHILE
    GET_KEY((n=.n+1),.edit[EDIT_MOD_LIST],mod_name) EQL true DO
	BEGIN
	mod_key = $GEN_RKEY ;
	IF NOT T_LOOKUP(.cop_list,.mod_key,tedit)
	THEN
	    BEGIN
	    T_ENTER(.cop_list,.mod_key,.edit) ;
            IF NOT FILE_COPY(.pat_file,.new_file)
            THEN
                value = false;
	    END ;
	END ;
    RETURN .value;
    END;                            !DO_COPY
ROUTINE GENMKL(product) =         !This routine added in edit 114 

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function generates an indirect file for  patching  the
!   product  specified in the argument.  The file to be written
!   is specified in the "product command  file"  entry  in  the
!   product  descriptor.  The file will contain MAKLIB commands
!   for applying all 'selected' patches for this product.
!
!   The exact contents of the file for each library will be:
!
!   library copy commands to move the distribution libraries to
!   the patching area.
!
!   a command to apply each edit for all selected patches to
!   that library
!
!   /TRACE commands to print trace block information on the new
!   libraries
!
!   The file ends with a /EXIT
!
!
! FORMAL PARAMETERS:
!
!	product:
!		the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if 
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN				!Beginning ROUTINE GENMKL

    LITERAL
	byte_size_7 = 7,		! ASCII byte size of CCL file
	byte_size_36 = 36 ;		! Word byte size of CCL file
    LOCAL
	checksum,
	error,
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	n,
	nn;

    MAP
	product:	REF PRODUCT$$ ;

    CK_DATATYPE(product,PRODUCT) ;

    file = .product[PROD_PCF_FILE] ;
    CK_DATATYPE(file,FILE) ;

    IF .rep_list EQL 0
    THEN
	rep_list = GET_TABLE(30) ;		! Create table
    IF .fix_list EQL 0
    THEN
	fix_list = GET_TABLE(30) ;		! Create table

    PURGE_TABLE(rep_list) ;
    PURGE_TABLE(fix_list) ;

    IF NOT OPEN_O(.file,byte_size_7)
    THEN
	RETURN false ;
!
! For all product libraries, generate a command
!
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_LIB_LIST],lib) EQL true DO
	IF NOT GEN_LIBCPY(.file,.lib)
	THEN
	    RETURN false ;
!
! For each selected patch, generate commands for all replacement
! REL type edits.
!
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) EQL true DO
        BEGIN
	CK_DATATYPE(patch,PATCH) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO
	    BEGIN
	    CK_DATATYPE(edit,EDIT) ;
	    IF .edit[EDIT_TYPE] EQL et_rel
	    THEN
	        IF NOT GEN_REPCMD(.file,.edit)
		THEN
		    RETURN false ;
	    END ;
	END ;
!
! For each selected patch, generate commands for all FIX type edits.
!
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) EQL true DO
	BEGIN
	CK_DATATYPE(patch,PATCH) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO
	    BEGIN
	    CK_DATATYPE(edit,EDIT) ;
	    IF .edit[EDIT_TYPE] EQL et_fix
	    THEN
		IF NOT GEN_FIXCMD(.file,.edit)
		THEN
		    RETURN false ;
	    END ;
	END ;
!
! For all product libraries, generate a /TRACE command
!
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_LIB_LIST],lib) EQL true DO
        IF NOT GEN_TRACE(.file,.lib)
        THEN
            RETURN false ;
!
! Terminate file
!
    OUT(.file,S('/EXIT',cr_lf)) ;

    IF NOT CLOSE(.file)
    THEN
	RETURN false ;
!
! Take checksum of file
!
    IF NOT OPEN_I(.file,byte_size_36)
    THEN
	RETURN false ;

    IF $F$CHKS(.file[FILE_IFN],checksum,error)
    THEN
        BEGIN
        file[FILE_ACT_CKSUM] = .checksum ;
        file[FILE_EXP_CKSUM] = .checksum ;
        END
    ELSE
        BEGIN
        file[FILE_ACT_CKSUM] = 0 ;
        file[FILE_EXP_CKSUM] = 0 ;
        $ERROR(W$CGC,*,FMT_FILE(file),$GERROR(.error)) ;
        END ;

    IF NOT CLOSE(.file)
    THEN
	RETURN false ;

    true
    END ;				!end GENMKL
ROUTINE GENSRC(product) =         !This routine added in edit 114 

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function generates an indirect file for source patching
!   the product  specified  in the  argument.   The file  to  be
!   written is specified in the "product command file" entry  in
!   the product  descriptor.  The  file will  contain UPDATE  (a
!   piece of SOUPR) commands for applying all 'selected' patches
!   for this product.
!
!
!
! FORMAL PARAMETERS:
!
!	product:
!		the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if 
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN				!Beginning ROUTINE GENSRC

    LITERAL
	byte_size_7 = 7,		! ASCII byte size of CCL file
	byte_size_36 = 36 ;		! Word byte size of CCL file
    LOCAL
	checksum,
	error,
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	n,
	nn;

    MAP
	product:	REF PRODUCT$$ ;

    CK_DATATYPE(product,PRODUCT) ;

    file = .product[PROD_PCF_FILE] ;
    CK_DATATYPE(file,FILE) ;

    IF .src_list EQL 0				
    THEN					
	src_list = GET_TABLE(30) ;		

    PURGE_TABLE(src_list) ;			

    IF NOT OPEN_O(.file,byte_size_7)
    THEN
	RETURN false ;

!
! For each selected patch, generate commands for all source
! type edits.
!
    n = 0 ;								
    WHILE								
    GET_VALUE((n=.n+1),.product[PROD_SP_LIST],patch) EQL true DO	
	BEGIN								
	CK_DATATYPE(patch,PATCH) ;					
	nn = 0 ;							
	WHILE								
	GET_VALUE((nn=.nn+1),.patch[PAT_EDIT_LIST],edit) EQL true DO	
	    BEGIN							
	    CK_DATATYPE(edit,EDIT) ;					
	    IF .edit[EDIT_TYPE] EQL et_src				
	    THEN							
		IF NOT GEN_SRCCMD(.file,.edit)				
		THEN							
		    RETURN false ;					
	    END ;							
	END ;								

    IF NOT CLOSE(.file)
    THEN
	RETURN false ;
!
! Take checksum of file
!
    IF NOT OPEN_I(.file,byte_size_36)
    THEN
	RETURN false ;

    IF $F$CHKS(.file[FILE_IFN],checksum,error)
    THEN
        BEGIN
        file[FILE_ACT_CKSUM] = .checksum ;
        file[FILE_EXP_CKSUM] = .checksum ;
        END
    ELSE
        BEGIN
        file[FILE_ACT_CKSUM] = 0 ;
        file[FILE_EXP_CKSUM] = 0 ;
        $ERROR(W$CGC,*,FMT_FILE(file),$GERROR(.error)) ;
        END ;

    IF NOT CLOSE(.file)
    THEN
	RETURN false ;

    true
    END ;				!End of GENSRC

ROUTINE GEN_FIXCMD(ccl_file,edit) =

    BEGIN				!Beginning ROUTINE GEN_FIXCMD

    LOCAL
	cur_file:	REF FILE$$,
	new_file:	REF FILE$$,
	pat_file:	REF FILE$$,
	lib:		REF LIBRARY$$,
	tedit:		REF EDIT$$,
	n ;
    MAP
	edit:		REF EDIT$$,
	ccl_file:	REF FILE$$ ;

    CK_DATATYPE(ccl_file,FILE) ;
    CK_DATATYPE(edit,EDIT) ;

    lib = .edit[EDIT_LIB] ;
    CK_DATATYPE(lib,LIBRARY) ;
    cur_file = .lib[LIB_FILE] ;
    CK_DATATYPE(cur_file,FILE) ;
    new_file = .cur_file[FILE_NEWEST] ;
    CK_DATATYPE(new_file,FILE) ;
    pat_file = .edit[EDIT_FILE] ;
    CK_DATATYPE(pat_file,FILE) ;

    OUT(.ccl_file,S(cr_lf,'; edit ')) ;
    OUT(.ccl_file,.edit[EDIT_NAME]) ;
    OUT(.ccl_file,S(cr_lf)) ;
    IF A_LOOKUP(.fix_list,.pat_file,tedit)
    THEN
        BEGIN
        OUT(.ccl_file,S(';   this edit installed with edit ')) ;
        OUT(.ccl_file,.tedit[EDIT_NAME]) ;
        OUT(.ccl_file,S(cr_lf)) ;
        END
    ELSE
        BEGIN
        A_ENTER(.fix_list,.pat_file,.edit) ;
        OUT(.ccl_file,FMT_FILE(new_file)) ;
        OUT(.ccl_file,S('=')) ;
        OUT(.ccl_file,FMT_FILE(new_file)) ;
        OUT(.ccl_file,S(',')) ;
        OUT(.ccl_file,FMT_FILE(pat_file)) ;
        OUT(.ccl_file,S('/FIX/WHO:PEP',cr_lf)) ;
        END ;
    true
    END ;				!End of GEN_FIXCMD

ROUTINE GEN_LIBCPY(ccl_file,lib) =

    BEGIN				!Beginning ROUTINE GEN_LIBCPY

    LOCAL
	cur_file:	REF FILE$$,
	new_file:	REF FILE$$,
	n ;
    MAP
	ccl_file:	REF FILE$$,
	lib:		REF LIBRARY$$ ;

    CK_DATATYPE(ccl_file,FILE) ;
    CK_DATATYPE(lib,LIBRARY) ;
    cur_file = .lib[LIB_FILE] ;
    CK_DATATYPE(cur_file,FILE) ;
    new_file = .cur_file[FILE_NEWEST] ;
    CK_DATATYPE(new_file,FILE) ;

    OUT(.ccl_file,FMT_FILE(new_file)) ;
    OUT(.ccl_file,S('=')) ;
    OUT(.ccl_file,FMT_FILE(cur_file)) ;
    OUT(.ccl_file,S('/APPEND',cr_lf)) ;

    true

    END ;				!End of GEN_LIBCPY
ROUTINE GEN_REPCMD(ccl_file,edit) =

    BEGIN				!Beginning ROUTINE GEN_REPCMD

    MACRO $GEN_RKEY =
	BEGIN
	LOCAL
	    a,
	    l1,
	    l2 ;
	l1 = CH$LEN(.mod_name) ;
	l2 = CH$LEN(FMT_FILE(pat_file)) ;
	$M_GMEM(((.l1+.l2+1-1)/5)+1,a) ;
	CH$COPY(.l1,CH$PTR(.mod_name),
		 .l2,CH$PTR(FMT_FILE(pat_file)),
		 0,
		 (.l1+.l2+1),CH$PTR(.a) ) ;
	.a
	END % ;

    LOCAL
	cur_file:	REF FILE$$,
	new_file:	REF FILE$$,
	pat_file:	REF FILE$$,
	lib:		REF LIBRARY$$,
	tedit:		REF EDIT$$,
	mod_key,
	mod_name,
	n ;
    MAP
	edit:		REF EDIT$$,
	ccl_file:	REF FILE$$ ;
    CK_DATATYPE(ccl_file,FILE) ;
    CK_DATATYPE(edit,EDIT) ;

    lib = .edit[EDIT_LIB] ;
    CK_DATATYPE(lib,LIBRARY) ;
    cur_file = .lib[LIB_FILE] ;
    CK_DATATYPE(cur_file,FILE) ;
    new_file = .cur_file[FILE_NEWEST] ;
    CK_DATATYPE(new_file,FILE) ;
    pat_file = .edit[EDIT_FILE] ;
    CK_DATATYPE(pat_file,FILE) ;

    OUT(.ccl_file,S(cr_lf,'; edit ')) ;
    OUT(.ccl_file,.edit[EDIT_NAME]) ;
    OUT(.ccl_file,S(cr_lf)) ;
    n = 0 ;
    WHILE
    GET_KEY((n=.n+1),.edit[EDIT_MOD_LIST],mod_name) EQL true DO
	BEGIN
	mod_key = $GEN_RKEY ;
	IF T_LOOKUP(.rep_list,.mod_key,tedit)
	THEN
	    BEGIN
	    OUT(.ccl_file,S(';   module ')) ;
	    OUT(.ccl_file,.mod_name) ;
	    OUT(.ccl_file,S(' replaced in edit ')) ;
	    OUT(.ccl_file,.tedit[EDIT_NAME]) ;
	    OUT(.ccl_file,S(cr_lf)) ;
	    END
	ELSE
	    BEGIN
	    T_ENTER(.rep_list,.mod_key,.edit) ;
	    OUT(.ccl_file,FMT_FILE(new_file)) ;
	    OUT(.ccl_file,S('=')) ;
	    OUT(.ccl_file,FMT_FILE(new_file)) ;
	    OUT(.ccl_file,S('/MASTER:')) ;
	    OUT(.ccl_file,.mod_name) ;
	    OUT(.ccl_file,S(',')) ;
	    OUT(.ccl_file,FMT_FILE(pat_file)) ;
	    OUT(.ccl_file,S('/REPLACE:')) ;
	    OUT(.ccl_file,.mod_name) ;
	    OUT(.ccl_file,S(cr_lf)) ;
	    END ;
	END ;
    true
    END ;				!End of GEN_REPCMD
![010] Add routine to generate a command line for UPDATE.
ROUTINE GEN_SRCCMD(ccl_file,edit) =

    BEGIN				!Beginning ROUTINE GEN_SRCCMD

    MACRO $GEN_RKEY =
	BEGIN
	LOCAL
	    a,
	    l1,
	    l2 ;
	l1 = CH$LEN(.mod_name) ;
	l2 = CH$LEN(FMT_FILE(pat_file)) ;
	$M_GMEM(((.l1+.l2+1-1)/5)+1,a) ;
	CH$COPY(.l1,CH$PTR(.mod_name),
		 .l2,CH$PTR(FMT_FILE(pat_file)),
		 0,
		 (.l1+.l2+1),CH$PTR(.a) ) ;
	.a
	END % ;

![075][076] Macro to fetch a filespec (1st argument) and, if it contains
![075][076] a logical name, change it to that specified in the second
![075][076] argument for output to the UPDATE CCL. If there is
![075][076] no logical name, do nothing.  In either case, return the address
![075][076] of the (possibly modified) filespec string.

    MACRO $SRC_NLFIL (file,new_log) = 	![076]
	BEGIN
	LOCAL
	    a,
	    p1,
	    p2 ;
	p1 = CH$LEN(FMT_FILE(file)) ;		![075][076] filespec length
	p2 = CH$PTR(FMT_FILE(file)) ;		![075][076] Ptr to filespec
	$M_GMEM(((.p1+1-1)/5)+1,a) ;		![075] Get buffer 
	CH$MOVE(.p1,.p2,CH$PTR(.a)) ;		![075] Copy filespec to buffer
	IF CH$FAIL(CH$FIND_CH(.p1,.p2,%C':')) EQL true  ![075] Logical name?
	THEN
	    .a					![075] No, return buffer adr
	ELSE
	    BEGIN				![075][076] Yes, make it new
	    CH$MOVE(CH$LEN(new_log),CH$PTR(new_log),CH$PTR(.a)) ; ![076]
	    .a
	    END 
	END % ;


    LOCAL
	cur_file:	REF FILE$$,
	new_file:	REF FILE$$,
	pat_file:	REF FILE$$,
	lib:		REF LIBRARY$$,
	tedit:		REF EDIT$$,
	mod_key,
	mod_name,
	n ;
    MAP
	edit:		REF EDIT$$,
	ccl_file:	REF FILE$$ ;
    CK_DATATYPE(ccl_file,FILE) ;
    CK_DATATYPE(edit,EDIT) ;

    lib = .edit[EDIT_LIB] ;
    CK_DATATYPE(lib,LIBRARY) ;
    cur_file = .lib[LIB_FILE] ;
    CK_DATATYPE(cur_file,FILE) ;
    new_file = .cur_file[FILE_NEWEST] ;
    CK_DATATYPE(new_file,FILE) ;
    pat_file = .edit[EDIT_FILE] ;
    CK_DATATYPE(pat_file,FILE) ;

    n = 0 ;
    WHILE
    GET_KEY((n=.n+1),.edit[EDIT_MOD_LIST],mod_name) EQL true DO
	BEGIN
	mod_key = $GEN_RKEY ;
	IF T_LOOKUP(.src_list,.mod_key,tedit) EQL false THEN
	    BEGIN
	    T_ENTER(.src_list,.mod_key,.edit) ;
	    mod_name = $SRC_NLFIL(new_file,ln_pat) ;	![075][076]
	    OUT(.ccl_file,.mod_name) ;	![075] now in mod_name
	    OUT(.ccl_file,S('=')) ;
	    mod_name = $SRC_NLFIL(cur_file,ln_asl) ;	![076]
	    OUT(.ccl_file,.mod_name) ;			![076]
	    OUT(.ccl_file,S(',')) ;
	    OUT(.ccl_file,FMT_FILE(pat_file)) ;
	    OUT(.ccl_file,S(cr_lf)) ;
	    END ;
	END ;
    true
    END ;			![010] End of added routine GEN_SRCCMD
ROUTINE GEN_TRACE(ccl_file,lib) =

    BEGIN				!Beginning ROUTINE GEN_TRACE

    LOCAL
	cur_file:	REF FILE$$,
	new_file:	REF FILE$$,
	n ;
    MAP
	ccl_file:	REF FILE$$,
	lib:		REF LIBRARY$$ ;

    CK_DATATYPE(ccl_file,FILE) ;
    CK_DATATYPE(lib,LIBRARY) ;
    cur_file = .lib[LIB_FILE] ;
    CK_DATATYPE(cur_file,FILE) ;
    new_file = .cur_file[FILE_NEWEST] ;
    CK_DATATYPE(new_file,FILE) ;

    OUT(.ccl_file,S('TTY:=')) ;
    OUT(.ccl_file,FMT_FILE(new_file)) ;
    OUT(.ccl_file,S('/TRACE',cr_lf)) ;

    true

    END ;				!End of GEN_TRACE

GLOBAL ROUTINE GET_PAT_DIR(num,file) =

!++
!
! FUNCTIONAL DESCRIPTION:
!
!   This function returns a  file  descriptor  FILE$$  for  the
!   patch directory for a specified patch tape number.
!
!
! FORMAL PARAMETERS:
!
!	num:	the patch tape number
!
!	file:	the address to return the address of the file
!		descriptor in
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if patch tape number in range 1-25
!	Returns FALSE if not in that range
!
! SIDE EFFECTS:
!
!	None
!
!--

    BEGIN
    LITERAL
	last_tape = 25 ;			! Last tape to check for
    OWN
	f:	FILE$$ 	INITIAL((FILE_SZ^18) OR DT_FILE) ;

    $TRACE('Beginning','GET_PAT_DIR') ;
    IF ((.num GEQ 1) AND (.num LEQ last_tape))
    THEN
	BEGIN
	f[FILE_FD] = $A$PDFD(.num) ;		! Get system-specific FD
	f[FILE_IFN] = 0 ;
	f[FILE_EXP_CKSUM] = 0 ;
	f[FILE_EXP_VER] = 0 ;
	f[FILE_ACT_CKSUM] = 0 ;
	f[FILE_ACT_VER] = 0 ;
	f[FILE_BACKUP] = 0 ;
	f[FILE_NEWEST] = 0 ;
	.file = f ;
	true
	END
    ELSE
	false
    END ;

GLOBAL ROUTINE SEL_PAT(product) =

!++
! FUNCTIONAL DESCRIPTION:
!
!   This function  checks  all  the  patches  for  the  product
!   specified.   The  status  of  a  patch  will  be changed to
!   "selected" for the following cases:
!
!	The current status is "applied"
!	The current status is "selected"
!	The current status is "retrieved" and this is a "mandatory"
!	  patch.
!
!   Using this algorithm means that once a patch is selected or
!   INCLUDEd,  it  will  always  be selected.  Likewise, once a
!   patch has  been  EXCLUDEd,  it  will  always  be  excluded.
!   However,  the  status of a patch can be changed at any time
!   using the INCLUDE or EXCLUDE commands.
!
!   This  function  returns  a list of all selected patches for
!   the product as well as a count of the  number  of  selected
!   patches.    These   values   are   placed  in  the  product
!   descriptor.
!
! FORMAL PARAMETERS:
!
!	product:
!		the product descriptor (PRODUCT$$)
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!   The  list  of  selected patches and the count are stored in
!   the product descriptor.
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!	None
!
!--


    BEGIN				!Beginning ROUTINE SEL_PAT

    LOCAL
	patch:		REF PATCH$$,
	list:		REF TABLE$$,
	n ;
    MAP
	product:	REF PRODUCT$$ ;
 
    $TRACE('Beginning','SEL_PAT') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    list = .product[PROD_SP_LIST] ;
    CK_DATATYPE(list,TABLE) ;
    PURGE_TABLE(list) ;
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.product[PROD_PAT_LIST],patch) EQL true DO
	BEGIN
	CK_DATATYPE(patch,PATCH) ;
	IF ((.patch[PAT_STATUS] EQL ps_app) OR
	    (.patch[PAT_STATUS] EQL ps_sel) OR
	    ((.patch[PAT_STATUS] EQL ps_ret) AND
	     (.patch[PAT_CATEGORY] EQL pc_man)))
	THEN
	    BEGIN
	    patch[PAT_STATUS] = ps_sel ;
	    product[PROD_PAT_COUNT] = .product[PROD_PAT_COUNT] + 1 ;
	    IF NOT
	      T_ENTER(.product[PROD_SP_LIST],.patch[PAT_NAME],.patch)
	    THEN
		RETURN false
	    END
	END ;
    true

    END ;				!End of SEL_PAT

 
 
END
 
ELUDOM
! Local Modes:
! Mode:TEXT
! Display Matching Paren:	-1
! Tab Stop Definitions:	"    :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :"
! End: