Google
 

Trailing-Edge - PDP-10 Archives - BB-L054E-RK - apxini.b36
There are no other files named apxini.b36 in the archive.
MODULE APXINI (
		LANGUAGE(BLISS36),
		MAIN = APEX
		) =
BEGIN
 
!
!		       COPYRIGHT (c) 1980, 1982 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 Initialization and Command Parser Module
!
! ABSTRACT:
!
!
!
!
! ENVIRONMENT: TOPS-20 / TOPS-10
!
! AUTHOR: Donald R. Brandt, CREATION DATE: 7 Mar 1980
!
! MODIFIED BY:
!
!	Revision history follows
!
!--

!
! Edit History for APXINI
!
! INI001  by DRB on 15-Oct-80
!   Added error SIB to SETUP routine to generate a warning if a
!   SETUP was attempted after the batch job was submitted.
!
! INI002  by DRB on 15-Oct-80
!   Added  error  DDH to DESELECT routine to generate a warning
!   message before continuing with the DESELECT operation.
!
! INI003  by DRB on 16-Oct-80
!   Added message to SETUP routine to display number of patches
!   that will be applied.  '[OK]' message removed.
!
! INI004  by DRB on 16-Oct-80
!   Changed NDF error in RETRIEVE to display patching directory.
!
! INI005  by DRB on 31-Oct-80
!   Added error dispatch address ($ER$HK) to HELP command tree.
!
! INI006  by DRB on 31-Oct-80
!   Modified SUMMARY  routine  to  call  DISP_PAT_LIST.   Added
!   error NPR.
!
! INI007  by DRB on 7-Nov-80
!   Modified  SELECT_  routine   to   check   that   the   same
!   directories  are  not  specified as patching, distribution,
!   backup, and installation areas.
!
! INI010  by DRB on 11-Nov-80
!   Modified SELECT_ routine so that logical  name  definitions
!   are  always  kept  as  upper  case  ASCIZ strings.  SELECT_
!   routine now prints  out  logical  defn.   This  edit  makes
!   INI007 work as intended.
!
! INI011  by DRB on 24-Dec-80
!   Modified  message   strings   so   that   they   refer   to
!   "autopatching"  rather  than "patching" directory.  This is
!   then consistent with the documentation.
!
! INI012  by DRB on 29-Dec-80
!   Modified message string on SUBMIT command so that it  works
!   as intended with Galaxy 2 and Galaxy 4.  Without specifying
!   an explicit argument of 1 hour,  /TIME  produces  different
!   defaults under versions 2 & 4.
!
!
! Continued Edit History for APXINI
!
! INI013  by DRB on 30-Dec-80
!   Added  start_flag  to determine if program has already been
!   initialized and is being restarted (via  START).   In  such
!   cases,  GLXLIB stopcodes are produced.  This fix terminates
!   the program with a message to do a GET first.  A better fix
!   requires  GLXLIB  changes  (GLXLIB edit level 631 at least)
!   and more thorough testing than time permits for version  1.
!
! INI014  by DRB on 3-Feb-81
!   Added a call to CK_BATCH at the beginning  of  the  INSTALL
!   routine.   Then,  if the batch job completes after starting
!   PEP, INSTALL processing will check for this first and  then
!   proceed accordingly.
!
! INI015  by DRB on 5-Feb-81
!   Added a call to PS_INIT during SELECT routine to allow  for
!   product-secific initialization during SELECT processing.
!
! INI016  by DRB on 16-Mar-81
!   Changed  routine  PAT_BUILD  so  that  the key used for the
!   patch edit list consists of the edit number and the library
!   name  rather  than  just  the edit number.  This allows the
!   same patch to include  edits  with  the  same  numbers  but
!   different target libraries.
!
! INI017  by ESB on 21-Dec-81
!   Add SRC to keyword table of edit types for source patching.
!
! 060  by ESB on 12-Jan-82
!   Move Global Edit History to new module APXVER.   Local edit
!   numbers will now be the same as global  edit  numbers.   No
!   changes.
!
! 061  by ESB on 18-Jan-82
!   Break up the big Product Description File.  Create a new table
!   PDF_NAMES to keep the PDF file names.  There will now be one
!   PDF file for each system, with INITIALIZE commands only, and
!   one PDF file for each product.  The INITIALIZE command gives
!   the product name for MP_LIST, and the product's PDF file name
!   for PDF_NAMES.
!
! 062  by ESB on 3-Feb-82
!   Remove the message in SETUP that gives the total number of patches
!   being applied to the product.  The number is stored in 8 bits, and
!   overflows too easily.  Fixing this properly will require changing
!   the format of the checkpoint files in the field.
!
! 063  by ESB on 25-Mar-82
!   Add two blank lines to the output after the INFORMATION (STATUS)
!   command.  This will make the INFORMATION * command look better.
!
! 064  by ESB on 1-Apr-82
!   Add ability to update checksums, versions, and filenames of the utility
!   files in the PDB.  PEP will read PAT:UTILTY.UPD if it can, and update
!   the appropriate entires.
!
! 072  by ESB on 2-Jul-82
!   Ask for definition of PAT: when SELECTing each product.  This will
!   allow each product to have a different PAT:.
!
! 077 by HAH on 31-MAY-83
!   Increase table size of IP_LIST_SZ and MP_LIST_SZ from 15 to 30 to
!   support more products.
!
! 100 by HAH on 31-MAY-83
!   Implement additional patch type 'REP' (replace). No action is taken
!   in GEN_CCL when this type is seen in the DPD file. This patch type
!   is intended for replacement modules where no patching is required
!   in the build process.
!
! 101 by HAH on 31-MAY-83
!   Suppress checkpointing during SETUP and BUILD processing invoked
!   by an AUTOPATCH command. A final checkpoint is done.
!
! 103 by HAH on 11-JUL-83
!   Eliminate use of TTY_PAT_COUNT and type either 'No patches retrieved'
!   or 'Patches retrieved'.
!
! 112 by RBW on 05-OCT-83
!       Implemented a short status command which displays status
!   information only,  without  display all  the  checksums  and
!   other miscellaneous clutter.
!
! 113 by RBW on 11-NOV-83
!       Implemented   the   capability   to   declare   products
!   "Obsolete".  This means that no more edits will be delivered
!   for this product, starting with the current Autopatch  Tape.
!   The entry in the MP_LIST for  the product is deleted and  if
!   the product is currently SELECTed, the user is cautioned  to
!   DESELECT the product.  Products  are declared "obsolete"  by
!   an appropriate entry in the PEPnnn.PDF file.
!
! 120 by RBW on 13-JAN-84
!       Fix problem  with edit  113.  Force  an exact  match  by
!   T_LOOKUP when  checking for  the  existance of  an  OBSOLETE
!   product in MP_LIST and IP_LIST.  NOTE that this implies that
!   the product name in the PDF file CANNOT BE ABREVIATED!

GLOBAL  BIND  EDTINI  = %O'120' ;		! Edit level of this module
 
!
! TABLE OF CONTENTS:
!
 
FORWARD ROUTINE
 
	APEX:		NOVALUE,
	COMMAND_DISPATCH,
	AUTOPATCH,
	BUILD,
	DESELECT,
	EXCLUDE,
	HELP,
	INCLUDE,
	INFORM,				! [112]
	INSTALL,
	RESTORE,
	RETRIEVE,
	SELECT_,
	SETUP,
	STATUS,
	SUMMARY,

	BUILD_MP_LIST,
	SEL_BUILD,
	PAT_BUILD,
	UTL_UPDATE,			![064]
	MP_ERROR,
	SEL_ERROR,
	PAT_ERROR ;
 
 
!
! INCLUDE FILES:
!
 
LIBRARY 'BLI:TENDEF'	;		!PDP-10 Definitions
LIBRARY 'BLI:MONSYM'	;		!TOPS-20 Monitor Symbols
LIBRARY 'APEX'		;		!APEX macros
LIBRARY 'BLSPAR'	;		!BLISS parser macros
LIBRARY 'DEBUG'		;		!Debugging macros

REQUIRE 'FILES.REQ'	;		!System dependent file info
 
!
! Edit symbol definitions
!


!
! Global edit symbols
!

EXTERNAL
    EDTCHK,				! edit level of module APXCHK
    EDTCKP,				! edit level of module APXCKP
    EDTCMD,				! edit level of module APXCMD
    EDTERR,				! edit level of module APXERR
    EDTFIL,				! edit level of module APXFIL
    EDTPAT,				! edit level of module APXPAT
    EDTTBL,				! edit level of module APXTBL
    EDTEXT,				! edit level of module GLXEXT
    EDTGLX,				! edit level of module BLSGLX
    EDTPAR ;				! edit level of module BLSPAR

GLOBAL BIND EDTAPX = APEX_EDT ;		! Edit level of APEX.R36
 
!
! EXTERNAL REFERENCES:
!
    
EXTERNAL
    TAKFDB:	PDB_BLOCK ;		!PDB for TAKE command
					! (defined in OPRPAR)

EXTERNAL				!Parser error routines for
    $ERR$C,				!Illegal command
    $ERR$G,				!Not confirmed
    $ER$HK,				!Illegal HELP keyword
    $ER$IP,				!Illegal product in IP list
    $ER$MP ;				!Illegal product in MP list

!
!  The BLISS interface routines to GALAXY parser routines
!   These are defined in BLSPAR.B36
!
 
EXTERNAL ROUTINE $PRINIT ;		!Library Initialization
EXTERNAL ROUTINE $PRCMND ;		!Parse command
EXTERNAL ROUTINE $PARSE ;		!Parse command
EXTERNAL ROUTINE $P$TAKE ;		!Setup for TAKE
EXTERNAL ROUTINE $P$HELP ;		!Setup for HELP
EXTERNAL ROUTINE $PRSETUP ;		!Setup after parse
EXTERNAL ROUTINE $PRNFLD ;		!Return next field type
EXTERNAL ROUTINE $PRKEY ;		!Return keyword
EXTERNAL ROUTINE $PRNUM ;		! number
EXTERNAL ROUTINE $PRSWI ;		! switch value
EXTERNAL ROUTINE $PRFIL ;		! file spec
EXTERNAL ROUTINE $PRFLD ;		! character field
EXTERNAL ROUTINE $PRCFM ;		! confirmation (CRLF)
EXTERNAL ROUTINE $PRDIR ;		! directory
EXTERNAL ROUTINE $PRUSR ;		! user name
EXTERNAL ROUTINE $PRCMA ;		! comma
EXTERNAL ROUTINE $PRFLT ;		! floating point number
EXTERNAL ROUTINE $PRDEV ;		! device name
EXTERNAL ROUTINE $PRTXT ;		! text to EOL
EXTERNAL ROUTINE $PRTAD ;		! time and date
EXTERNAL ROUTINE $PRQST ;		! quoted string
EXTERNAL ROUTINE $PRUNQ ;		! unquoted string
EXTERNAL ROUTINE $PRTOK ;		! token
EXTERNAL ROUTINE $PRNUX ;		! digits terminated by nondigit
EXTERNAL ROUTINE $PRACT ;		! account string
EXTERNAL ROUTINE $PRNOD ;		! node name
EXTERNAL ROUTINE $PRSXF ;		! sixbit field
 
!
! EXTERNAL REFERENCES CONTINUED:
!
 
!
!  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 $FMT$VRS ;		!Format version number
EXTERNAL ROUTINE $K_SOUT ;		!String output routine
EXTERNAL ROUTINE $M_GMEM ;		!Memory allocation routine
EXTERNAL ROUTINE $M_RMEM ;		!Memory deallocation routine
EXTERNAL ROUTINE $A$INIT ;		!Initialize APEX
EXTERNAL ROUTINE $DEF$LN ;		!Define a logical name
EXTERNAL ROUTINE $GET$LND ;		!Return logical name definition
EXTERNAL ROUTINE $FMT$FD ;		!Format name from FD for a file
EXTERNAL ROUTINE $FMT$NUM ;		!Format number
 
 
!
! EXTERNAL REFERENCES CONTINUED:
!
 
!
!  APEX support routines
!
 
EXTERNAL ROUTINE CK_FILE ;		!Check a file
EXTERNAL ROUTINE CLOSE ;		!Close a file
EXTERNAL ROUTINE DEF_LN ;		!Define logical names
EXTERNAL ROUTINE DELETE ;		!Delete a file
EXTERNAL ROUTINE R_REL ;		![064] Reset and Release file
EXTERNAL ROUTINE DISP_LN_DEFS ;		!Display logical names
EXTERNAL ROUTINE DISPLAY_FILES ;	!Display files for a product
EXTERNAL ROUTINE OPEN_I ;		!Open a file for input
EXTERNAL ROUTINE SCK_FILE ;		!Silently check a file

EXTERNAL ROUTINE GET_COMMAND ;		!Process a command
EXTERNAL ROUTINE GET_YES_NO ;		!Get YES or NO response
EXTERNAL ROUTINE READ_FILE ;		!Process a file of commands
EXTERNAL ROUTINE SET_LN ;		!Setup a logical name

EXTERNAL ROUTINE DB_READ ;		!Read checkpointed database
EXTERNAL ROUTINE DB_WRITE ;		!Write checkpointed database

EXTERNAL ROUTINE GET_VALUE ;		!Get item value 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 BCHECK ;		!BUILD processing check
EXTERNAL ROUTINE ICHECK ;		!INSTALL processing check
EXTERNAL ROUTINE RCHECK ;		!RESTORE processing check
EXTERNAL ROUTINE SCHECK ;		!SELECT processing check
EXTERNAL ROUTINE INS_INIT_FILES ;	!Init files for INSTALL
EXTERNAL ROUTINE RES_INIT_FILES ;	!Init files for RESTORE
EXTERNAL ROUTINE BACKUP	;		!Product backup processing
EXTERNAL ROUTINE REPLACE ;		!Product replacement processing
EXTERNAL ROUTINE REVERT	;		!Product restore processing
EXTERNAL ROUTINE CK_BATCH ;		!Check batch job status

EXTERNAL ROUTINE BLD_MAST_PAT_LIST ;	!Build master patch list
EXTERNAL ROUTINE BLD_PAT_LIST ;		!Build selected patch list
EXTERNAL ROUTINE BLD_PROD_LIST ;	!Build product list for RETRIEVE
EXTERNAL ROUTINE CHANGE_PS ;		!Change patch status
EXTERNAL ROUTINE DISP_PAT_LIST ;	!Display patch list for product
EXTERNAL ROUTINE GENCCL ;		!Generate patch command file
EXTERNAL ROUTINE GET_PAT_DIR ;		!Get patch directory FILE$$
EXTERNAL ROUTINE SEL_PAT ;		!Select patches to be applied

EXTERNAL ROUTINE PS_INIT ;		!Do additional SELECT processing

 
!
! MACROS:
!

MACRO
    CHECKPOINT(f) =
	BEGIN
	TTY((cr_lf,'[Checkpointing]')) ;
	IF DB_WRITE(f)
	THEN
	    TTY_OK
	ELSE
	    RETURN $ERROR(F$CCD,*,FMT_FILE(db_file))
	END %,

    $GEN_PROMPT(s1,s2) =
	BEGIN
	LOCAL
	    a,
	    l1,
	    l2 ;
	l1 = CH$LEN(s1) ;
	l2 = CH$LEN(s2) ;
	$M_GMEM(((.l1+.l2+3-1)/5)+1,a) ;
	CH$COPY(.l1,CH$PTR(s1),
		.l2,CH$PTR(s2),
		3,CH$ASCIZ('? '),
		0,
		(.l1+.l2+3),CH$PTR(.a) ) ;
	.a
	END % ;

 
!
! EQUATED SYMBOLS:
!
 
!
!   Define parameter values for compilation
!

LITERAL
    IP_LIST_SZ	= 30,		![077] Size of TBLUK portion of IP_LIST
				!  (does not include header)

    MP_LIST_SZ	= 30,		![077] Size of TBLUK portion of MP_LIST
				!  (does not include header)

    PAT_LIST_SZ	= 100 ;		! Size of PAT_LIST

!
!  Define associated values for keyword tables
!
 
LITERAL
    $$AUTOPATCH = 1,
    $$BUILD	= 2,
    $$EXCLUDE	= 3,
    $$EXIT	= 4,
    $$HELP	= 5,
    $$INCLUDE	= 6,
    $$INFORMATION= 47,	! [112]
    $$INSTALL	= 7,
    $$RESTORE	= 8,
    $$RETRIEVE	= 9,
    $$SELECT	= 10,
    $$SETUP	= 11,
    $$STATUS	= 12,
    $$SUMMARY	= 13,
 
    $$PRODUCT	= 14,
    $$COMPONENT	= 15,
    $$FILE	= 16,
    $$END	= 17,
    $$INITIALIZE= 46,			![061]

    $$BCF	= 18,
    $$BLD	= 19,
    $$CTL	= 20,
    $$INP	= 21,
    $$LIB	= 22,
    $$OUT	= 23,
    $$PCF	= 24,
    $$UTL	= 25,

    $$BAK	= 26,
    $$CUR	= 27,
    $$NEW	= 28,

    $$CATEGORY	= 29,
    $$DATE	= 30,
    $$DESCRIPTION = 31,
    $$EDIT	= 32,
    $$ENDEDIT	= 33,
    $$ENDPATCH	= 34,
    $$FORMAT	= 35,
    $$LIBRARY	= 36,
    $$MODULE	= 37,
    $$PATCH	= 38,
    $$REQUIRES	= 40,
    $$SPR	= 41,
    $$SYSTEM	= 42,
    $$TAPE	= 43,
    $$TYPE	= 44,

    $$DESELECT	= 45,
    $$OBSOLETE  = 48 ;      ![113]

 
!
! EQUATED SYMBOLS CONTINUED:
!
 
!
!  Make forward reference for keyword tables
!    note allocation is # entries + 1
!
 
FORWARD
    CMDTAB:	VECTOR[14],			! [112] 13 => 14
    CMDSTB:	VECTOR[4],
    E_TTAB:	VECTOR[5],			! [017][100] Edit types
    FIITAB:	VECTOR[4],
    FITTAB:	VECTOR[9],
    P_CTAB:	VECTOR[3],			! Patch categories
    PATTAB:	VECTOR[18],			! Keywords in patch file
    PDFTAB:	VECTOR[3],			![061][113]
                                                     !Keywords in prod file
    SPDTAB:	VECTOR[5],
    UPDTAB:	VECTOR[4],			![064] Keywords in utl update
    SPRTAB:	VECTOR[ip_list_sz + 1],
    CMD_LIST:	VECTOR[13],
    IP_TBLUK:	VECTOR[ip_list_sz + 1],
    MP_TBLUK:	VECTOR[mp_list_sz + 1],
    PDF_TBLUK:	VECTOR[mp_list_sz + 1] ;	![061]
!
!  Make forward references for PDB's using the
!   special macro provided
!
 
$PDB (CMDIN0,
      CMDIN1,
      CMDSKY,
      CMDKEY,
      CMDIPL,
      CMDMPL,
      CMDWLD,
      CMDHLP,
      CMDCFM,
      NP0AUT,
      NP0BUI,
      NP0DES,
      NP0EXC,
      NP0EXI,
      NP0HEL,
      NP0INC,
      NP0INS,
      NP0RES,
      NP0RET,
      NP0SEL,
      NP0SET,
      NP0SUM,
      NP0STA,
      PDFINI,
      PDF001,
      SPDINI,
      SPD001,
      UPDINI,			![064]
      UPD001,			![064]
      PRD001,
      PRD002,
      PRD003,
      PRD004,
      PRD005,
      PRD006,
      PRD007,
      SPR001,
      COM001,
      COM002,
      COM003,
      END001,
      INI001,			![061]
      INI002,			![061]
      INI003,			![061]
      FIL001,
      FIL002,
      FIL003,
      FIL004,
      FIL005,
      FIL006,
      FIL007,
!      FIL008,
!      FIL009,
      FIL010,
      FIL011,
      FIL012,
      FIL013,
      FIL014,
      FIL015,

      PATINI,
      PATKEY,
      PATDAT,
      PATFIL,
      PATFLD,
      PATNUM,
      PATTXT,
      PAT001,
      PAT002) ;
!
! GLOBAL STORAGE:
!

!
!   MP_LIST  and  IP_LIST  are  static  tables  and  cannot  be
!   expanded.   The master product list, MP_LIST, has one entry
!   for every possible autopatchable product.  The installation
!   product  list,  IP_LIST,  has  one entry for every SELECTed
!   product.   The   tables   are   initialized   during   APEX
!   initialization.   The  tables must remain static since some
!   of the command syntax PDBs reference the TBLUK  portion  of
!   these tables.
!
!*** NOTE:  MP_LIST and IP_LIST are dynamic tables as of edit 54.
!
 
GLOBAL
    IP_LIST:	DTABLE$$(IP_TBLUK),	! Installation Product List
    IP_TBLUK:	TBLUK$$(ip_list_sz) ;
 
GLOBAL
    MP_LIST:	DTABLE$$(mp_tbluk),	! Master Product List
    MP_TBLUK:	TBLUK$$(mp_list_sz) ;

GLOBAL
    PDF_NAMES:	DTABLE$$(pdf_tbluk),	![061] Product PDF Filenames
    PDF_TBLUK:	TBLUK$$(mp_list_sz) ;	![061]

 
!
! OWN STORAGE:
!
 
OWN
    cur_command:	INITIAL (0);	![101]

OWN
    EXIT_FLAG: INITIAL (false) ;
OWN
    START_FLAG: INITIAL (false) ;
OWN
    sel_p_flag:	INITIAL(false) ;	!Select processing flag
OWN
    OBSOLETE_PRODUCT_FLAG: INITIAL(false) ; ![113]
OWN
    LND_BAK:
	INITIAL(LND_BAK_DEF),	! Logical defn for backup directory
    LND_DIS:
	INITIAL(LND_DIS_DEF),	! Logical defn for distribution dir
    LND_INS:
	INITIAL(LND_INS_DEF),	! Logical defn for installation dir
    LND_PAT:
	INITIAL(LND_PAT_DEF) ;	! Logical defn for patching directory

!
!   MAST_PAT_LIST is the master list of  all  patches.   It  is
!   built dynamically during initialization.
!

OWN
    MAST_PAT_LIST:	REF TABLE$$ ;	! Master Patch List

!
!   PAT_LIST is the master list of  "selectable"  patches.   It
!   is also built dynamically during initialization.
!

OWN
    PAT_LIST:		REF TABLE$$ ;	! Master Selected Patch List

!
!   SPR_LIST  is  a  list  of  products  meeting some specified
!   criteria.  It is initialized when it is needed.  The  TBLUK
!   portion  is  referenced in the command syntax tree used for
!   SELECT processing.
!

OWN
    SPR_LIST:	DTABLE$$(sprtab),	! Specified Product List
    SPRTAB:	TBLUK$$(ip_list_sz) ;
 
!
! OWN STORAGE CONTINUED:
!
!  Define the command parser related tables and data structures
!
 
!
!   Dispatch keyword table for APEX commands
!    (full command list after product selection)
!
 
OWN CMDTAB: $DSPTAB (((NP0AUT,'AUTOPATCH',$$AUTOPATCH),
		      (NP0BUI,'BUILD',$$BUILD),
		      (NP0DES,'DESELECT',$$DESELECT),
!		      (NP0EXC,'EXCLUDE',$$EXCLUDE),
		      (NP0EXI,'EXIT',$$EXIT),
		      (NP0HEL,'HELP',$$HELP),
!		      (NP0STA,(%O'002000000001','I'),$$INFORMATION),
!		      (NP0INC,'INCLUDE',$$INCLUDE),
		      (NP0STA,'INFORMATION',$$INFORMATION),! [112] Status=>Info
		      (NP0INS,'INSTALL',$$INSTALL),
		      (NP0RES,'RESTORE',$$RESTORE),
		      (NP0RET,'RETRIEVE',$$RETRIEVE),
		      (NP0SEL,'SELECT',$$SELECT),
		      (NP0SET,'SETUP',$$SETUP),
		      (NP0STA,'STATUS',$$STATUS),	! [112]
		      (NP0SUM,'SUMMARY',$$SUMMARY)
!		      (TAKFDB,'TAKE',$KYTAK)
			)) ;
 
!
!   Dispatch keyword table for APEX commands
!    (short command list before any product selection)
!
 
OWN CMDSTB: $DSPTAB (((NP0EXI,'EXIT',$$EXIT),
		      (NP0HEL,'HELP',$$HELP),
		      (NP0SEL,'SELECT',$$SELECT),
			)) ;
 
!
!   Command List for HELP command
!
 
OWN CMD_LIST: $KEYKEY ((('AUTOPATCH'),
		       ('BUILD'),
		       ('DESELECT'),
!		       ('EXCLUDE'),
		       ('EXIT'),
		       ('HELP'),
!		       ('INCLUDE'),
		       ('INFORMATION'),
		       ('INSTALL'),
		       ('RESTORE'),
		       ('RETRIEVE'),
		       ('SELECT'),
		       ('SETUP'),
		       ('SUMMARY'))) ;
 
!
! OWN STORAGE CONTINUED:
!
!   Dispatch table for entries in product description file
!
%( [061]
OWN
    PDFTAB:	$DSPTAB(((COM001,'COMPONENT',$$COMPONENT),
			(END001,'END',$$END),
			(FIL001,'FILE',$$FILE),
			(PRD001,'PRODUCT',$$PRODUCT))) ;
[061] )%
OWN
    PDFTAB:	$DSPTAB(((INI001,'INITIALIZE',$$INITIALIZE),	![061]
                        (INI001,'OBSOLETE',$$OBSOLETE))) ;      ![113]
!
!   Dispatch table for entries in product description file
!   when product entries are specified.
!

OWN
    SPDTAB:	$DSPTAB(((COM001,'COMPONENT',$$COMPONENT),
			(END001,'END',$$END),
			(FIL001,'FILE',$$FILE),
			(SPR001,'PRODUCT',$$PRODUCT))) ;

![064]
!
!   Dispatch table for entries in utility update file
!

OWN								![064]
    UPDTAB:	$DSPTAB(((END001,'END',$$END),			![064]
			(FIL001,'FILE',$$FILE),			![064]
			(PRD001,'PRODUCT',$$PRODUCT))) ;	![064]

!
!   Keyword table of file types for file entries in product
!   description file
!

OWN
    FITTAB:	$KEYTAB((('BCF',$$BCF),
			('BLD',$$BLD),
			('CTL',$$CTL),
			('INP',$$INP),
			('LIB',$$LIB),
			('OUT',$$OUT),
			('PCF',$$PCF),
			('UTL',$$UTL))) ;

!
!   Keyword table of file instances for file entries in product
!   description file
!

OWN
    FIITAB:	$KEYTAB((('BAK',$$BAK),
			('CUR',$$CUR),
			('NEW',$$NEW))) ;
!
! OWN STORAGE CONTINUED:
!
!   Dispatch table for entries in patch directory file
!

OWN
    PATTAB:	$DSPTAB((
			(PAT001,'CATEGORY',$$CATEGORY),
!			(PATDAT,'DATE',$$DATE),
			(PATTXT,'DATE',$$DATE),
			(PATTXT,'DESCRIPTION',$$DESCRIPTION),
			(PATFLD,'EDIT',$$EDIT),
			(PATFLD,'ENDEDIT',$$ENDEDIT),
			(PATTXT,'ENDPATCH',$$ENDPATCH),
			(PATFIL,'FILE',$$FILE),
			(PATNUM,'FORMAT',$$FORMAT),
			(PATFLD,'LIBRARY',$$LIBRARY),
			(PATTXT,'MODULE',$$MODULE),
			(PATTXT,'PATCH',$$PATCH),
			(PATFLD,'PRODUCT',$$PRODUCT),
			(PATFLD,'REQUIRES',$$REQUIRES),
			(PATTXT,'SPR',$$SPR),
			(PATNUM,'SYSTEM',$$SYSTEM),
			(PATNUM,'TAPE',$$TAPE),
			(PAT002,'TYPE',$$TYPE))) ;

!
!   Keyword table of patch categories for entries in patch
!   directory file
!

OWN
    P_CTAB:	$KEYTAB((
			('MANDATORY',PC_MAN),
			('OPTIONAL',PC_OPT))) ;

!
!   Keyword table of edit types for entries in patch
!   directory file
!

OWN
    E_TTAB:	$KEYTAB((
			('FIX',ET_FIX),
			('REL',ET_REL),			![017]
			('REP',ET_REP),			![100]
			('SRC',ET_SRC))) ;		![017]

 
!
! OWN STORAGE CONTINUED:
!
!
!   Syntax tree for KEYWORD entry in product description file
!

OWN
    PDFINI:	$INIT(NEXT=PDF001),
    PDF001:	$KEYDSP(TABLE=PDFTAB) ;		! Dispatch KEYWORD

!
!   Syntax tree for KEYWORD entry in product description file
!   when product entries are specified.
!

OWN
    SPDINI:	$INIT(NEXT=SPD001),
    SPD001:	$KEYDSP(TABLE=SPDTAB) ;		! Dispatch KEYWORD

![064]
!
!   Syntax tree for KEYWORD entry in utility update file
!

OWN						![064]
    UPDINI:	$INIT(NEXT=UPD001),		![064]
    UPD001:	$KEYDSP(TABLE=UPDTAB) ;		![064] Dispatch KEYWORD

!
!   Syntax tree for PRODUCT entry in product description file
!

OWN
    PRD001:	$FIELD(NEXT=PRD002),		! Product name
    PRD002:	$COMMA(NEXT=PRD003),		! comma
    PRD003:	$FIELD(NEXT=PRD004),		! Product code
    PRD004:	$COMMA(NEXT=PRD005),		! comma
    PRD005:	$NUMBER(RADIX=10,		! Product status
			NEXT=PRD006),
    PRD006:	$COMMA(NEXT=PRD007),		! comma
    PRD007:	$NUMBER(RADIX=10,		! Product patch_level
			NEXT=CMDCFM) ;

!
!   Syntax tree for PRODUCT entry in product description file
!   when product entries are specified in SPRTAB.
!

OWN
    SPR001:	$KEY(TABLE=SPRTAB,		! Product name
		     NEXT=PRD002) ;

!
!   Syntax tree for COMPONENT entry in product description file
!

OWN
    COM001:	$FIELD(NEXT=COM002),		! Component name
    COM002:	$COMMA(NEXT=COM003),		! comma
    COM003:	$FIELD(NEXT=CMDCFM) ;		! Component code
!
! OWN STORAGE CONTINUED:
!
!   Syntax tree for FILE entry in product description file
!

OWN
    FIL001:	$FIELD(NEXT=FIL002),		! File identifier
    FIL002:	$COMMA(NEXT=FIL003),		! comma
    FIL003:	$FIELD(NEXT=FIL004),		! Owner code
    FIL004:	$COMMA(NEXT=FIL005),		! comma
    FIL005:	$KEY(TABLE=FIITAB,		! File instance
		     NEXT=FIL006),
    FIL006:	$COMMA(NEXT=FIL007),		! comma
    FIL007:	$KEY(TABLE=FITTAB,		! File type
		     NEXT=FIL010),
    FIL010:	$COMMA(NEXT=FIL011),		! comma
    FIL011:	$NUMBER(RADIX=8,		! File checksum
			NEXT=FIL012),
    FIL012:	$COMMA(NEXT=FIL013),		! comma
    FIL013:	$NUMBER(RADIX=8,		! File version
			NEXT=FIL014),
    FIL014:	$COMMA(NEXT=FIL015),		! comma
    FIL015:	$FILE_SPEC((NEXT=CMDCFM)) ;	! File spec


!   Syntax tree for END entry in product description file
!

OWN
    END001:	$FIELD(NEXT=CMDCFM) ;		! Product name

![061]
![061] Syntax tree for INITIALIZE entry in PEPn01.PDF file
![061]

OWN						![061]
    INI001:	$FIELD(NEXT=INI002),		![061] Product name
    INI002:	$COMMA(NEXT=INI003),		![061] comma
    INI003:	$FILE_SPEC(NEXT=CMDCFM) ;	![061] PDF file name
!
!   Define the Parser Descriptor Blocks (PDBs) for entries in
!   a patch directory file.
!

OWN
    PATINI:	$INIT(NEXT=PATKEY),
    PATKEY:	$KEYDSP(TABLE=PATTAB),

    PATDAT:	$DATE(NEXT=CMDCFM),
    PATFIL:	$FILE_SPEC((NEXT=CMDCFM)),
    PATFLD:	$FIELD(NEXT=CMDCFM),
    PATNUM:	$NUMBER(RADIX=10,
			NEXT=CMDCFM),
    PATTXT:	$TEXT(NEXT=CMDCFM),

    PAT001:	$KEY(TABLE=P_CTAB,
		     NEXT=CMDCFM),
    PAT002:	$KEY(TABLE=E_TTAB,
		     NEXT=CMDCFM) ;
 
!
! OWN STORAGE CONTINUED:
!
!   Define the Parser Descriptor Blocks (PDB) for APEX commands
!
 
OWN
    CMDIN0: $INIT (NEXT=CMDSKY),	!Initialize parse and set prompt
					! for short command list
    CMDIN1: $INIT (NEXT=CMDKEY) ;	!Initialize parse and set prompt
					! for long command list
 
OWN
    CMDKEY: $KEYDSP (TABLE=CMDTAB,	!Parse command keyword and
 		     ERROR=$ERR$C),	! dispatch

    CMDSKY: $KEYDSP (TABLE=CMDSTB,	!Parse command keyword and
 		     ERROR=$ERR$C) ;	! dispatch
 
OWN
    CMDIPL: $KEY (TABLE=IP_TBLUK,	!Product from installation list
		  ALTERNATE=CMDWLD,
		  ERROR=$ER$IP,
		  NEXT=CMDCFM) ;
OWN
    CMDMPL: $KEY (TABLE=MP_TBLUK,	!Parse product from master list
		  ALTERNATE=CMDWLD,
		  ERROR=$ER$MP,
		  NEXT=CMDCFM) ;
OWN
    CMDWLD: $TOKEN (CHAR='*',		!Parse wild character *
		    FLAGS=cm_sdh,	!Suppress default help
		    HELP= '* for all of these products',
		    NEXT=CMDCFM) ;
 
OWN
    CMDHLP: $KEY (TABLE=CMD_LIST,	!Parse a command from HELP list
		  DEFAULT='HELP',
		  ERROR=$ER$HK,
		  NEXT=CMDCFM) ;
 
OWN
    CMDCFM: $CONFIRM (ERROR=$ERR$G) ;	!Parse command termination
 
!
! OWN STORAGE CONTINUED:
!   Parser Descriptor Blocks (PDB) continued
!	Noise phrases
!
 
OWN
    NP0AUT: $NOISE (NEXT=CMDIPL,
		    TEXT='product name'),
 
    NP0BUI: $NOISE (NEXT=CMDIPL,
		    TEXT='product name'),
 
    NP0DES: $NOISE (NEXT=CMDIPL,
		    TEXT='product name'),
 
    NP0EXC: $NOISE (NEXT=CMDCFM,
		    TEXT='the patch'),
 
    NP0EXI: $NOISE (NEXT=CMDCFM,
		    TEXT='from program'),
 
    NP0HEL: $NOISE (NEXT=CMDHLP,
		    TEXT='with subject name'),
 
    NP0INC: $NOISE (NEXT=CMDCFM,
		    TEXT='the patch'),
 
    NP0INS: $NOISE (NEXT=CMDIPL,
		    TEXT='product name'),
 
    NP0RES: $NOISE (NEXT=CMDIPL,
		    TEXT='product name'),
 
    NP0RET: $NOISE (NEXT=CMDCFM,
		    TEXT='patch entries for all SELECTEd products'),

    NP0SEL: $NOISE (NEXT=CMDMPL,
		    TEXT='product name'),
 
    NP0SET: $NOISE (NEXT=CMDIPL,
		    TEXT='product name'),
 
    NP0STA: $NOISE (NEXT=CMDIPL,
		    TEXT='about product name'),
 
    NP0SUM: $NOISE (NEXT=CMDIPL,
		    TEXT='of the patches to product name') ;
ROUTINE APEX :NOVALUE =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!
!--
 
    BEGIN
 
    BIND
	module_name = %SIXBIT 'PEP',		!Our name for GLXLIB
	prompt = CH$ASCIZ(cr_lf,'PEP>') ;	!Command prompt string
    LOCAL
	address,
	cmd_tree,
	error,
	len,
	n,
	product:	REF PRODUCT$$,
	value ;

!
! Do preliminary initialization for object time system.
!
    $A$INIT() ;				!Initialize APEX
    $PRINIT(module_name) ;		!Initialize GALAXY library
!
!   See if we have already initialized; if so,  force  user  to
!   GET  new  copy  of  program.   (This is a hack, but it will
!   prevent BPN and other GLXLIB stopcodes.  A better  solution
!   will go into PEP version 2.)
!
    IF .start_flag
    THEN
	BEGIN
	TTY((cr_lf,'?Type GET SYS:PEP before typing START')) ;
	RETURN false
	END ;

    start_flag = true ;

    TTY(('[PEP version '),FMT_VER(.JBVER),(']',cr_lf)) ;

!
! Pick up the logical definition for PAT:
!  If it is not defined, we need to ask user;
!
    IF $GET$LND(ln_pat,address,error)
    THEN
	BEGIN
	lnd_pat = COPY_STR(.address) ;
	TTY(('['),ln_pat,(': (autopatching directory) defined as '),
	  .lnd_pat,(']')) ;
	END
    ELSE
	BEGIN
	SET_LN(S('What is the autopatching directory? '),
	  ln_pat,lnd_pat,lnd_pat_def) ;
	TTY(('  '),ln_pat,(': defined as '),.lnd_pat) ;
	END ;

    TTY((cr_lf,'[Initializing ...]')) ;
 
!
! Read database file if it is around
!
    IF SCK_FILE(db_file)
    THEN
	IF NOT DB_READ(db_file)
	THEN
	    RETURN $ERROR(C$CRC,*,FMT_FILE(db_file)) ;
!
! Build the master product definition list (MP_LIST)
!  If MP_LIST already exists, it will be augmented with
!  any new products.
!
    CK_FILE(mpd_file) ;
    IF NOT READ_FILE(mpd_file,pdfini,build_mp_list,mp_error)
    THEN
	RETURN $ERROR(C$CBM,*,FMT_FILE(mpd_file)) ;

    mast_pat_list = GET_TABLE(pat_list_sz) ;	! Master patch list
    pat_list = GET_TABLE(pat_list_sz) ;		! Selected patch list
    TTY_OK ;

    IF .OBSOLETE_PRODUCT_FLAG           ![113]
    THEN                                ![113]
        CHECKPOINT(db_file);            ![113]

![064]
!  Read utility update file if its around
!
    IF SCK_FILE(upd_utl_file)		![064] if the file is there
    THEN				![064]
	BEGIN				![064]
	TTY((cr_lf,
	'[Updating utility file information for all SELECTed products]')) ; ![064]
	IF READ_FILE(upd_utl_file,updini,utl_update,mp_error)	![064]
	THEN				![064]
	    BEGIN			![064]
	    CHECKPOINT(db_file) ;	![064] save the changes
	    R_REL(upd_utl_file) ;	![064] close and delete the file
	    DELETE(upd_utl_file) ;	![064]
	    END				![064]
	ELSE				![064]
	    RETURN $ERROR(C$CUU,*,FMT_FILE(upd_utl_file))	![064]
	END ;				![064]

    IF .ip_list[TBL_ACTUAL_ENTRIES] EQL 0
    THEN
	BEGIN
	TTY((cr_lf,
'Now use the SELECT command to define the autopatchable products.')) ;
	END
    ELSE
	BEGIN
	IF NOT BLD_MAST_PAT_LIST(ip_list,.mast_pat_list)
	THEN
	    RETURN $ERROR(C$CBL,*) ;
	IF NOT BLD_PAT_LIST(ip_list,.pat_list)
	THEN
	    RETURN $ERROR(C$CBL,*) ;

	n = 0 ;
	value = false ;
	WHILE GET_VALUE((n=.n+1),ip_list,product) EQL true DO
	    BEGIN
	    CK_DATATYPE(product,PRODUCT) ;
	    IF CK_BATCH(.product)
	    THEN
		value = true ;
	    END ;
	IF .value
	THEN
	    CHECKPOINT(db_file) ;
	END ;
!
! Main processing loop
!
    DO
	BEGIN
	IF .ip_list[TBL_ACTUAL_ENTRIES] EQL 0
	THEN
	    cmd_tree = cmdin0
	ELSE
	    cmd_tree = cmdin1 ;
	GET_COMMAND(prompt,0,.cmd_tree,command_dispatch)
	END
    UNTIL .exit_flag EQL true ;
 
    END ;				!End of APEX
 
ROUTINE COMMAND_DISPATCH =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   This is the command processing routine for  APEX  commands.
!   It  picks up the values stored during the parsing.  In most
!   cases it then  dispatches  to  another  routine  where  the
!   actual  processing  is  initiated.   When  this  routine is
!   invoked, the parser should have ensured  that  the  command
!   syntax is correct.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!   Command parsing  and  P$SETUP  processing  must  have  been
!   completed successfully.
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if a dispatch can't be made for this command.
!
! SIDE EFFECTS:
!
!   Any processing associated with a command is performed.
!
!--
 
    BEGIN
 
    MACRO
	DISPATCH (ROUTINE_NAME,LIST) =
	IF .type EQL $CMKEY
	THEN
	    ROUTINE_NAME(.code)
	ELSE
	    BEGIN
	    n = 0 ;
	    WHILE GET_VALUE((n=.n+1),LIST,code) EQL true DO
		ROUTINE_NAME(.code)
	    END% ;

 
    LOCAL
	code,
	command,
	n,
	type ;
    $TRACE('Beginning','COMMAND_DISPATCH') ;
 
    IF NOT $PRKEY(type,command) THEN RETURN false ;
    cur_command = .command ;	![101]
    SELECTONE .command OF
	SET
	[$$AUTOPATCH, $$BUILD, $$DESELECT, $$EXCLUDE, $$HELP,
	 $$INCLUDE, $$INSTALL, $$RESTORE, $$SELECT, $$SETUP, 
	 $$INFORMATION, $$STATUS, $$SUMMARY]:			! [112] >$$info
 
	    BEGIN
	    $PRKEY(type,code) ;
	    SELECTONE .command OF
		SET
		[$$AUTOPATCH]:
![101] ADD CHECKPOINT
		    BEGIN
		    IF RETRIEVE()
		    THEN
			BEGIN
			  DISPATCH(AUTOPATCH,IP_LIST) ;
		          CHECKPOINT(db_file)  ;
			END;
		    true
		    END ;
 
		[$$BUILD]:	( DISPATCH(BUILD,IP_LIST) ; true ) ;
 
		[$$DESELECT]:	( DISPATCH(DESELECT,IP_LIST) ; true ) ;
 
		[$$EXCLUDE]:	true ;
 
		[$$HELP]:	( HELP(.code) ; true ) ;
 
		[$$INCLUDE]:	true ;
 
		[$$INFORMATION]:( DISPATCH(INFORM,IP_LIST) ; true ) ; ! [112]

		[$$INSTALL]:	( DISPATCH(INSTALL,IP_LIST) ; true ) ;
 
		[$$RESTORE]:	( DISPATCH(RESTORE,IP_LIST) ; true ) ;
 
		[$$SELECT]:	( DISPATCH(SELECT_,MP_LIST) ; true ) ;
 
		[$$SETUP]:	( DISPATCH(SETUP,IP_LIST) ; true ) ;
 
		[$$STATUS]:	( DISPATCH(STATUS,IP_LIST) ; true ) ;

		[$$SUMMARY]:	( DISPATCH(SUMMARY,IP_LIST) ; true ) ;
 
		[OTHERWISE]:	false ;
		TES
	    END ;
 
	[$$EXIT]:	exit_flag = true ;
 
	[$$RETRIEVE]:	( RETRIEVE() ; true ) ;
 
	[OTHERWISE]:	false ;
	TES
    END ;				 !End of COMMAND_DISPATCH
 
 
ROUTINE AUTOPATCH(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to "autopatch" a specific product.  The  product  must
!   be  one  of the installation autopatchable products.  (That
!   is, it was previously  SELECTed).   This  routine  performs
!   SETUP  processing  as  well  as  BUILD  processing  for the
!   product.  RETRIEVE processing must be done prior to calling
!   this routine.
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$ to be autopatched
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','AUTOPATCH') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    TTY((cr_lf)) ;
    IF NOT SETUP(.product) THEN RETURN false ;
    TTY((cr_lf)) ;
    IF NOT BUILD(.product) THEN RETURN false ;
    RETURN true ;
 
    END ;				!End of AUTOPATCH
 
 
ROUTINE BUILD(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here  to  perform  BUILD processing for a specific product.
!   The product must be one of the  installation  autopatchable
!   products.  (That is, it was previously SELECTed).
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$ to be built
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--

 
    BEGIN

    LOCAL
	prompt,
	file:	REF FILE$$ ;
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','BUILD') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CBP,.product[PROD_NAME],*) ;
 
    IF .product[PROD_STATUS] NEQ prod_state_suc
    THEN
	RETURN $ERROR(F$PNS,.product[PROD_NAME],*,
		    S(' before the product can be built')) ;

    TTY((cr_lf,'[Checking files for building '),
      .product[PROD_NAME],(']')) ;

    IF BCHECK(.product)
    THEN
	TTY_OK
    ELSE
	RETURN $ERROR(F$CBP,.product[PROD_NAME],*) ;

!    prompt = $GEN_PROMPT(
!      S('Do you want PEP to SUBMIT the batch control file for '),
!      .product[PROD_NAME]) ;
!
!    IF GET_YES_NO(.prompt,S('YES'))
!    THEN
!	BEGIN
!	product[PROD_STATUS] = prod_state_bfq ;
!	END
!    ELSE
	BEGIN
	product[PROD_STATUS] = prod_state_rbb ;
	file = .product[PROD_CTL_FILE] ;
	OPEN_I(.file,36) ;
	TTY((cr_lf,'[To patch and rebuild '),.product[PROD_NAME],
	      (', issue the monitor command ...]',cr_lf,' SUBMIT '),
	      FMT_FILE(file),('/TIME:1:00:00/RESTART')) ;
	CLOSE(.file) ;
	END ;

![101] ADD TEST FOR CHECKPOINTING

     IF .cur_command NEQ $$AUTOPATCH
     THEN
	CHECKPOINT(db_file) ;
    RETURN true ;
 
    END;				!End of BUILD
 
 
ROUTINE DESELECT(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to DESELECT a specific product.  The product  must  be
!   one  of the installation autopatchable products.  (That is,
!   it was previously SELECTed).
!
!   DESELECTing a product will  remove  it  from  the  list  of
!   installation autopatchable products.
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$ to be DESELECTed
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--

    BEGIN				!Beginning routine DESELECT
 
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','DESELECT') ;

    CK_DATATYPE(product,PRODUCT) ;

    IF .product[PROD_PAT_LEVEL] GTR 0
    THEN
	BEGIN
	$ERROR(W$DDH,*,.product[PROD_NAME]) ;
	IF NOT GET_YES_NO(S('Do you want to continue? '),S('NO'))
	THEN
	    RETURN true ;
	END
    ELSE
	TTY((cr_lf)) ;

    IF T_DELETE(ip_list,.product[PROD_NAME])
    THEN
	BEGIN
	TTY(('['),.product[PROD_NAME],
	  (' removed from the list of SELECTed products]')) ;

	IF NOT BLD_MAST_PAT_LIST(ip_list,.mast_pat_list)
	THEN
	    RETURN $ERROR(C$CBL,*) ;

	IF NOT BLD_PAT_LIST(ip_list,.pat_list)
	THEN
	    RETURN $ERROR(C$CBL,*) ;

	CHECKPOINT(db_file) ;

	IF .ip_list[TBL_ACTUAL_ENTRIES] EQL 0
	THEN
	    TTY((cr_lf,cr_lf,
'Use the SELECT command to define the autopatchable products.')) ;
	true
	END
    ELSE
	false
 
    END;				!End of DESELECT
 
 
ROUTINE EXCLUDE(patch) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to mark a patch to be excluded from any future product
!   setups.   A patch can be EXCLUDEd only if it is selectable.
!   That is, it has  not  been	permanently  installed	in  the
!   library.   This  is  insured,  since the legal arguments to
!   the EXCLUDE command are only selectable patches.
!
! FORMAL PARAMETERS:
!
!	patch:
!		the address of the PATCH$$ to be excluded
!
! IMPLICIT INPUTS:
!
!	NONE
!
! IMPLICIT OUTPUTS:
!
!	NONE
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	NONE
!
! SIDE EFFECTS:
!
!	NONE
!
!--
 
    BEGIN
 
    MAP
	patch: REF PATCH$$ ;
 
    $TRACE('Beginning','EXCLUDE') ;
 
    RETURN true ;
 
    END;				!End of EXCLUDE
 
 
 
ROUTINE HELP(command) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to produce a help text message for a specific command.
!   This  routine dispatches to the GALAXY P$HELP routine which
!   handles all the details of reading the .HLP file.
!
! FORMAL PARAMETERS:
!
!	command:
!		address of string that is the key in .HLP file
!
! IMPLICIT INPUTS:
!
!	help_file:
!		the file descriptor (FILE$$) for PEP.HLP
!
! IMPLICIT OUTPUTS:
!
!	Error messages if:
!		no .HLP file
!		specified key not found
!		IO error
!
! ROUTINE VALUE:
!
!	Always returns TRUE.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    $TRACE('Beginning','HELP') ;
 
    $P$HELP(.help_file[FILE_FD],.command) ;
    true

    END;				!End of HELP
 
 
ROUTINE INCLUDE(patch) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here  to  mark a patch to be included in all future product
!   setups.  A patch can be INCLUDEd only if it is  selectable.
!   That  is,  it  has	not  been  permanently installed in the
!   library.  This is insured, since  the  legal  arguments  to
!   the INCLUDE command are only selectable patches.
!
!   If this operation changes the status code of the patch, the
!   master  patch file is updated.  A patch will be included in
!   a  product  setup  if  it  meets  any  of   the   following
!   requirements.
!
!	The current status is "applied"
!	The current status is "selected"
!	The current status is "retrieved" and this is a
!	 "mandatory" patch.
!
! FORMAL PARAMETERS:
!
!	patch:
!		the address of the PATCH$$ to be excluded
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	None
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    MAP
	patch: REF PATCH$$ ;
 
    $TRACE('Beginning','INCLUDE') ;
  
    RETURN true ;
  
    END; 				!End of INCLUDE
 
ROUTINE INFORM(product) =	! [112] This routine replaces the old Status
				! Routine.  It does the same thing...  
!++ 
! FUNCTIONAL DESCRIPTION: 
!  
!  Here to provide status and other information for a specific 
!  product.  The product must be one of the installation 
!  autopatchable products.  (That is, it was previously SELECTed).  
!  
!
! FORMAL PARAMETERS: 
!
!	product:
!		the address of the PRODUCT$$ 
!  
! IMPLICIT INPUTS: 
!
!	None 
!  
! IMPLICIT OUTPUTS: 
!
!	None 
!  
! ROUTINE VALUE: 
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.  
!  
! SIDE EFFECTS: 
!
!	None 
!  
!--
 
    BEGIN
 
    LOCAL
	error ;
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','INFORM') ;
 
    CK_DATATYPE(product,PRODUCT) ;

    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CPI,*,.product[PROD_NAME]) ;
 
    IF CK_BATCH(.product)
    THEN
	CHECKPOINT(db_file) ;

    STATUS(.PRODUCT);			! [112] The Status routine only 
					! displays the status info, and
                                        ! logical names...
    DISPLAY_FILES(.product) ;

![112]    TTY((cr_lf)) ;
![112]    TTY((cr_lf,' Logical names:')) ;

![112]    DISP_LN_DEFS() ;

    TTY((cr_lf,cr_lf)) ;		![063] Make the output look nice

    RETURN true ;
 
    END;				!End of INFORM
ROUTINE INSTALL(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to perform INSTALL processing for a specific  product.
!   The  product  must be one of the installation autopatchable
!   products.  (That is, it was previously SELECTed).
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$ to be installed
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    MAP
	product: REF PRODUCT$$ ;
    OWN
	msgext:
!	    INITIAL(S(cr_lf,' before the product can be installed')) ;
	    INITIAL(S(' before the product can be installed')) ;
 
    $TRACE('Beginning','INSTALL') ;

    CK_DATATYPE(product,PRODUCT) ;
    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CIP,.product[PROD_NAME],*) ;
 
    IF CK_BATCH(.product)
    THEN
	CHECKPOINT(db_file) ;
 
    SELECT .product[PROD_STATUS] OF
	SET
	[prod_state_inc]:
	    BEGIN
	    TTY((cr_lf,'['),.product[PROD_NAME],
		(' is already INSTALLed]')) ;
	    RETURN $ERROR(F$PNS,.product[PROD_NAME],*,
		      S(' and rebuilt'),.msgext,S(' again')) ;
	    END ;

	[prod_state_bjf]:  ( $ERROR(W$BJF,*,.product[PROD_NAME]) ) ;

	[prod_state_dis, prod_state_psc,
	 prod_state_rec, prod_state_bjf]:
	    RETURN $ERROR(F$PNS,.product[PROD_NAME],*,
		      S(' and rebuilt'),.msgext) ;

	[prod_state_bfq]:  ( $ERROR(W$JNF,.product[PROD_NAME],*) ) ;

	[prod_state_bfq, prod_state_suc, prod_state_rbb]:
	    RETURN $ERROR(F$PNB,.product[PROD_NAME],*,.msgext) ;

	[prod_state_rei]:
	    RETURN $ERROR(F$MBR,.product[PROD_NAME],*) ;

	[prod_state_ini]:  true ;

	[prod_state_bjs]:
	    BEGIN
	    TTY((cr_lf,'[Checking files for installing '),
	         .product[PROD_NAME],(']')) ;
	    IF ICHECK(.product)
	    THEN
		BEGIN
		TTY_OK ;
		INS_INIT_FILES(.product) ;
		product[PROD_STATUS] = prod_state_ini ;
		END
	    ELSE
		RETURN $ERROR(F$CIP,.product[PROD_NAME],*) ;
	    END ;
	TES ;
 
    TTY((cr_lf,'[Backing up files for '),.product[PROD_NAME],(']')) ;
    IF BACKUP(.product)
    THEN
	BEGIN
	CHECKPOINT(db_file) ;
	TTY((cr_lf,'[Installing new files for '),
	    .product[PROD_NAME],(']')) ;
	IF REPLACE(.product)
	THEN
	    BEGIN
	    product[PROD_STATUS] = prod_state_inc ;
	    product[PROD_INS_FLAG] = true ;
	    CHANGE_PS(.product,ps_ins,ps_per) ;
	    CHANGE_PS(.product,ps_app,ps_ins) ;
	    IF NOT BLD_PAT_LIST(ip_list,.pat_list)
	    THEN
		( $ERROR(W$CBL,*) ) ;
	    CHECKPOINT(db_file) ;
	    RETURN true ;
	    END
	ELSE
	    BEGIN
	    $ERROR(W$FNR,*,.product[PROD_NAME]) ;
	    END ;
	END
    ELSE
	BEGIN
	$ERROR(W$FNB,*,.product[PROD_NAME]) ;
	END ;

    RETURN $ERROR(F$INC,*,.product[PROD_NAME]) ;
 
    END;				!End of INSTALL
 
 
ROUTINE RESTORE(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here  to perform RESTORE processing for a specific product.
!   The product must be one of the  installation  autopatchable
!   products.  (That is, it was previously SELECTed).
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$ to be autopatched
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--

    BEGIN
 
    MAP
	product: REF PRODUCT$$ ;

    $TRACE('Beginning','RESTORE') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CRP,.product[PROD_NAME],*) ;
 
    SELECT .product[PROD_STATUS] OF
	SET
	[prod_state_rec]:
	    BEGIN
	    TTY((cr_lf,'['),.product[PROD_NAME],
		(' has already been RESTOREd]')) ;
	    RETURN $ERROR(F$CRP,.product[PROD_NAME],*) ;
	    END ;

	[prod_state_dis, prod_state_suc, prod_state_psc,
	 prod_state_bjs, prod_state_bjf]:
	    BEGIN
	    IF .product[PROD_INS_FLAG]
	    THEN
		true
	    ELSE
		RETURN $ERROR(F$PNI,.product[PROD_NAME],*) ;
	    END ;

	[prod_state_bfq, prod_state_rbb]:
	    BEGIN
	    IF .product[PROD_INS_FLAG]
	    THEN
		RETURN $ERROR(F$CRP,.product[PROD_NAME],*,
		   S(' until the batch job completes',
		      cr_lf,' or a new SETUP is done'))
	    ELSE
		RETURN $ERROR(F$PNI,.product[PROD_NAME],*) ;
	    END ;

	[prod_state_ini]:
	    RETURN $ERROR(F$MBI,.product[PROD_NAME],*) ;

	[prod_state_rei]:  true ;

	[prod_state_dis, prod_state_suc, prod_state_psc,
	 prod_state_bjs, prod_state_bjf, prod_state_inc]:
	    BEGIN
	    TTY((cr_lf,'[Checking files for restoring '),
	         .product[PROD_NAME],(']')) ;
	    IF RCHECK(.product)
	    THEN
		BEGIN
		TTY_OK ;
		RES_INIT_FILES(.product) ;
		product[PROD_STATUS] = prod_state_rei ;
		CHECKPOINT(db_file) ;
		END
	    ELSE
		RETURN $ERROR(F$CRP,.product[PROD_NAME],*) ;
	    END ;
	TES ;
 
    TTY((cr_lf,'[Restoring files for '),.product[PROD_NAME],(']')) ;

    IF REVERT(.product)
    THEN
	BEGIN
	product[PROD_STATUS] = prod_state_rec ;
	CHANGE_PS(.product,ps_app,ps_sel) ;
	CHANGE_PS(.product,ps_ins,ps_app) ;
	IF NOT BLD_PAT_LIST(ip_list,.pat_list)
	THEN
	    ( $ERROR(W$CBL,*) ) ;
	CHECKPOINT(db_file) ;
	RETURN true ;
	END
    ELSE
	RETURN $ERROR(F$RNC,*,.product[PROD_NAME]) ;

    END;				!End of RESTORE
 
ROUTINE RETRIEVE =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to retrieve new patch files and enter the  patches  in
!   the  directory.   All  new	patches  for  any  installation
!   autopatchable  product  will  be  added   to   the	 master
!   directory.	If a patch already exists in the directory, the
!   new patch will NOT supersede the current patch.
!
!   Patch information will be retrieved from patch tape  n  for
!   all  products  that  have  previously been SELECTed and are
!   currently at patch level n-1.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN				!Beginning routine RETRIEVE
 
    MACRO
	READPF(f) =
	    READ_FILE(f,patini,pat_build,pat_error) % ;

    LOCAL
	dir_found,
	file:		REF FILE$$,
	product:	REF PRODUCT$$,
	n,
	tape_num ;

    $TRACE('Beginning','RETRIEVE') ;

    dir_found = false ;
    tape_num = 0 ;
    UNTIL GET_PAT_DIR((tape_num=.tape_num+1),file) EQL false DO
	BEGIN
	IF SCK_FILE(.file)
	THEN
	    BEGIN
	    dir_found = true ;
	    TTY((cr_lf,'[Processing information from patch tape '),
		 FMT_NUM(.tape_num),(']')) ;
	    IF NOT BLD_PROD_LIST(ip_list,spr_list,.tape_num-1)
	    THEN
		RETURN $ERROR(C$CCR,*) ;
	    IF .spr_list[TBL_ACTUAL_ENTRIES] GTR 0
	    THEN
		BEGIN
		TTY((cr_lf,'[Reading patch directory file]')) ;
		IF READPF(.file)
		THEN
		    BEGIN
		    TTY_OK ;
		    n = 0 ;
		    UNTIL GET_VALUE((n=.n+1),spr_list,product) EQL false
		    DO
			BEGIN
			product[PROD_PAT_LEVEL] = .tape_num ;
			TTY((cr_lf,'[')) ;
![103]			TTY_PAT_COUNT(.product[PROD_PAT_COUNT]) ;
			IF .product[PROD_PAT_COUNT] EQL 0	![103]
			   THEN  TTY(('No p'))			![103]
			   ELSE  TTY(('P'));
			TTY(('atches retrieved for '),		![103]
			  .product[PROD_NAME],(']')) ;
			END
		    END
		ELSE
		    RETURN $ERROR(C$CRD,*,FMT_FILE(file)) ;
		END
	    ELSE
		TTY((cr_lf,
'[Patches for all SELECTed products already processed from this tape]')
		) ;
	    TTY((cr_lf)) ;
	    END
	END ;
 
    IF .dir_found
    THEN
	BEGIN
	IF NOT BLD_PAT_LIST(ip_list,.pat_list)
	THEN
	    $ERROR(W$CBL,*) ;
	CHECKPOINT(db_file) ;
	END
    ELSE
	$ERROR(W$NDF,*,.lnd_pat) ;
 
    RETURN true ;

    END;				!End of RETRIEVE
 
 
ROUTINE SELECT_(product_name) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here  to  SELECT  a  product for autopatching.  The product
!   must be defined in the master product definition  file  (an
!   element of MP_LIST).  Selection processing will verify that
!   the necessary components of the product are  present.   The
!   product  is  then  added  to the installation autopatchable
!   product list.  Once a product has been added to IP_LIST, it
!   will not have to be SELECTed again.
!
! FORMAL PARAMETERS:
!
!	PRODUCT_NAME:
!		the address of the string specifying the product
!		 to be SELECTed
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if product cannot be SELECTed for autopatching.
!
! SIDE EFFECTS:
!
!	None
!
!--

    BEGIN				!Beginning routine SELECT_
 
    MACRO
	READPRF(f) =
	    READ_FILE(f,spdini,sel_build,sel_error) % ;

    LOCAL
	value,
	prompt,
	product_pdf:	REF FILE$$,			![061]
	product:	REF PRODUCT$$ ;
    OWN
	msgext:
	  INITIAL(S(cr_lf,
    ' (If you need to SELECT this product again, first DESELECT it)')) ;

    $TRACE('Beginning','SELECT') ;
 
    IF T_LOOKUP(ip_list,.product_name,product)
    THEN
	RETURN $ERROR(F$PAS,.product_name,*,.msgext) ;

![072] Get defintion of PAT:

    prompt = $GEN_PROMPT(S('What is the patching directory for '),	![072]
		.product_name) ;					![072]
    SET_LN(.prompt,ln_pat,lnd_pat,lnd_pat_def) ;			![072]
    TTY(('  '),ln_pat,(': defined as '),.lnd_pat) ;			![072]

    prompt = $GEN_PROMPT(S('What is the distribution directory for '),
		.product_name) ;
    DO
	BEGIN
        value = true ;
	SET_LN(.prompt,ln_dis,lnd_dis,lnd_dis_def) ;
	IF EQL_STR(.lnd_dis,.lnd_pat)
	THEN
	  value = $ERROR(W$DAD,.lnd_dis,*,S('autopatching directory')) ;
	END
    UNTIL .value ;
    TTY(('  '),ln_dis,(': defined as '),.lnd_dis) ;

    prompt = $GEN_PROMPT(S('What is the backup directory for '),
		.product_name) ;
    DO
	BEGIN
	value = true ;
	SET_LN(.prompt,ln_bak,lnd_bak,lnd_bak_def) ;
	IF EQL_STR(.lnd_bak,.lnd_pat)
	THEN
	  value = $ERROR(W$DAD,.lnd_bak,*,S('autopatching directory')) ;
	IF EQL_STR(.lnd_bak,.lnd_dis)
	THEN
	  value = $ERROR(W$DAD,.lnd_bak,*,S('distribution directory')) ;
	END
    UNTIL .value ;
    TTY(('  '),ln_bak,(': defined as '),.lnd_bak) ;

    prompt = $GEN_PROMPT(S('What is the installation directory for '),
		.product_name) ;
    DO
	BEGIN
	value = true ;
	SET_LN(.prompt,ln_ins,lnd_ins,lnd_ins_def) ;
	IF EQL_STR(.lnd_ins,.lnd_pat)
	THEN
	  value = $ERROR(W$DAD,.lnd_ins,*,S('autopatching directory')) ;
	IF EQL_STR(.lnd_ins,.lnd_dis)
	THEN
	  value = $ERROR(W$DAD,.lnd_ins,*,S('distribution directory')) ;
	IF EQL_STR(.lnd_ins,.lnd_bak)
	THEN
	  value = $ERROR(W$DAD,.lnd_ins,*,S('backup directory')) ;
	END
    UNTIL .value ;
    TTY(('  '),ln_ins,(': defined as '),.lnd_ins) ;

    PURGE_TABLE(spr_list) ;
    T_ENTER(spr_list,.product_name,.product_name) ;

    TTY((cr_lf,'[Checking components and files for '),
      .product_name,(']')) ;

!**![061] Get the name of the product's PDF file.
    IF NOT T_LOOKUP(PDF_NAMES,.product_name,product_pdf)	![061]
    THEN							![061]
	$ERROR(C$SSF,*,.product_name) ;				![061]

    IF NOT READPRF(.product_pdf)				![061]
    THEN
	RETURN $ERROR(F$CRE,*,FMT_FILE(product_pdf)) ;		![061]

    IF T_LOOKUP(spr_list,.product_name,product)
    THEN
	BEGIN
	product[PROD_BAK_LND] = .lnd_bak ;
	product[PROD_DIS_LND] = .lnd_dis ;
	product[PROD_INS_LND] = .lnd_ins ;
	product[PROD_PAT_LND] = .lnd_pat ;
	IF NOT DEF_LN(.product)
	THEN
	    RETURN $ERROR(F$CSP,.product_name,*) ;
	IF NOT PS_INIT(.product)
	THEN
	    RETURN $ERROR(F$CSP,.product_name,*) ;
	IF SCHECK(.product)
	THEN
	    BEGIN
	    TTY_OK ;
	    IF T_ENTER(ip_list,.product[PROD_NAME],.product)
	    THEN
		BEGIN
		TTY((cr_lf,'['),.product[PROD_NAME],
		    (' SELECTed for autopatching]')) ;
		CHECKPOINT(db_file) ;
		RETURN true
		END
	    END
	ELSE
	    false
	END
    ELSE
	$ERROR(C$SSF,*,.product_name) ;

    $ERROR(F$CSP,.product_name,*)
 
    END;				!End of SELECT_
 
 
ROUTINE SETUP(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here  to setup a product for a patch and rebuild operation.
!   The product must be one of the  installation  autopatchable
!   products.  (This is, it was previously SELECTed.)
!
!   First  all	the patches that will be applied to the product
!   libraries are given a "selected" status.  A patch  will  be
!   selected if:
!
!	The current status is "applied"
!	The current status is "selected"
!	The current status is "retrieved" and this is a
!	  "mandatory" patch.
!
!   Then an indirect file is generated to  apply  the  selected
!   patches.
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$ to be setup
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!   The patch count field of the product descriptor is  set  to
!   the number of selected patches.
!
!   A list of selected patches for this product is built.
!
!   The  indirect  files  required  for  applying  the selected
!   patches to the product libraries are generated.
!
!   If a batch communication file exists for this  product,  it
!   is deleted.
!
!--
 
    BEGIN				!Beginning routine SETUP
 
    MAP
	product: REF PRODUCT$$ ;
    OWN
	msgsib:	    INITIAL(S(cr_lf,
	 ' (If you have already submitted this batch job, cancel it',
	 cr_lf,
	 '  or wait until it completes, before you proceed)'
	 )) ;

    $TRACE('Beginning','SETUP') ;
 
    CK_DATATYPE(product,PRODUCT) ;
    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CCS,*,.product[PROD_NAME]) ;
 
    SELECT .product[PROD_STATUS] OF
	SET
	[prod_state_dis, prod_state_suc, prod_state_psc,
	 prod_state_bjf, prod_state_bjs, prod_state_inc,
	 prod_state_rec]:
	    true ;

	[prod_state_ini]:
	    RETURN $ERROR(F$MBI,.product[PROD_NAME],*) ;

	[prod_state_rei]:
	    RETURN $ERROR(F$MBR,.product[PROD_NAME],*) ;

	[prod_state_rbb, prod_state_bfq]:
	    BEGIN
	    $ERROR(W$SIB,*,.product[PROD_NAME],.msgsib) ;
	    IF NOT GET_YES_NO(S('Do you want to continue? '),S('NO'))
	    THEN
		RETURN false ;
	    END ;
	TES ;

    IF SCK_FILE(.product[PROD_BCF_FILE])
    THEN
	DELETE(.product[PROD_BCF_FILE]) ;

    TTY((cr_lf,'[Setting up '),
	.product[PROD_NAME],(' for patch and rebuild]')) ;

    product[PROD_PAT_COUNT] = 0 ;
    IF NOT SEL_PAT(.product)
    THEN
	RETURN $ERROR(F$CCS,*,.product[PROD_NAME]) ;

!**;[062] Comment out 3 lines near the end of routine SETUP.
!**;[062] PROD_PAT_COUNT is an 8 bit field, and overflows too easily.
!**;[062] Fixing this properly will require changing the format of
!**;[062]  the checkpoint files in the field.
%( [062]
    TTY((cr_lf,'[')) ;
    TTY_PAT_COUNT(.product[PROD_PAT_COUNT]) ;
    TTY((' will be applied to '),.product[PROD_NAME],(']')) ;
 [062] )%

    IF NOT GENCCL(.product)
    THEN
	RETURN $ERROR(F$CCS,*,.product[PROD_NAME]) ;

    product[PROD_STATUS] = prod_state_suc ;
![101] ADD TEST FOR CHECKPOINTING

     IF .cur_command NEQ $$AUTOPATCH
     THEN
	CHECKPOINT(db_file) ;
    RETURN true ;
 
    END;				!End of SETUP
 
 
%(  This routine commented out in edit 112...
ROUTINE STATUS(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here  to provide status information for a specific product.
!   The product must be one of the  installation  autopatchable
!   products.  (That is, it was previously SELECTed).
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    LOCAL
	error ;
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','STATUS') ;
 
    CK_DATATYPE(product,PRODUCT) ;

    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CPI,*,.product[PROD_NAME]) ;
 
    IF CK_BATCH(.product)
    THEN
	CHECKPOINT(db_file) ;

    TTY((cr_lf),.product[PROD_NAME]) ;
    SELECTONE .product[PROD_STATUS] of
	SET
	[prod_state_dis]: TTY((' is ready to be SETUP for patch and rebuild')) ;

	[prod_state_suc]: TTY((' is setup and ready for BUILD')) ;

	[prod_state_rbb]: TTY((' is ready to be built via batch control file')) ;

	[prod_state_bfq]: TTY((' is being built (batch job was submitted)')) ;

	[prod_state_bjs]: TTY((' is ready to be INSTALLed ')) ;

	[prod_state_bjf]: TTY((' could not be rebuilt (batch job failed)')) ;

	[prod_state_ini]:
	    TTY((' was not successfully INSTALLed')) ;

	[prod_state_inc]: TTY((' was successfully INSTALLed')) ;

	[prod_state_rei]:
	    TTY((' was not successfully RESTOREd')) ;

	[prod_state_rec]: TTY((' was successfully RESTOREd')) ;

	[OTHERWISE]: TTY((' has unknown status')) ;
	TES ;

    IF .product[PROD_PAT_LEVEL] GTR 0
    THEN
	TTY((cr_lf,' Patches retrieved through patch tape '),
	     FMT_NUM(.product[PROD_PAT_LEVEL]))
    ELSE
	TTY((cr_lf,' No patches have been retrieved')) ;

    DISPLAY_FILES(.product) ;

    TTY((cr_lf)) ;
    TTY((cr_lf,' Logical names:')) ;

    DISP_LN_DEFS() ;

    TTY((cr_lf,cr_lf)) ;		![063] Make the output look nice

    RETURN true ;
 
    END;				!End of STATUS
The previous routine was commented out in edit 112 )%   
 
ROUTINE STATUS(product) = 	! [112] This routine was rewritten to 
				! provide status information only... 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to provide status information (only) for a specific product.
!   The product must be one of the  installation  autopatchable
!   products.  (That is, it was previously SELECTed).
!
! FORMAL PARAMETERS:
!
!	product:
!		the address of the PRODUCT$$
!
! IMPLICIT INPUTS:
!
!	None
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    LOCAL
	error ;
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','STATUS') ;
 
    CK_DATATYPE(product,PRODUCT) ;

    IF NOT DEF_LN(.product)
    THEN
	RETURN $ERROR(F$CPI,*,.product[PROD_NAME]) ;
 
    TTY((cr_lf),.product[PROD_NAME]) ;
    SELECTONE .product[PROD_STATUS] of
	SET
	[prod_state_dis]: TTY((' is ready to be SETUP for patch and rebuild')) ;

	[prod_state_suc]: TTY((' is setup and ready for BUILD')) ;

	[prod_state_rbb]: TTY((' is ready to be built via batch control file')) ;

	[prod_state_bfq]: TTY((' is being built (batch job was submitted)')) ;

	[prod_state_bjs]: TTY((' is ready to be INSTALLed ')) ;

	[prod_state_bjf]: TTY((' could not be rebuilt (batch job failed)')) ;

	[prod_state_ini]:
	    TTY((' was not successfully INSTALLed')) ;

	[prod_state_inc]: TTY((' was successfully INSTALLed')) ;

	[prod_state_rei]:
	    TTY((' was not successfully RESTOREd')) ;

	[prod_state_rec]: TTY((' was successfully RESTOREd')) ;

	[OTHERWISE]: TTY((' has unknown status')) ;
	TES ;


    IF .product[PROD_PAT_LEVEL] GTR 0
    THEN
	TTY((cr_lf,' Patches retrieved through patch tape '),
	     FMT_NUM(.product[PROD_PAT_LEVEL]))
    ELSE
	TTY((cr_lf,' No patches have been retrieved')) ;

    TTY((cr_lf)) ;
    TTY((cr_lf,' Logical names:')) ;

    DISP_LN_DEFS() ;

    TTY((cr_lf,cr_lf)) ;		![063] Make the output look nice

    RETURN true ;
 
    END;				!End of STATUS
 
 
ROUTINE SUMMARY(product) =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Here to provide summary information for a specific product.
!   The  product  must be one of the installation autopatchable
!   products.  (That is, it was previously SELECTed).
!
! 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 not completed successfully.
!
! SIDE EFFECTS:
!
!	None
!
!--
 
    BEGIN
 
    MAP
	product: REF PRODUCT$$ ;
 
    $TRACE('Beginning','SUMMARY') ;
    CK_DATATYPE(product,PRODUCT) ;

    DISP_PAT_LIST(.product) ;

    RETURN true ;
 
    END;				!End of SUMMARY
ROUTINE BUILD_MP_LIST =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Command processing routine  for  product  description  file
!   entries.  From all "product" entries in the data file, this
!   routine builds the master product list.  When this  routine
!   is invoked, the parser should have ensured that the command
!   syntax of the entry is correct.
!
![061] It also builds PDF_NAMES, which is a table of pointers to
![061] PDF file names for each product.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!   Command parsing  and  P$SETUP  processing  must  have  been
!   completed successfully.
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if product can't be added to list
!
! SIDE EFFECTS:
!
!   Builds MP_LIST.
!
!--
 
    BEGIN				!Beginning ROUTINE BUILD_MP_LIST

    LOCAL
	a,
	c,
	command,
	name_adr,
	fd_adr,			![061]
	t,			![061]
	type ;

    OWN
	file:	REF FILE$$ ;	![061]

    $TRACE('Beginning','BUILD_MP_LIST') ;
 
    IF NOT $PRKEY(type,command) THEN RETURN false ;
    SELECTONE .command OF
	SET
![061]	[$$COMPONENT]: 	true ;
 
![061]	[$$END]:	true ;
 
![061]	[$$FILE]:	true ;
 
![061]	[$$PRODUCT]:	true ;

	[$$INITIALIZE]:					![061]
	    BEGIN
	    $PM($PRFLD(type,a,c),name_adr) ;
	    IF T_LOOKUP(MP_LIST,.name_adr,a)
	    THEN
		true
	    ELSE
		T_ENTER(MP_LIST,.name_adr,.name_adr) ;
![061] Get the PDF filename.
	    $PRCMA(t) ;					![061] comma first
	    $PMFIL(fd_adr) ;				![061] file spec
	    file = GET_FILE ;				![061]
	    file[FILE_FD] = .fd_adr ;			![061] save filename
	    T_ENTER(PDF_NAMES,.name_adr,.file)		![061]
	    END ;
 
        [$$OBSOLETE]:                                   ![113]
            BEGIN                                       ![113]
            $PM($PRFLD(type,a,c),name_adr);             ![113]
![120]      IF T_LOOKUP(MP_LIST,.name_adr,a)            ![113]
            IF T_LOOKUP(MP_LIST,.name_adr,a) EQL 1      ![120]Force EXACT match
            THEN                                        ![113]
                BEGIN                                   ![113]
![120]          IF T_LOOKUP(IP_LIST,.name_adr,a)        ![113]
                IF T_LOOKUP(IP_LIST,.name_adr,a) EQL 1  ![120]Force EXACT match
                THEN                                    ![113]
                    tty((cr_lf,cr_lf,'['),              ![113]
                        .name_adr,(' is now obsolete.',cr_lf,
                        ' Edits are no longer being delivered.',cr_lf,
                        ' You should DESELECT this product.]'));
                                                        ![113]
                T_DELETE(MP_LIST,.name_adr);            ![113]
                OBSOLETE_PRODUCT_FLAG = true            ![113]
                END;                                    ![113]
            RETURN true                                 ![113]
            END;                                        ![113]

	[OTHERWISE]:	false ;
	TES
    END ;				 !End of BUILD_MP_LIST
ROUTINE SEL_BUILD =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Command processing routine  for  product  description  file
!   entries.   This  routine  is  called  to  process  specific
!   entries in the product description file.  From the  product
!   description entries, the corresponding internal descriptors
!   are built.  WHEN THIS ROUTINE IS CALLED, SPR_LIST  CONTAINS
!   THE NAMES OF THE PRODUCTS TO BE SELECTED.  AFTER GENERATING
!   THE NECESSARY DESCRIPTORS  FOR  A  PRODUCT,  THE  ENTRY  IN
!   SPR_LIST IS UPDATED TO POINT TO THE PRODUCT DESCRIPTOR.
!
!   When  this  routine  is  invoked,  the  parser  should have
!   ensured that the command syntax of the entry is correct.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!   Command parsing  and  P$SETUP  processing  must  have  been
!   completed successfully.
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!   Builds internal data descriptors and UPDATES entry in SPR_LIST.
!
!--
 
    BEGIN				!Beginning ROUTINE SEL_BUILD

    LOCAL
	command,
	type ;
    OWN
	table:		REF TABLE$$ INITIAL(0),
	component:	REF COMPONENT$$,
	file:		REF FILE$$,
	tfile:		REF FILE$$,
	lib:		REF LIBRARY$$,
	product:	REF PRODUCT$$ ;

    $TRACE('Beginning','SEL_BUILD') ;
 
    IF NOT $PRKEY(type,command) THEN RETURN false ;
    SELECTONE .command OF
	SET
	[$$COMPONENT]:
	    IF NOT .sel_p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		LOCAL
		    a,
		    c,
		    code_adr,
		    name_adr,
		    t ;

		$PM($PRFLD(t,a,c),name_adr) ;	! Component name
		$PRCMA(t) ;			! Comma
		$PM($PRFLD(t,a,c),code_adr) ;	! Component code

		component = GET_component ;
		component[COMP_NAME] = .name_adr ;
		component[COMP_CODE] = .code_adr ;
		component[COMP_PROD] = .product ;
		IF NOT T_ENTER(.table,.code_adr,.component)
		THEN
		   RETURN $ERROR(C$CEC,*) ;
		T_ENTER(.product[PROD_COMP_LIST],.name_adr,.component)
		END ;

 
	[$$END]:
	    BEGIN
	    IF NOT .sel_p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		sel_p_flag = false ;
		true
	    END ;

	[$$FILE]:
	    IF NOT .sel_p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		MACRO INIT_FILE(f) =
		    BEGIN
		    f[FILE_FD]	= .fd_adr ;
		    f[FILE_EXP_CKSUM] = .exp_cksum ;
		    f[FILE_EXP_VER] = .exp_ver ;
		    f[FILE_ACT_CKSUM] = 0 ;
		    f[FILE_ACT_VER] = 0 ;
		    END % ;
		LOCAL
		    a,
		    c,
		    code_adr,
		    exp_cksum,
		    exp_ver,
		    fd_adr,
		    file_ins,
		    file_typ,
		    name_adr,
		    radix,
		    t ;

		$PM($PRFLD(t,a,c),name_adr) ;	! File identifier
		$PRCMA(t) ;			! Comma
		$PM($PRFLD(t,a,c),code_adr) ;	! Owner Code
		$PRCMA(t) ;			! Comma
		$PRKEY(t,file_ins) ;		! File instance
		$PRCMA(t) ;			! Comma
		$PRKEY(t,file_typ) ;		! File type
		$PRCMA(t) ;			! Comma
		$PRNUM(t,exp_cksum,radix) ;	! Checksum
		$PRCMA(t) ;			! Comma
		$PRNUM(t,exp_ver,radix) ;	! Version
		$PRCMA(t) ;			! Comma
		$PMFIL(fd_adr) ;		! File spec

		file = GET_FILE ;
		INIT_FILE(file) ;

		SELECTONE .file_typ OF
		    SET
		    [$$BCF]: ( product[PROD_BCF_FILE] = .file ; true ) ;

		    [$$BLD]:
			BEGIN
			IF T_LOOKUP(.table,.code_adr,component)
			THEN
			    component[COMP_BLD] = .file
			ELSE
			    RETURN $ERROR(F$SSF,*,.code_adr) ;
			true
			END ;

		    [$$CTL]: ( product[PROD_CTL_FILE] = .file ; true ) ;

		    [$$INP]:
			BEGIN
			IF T_LOOKUP(.table,.code_adr,component)
			THEN
			    T_ENTER
			     (.component[COMP_INP_LIST],.name_adr,.file)
			ELSE
			    $ERROR(F$SSF,*,.code_adr)
			END ;

		    [$$LIB]:
			BEGIN
			IF NOT
			 T_LOOKUP(.product[PROD_LIB_LIST],.name_adr,lib)
			THEN
			    BEGIN
			    lib = GET_LIBRARY ;
			    lib[LIB_NAME] = .name_adr ;
			    lib[LIB_PROD] = .product ;
			    T_ENTER
			      (.product[PROD_LIB_LIST],.name_adr,.lib) ;
			    END ;

			IF .lib[LIB_FILE] NEQA 0
			THEN
			    tfile = .lib[LIB_FILE]
			ELSE
			    BEGIN
			    tfile = GET_FILE ;
			    lib[LIB_FILE] = .tfile ;
			    END ;
			SELECTONE .file_ins OF
			    SET
			    [$$BAK]:
				tfile[FILE_BACKUP] = .file ;

			    [$$CUR]:
				BEGIN
			        INIT_FILE(tfile) ;
				$M_RMEM(file_sz,.file) ;
				END ;

			    [$$NEW]:
				tfile[FILE_NEWEST] = .file ;

			    [OTHERWISE]:
			        RETURN false ;
			    TES ;
			true
			END ;

		    [$$OUT]:
			BEGIN
			IF  NOT T_LOOKUP(.table,.code_adr,component)
			THEN
			    RETURN $ERROR(C$SSF,*,.code_adr) ;

			IF NOT T_LOOKUP
			  (.component[COMP_OUT_LIST],.name_adr,tfile)
			THEN
			    BEGIN
			    tfile = GET_FILE ;
			    T_ENTER(.component[COMP_OUT_LIST],
				    .name_adr,.tfile) ;
			    END ;

			SELECTONE .file_ins OF
			    SET
			    [$$BAK]:
				tfile[FILE_BACKUP] = .file ;

			    [$$CUR]:
				BEGIN
				INIT_FILE(tfile) ;
				$M_RMEM(file_sz,.file) ;
				END ;

			    [$$NEW]:
				tfile[FILE_NEWEST] = .file ;

			    [OTHERWISE]:
				RETURN false ;
			    TES ;
			true
			END ;
		    [$$PCF]: ( product[PROD_PCF_FILE] = .file ; true ) ;

		    [$$UTL]:
			T_ENTER
			  (.product[PROD_UTL_LIST],.name_adr,.file) ;

		    [OTHERWISE]:  false ;
		    TES
		END ;
 
	[$$PRODUCT]:
	    BEGIN
	    LOCAL
		a,
		c,
		code_adr,
		level_val,
		radix,
		status_val,
		name_adr,
		t ;

	    sel_p_flag = true ;
	    IF NOT DATATYPE(table)
	    THEN
		table = GET_TABLE(30) ;		! Symbol table
	    PURGE_TABLE(table) ;		! Purge symbol table

	    $PRKEY(t,name_adr) ;		! Product name
	    $PRCMA(t) ;				! Comma
	    $PM($PRFLD(t,a,c),code_adr) ;	! Product code
	    $PRCMA(t) ;				! Comma
	    $PRNUM(t,status_val,radix) ;	! Product status
	    $PRCMA(t) ;				! Comma
	    $PRNUM(t,level_val,radix) ;		! Patch level

	    product = GET_PRODUCT ;
	    product[PROD_NAME] = .name_adr ;
	    product[PROD_CODE] = .code_adr ;
	    product[PROD_STATUS] = .status_val ;
	    product[PROD_PAT_LEVEL] = .level_val ;

	    IF NOT T_ENTER(.table,.code_adr,.product)
	    THEN
		RETURN $ERROR(C$CEC,*) ;
	    T_DELETE(SPR_LIST,.name_adr) ;
	    T_ENTER(SPR_LIST,.name_adr,.product)

	    END ;
 
	[OTHERWISE]:	false ;
	TES

    END ;				 !End of SEL_BUILD
ROUTINE PAT_BUILD =
 
!++
! FUNCTIONAL DESCRIPTION:
!
!   Command   processing   routine  for  patch  directory  file
!   entries.  When this routine is invoked, the  parser  should
!   have  ensured  that  the  command  syntax  of  the entry is
!   correct.
!
!   This  routine  will  build  the  internal  patch  and  edit
!   descriptors from the data in the patch directory file being
!   processed.   Descriptors  will  only  be  built  for  those
!   products in SPR_LIST (specified product list).   A  product
!   will  be  in SPR_LIST if it has been SELECTed and its patch
!   level is one less than the number of the patch  tape  being
!   processed.   That  is,  all  previous patch directory files
!   have been processed for the product.  If  a  patch  already
!   has  a  descriptor,  this  routine  will  NOT supersede the
!   existing data structures.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!   Command parsing  and  P$SETUP  processing  must  have  been
!   completed successfully.
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!   Builds internal data descriptors.
!
!--
 
    BEGIN				!Beginning ROUTINE PAT_BUILD

!   Macro to generate an edit key for the patch edit list.  Key
!   consists  of edit number and library name so that duplicate
!   edit numbers can be applied to different libraries as  part
!   of the same patch.

    MACRO $GEN_EKEY =
	BEGIN
	LOCAL
	    aa,
	    l1,
	    l2 ;
	l1 = CH$LEN(.edit[EDIT_NAME]) ;
	l2 = CH$LEN(.lib[LIB_NAME]) ;
	$M_GMEM(((.l1+.l2+1-1)/5)+1,aa) ;
	CH$COPY(.l1,CH$PTR(.edit[EDIT_NAME]),
		 .l2,CH$PTR(.lib[LIB_NAME]),
		 0,
		 (.l1+.l2+1),CH$PTR(.aa) ) ;
	.aa
	END % ;

    LOCAL
	a,
	address,
	c,
	command,
	file_key,
	t,
	type,
	value ;
    OWN
	table:		REF TABLE$$ INITIAL(0),
	component:	REF COMPONENT$$,
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	tfile:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	product:	REF PRODUCT$$,
	p_flag:		INITIAL(false) ;	!Processing flag
    $TRACE('Beginning','PAT_BUILD') ;
 
    IF NOT $PRKEY(type,command) THEN RETURN false ;
    SELECTONE .command OF
	SET
!
!   Patch directory header entries
!
	[$$FORMAT]:  true ;

	[$$SYSTEM]:  true ;

	[$$TAPE]:
	    BEGIN
	    IF NOT DATATYPE(table)
	    THEN
		table = GET_TABLE(30) ;		! Symbol table
	    PURGE_TABLE(table) ;		! Purge symbol table
	    true
	    END ;

	[$$DATE]:  true ;

!
!   Patch entries
!

	[$$PATCH]:
	    BEGIN
	    $PM($PRTXT(t,a,c),address) ;

	    IF T_LOOKUP(.mast_pat_list,.address,patch)
	    THEN
		BEGIN
		p_flag = false ;	! Entry already there
		true
		END
	    ELSE
		BEGIN
		patch = GET_PATCH ;
		patch[PAT_NAME] = .address ;
		p_flag = true
		END
	    END ;

	[$$DESCRIPTION]:  true ;

	[$$SPR]:  true ;

	[$$CATEGORY]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PRKEY(t,value) ;
		patch[PAT_CATEGORY] = .value ;
		true
		END
	    END ;

	[$$REQUIRES]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PM($PRFLD(t,a,c),address) ;
		T_ENTER(.patch[PAT_RP_list],.address,0)	! needs more
		END
	    END ;

	[$$PRODUCT]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true ;		! Don't want to process this

	    $PM($PRFLD(t,a,c),address) ;

	    IF T_LOOKUP(spr_list,.address,product)
	    THEN
		BEGIN
		CK_DATATYPE(product,PRODUCT) ;
		p_flag = true ;
		product[PROD_PAT_COUNT] = .product[PROD_PAT_COUNT] + 1 ;
		patch[PAT_PROD] = .product ;
		T_ENTER(.product[PROD_PAT_LIST],
			.patch[PAT_NAME],.patch) ;
		T_ENTER(.mast_pat_list,.patch[PAT_NAME],.patch)
		END
	    ELSE
		BEGIN
		p_flag = false ;	! still need to deallocate patch
		true
		END
	    END ;

	[$$LIBRARY]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PM($PRFLD(t,a,c),address) ;

		IF T_LOOKUP(.product[PROD_LIB_LIST],.address,lib)
		THEN
		    true
		ELSE
		    $ERROR(W$UPL,.address,*,.product[PROD_NAME])
		END
	    END;

	[$$EDIT]:
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PM($PRFLD(t,a,c),address) ;

		edit = GET_EDIT ;
		edit[EDIT_NAME] = .address ;
		edit[EDIT_LIB] = .lib ;
		T_ENTER(.lib[LIB_EDIT_LIST],.address,.edit) ;
		T_ENTER(.patch[PAT_EDIT_LIST],$GEN_EKEY,.edit)
		END ;

	[$$MODULE]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PM($PRTXT(t,a,c),address) ;
		T_ENTER(.edit[EDIT_MOD_LIST],.address,.address)
		END
	    END ;

	[$$TYPE]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PRKEY(t,value) ;
		edit[EDIT_TYPE] = .value ;
		true
		END
	    END ;

	[$$FILE]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		$PMFIL(address) ;		! File spec

		tfile = GET_FILE ;
		tfile[FILE_FD] = .address ;
		address = (FMT_FILE(tfile)) ;
		IF NOT T_LOOKUP(.table,.address,file)
		THEN
		    BEGIN
		    file = .tfile ;
		    file_key = COPY_STR(.address) ;
		    T_ENTER(.table,.file_key,.file) ;
		    END ;
		edit[EDIT_FILE] = .file ;
		true
		END
	    END ;

	[$$ENDEDIT]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		RETURN true		! Don't want to process this
	    END ;

	[$$ENDPATCH]:
	    BEGIN
	    IF NOT .p_flag
	    THEN
		RETURN true		! Don't want to process this
	    ELSE
		BEGIN
		IF .patch[PAT_STATUS] EQL 0
		THEN
		    patch[PAT_STATUS] = ps_ret ;
		p_flag = false ;
		true
		END
	    END ;


	[OTHERWISE]:	false ;
	TES

    END ;				!End of PAT_BUILD
ROUTINE UTL_UPDATE =

!++
![064] Add this routine.
! FUNCTIONAL DESCRIPTION:
!
!   Command processing routine for utilities update file.
!
! FORMAL PARAMETERS:
!
!	None
!
! IMPLICIT INPUTS:
!
!   Command parsing  and  P$SETUP  processing  must  have  been
!   completed successfully.
!
! IMPLICIT OUTPUTS:
!
!	None
!
! ROUTINE VALUE:
!
!	Returns TRUE if no errors.
!	Returns FALSE if operation fails
!
! SIDE EFFECTS:
!
!   Updates FILE$$ descriptors for utility files.
!
!--
 
    BEGIN				![064] Beginning ROUTINE UTL_UPDATE

    LOCAL
	type,
	command ;

    OWN
	sel_flag,
	file:		REF FILE$$,
	product:	REF PRODUCT$$ ;

    $TRACE('Beginning','UTL_UPDATE') ;

    IF NOT $PRKEY(type,command) THEN RETURN false ;
    SELECTONE .command OF
	SET
	[$$PRODUCT]:
	    BEGIN
	    LOCAL
		t,
		a,
		c,
		name_adr ;

	    sel_flag = 0;

	    $PM($PRFLD(t,a,c),name_adr) ;	! Product name

	    IF T_LOOKUP(ip_list,.name_adr,product)
	    THEN
		sel_flag = name_adr ;
	    true
	    END ;

	[$$END]:
	    BEGIN
	    sel_flag = 0 ;
	    true
	    END ;

	[$$FILE]:
	    BEGIN
	    IF .sel_flag EQL 0
	    THEN
		RETURN true		! The current product is not selected
	    ELSE
		BEGIN
		LOCAL
		    file:		REF FILE$$,
		    t,
		    a,
		    c,
		    exp_cksum,
		    exp_ver,
		    fd_adr,
		    file_typ,
		    name_adr,
		    radix ;

		$PM($PRFLD(t,a,c),name_adr) ;	! File identifier
		$PRCMA(t) ;			! Comma
		$PRFLD(t,a,c) ;			! Owner Code
		$PRCMA(t) ;			! Comma
		$PRKEY(t,a) ;			! File instance
		$PRCMA(t) ;			! Comma
		$PRKEY(t,file_typ) ;		! File type
		$PRCMA(t) ;			! Comma
		$PRNUM(t,exp_cksum,radix) ;	! Checksum
		$PRCMA(t) ;			! Comma
		$PRNUM(t,exp_ver,radix) ;	! Version
		$PRCMA(t) ;			! Comma
		$PMFIL(fd_adr) ;		! File spec

		IF .file_typ EQL $$UTL
		THEN
		    BEGIN
		    IF T_LOOKUP(.product[PROD_UTL_LIST],.name_adr,file)
		    THEN
			BEGIN
			file[FILE_EXP_CKSUM] = .exp_cksum ;
			file[FILE_EXP_VER] = .exp_ver ;
			file[FILE_FD] = .fd_adr
			END
		    ELSE
			!This utility file is not in the PDB for this product.
			!It could be added at this point, if desired.
		        RETURN false		! this utl not in PDB
		    END
		ELSE
		    RETURN false		! not a utl file
		END ;
	    END ;
	TES ;
    true
    END ;				![064] End of UTL_UPDATE

 
ROUTINE MP_ERROR(file,line,error_msg) =

    BEGIN
    MAP
	file:	REF FILE$$ ;
    $ERROR(W$IDL,*,FMT_NUM(.line),S(' of '),FMT_FILE(file),
	S(cr_lf,' ('),.error_msg,S(')'))
    END ;

ROUTINE SEL_ERROR(file,line,error_msg) =

    BEGIN
    MAP
	file:	REF FILE$$ ;
    IF .sel_p_flag
    THEN
	$ERROR(W$IDL,*,FMT_NUM(.line),S(' of '),FMT_FILE(file),
	S(cr_lf,' ('),.error_msg,S(')'))
    ELSE
	true
    END ;
 
 
ROUTINE PAT_ERROR(file,line,error_msg) =

    BEGIN
    MAP
	file:	REF FILE$$ ;
    $ERROR(W$IDL,*,FMT_NUM(.line),S(' of '),FMT_FILE(file),
	S(cr_lf,' ('),.error_msg,S(')'))
    END ;

ROUTINE DSP_PAT_LIST(prod_list) =

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

    BEGIN				!Beginning ROUTINE DSP_PAT_LIST

    LOCAL
	edit:		REF EDIT$$,
	file:		REF FILE$$,
	lib:		REF LIBRARY$$,
	patch:		REF PATCH$$,
	product:	REF PRODUCT$$,
	n,
	nn,
	nnn ;
    MAP
	prod_list:	REF TABLE$$ ;
 
    $TRACE('Beginning','DSP_PAT_LIST') ;
 
    CK_DATATYPE(prod_list,TABLE) ;
    n = 0 ;
    WHILE
    GET_VALUE((n=.n+1),.prod_list,product) EQL true DO
	BEGIN
	CK_DATATYPE(product,PRODUCT) ;
	TTY((cr_lf),.product[PROD_NAME]) ;
	nn = 0 ;
	WHILE
	GET_VALUE((nn=.nn+1),.product[PROD_PAT_LIST],patch) EQL true DO
	    BEGIN
	    CK_DATATYPE(patch,PATCH) ;
	    TTY((cr_lf,'  '),.patch[PAT_NAME]) ;
	    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],(' from file '),FMT_FILE(file)) ;
		END
	    END 
	END ;
    true

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