Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/nml/nmlvdb.bli
There are 2 other files named nmlvdb.bli in the archive. Click here to see a list.
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 8-Dec-82 11:45:13, Edit by BRANDT
!
!   Ident 89.
!     Change MATCH_NODE_ID so that it checks only for matching addresses
!     rather than matching addresses and names.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 13-Oct-82 10:54:23, Edit by BRANDT
!
!   Ident 88.
!     For CLEAR functions in NML$VDB, modify the code for returning
!     value.  Before this edit, the right conditions would return the
!     value of of an uninitialized local variable (NMX).
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 12-Oct-82 00:45:32, Edit by BRANDT
!
!   Ident 87.
!     In VDB_CHANGE, when setting a SERVICE CIRCUIT parameter for a
!     node, don't fail with a CWS error if the circuit is already
!     assigned to that node.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 11-Oct-82 12:23:14, Edit by BRANDT
!
!   Ident 86.
!     In NML$VDB add additional code to return a CWS error for CLEAR
!     ALL, CLEAR NAME, and CLEAR ADDRESS operations for the executor
!     node.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 28-Sep-82 13:43:41, Edit by BRANDT
!
!   Ident 85.
!     In NML$VDB add additional code to return ERR_DETAIL for errors
!     CWS and IID.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 28-Sep-82 12:39:14, Edit by BRANDT
!
!   Ident 84.
!     In ENTITY_IS_VALID, for NODE entities, check for OCM error if MCB
!     and REE error if TOPS20.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 28-Sep-82 11:13:07, Edit by PECKHAM
!
!   Ident 83.
!     Fix X_NOD_NDB dot bugs in NML$VDB_INITIALIZE for setting
!     EXECUTOR HOST and IDENTIFICATION parameters (introduced by #76).
!     Fix NML$SET_VDB_PARAMETER not to exclude node entity changes.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 27-Sep-82 15:38:41, Edit by BRANDT
!
!   Ident 82.
!     In ENTITY_IS_VALID, for NODE entities, check for OCM error rather
!     than REE error.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 23-Sep-82 9:38:14, Edit by BRANDT
!
!   Ident 81.
!     In NML$VDB add additional argument ERR_DETAIL for returning the
!     error detail field for response messages signalling errors.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 20-Sep-82 16:49:32, Edit by BRANDT
!
!   Ident 80.
!     More for edit 78.  Change the way ENTITY_IS_VALID checks for a
!     NODE entity since a valid LOOP node will have a zero address.
!     Also, in NML$VDB, for SET functions, add a check to see if the
!     NODE parameters specified for either SERVICE CIRCUIT or CIRCUIT
!     are valid entities.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 20-Sep-82 10:29:57, Edit by BRANDT
!
!   Ident 79.
!     In NML$VDB, for SET functions, add a check to see if the parameter
!     is applicable for executor nodes only.  If it
!     turns out that the parameter is a lower layer parameter, $NML$SET
!     is called rather than VDB_CHANGE.  (VDB_CHANGE calls APPLICABLE,
!     $NML$SET does not.)  So, if an executor node only param (e.g.,
!     DELAY FACTOR) that is a lower layer param is specified for an
!     entity that is not the executor, we miss the call to APPLICABLE,
!     and the NTMAN JSYS does the wrong thing--sets the parameter for
!     the executor.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 20-Sep-82 9:43:27, Edit by BRANDT
!
!   Ident 78.
!     In NML$VDB, for SHOW functions, immediately return the error code
!     from VDB_READ for REE as well as URC errors.  Since VDB_READ
!     calls ENTITY_IS_VALID, the URC error is valid for NML as well as
!     lower layers.  Without this fix, a SHOW NODE X with the DN20 as
!     EXECUTOR will succeed even though X is invalid.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 17-Sep-82 13:34:43, Edit by BRANDT
!
!   Ident 77.
!     In REMOVE_PARAMETER, fix code that loops over PVB so that CLEAR
!     ALL works.  As loop was coded, some parameters were deleted more
!     than once since after a deletion, the PVB is compacted but we
!     always advanced on to the next entry.  Eventually, we reach the
!     "old copies" of entries that have already bubbled up the vector.
!     This caused problems when we tried to re-release any dynamic
!     memory associated with the entry.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 15-Sep-82 13:43:34, Edit by BRANDT
!
!   Ident 76.
!     Move the executor node's EDB and its associated parameter vector
!     from OWN storage to dynamic storage.  Then when a command is given
!     to modify an executor parameter, we don't die trying to deallocate
!     a chunk of permanent data.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 13-Sep-82 09:59:03, Edit by PECKHAM
!
! Ident 75.
!  Correct input to INSERT_PARAMETER for HOST (bug introduced by #73).
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 2-Sep-82 13:43:34, Edit by BRANDT
!
!   Ident 74.
!     Special case SET NODE foo ADDRESS so it returns CWS error
!     if foo is the EXECUTOR.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.7  2-Sep-82 10:19:42, Edit by PECKHAM
!
! Ident 73.
!  Remove the default EXECUTOR IDENTIFICATION for NMLMCB
!   (it will be set by NMLEVT).
!  Move PRM_BFR from NML$SET_VDB_PARAMETER to module
!   (for access by NML$VDB_INITIALIZE).
!  Make NML$VDB_INITIALIZE get EXECUTOR HOST from SC for NMLMCB.
!  Fix NML$VDB to set EXECUTOR HOST to NMX for NMLMCB.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 29-Jun-82 15:31:35, Edit by PECKHAM
!
! Ident 72.
!  Fix duplicate executor node in returned node list from NML$VDB.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 22-Jun-82 17:34:43, Edit by BRANDT
!
!   Ident 71.
!     Move the check in READ_PARAMETER so that a buffer length of at
!     least 3 is quaranteed before calling READ_PARAMETER_DATA.
!     The current check is useless once we get into the loop.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 9-Jun-82 14:34:43, Edit by BRANDT
!
!   Ident 70.
!     In READ_PARAMETER_DATA always check the current available space
!     remaining in the buffer before copying in any data.
!     This was not done for multiple field parameters, and so buffer
!     overflow occurred.  Also, in READ_PARAMETER, check for an initial
!     availability of at least 3 bytes, since each entry requires a 3
!     byte header.
!
!
! Ident 69.
! Remove TOPS20 accomodation for NICE$_IID.
! Do not change parameters in INSERT_PARAMETER if they are read-only.
! Add PRIVLEDGED parameter to INSERT_PARAMETER to allow read-only override.
! Conditionalize filter handling.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.5 27-May-82 10:20:08, Edit by PECKHAM
!
! Ident 68.
! Incorrect assumptions were being made about the executor entry in
! the returned node list from $NML$RETURN in NML$VDB.
! Fix it so the returned length is correct.
! Do not play with EXECUTOR for return LOOP NODES.
! Accomodate TOPS20's return of NICE$_IID to loop nodes by changing
! that return status to NICE$_URC.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 24-May-82 09:35:07, Edit by PECKHAM
!
! Ident 67.
! Fix NML$VDB_INITIALIZE to dynamically set the IDENTIFICATION
! instead of hard-coding it.
! This is to keep from crashing when someone CLEARs it!
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.5 20-May-82 14:58:04, Edit by PECKHAM
!
! Ident 66.
! Move the code that disables display of CIRCUIT/LINE STATE
! from READ_PARAMETER_DATA to READ_PARAMETERS.
! Also allow display for the TOPS20 version.
! Optimize code in READ_PARAMETERS.
! Optimize layer choice code in NML$VDB and
! avoid setting state in lower layer for TOPS20.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 14-May-82 10:34:43, Edit by BRANDT
!
!   Ident 65.
!     Have ENTITY_IS_VALID return $TRUE for a node only when there is
!     a non zero address specified in the entity id.
!     At this time, the entity id will be the full id, and if an
!     address is associated with the name, it will be specified.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.6 14-May-82 17:50:16, Edit by PECKHAM
!
! Ident 64.
! Fix TOPS20 'SHO KNO/ACT CIR' to call new routine NMU$DLX_RETURN_CIRCUITS
! to get circuit list.
! Move NMU$DLX_KNOWN_DEVICE synonym to NMUCOM.
! Fix returned NODE lists to have the EXECUTOR node first
! Fix TOPS20 SHOW CIRCUIT to return success if RESULT was URC
! and ENTITY_IS_VALID.  This is so circuits with no data bases get recognized.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 14-May-82 10:34:43, Edit by BRANDT
!
!   Ident 63.
!     Special case the STATE parameter in READ_PARAMETER_DATA and do
!     not return any information from the VDB.  
!     Routine NML$GET_VDB_PARAMETER will still be able to obtain this
!     parameter from the VDB.
!     This fix prevents the SHOW commands from displaying this
!     parameter twice;  once from the VDB and once from the lower layer.
!     However, other NML processes can still access the data from the
!     VDB.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 10-May-82 10:34:43, Edit by BRANDT
!
!   Ident 62.
!     Rework of edit 60.  Have ENTITY_IS_VALID always return TRUE for
!     NODE entities.  This is as it was before.  In routine VDB_READ,
!     don't call ENTITY_IS_VALID if no entry exists in the volatile
!     database.  Have VDB_READ return URC error.  If the entity does
!     exist in a lower layer, the routine that called VDB_READ will
!     discover this and not return the error.  This eliminates special
!     case checking in ENTITY_IS_VALID to see if this function is a
!     READ or SET, since it is legal to do a SET on a node that does not
!     yet exist in the database.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.1 10-May-82 9:44:43, Edit by BRANDT
!
!   Ident 61.
!     Fix ENTITY_IS_VALID so that for NODE entities, it checks the
!     lower layers for the existence of the entity.  As is, it always
!     returns TRUE for NODE entities, and so a SHOW for a non-existent
!     node returns a NICE success code.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.18 7-May-82 13:36:34, Edit by BRANDT
!
!   Ident 60.
!     Fix NML$VDB and READ_PARAMETER so that NICE$_REE gets returned
!     on read functions when the buffer is inadequate.
!
! <PLATUKIS>NMLVDB.BLI.4  6-May-82 14:26:52, Edit by PLATUKIS
!   ident 59.
!   disallow changing of local node name in routine NML$VDB.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.3  6-May-82 09:53:27, Edit by PECKHAM
!
! Ident 58.
! Allow NML$*_VDB_PARAMETER to override set/clear restrictions:
!  Add PRIVLEDGED switch to REMOVE_PARAMETER and REMOVE_QUALIFIED_PARAMETER.
!
! <BRANDT.DEVELOPMENT>NMLVDB.BLI.18 5-May-82 12:36:34, Edit by BRANDT
!
! Ident 57.
! Remove "Loadtest" from executor node identification parameter
!
! <VOBA.NML.DEVELOPMENT>NMLVDB.BLI.18 14-Apr-82 14:36:34, Edit by VOBA
!
! Ident 56.
! Fix REMOVE_PARAMETER to generate optimized code for the MCB.
! Fix it to clear all parameters appropriately, as well.
! Add REMOVE_QUALIFIED_PARAMETER for X25-ACCESS volatile data base.
! Fix bug in $NML$SHOW macro call (missing actual parameter), in routine
! ENTITY_IS_VALID.
!
! <VOBA.NML.DEVELOPMENT>NMLVDB.BLI.88 25-Mar-82 18:12:36, Edit by VOBA
!
! Ident 55.
! Add code to handle MODULE X25-ACCESS volatile data base.
!
! <VOBA.NML.DEVELOPMENT>NMLVDB.BLI.15 10-Mar-82 14:12:00, Edit by VOBA
!
! Ident 54.
! Condition the X.25 code checking the validity of MODULE entity not to
! be included in the source for now (until we have the X.25 gateway in place).
! Fix a number of bugs in the source.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.27  8-Mar-82 02:27:48, Edit by PECKHAM
!
! Ident 53.
! Provide support for lower layers in this central place.
! Hard-code the event filter settings in.
!
! <VOBA.NML.DEVELOPMENT>NMLVDB.BLI.48  5-Mar-82 08:36:52, Edit by VOBA
!
! Ident 52.
! Added code to handle MODULE entities.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.12  2-Mar-82 15:06:25, Edit by PECKHAM
!
! Ident 51.
! Work on entities too numerous to mention.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.9 25-Feb-82 10:57:31, Edit by PECKHAM
!
! Ident 50.
! Add QH_LOGGING_FILTERS data base queue.
! Add global names of data bases for MCBDA.
! Remove restriction on modules from VDB_READ, VDB_CHANGE.
! Change input parameters to READ_FILTERS.
! Remove references to P$ALL by specifying parameter -1 to REMOVE_PARAMETER
! to remove all parameters.
! Fix REMOVE_PARAMETERS to not RELEASE_PVB until all parameter memory
! is released
! Set FIND_DB_FOR_ENTITY to only create data bases for NODE, LINE and CIRCUIT.
! Make GET_VDB_ENTITY handle the MODULE queue.
! General handling of NMU$MEMORY_GET failures.
! Add routine values to GET_PVB, EXPAND_PVB, SET_PARAMETER_DATA,
! SET_IMAGE_FIELD.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.3 23-Feb-82 13:48:42, Edit by PECKHAM
!
! Ident 49.
! Fix calculated length of existing memory block in SET_IMAGE_FIELD.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 23-Feb-82 08:46:26, Edit by PECKHAM
!
! Ident 48.
! Dummy! Fixed mis-spelled return codes.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.5 22-Feb-82 17:09:07, Edit by PECKHAM
!
! Ident 47.
! Fix NML$VDB, READ_* to return NICE$_SUC when nothing to SHOW
! when no counters to ZERO.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 22-Feb-82 12:17:07, Edit by PECKHAM
!
! Ident 46.
! Fix memory deallocation of image field buffers in CLEAR_PARAMETER_DATA.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 19-Feb-82 09:31:27, Edit by PECKHAM
!
! Ident 45.
! Add more items to EXECUTOR data base (LOOP variables).
! Support logging data base for STATE and NAME logging parameters.
! Increase PRM_BFR_LENGTH in NML$SET_VDB_PARAMETER
! and use OWN space instead of stack space.
!
! NET:<GROSSMAN>NMLVDB.BLI.3 27-Jan-82 08:58:17, Edit by GROSSMAN
!
! Ident 44.
! Fix call to NML$COUNTER_TIMER_SET. It now returns $false if the parameter
! was a counter timer, and its value is out of range. It will now return with
! a nice error code of "Illegal Parameter Value".
!
! NET:<GUNN>NMLVDB.BLI.8 21-Jan-82 17:13:17, Edit by GUNN
!
! Ident 43.
! Fix NODE HOST parameter to map the id when set so that
! a valid node address is displayed.
! Fix call to NML$COUNTER_TIMER_CLEAR.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.2 20-Jan-82 10:04:29, Edit by PECKHAM
!
! Ident 42.
! Fix call from NML$CHARACTERISTICS to NML$CHARACTERISTIC.
!
! NET:<PECKHAM.DEVELOPMENT>NMLVDB.BLI.8 18-Jan-82 19:50:42, Edit by PECKHAM
!
! Ident 41.
! Add selector recognition in READ_PARAMETERS so that right parameters
! are displayed for right selectors.
! Begin work on logging data base support.
! Add calls for counter timer data base maintenance (for GROSSMAN).
!
! NET:<GUNN.DEVELOPMENT>NMLVDB.BLI.4 12-Jan-82 15:45:44, Edit by GUNN
!
! Ident 40.
! Fix C_STRING and C_CHAR macros for BLIS16.
!
! NET:<GUNN.DEVELOPMENT>NMLVDB.BLI.34  6-Jan-82 15:26:52, Edit by GUNN
!
! Ident 39.
!
!   Add support for reading Network Management Version, 
!   (Parameter #101) from Volatile Data Base. Initialize
!   a node data base for the EXECUTOR node.
!
!   Add routine SET_NODE_ENTITY.
!
!   Remove declaration of QH_CIRCUIT_NDB. It was not used or needed.
!
! NET:<BRANDT.DEVELOP>NMLVDB.BLI.2 23-Dec-81 17:13:30, Edit by BRANDT
!
! Ident 38.
!   Change names of "matching routines" so they are all unique in
!   the first six characters to facilitate DDT debugging.
!
!   Reduce size of code for MCB by--
!     changing some CASE statements to IF THEN ELSEs
!     restructure code and make common code into callable routines
!     eliminate some parameters in routine interfaces
!
!   Fix SVC_CKT_MATCH to pick up parameter correctly.  Eliminate setting
!   the additional field in the NODE_DB because currently all data base
!   entries are allocated as ENTITY_DBs.  These are smaller than
!   NODE_DBs.
!
!   Change some comments and/or variable names so they are correct
!   and not misleading
!
!   In REMOVE_PARAMETER add an EXITLOOP after the code that clears
!   the parameter.  Otherwise we would loop again with everything
!   off by one because the parameter vector has been shrunk.
!
!   In NML$SET_VDB_PARAMETER make the parameter buffer a local block
!   because it is small, and the dynamic block was never released
!   anyway.
!
!   In NML$SET_VDB_PARAMETER return TRUE or FALSE in all cases.
!
!   Clean up code in INSERT_PARAMETER and add routines RELEASE_PVB,
!   GET_PVB, and EXPAND_PVB.
!
!   Fix MATCH_ID so it does not distinguish between cases.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.MCB>NMLVDB.BLI.2 16-Nov-81 11:31:30, Edit by WEBBER
!
! Ident 37.
!   Modify interface to GET_VDB_PARAMETER to pass back the value of all
!   binary fields, even if the field occupies more than one BLISS value.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLVDB.BLI.15 13-Oct-81 23:45:52, Edit by PECKHAM
!
! Ident 36.
! Correct parameter pass in NML$FIND_NDB.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.4 13-Oct-81 11:52:23, Edit by GUNN
!
! Ident 35.
! Fix READ_COUNTERS routine to make SHOW CIRCUIT xxx COUNTERS command
! to work properly.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLVDB.BLI.13  9-Oct-81 15:59:13, Edit by GUNN
!
! Ident 34.
! Change SELECTOR to not be system dependent.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.MCB>NMLVDB.BLI.2  3-Aug-81 08:46:13, Edit by GUNN
!
! Ident 33.
! Remove $INTERNAL_ERROR$ macros.
!
! NET:<DECNET20-V3P1.NMU.LIBRARY>NMLVDB.BLI.5 30-Jun-81 10:42:58, Edit by GUNN
!
! Ident 32.
! Add routine NML$CLR_VDB_PARAMETER.
!
! NET:<DECNET20-V3P1.NMU.LIBRARY>NMLVDB.BLI.3 29-Jun-81 17:28:23, Edit by GUNN
!
! Ident 31.
! Fix NML$SET_VDB_PARAMETER to pass pointer to begginning of temporary
! parameter buffer when calling INSERT_PARAMETER.
!
! NET:<DECNET20-V3P1.NMU.LIBRARY>NMLVDB.BLI.2 29-Jun-81 16:15:11, Edit by JENNESS
!
! Ident 30.
! Fix dot problems in NML$SET_VDB_PARAMETER.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLVDB.BLI.9 25-Jun-81 16:33:11, Edit by JENNESS
!
! Ident 29.
! Fix SVC_CKT_MATCH, local PVB should be a ref.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.4 18-Jun-81 08:30:20, Edit by GUNN
!
! Ident 28.
! Move check for 'ALL' parameter prior to picking up parameter number
! in REMOVE_PARAMETER.
! Change test condition in loop in REMOVE_PARAMETER.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.3 17-Jun-81 17:08:31, Edit by GUNN
!
! Ident 27.
! Fix REMOVE_PARAMETER to make CLEAR command work. Unneeded dot on
! GETW of parameter number.
! Add code to NML$SET_VDB_PARAMETER.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.6 12-Jun-81 00:04:40, Edit by GUNN
!
! Ident 26.
! Move macro definition of NML$SET_VDB_PARAMETER to NMUCOM.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.5  3-Jun-81 20:19:05, Edit by GUNN
!
! Ident 25.
! Add code for NML$SET_VDB_PARAMETER.
! Fix code in NML$GET_VDB_PARAMETER to eliminate compiler INFO message.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.2  28-May-81 16:56:44, Edit by GUNN
!
! Ident 24.
! Add code to NML$GET_VDB_PARAMETER to return pointer if necessary based
! on data type of parameter.
! Change test in loop in NML$GET_VDB_PARAMETER.
!
! NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMLVDB.BLI.6 26-May-81 13:58:10, Edit by GUNN
!
! Ident 23.
! Remove use of RTN_COD in NML$GET_VDB_PARAMETER and return either
! $TRUE or $FALSE at point of detection.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.47 13-May-81 10:31:30, Edit by GUNN
!
! Ident 22.
! Only allocate new buffer for HOST id first time.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.46 13-May-81 10:19:36, Edit by GUNN
!
! Ident 21.
! Fix ch$move in HOST code.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.45 13-May-81 09:37:32, Edit by GUNN
!
! Ident 20.
! Update PRM_PTR on ch$move when reading HOST parameter.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.44 13-May-81 09:07:49, Edit by GUNN
!
! Ident 19.
! Fix code which sets HOST parameter. Handle fact that input format of
! node entity is either address or name.
! Fix typos in code which reads HOST parameter. Missing dots on PRM_PTR.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.42 12-May-81 17:50:47, Edit by GUNN
!
! Ident 18.
! Fix code to handle read/write parameters.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.41 12-May-81 09:02:00, Edit by GUNN
!
! Ident 17.
! Fix parameter handling routines to use DT_LENGTH for uncoded fields
! instead of DT_NUMBER.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.40 11-May-81 23:45:13, Edit by GUNN
!
! Ident 16.
! Fix code to read long binary number.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.39 11-May-81 10:02:29, Edit by GUNN
!
! Ident 15.
! Only add count for inserted parameter if it's not already in table.
! Handle binary number parameters longer than %BPVAL correctly.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.37  8-May-81 11:25:42, Edit by GUNN
!
! Ident 14.
! Fix REMOVE_PARAMETER code.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.36  8-May-81 11:04:22, Edit by GUNN
!
! Fix typo from last edit.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.35  8-May-81 10:00:31, Edit by GUNN
!
! Fix INSERT_PARAMETER logic. Not properly copying parameters from old
! vector.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.33  6-May-81 18:05:39, Edit by GUNN
!
! Yet more typos.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.32  6-May-81 17:57:38, Edit by GUNN
!
! Fix typos from last edit.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.31  6-May-81 17:39:32, Edit by GUNN
!
! Fix bad code in INSERT_PARAMETER and other places.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.29  5-May-81 17:40:45, Edit by GUNN
!
! Add code in VDB_READ for entities other than NODE.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.28  5-May-81 15:59:26, Edit by GUNN
!
! Remove 'ref' from bind of PVB_QE in READ_PARAMETERS routine.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.27  5-May-81 15:07:34, Edit by GUNN
!
! Make READ_PARAMETERS work.
! Fix call to VDB_READ from NML$VDB to pass pointer address not the
! argument address.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.26  5-May-81 12:08:17, Edit by GUNN
!
! Fix READ_ENTITY to return correct value. $NICE$ERR_MPE was generating
! a procedure call.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.24 17-Apr-81 16:57:19, Edit by GUNN
!
! Pass contents of PVB_QE in call to SET_PARAMETER_DATA from
! INSERT_PARAMETER_DATA.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.21 17-Apr-81 07:59:28, Edit by GUNN
!
! Fix BIND in INSERT_PARAMETER routine.
! Make SET_PARAMETER_DATA handle special cases for multiple fields.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.11  3-Apr-81 14:08:26, Edit by GUNN
!
! Add routine NML$GET_VDB_PARAMETER to return data for a specific parameter
! from the volatile data base.
!
! Add routine NML$FIND_NDB to find a NODE given a circuit id.
!
! Fix coding errors in INSERT_PARAMETER and REMOVE_PARAMETER.
!
! NET:<DECNET20-V3P1.NML>NMLVDB.BLI.71  5-Mar-81 13:00:10, Edit by GUNN
!
! Make NMX interface code symbols be system specific.
!
%title 'NMLVDB -- Volatile Data Base Processing'
module NMLVDB	(
		ident = 'X00.89'
		) =
begin

!                    COPYRIGHT (c) 1980, 1981, 1982
!                    DIGITAL EQUIPMENT CORPORATION
!                        Maynard, Massachusetts
!
!     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:	DECnet-10/20 V3.0 Network Management Layer (NML)
!
! ABSTRACT:
!
!	This module contains the volatile data base definitions 
!       and access routines.
!
! ENVIRONMENT:	TOPS-10/20 & MCB/RSX11 User mode under NML
!
! AUTHOR: Dale C. Gunn , CREATION DATE:  2-Feb-81
!
! MODIFIED BY:
!
!	, : VERSION
! 01	-
!--
!
! INCLUDE FILES:
!

library 'NMLLIB';                       ! All required definitions

literal
    NML$CFG_FILTERS = $false;

!
! TABLE OF CONTENTS
!

forward routine
        NML$VDB_INITIALIZE : novalue,   ! Initialize the Volatile DB
        NML$VDB,                        ! Perform NMX operation on DB
        NML$GET_VDB_PARAMETER,          ! Extract data for specific parameter
        NML$SET_VDB_PARAMETER,          ! Set parameter in Volatile DB
        NML$CLR_VDB_PARAMETER,          ! Remove parameter from VDB
        NML$FIND_NDB,                   ! Find NODE associated with CIRCUIT
        SELECT_LOGGING,
        SELECT_MODULE,
	VDB_READ,
        %if $X25 and not $MCB %then
        READ_QUALIFIED_ENTITY,
        READ_QUALIFIER : novalue,
        %fi
        READ_ENTITY,
        READ_PARAMETERS,
        READ_COUNTERS,
        READ_FILTERS,
        READ_FILTER,
        READ_FILTER_SINK,
        READ_FILTER_MASKS,
	VDB_CHANGE,
        %if $X25 and not $MCB %then
        SET_QUALIFIED_ENTITY,
        %fi
        SET_NODE_ENTITY : novalue,
        GET_EXISTING_ENTITY_DB,
        SET_ENTITY_DB,
        ENTITY_IS_VALID,
        MODULE_IS_VALID,
        GET_VDB_ENTITY_QUEUE,
        INSERT_PARAMETER,
        COPY_PARAMETER_VECTOR: novalue,
        APPLICABLE,
        %if $X25 and not $MCB %then
        REMOVE_QUALIFIED_PARAMETER,
        %fi
        REMOVE_PARAMETER: novalue,
        RELEASE_PVB: novalue,
        GET_PVB,
        EXPAND_PVB,
        SET_PARAMETER_DATA,
        SET_FILTER,
        SET_IMAGE_FIELD,
        CLEAR_PARAMETER_DATA: novalue,
        CLEAR_FILTER,
        READ_PARAMETER_DATA,
        LOGGING_ID_MATCH,
        NODE_ID_MATCH,
        NON_NODE_ID_MATCH,
        SVC_CKT_MATCH,
        MATCH_ID;

!
! MACROS
!

! Macro - GETMB
!
! Function - To get the next 8 bit value from a byte string
!            and map lower case ASCII codes into the
!            corresponding upper case ASCII code.
!            The byte pointer is updated to point to the next
!	     byte to read.
!
! Parameters -
!
!    PTR_ADR	Address of byte string pointer
!
! Value returned -
!
!    The next byte in the string.
!

macro
     GETMB (PTR_ADR) =
         begin
         local C;

         C = ch$rchar_a(PTR_ADR);
         if .C geq %C'a' and .C leq %C'z'
         then .C - %C'a' + %C'A'
         else .C
         end %;

macro
     $EXPAND_FIELD (FIELD_NAME) =
         %print ('field-name ', %string(FIELD_NAME), ' = [',
                 %fieldexpand(FIELD_NAME,0), ', ',
                 %fieldexpand(FIELD_NAME,1), ', ',
                 %fieldexpand(FIELD_NAME,2), ', ',
                 %fieldexpand(FIELD_NAME,3), ']') %;

macro
     $SHOW_EDB =
         $EXPAND_FIELD (EDB_QLINK)
         $EXPAND_FIELD (EDB_ENTITY_ID)
         $EXPAND_FIELD (NDB_ENTITY_ID)
         $EXPAND_FIELD (NDB_NODE_TYPE)
         $EXPAND_FIELD (EDB_PARAMETER_COUNT)
         $EXPAND_FIELD (EDB_PARAMETER_ALLOCATION)
         $EXPAND_FIELD (EDB_PARAMETER_VECTOR) %;

macro
     $SHOW_NDB =
         $EXPAND_FIELD (EDB_QLINK)
         $EXPAND_FIELD (EDB_ENTITY_ID)
         $EXPAND_FIELD (NDB_ENTITY_ID)
         $EXPAND_FIELD (NDB_NODE_TYPE)
         $EXPAND_FIELD (EDB_PARAMETER_COUNT)
         $EXPAND_FIELD (EDB_PARAMETER_ALLOCATION)
         $EXPAND_FIELD (EDB_PARAMETER_VECTOR)
         $EXPAND_FIELD (EDB_FIELDS)
         $EXPAND_FIELD (NDB_CIRCUIT_QLINK)
         $EXPAND_FIELD (NDB_SVC_CIRCUIT) %;

!
! EQUATED SYMBOLS:
!
$show (fields);                         ! Turn on XPORT field display
$show (literals);                       ! Turn on XPORT literal display

literal
    PRM_BFR_LENGTH = 2 + 1 + 255, ! Length in bytes
    PRM_BFR_SIZE = ch$allocation (PRM_BFR_LENGTH,8),
    PRM_BFR_ALLOCATION = PRM_BFR_SIZE * %upval;

!
! Miscelaneous data definitions
!
$field                                  ! For event logging filter masks
    MASK_BITS = [$bits (32)];

literal
    MASK_SIZE = $field_set_size;

!
! FDB_*
!  QH_LOGGING_FILTER entry.
!  Contains identification for a sink node and
!  pointers to event filter sets for CONSOLE_, FILE_, and MONITOR_.
!
$field FDB_FIELDS =
    set
    FDB_BASE = [$sub_block (0)],
    FDB_QLINK = [$sub_block (Q_ENTRY_SIZE)],
    FDB_NODE_ID = [$bytes (2 + 1 + 6)],
    FDB_CONSOLE_FILTERS = [$sub_block (Q_ENTRY_SIZE)],
    FDB_FILE_FILTERS = [$sub_block (Q_ENTRY_SIZE)],
    FDB_MONITOR_FILTERS = [$sub_block (Q_ENTRY_SIZE)]
    tes;

literal
    FDB_SIZE = $field_set_size;

macro
    FDB_BLOCK = block [FDB_SIZE] field (FDB_FIELDS) %;

!
! FDBS_*
!  General or entity specific filter mask set
!  Contains an entity type (2 bytes) and identification for
!   NO_ENTITY_ (0 bytes)
!   NODE_E (9 bytes)
!   LINE_, CIRCUIT_, or MODULE_ (17 bytes)
!  The first filter mask set is also part of this data base.
!
$field
    FDBS_FIELDS =
        set
        FDBS_BASE = [$sub_block (0)],
        FDBS_QLINK = [$sub_block (Q_ENTRY_SIZE)],
        FDBS_ENTITY = [$bytes (2 + max (0, 9, 17))],
        FDBS_MASKS = [$sub_block (0)]
        tes;

literal
    FDBS_SIZE = $field_set_size;

macro
    FDBS_BLOCK = block [FDBS_SIZE] field (FDBS_FIELDS) %;

!
! FDNM_*
!  Filter mask set.
!  Contains a set of 8 filter masks for the given range of
!  event types.
!
$field
    FDBM_FIELDS =
        set
        FDBM_BASE = [$sub_block (0)],
        FDBM_QLINK = [$sub_block (Q_ENTRY_SIZE)],
        FDBM_LOW = [$short_integer],
        FDBM_HIGH = [$short_integer],
        FDBM_MASKS = [$sub_block (8*MASK_SIZE)]
        tes;

literal
    FDBM_SIZE = $field_set_size;

macro
    FDBM_BLOCK = block [FDBM_SIZE] field (FDBM_FIELDS) %;

!
! PBF_*
!  Parameter block for filter handling routines.
!  This block is used to hold all the pertinent parameters to
!  allow generation of more efficient code, and also to allow
!  parameter passage through NMU$QUEUE_SCAN.
!
$field
    PBF_FIELDS =
        set
        PBF_BASE = [$sub_block (0)],
        PBF_PE = [$sub_block (PVB_ENTRY_SIZE)],
        PBF_NODE_ID_PTR = [$pointer],   ! Pointer to current FDB_NODE_ID
        PBF_ENTITY_PTR = [$pointer],    ! Pointer to current FDBS_ENTITY
        PBF_BUF_PTR_ADR = [$address],   ! Address of buffer pointer
        PBF_LEN_ADR = [$address],       ! Address of buffer length
        PBF_MASK = [$bytes (4)],        ! Local copy of current filter mask
        PBF_SELECTOR = [$tiny_integer], ! Return list selector
        PBF_SINK = [$tiny_integer]      ! Current sink type
        tes;

literal
    PBF_SIZE = $field_set_size;

macro
    PBF_BLOCK = block [PBF_SIZE] field (PBF_FIELDS) %;

!
! PBM_*
!  Parameter block for module handling routines.
!  This block is used to hold all the pertinent parameters to
!  allow generation of more efficient code, and also to allow
!  parameter passage through NMU$QUEUE_SCAN.
!
$field
    PBM_FIELDS =
        set
        PBM_BASE = [$sub_block (0)],
        PBM_BUF_PTR_ADR = [$address],   ! Address of buffer pointer
        PBM_LEN_ADR = [$address],       ! Address of buffer length
        PBM_SELECTOR = [$tiny_integer]  ! Return list selector
        tes;

literal
    PBM_SIZE = $field_set_size;

macro
    PBM_BLOCK = block [PBM_SIZE] field (PBM_FIELDS) %;

!
! Parameter block usage being phased in
!

$field
    PARAMETER_FIELDS =
        set
        PB_BASE = [$sub_block (0)],
        PB_ENTITY_POINTER = [$pointer],
        PB_QUALIFIER_POINTER = [$pointer],
        PB_FUNCTION = [$integer],
        PB_ENTITY_TYPE = [$integer],
        PB_SELECTOR = [$integer],
        PB_DATA_LENGTH = [$integer],
        PB_DATA_POINTER = [$integer],
        PB_PARAMETER_NUMBER = [$integer],
        PB_EDB = [$address],
        PB_PARAMETER_DATA_BLOCK = [$address],
        PB_PRIVLEDGED = [$bit]
        tes;

literal
    PARAMETER_BLOCK_SIZE = $field_set_size,
    PARAMETER_BLOCK_ALLOCATION = $field_set_units;

macro
    PARAMETER_BLOCK = block [PARAMETER_BLOCK_SIZE] field (PARAMETER_BLOCK_FIELDS) %;

$show (none);                           ! Turn off XPORT display
!
! OWN STORAGE:
!

own
   PRM_BFR: block [PRM_BFR_ALLOCATION];

%( N.B. - To ensure integrity of the volatile data base when running
          in the multi-tasking environment, the data bases must be
          locked during access. )%

own                                     ! Heads of NML volatile parameter DB
    QH_NODE_PARAMETERS: Q_HEADER,
    QH_LINE_PARAMETERS: Q_HEADER,
    QH_CIRCUIT_PARAMETERS: Q_HEADER,
    QH_LOGGING_PARAMETERS: Q_HEADER,
    QH_LOGGING_FILTERS: Q_HEADER,
    QH_MODULE_PARAMETERS: Q_HEADER;

%if $MCB %then
global bind
    NODDB = QH_NODE_PARAMETERS,
    LINDB = QH_LINE_PARAMETERS,
    CKTDB = QH_CIRCUIT_PARAMETERS,
    LOGDB = QH_LOGGING_PARAMETERS,
    FLTDB = QH_LOGGING_FILTERS,
    MODDB = QH_MODULE_PARAMETERS;
%fi

!
! EXTERNAL REFERENCES:
!

external routine
         NMU$MEMORY_MANAGER,
         NMU$QUEUE_MANAGER,
         NMU$NETWORK_LOCAL,
         NML$VDB_PARAMETER,
         NML$EXECUTOR_ONLY,
         NML$SUMMARY,
         NML$STATUS,
         NML$CHARACTERISTIC,
         NML$CLEARABLE,
         NML$READ_ONLY,
         NML$GET_PDB_DATA_TYPE,
         NML$COUNTER_TIMER_SET,
         NML$COUNTER_TIMER_CLEAR;
%global_routine ('NML$VDB_INITIALIZE') : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Resets the NML volatile data bases to an initially
!       cleared state. 
!
!       Initializes volatile data base for EXECUTOR NODE.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    macro
         C_STRING [ ] =                 ! Counted string
             %if not $MCB
             %then C_CHAR(%char(%charcount(%remaining)), %explode(%remaining)) 
             %else %string(%char(%charcount(%remaining)), %remaining)
             %fi %;

    %if not $MCB
    %then
    macro
         C_CHAR [B1,B2,B3,B4] =
             ((%C B1 ^ (%bpval-8))
              %if not %null(B2)
              %then or (%C B2 ^ (%bpval-16))
                    %if not %null(B3)
                    %then or (%C B3 ^ (%bpval-24))
                          %if not %null(B4)
                          %then or (%C B4 ^ (%bpval-32)) %fi
                    %fi
              %fi) %;
    %else
    macro
         C_CHAR [] =
             (%string (%remaining)) %;
    %fi

!
! Reset the volatile parameter data base header for each entity.
!

    NMU$QUEUE_RESET (QH_NODE_PARAMETERS);
    NMU$QUEUE_RESET (QH_LINE_PARAMETERS);
    NMU$QUEUE_RESET (QH_CIRCUIT_PARAMETERS);
    NMU$QUEUE_RESET (QH_LOGGING_PARAMETERS);
    NMU$QUEUE_RESET (QH_LOGGING_FILTERS);
    NMU$QUEUE_RESET (QH_MODULE_PARAMETERS);

!
! Set up the initial data base for EXECUTOR NODE.
!
    begin

    external
            NMLVER;                     ! NML Version Number

    literal
           N_PARMS = 4,                 ! Number of initial EXECUTOR parameters
           M_PARMS = 7;                 ! Maximum number of EXECUTOR parameters
                                        ! Allow for maximum number parameters
                                        ! so the parameter vector never needs
                                        ! to be deallocated.

    own
       X_NOD_NDB : ref ENTITY_DB_BLOCK,

       X_NOD_PVB : $NML$PVB_ENTRY_VECTOR (M_PARMS)
                   preset ([0,PE_NUMBER] = 101, ! MANAGEMENT VERSION
                           [0,PE_ADDRESS] = NMLVER,
                           [1,PE_NUMBER] = 150, ! LOOP COUNT 1
                           [1,PE_ADDRESS] = 1,
                           [2,PE_NUMBER] = 151, ! LOOP LENGTH 127
                           [2,PE_ADDRESS] = 127, ! (to work with RSX-11M)
                           [3,PE_NUMBER] = 152, ! LOOP WITH MIXED
                           [3,PE_ADDRESS] = 2);

    X_NOD_NDB = SET_ENTITY_DB (NODE_E, NMU$NETWORK_LOCAL ());

    X_NOD_NDB[NDB_NODE_TYPE] = NDB$EXECUTOR;
    X_NOD_NDB[EDB_PARAMETER_COUNT] = N_PARMS;
    X_NOD_NDB[EDB_PARAMETER_ALLOCATION] = PVB_ENTRY_ALLOCATION * M_PARMS;
    X_NOD_NDB[EDB_PARAMETER_VECTOR] =
		NMU$MEMORY_GET (.X_NOD_NDB[EDB_PARAMETER_ALLOCATION]);

    COPY_PARAMETER_VECTOR (X_NOD_PVB, .X_NOD_NDB[EDB_PARAMETER_VECTOR],
			   M_PARMS);

%if $MCB
%then
    begin                               ! Get host node from Session Control

    bind
        DATA_ID = uplit (141);

    local
        PTR;

    PTR = ch$ptr (PRM_BFR,, 8);
    PUTW (DATA_ID, PTR);
    PUTB (0, PTR);
    $NML$GET_HOST_ID (uplit (2 + 1 + 6), .PTR);
    INSERT_PARAMETER (.X_NOD_NDB, NODE_E, ch$ptr (PRM_BFR,,8), $true);
    end;
%else
    begin

    macro
        DEFAULT_IDENTIFICATION = 'DECnet-20 Version 3.0' %;

    INSERT_PARAMETER (.X_NOD_NDB, NODE_E,
                     ch$ascii (%char ((100 and %o'377'),
                                      (100^-8 and %o'377'),
                                      %charcount (DEFAULT_IDENTIFICATION)),
                               DEFAULT_IDENTIFICATION), $true);
    end;
%fi
    end;

!
! Set up the logging filter data base
!

%if NML$CFG_FILTERS
%then
    begin

    $field
        BYTE_0 = [$byte],
        BYTE_1 = [$byte];

    own
        FDB : block [FDB_SIZE] field (FDB_FIELDS)
              initial (rep FDB_SIZE of (0)),
        FDBS : block [FDBS_SIZE + FDBM_SIZE] field (FDBS_FIELDS)
              initial (rep FDBS_SIZE of (0));

    bind
        ENTITY_ID = uplit (NO_ENTITY_),
        FDBM = FDBS [FDBS_MASKS] : block [FDBM_SIZE] field (FDBM_FIELDS);

    $NML$GET_HOST_ID (uplit (2 + 1 + 6), ch$ptr (FDB [FDB_NODE_ID],, 8));
    NMU$QUEUE_RESET (FDB [FDB_CONSOLE_FILTERS]);
    NMU$QUEUE_RESET (FDB [FDB_FILE_FILTERS]);
    NMU$QUEUE_RESET (FDB [FDB_MONITOR_FILTERS]);
    PUTW (ENTITY_ID, ch$ptr (FDBS [FDBS_ENTITY],, 8));
    NMU$QUEUE_RESET (FDBM [FDBM_QLINK]);
    FDBM [FDBM_LOW] = 0;
    FDBM [FDBM_HIGH] = 7;
    NMU$QUEUE_INSERT (FDB [FDB_FILE_FILTERS], FDBS);
    NMU$QUEUE_INSERT (QH_LOGGING_FILTERS, FDB);
    end;
%fi

%( N.B. - Maybe we want to call the interface function here to
   return a list of known entities for each data base. )%

    end;				! End of NML$VDB_INITIALIZE
%global_routine ('NML$VDB', FUNCTION, TYPE, ENTITY, QUALIFIER, SELECTOR, LENGTH, BUFFER, ERR_DETAIL) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Performs operations on NML volatile parameters.
!
! FORMAL PARAMETERS
!
!	FUNCTION  - Code to denote whether the specified parameter is to be
!                   defined or purged, etc.
!       TYPE      - The NML entity type number of the entity to which the
!                   parameter pertains.
!       ENTITY    - Character sequence pointer to the entity id.
!       QUALIFIER - An optional character sequence pointer to a qualifier in
!                   parameter format.
!       SELECTOR  - For the return function, the class of entities to return.
!       LENGTH    - The address of a variable.
!		    For SHOW functions, the variable will
!		    contain the size of space available in the buffer.
!		    It will be reduced by the length of the data
!		    returned in the buffer.
!		    For SET and CLEAR functions, the address will
!		    contain the length of the specified parameter.
!       BUFFER   -  For SHOW functions, the address of a
!		    character sequence pointer to the buffer in which
!		    to return the parameter data.  These functions will
!		    update the pointer to point to the next available
!		    byte in the buffer.
!		    For SET and CLEAR functions, a character sequence
!		    pointer to the specific parameter.
!       ERR_DETAIL- The address of a variable in which to return the
!		    error detail field for the response message if this
!		    request fails.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    case .FUNCTION from %bliss36($NTSET) %bliss16(N$FSET) 
                   to %bliss36($NTRET) %bliss16(N$FRET)  of
        set
        [%bliss36($NTSET) %bliss16(N$FSET)]: ! Set parameter
            begin
            macro HIGHER_LAYER = NML <0, 1>%,
                  LOWER_LAYER = NML <1, 1>%;
            local NML, PARAMETER, RESULT;

            PARAMETER = GETW_NA (.BUFFER); ! Get parameter number

            if NML$VDB_PARAMETER (.TYPE, .PARAMETER)
            then NML = 1
            else NML = 2;

            selectone .TYPE of
                set
                [NODE_E]:
		    begin
                        local PTR, LOCAL_NODE; 
                        PTR = NMU$NETWORK_LOCAL();
                        LOCAL_NODE = ch$eql( 9, .PTR, 9, .ENTITY);
%if $TOPS20
%then
		    if NML$EXECUTOR_ONLY (.TYPE, .PARAMETER)
		    then
			if not .LOCAL_NODE
                        then return $NICE$ERR_PNA;
%fi
                    selectone .PARAMETER of
                        set
			[110, 501]:	    ! SERVICE CIRCUIT or CIRCUIT
                            begin
			    PTR = ch$plus (.BUFFER, 2); ! Circuit_id
			    if not ENTITY_IS_VALID (CIRCUIT_, .PTR)
                            then begin
				.ERR_DETAIL = CIRCUIT_;
				 return $NICE$ERR_URC;
				 end;
                            end;

                        [500, 502]:         ! NAME or ADDRESS
                            begin
                            if .local_node
                            then begin
				.ERR_DETAIL = NODE_E;
				 return $NICE$ERR_CWS;
				 end;
                            end;
%if $MCB
%then
                        [141]:              ! HOST
                            NML = 3;
%fi
                        [otherwise]:
                            0;
                        tes;
		    end;
%if $MCB
%then
                [LINE_, CIRCUIT_]:
                    if .PARAMETER eql 0
                    then NML = 3;
%fi
                [otherwise]:
                    ;
                tes;

            if .HIGHER_LAYER            ! If NML parameter
            then RESULT = VDB_CHANGE (.FUNCTION,
                                      .TYPE,
                                      .QUALIFIER,
                                      .ENTITY,
                                      ..LENGTH,
                                      .BUFFER,
				      .ERR_DETAIL);

            if .LOWER_LAYER             ! If NMX parameter
            then begin
                 RESULT = $NML$SET (.TYPE,
                                    .ENTITY,
                                    .QUALIFIER,
                                    .LENGTH,
                                    .BUFFER);

		 if ((.RESULT eql NICE$_URC) or
		     (.RESULT eql NICE$_CWS) or
		     (.RESULT eql NICE$_IID))
		 then .ERR_DETAIL = .TYPE;
                 end;

            .RESULT
            end;

        [%bliss36($NTCLR) %bliss16(N$FCLR)]: ! Clear parameter
            begin
            macro HIGHER_LAYER = NML <0, 1>%,
                  LOWER_LAYER = NML <1, 1>%;
            local NML, PARAMETER, VDB, NMX, RESULT;

            if ..LENGTH eql 0
            then
		begin
		PARAMETER = -1;			! Clear ALL
		NML = 3;
		end
            else
		begin
                PARAMETER = GETW_NA (.BUFFER); ! Get parameter number
                if NML$VDB_PARAMETER (.TYPE, .PARAMETER)
                then NML = 1
                else NML = 2;
		end;

            selectone .TYPE of
                set
                [NODE_E]:
		    begin
                        local PTR, LOCAL_NODE; 
                        PTR = NMU$NETWORK_LOCAL();
                        LOCAL_NODE = ch$eql( 9, .PTR, 9, .ENTITY);
%if $TOPS20
%then
		    if NML$EXECUTOR_ONLY (.TYPE, .PARAMETER)
		    then
			if not .LOCAL_NODE
                        then return $NICE$ERR_PNA;
%fi
                    selectone .PARAMETER of
                        set
                        [-1, 500, 502]:     ! ALL, NAME, or ADDRESS
                            begin
                            if .local_node
                            then begin
				.ERR_DETAIL = NODE_E;
				 return $NICE$ERR_CWS;
				 end;
                            end;
%if $MCB
%then
                        [141]:              ! HOST
                            NML = 3;
%fi
                        [otherwise]:
                            ;
                        tes;
		    end;
                [otherwise]:
                    ;
                tes;

            if .HIGHER_LAYER            ! If NML parameter
            then RESULT = (VDB = VDB_CHANGE (.FUNCTION,
                                   	     .TYPE,
                                   	     .QUALIFIER,
                                   	     .ENTITY,
                                   	     ..LENGTH,
                                             .BUFFER,
				   	     .ERR_DETAIL));

            if .LOWER_LAYER             ! If NMX parameter
            then begin
                 RESULT = (NMX = $NML$CLR (.TYPE,
                                 	   .ENTITY,
	                                   .QUALIFIER,
	                                   .LENGTH,
	                                   .BUFFER));

		 if .NMX eql NICE$_URC
		 then .ERR_DETAIL = .TYPE;
                 end;

            if (.VDB eql 1) and (.NML eql 3)
            then 1                      ! If either one succeed, ok
            else .RESULT                ! Return last result
            end;

        [%bliss36($NTZRO) %bliss16(N$FZRO)]: ! Zero counters
            begin
            local
                NMX;
            NMX = $NML$ZERO (.TYPE, .ENTITY, .QUALIFIER);

	    if .NMX eql NICE$_URC
	    then .ERR_DETAIL = .TYPE;

            .NMX
            end;

        [%bliss36($NTSHO) %bliss16(N$FSHO)]: ! Show parameters
            begin
            local VDB_CODE, RESULT;

            !
            ! Get any parameters out of the volatile data base.
            !

            VDB_CODE = VDB_READ (.FUNCTION,
                                 .TYPE,
                                 .ENTITY,
                                 .QUALIFIER,
                                 .SELECTOR,
                                 .LENGTH,
                                 .BUFFER,
				 .ERR_DETAIL);

            if ((.VDB_CODE eql NICE$_REE) or  ! On resource error
                (.VDB_CODE eql NICE$_URC))    !  or illegal entity
            then return .VDB_CODE             !  return error, now
            else

            !
            ! Try to get parameters kept at lower layers of architecture.
            ! There may not be any, or entity may not be known there.
            ! Fail only if the entity is not known in either NML or other
            ! layers.
            !

                begin
                local BUFFER_LENGTH;

                BUFFER_LENGTH = ..LENGTH;
                RESULT = $NML$SHOW (.TYPE,
                                    .ENTITY,
                                    .QUALIFIER,
                                    .SELECTOR,
                                    BUFFER_LENGTH,
                                    ..BUFFER);

                if .RESULT eql 1        ! If successful, update buffer length
                then .LENGTH = ..LENGTH - .BUFFER_LENGTH;
                end;

            !
            ! If call across NMX interface failed, assume an empty buffer.
            ! Return NICE success if either VDB or NMX calls succeed.
            !

            if (.VDB_CODE eql 1) then RESULT = 1;
%if $TOPS20
%then
            if .RESULT eql NICE$_URC
            then if (.TYPE eql CIRCUIT_) and ENTITY_IS_VALID (.TYPE, .ENTITY)
                 then RESULT = 1;
%fi
            .RESULT
            end;

        [%bliss36($NTSZC) %bliss16(N$FSZC)]: ! Show and zero counters
            begin
            local BUFFER_LENGTH, STATUS;

            BUFFER_LENGTH = ..LENGTH;
            STATUS = $NML$SHOZC (.TYPE,
                                 .ENTITY,
                                 .QUALIFIER,
                                 BUFFER_LENGTH,
                                 ..BUFFER);
            .LENGTH = ..LENGTH - .BUFFER_LENGTH;

	    if .STATUS eql NICE$_URC
	    then .ERR_DETAIL = .TYPE;

            .STATUS
            end;

        [%bliss36($NTRET) %bliss16(N$FRET)]: ! Return list of entity ids
            selectone .TYPE of
                set
                [NODE_E,
%if not $TOPS20
%then            CIRCUIT_,
%fi
                 LINE_]:
                    begin
                    local BUF_LEN, BUF_PTR, LCL_ADDRESS, LCL_LEN, STATUS;
                    BUF_PTR = ..BUFFER;
                    BUF_LEN = ..LENGTH;

                    !
                    ! If asking for ACT/KNO NOD, then put the exeutor first
                    !

                    if (.TYPE eql NODE_E) and (.SELECTOR neq -3)
                    then
                        begin
                        LCL_ADDRESS = NMU$NETWORK_LOCAL ();
                        LCL_LEN = 3 + ch$rchar (ch$plus (.LCL_ADDRESS, 2));
                        if .LCL_LEN gtr ..LENGTH then return NICE$_REE;
                        BUF_PTR = ch$move (.LCL_LEN, .LCL_ADDRESS, .BUF_PTR);
                        BUF_LEN = .BUF_LEN - .LCL_LEN;
                        LCL_ADDRESS = GETW (LCL_ADDRESS);
                        end;

                    STATUS = $NML$RETURN (.TYPE,
                                          .SELECTOR,
                                          .QUALIFIER,
                                          BUF_LEN,
                                          .BUF_PTR);

                    if .STATUS eql 1    ! If successful,
                    then                ! then
                        begin           ! account for inserted info.
                        label SEARCH_FOR_EXECUTOR;
                        .LENGTH = ..LENGTH - .BUF_LEN;
                        if (.TYPE eql NODE_E) and (.SELECTOR neq -3)
                        then            ! For nodes,
SEARCH_FOR_EXECUTOR:                    ! juggle the executor.
                            begin       ! SEARCH_FOR_EXECUTOR
                            local CNT, LNG, TEMP;
                            .LENGTH = ..LENGTH - .LCL_LEN; ! Include our copy.
                            do          ! Look for returned copy
                                begin
                                if .BUF_LEN leq 0
                                then leave SEARCH_FOR_EXECUTOR;
                                TEMP = GETW(BUF_PTR);
                                CNT = GETB(BUF_PTR);
                                BUF_PTR = ch$plus (.BUF_PTR, .CNT);
                                BUF_LEN = .BUF_LEN - (3 + .CNT);
                                end
                            while .TEMP neq .LCL_ADDRESS;
                            ch$move (.BUF_LEN, .BUF_PTR, ch$plus (.BUF_PTR, -(3 + .CNT)));
                                        ! Squeeze returned copy out.
                            .LENGTH = ..LENGTH + (3 + .CNT);
                            end;        ! SEARCH_FOR_EXECUTOR
                        end;

                    .STATUS
                    end;
%if $TOPS20
%then           [CIRCUIT_]:
                    begin
                    local BUFFER_LENGTH, STATUS;
                    external routine NMU$DLX_RETURN_CIRCUITS;

                    BUFFER_LENGTH = ..LENGTH;
                    STATUS = NMU$DLX_RETURN_CIRCUITS (.SELECTOR,
                                                      BUFFER_LENGTH,
                                                      ..BUFFER);

                    if .STATUS eql 1
                    then .LENGTH = ..LENGTH - .BUFFER_LENGTH;

                    .STATUS
                    end;
%fi
                [LOGGING_]:
                    begin
                    local PBF : PBF_BLOCK;
                    PBF [PBF_LEN_ADR] = .LENGTH;
                    PBF [PBF_BUF_PTR_ADR] = .BUFFER;
                    PBF [PBF_SELECTOR] = .SELECTOR;
                    NMU$QUEUE_SCAN (QH_LOGGING_PARAMETERS, PBF [PBF_BASE], SELECT_LOGGING);
                    if ..LENGTH lss 0 then return $NICE$ERR_REE;
                    NICE$_SUC
                    end;

                [MODULE_]:
                    begin
                    local LEN, NMX, PBM : PBM_BLOCK;

                    if .SELECTOR neq -1 ! Check for known qualifier
                    then return $NICE$ERR_MPE;

                    PBM [PBM_LEN_ADR] = .LENGTH;
                    PBM [PBM_BUF_PTR_ADR] = .BUFFER;
                    PBM [PBM_SELECTOR] = .SELECTOR;
                    NMU$QUEUE_SCAN (QH_MODULE_PARAMETERS, PBM [PBM_BASE], SELECT_MODULE);
                    if ..LENGTH lss 0 then return $NICE$ERR_REE;

                    LEN = ..LENGTH;
                    NMX = $NML$RETURN (.TYPE, ! Get entity ids from NMX
                                       .SELECTOR,
                                       .QUALIFIER,
                                       LEN,
                                       ..BUFFER);

                    if .NMX eql 1       ! If successful, update buffer length
                    then .LENGTH = ..LENGTH - .LEN;

                    if .NMX eql NICE$_REE then return .NMX;

                    NICE$_SUC           ! Return success
                    end;

                [otherwise]:
                    $NICE$ERR_MPE;
                tes;

        [inrange,                       ! Invalid function code
         outrange]:
            $NICE$ERR_MPE;
        tes

    end;				! End of NML$VDB
%global_routine ('NML$GET_VDB_PARAMETER', ENTITY_TYPE, ENTITY_PTR, PARM_NO, DATA_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Extracts the data for a specific parameter from the volatile
!       data base. Upon return the value of the parameter is stored
!       at the address specified by DATA_ADDR.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - Entity type number.
!       ENTITY_PTR  - Character pointer to entity id.
!       PARM_NO     - Parameter number.
!       DATA_ADDR   - Address of returned data.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	TRUE, if the parameter exists in the volatile data base;
!       FALSE, otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         EDB_QE: ref ENTITY_DB_BLOCK,
         PVB: ref $NML$PVB_ENTRY_VECTOR (0);

    if (EDB_QE = GET_EXISTING_ENTITY_DB (.ENTITY_TYPE, .ENTITY_PTR)) eql 0
    then return $FALSE;

    !
    ! Perform special casing for parameters which have seperate
    ! parameter numbers for reading and writing.
    !

    if (.ENTITY_TYPE eql NODE_E)        ! HOST Parameter (Read)
    and (.PARM_NO eql 140)
    then PARM_NO = 141;        ! Make it 141

    if ((.EDB_QE[EDB_PARAMETER_ALLOCATION] eql 0) ! They better all be in
    and (.EDB_QE[EDB_PARAMETER_VECTOR] eql 0)) ! agreement.
    or (.EDB_QE[EDB_PARAMETER_COUNT] eql 0)
    then return $FALSE;

    PVB = .EDB_QE[EDB_PARAMETER_VECTOR];  ! Get address of parameter vector

    incr N from 0 to .EDB_QE[EDB_PARAMETER_COUNT] - 1
    do begin
       bind PVB_QE = PVB[.N,0,0,0,0]: $NML$PVB_ENTRY_BLOCK;

       if .PARM_NO leq .PVB_QE[PE_NUMBER]
       then begin
            if .PARM_NO eql .PVB_QE[PE_NUMBER]
            then begin
                 local DATA_TYPE: block [1] field (DATA_TYPE_FIELDS);

                 DATA_TYPE = NML$GET_PDB_DATA_TYPE (.ENTITY_TYPE, .PARM_NO);
                 if .DATA_TYPE[DT_CODED] eql 0 ! Not coded
                 then begin
                      if .DATA_TYPE[DT_FTYPE] eql 0
                      then begin        ! Binary number
                           if .DATA_TYPE[DT_LENGTH] eql 0 ! Image field
                           then .DATA_ADDR = ch$ptr (.PVB_QE[PE_ADDRESS],,8)
                           else begin   ! Data stored in ....
                                if .DATA_TYPE[DT_LENGTH] leq %bpval/8
                                then .DATA_ADDR = .PVB_QE[PE_DATA] ! Value
                                else begin ! Buffer
                                     local PTR;

                                     PTR = ch$ptr (.PVB_QE[PE_ADDRESS],,8);
                                     get32 (PTR, .DATA_ADDR);
                                     end;
                                end;
                           end
                      else begin        ! ASCII image field
                           .DATA_ADDR = ch$ptr (.PVB_QE[PE_ADDRESS],,8);
                           end;
                      end
                 else begin             ! Coded
                      if .DATA_TYPE[DT_FTYPE] eql 0
                      then .DATA_ADDR = .PVB_QE[PE_DATA] ! Single field
                      else begin  ! Multiple field
                           local DT: block [1] field (DATA_TYPE_FIELDS);

                           if (.ENTITY_TYPE eql NODE_E) ! Special cases.
                           and (.PVB_QE[PE_NUMBER] eql 141) ! HOST
                           then .DATA_ADDR = ch$ptr (.PVB_QE[PE_ADDRESS],,8)
                           else .DATA_ADDR = 0; ! Unknown multiple parameter
                           end;
                      end;

                 return $TRUE;
                 end;

            exitloop;
            end;
       end;

    return $FALSE;  
    end;				! End of NML$GET_VDB_PARAMETER
%global_routine ('NML$SET_VDB_PARAMETER', ENTITY_TYPE, ENTITY_PTR, PARM_NO, DATA_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Inserts the data for a specific parameter into the volatile
!       data base. The value of the parameter is stored
!       at the address specified by DATA_ADDR.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - Entity type number.
!       ENTITY_PTR  - Character pointer to entity id.
!       PARM_NO     - Parameter number.
!       DATA_ADDR   - Address of data for value.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	TRUE, if the parameter was set in the volatile data base;
!       FALSE, otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         LPVB_QE: $NML$PVB_ENTRY_BLOCK, ! Local PVB entry
         EDB_QE: ref ENTITY_DB_BLOCK,   ! Entity DB entry
         L,                             ! Length of parameter data
         PRM_PTR;                       ! Pointer to parameter buffer

    if (EDB_QE = GET_EXISTING_ENTITY_DB (.ENTITY_TYPE, .ENTITY_PTR)) eql 0
    then if (EDB_QE = SET_ENTITY_DB (.ENTITY_TYPE, .ENTITY_PTR)) eql 0
         then return $FALSE;            ! Could not get entity db

    !
    ! Allocate a buffer for parameter, build a local temporary PVB
    ! entry, and place the parameter number and data in the buffer
    ! in format for response. Then get rid of the data type byte in
    ! in the buffer.
    !

    PRM_PTR = ch$ptr (PRM_BFR,,8);

    LPVB_QE[PE_NUMBER] = .PARM_NO;      ! Get parameter number
    LPVB_QE[PE_DATA] = ..DATA_ADDR;

    L = READ_PARAMETER_DATA (.ENTITY_TYPE,
                             LPVB_QE,
                             PRM_BFR_LENGTH,
                             PRM_PTR);

    ch$move (.L, ch$ptr (PRM_BFR,3,8), ch$ptr (PRM_BFR,2,8));

    !
    ! Insert the parameter into the table vector.
    !

    return (INSERT_PARAMETER (.EDB_QE, .ENTITY_TYPE, ch$ptr (PRM_BFR,,8), $true) eql NICE$_SUC);
    end;				! End of NML$SET_VDB_PARAMETER
%global_routine ('NML$CLR_VDB_PARAMETER', ENTITY_TYPE, ENTITY_PTR, PARM_NO) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Removes a parameter from the volatile data base.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - Entity type number.
!       ENTITY_PTR  - Character pointer to entity id.
!       PARM_NO     - Parameter number.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	TRUE, if the parameter exists in the volatile data base;
!       FALSE, otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         EDB_QE: ref ENTITY_DB_BLOCK;   ! Entity DB entry

    if (EDB_QE = GET_EXISTING_ENTITY_DB(.ENTITY_TYPE,.ENTITY_PTR)) eql 0
    then return $FALSE;

    !
    ! Perform special casing for parameters which have seperate
    ! parameter numbers for reading and writing.
    !

    if (.ENTITY_TYPE eql NODE_E)        ! HOST Parameter (Read)
    and (.PARM_NO eql 140)
    then PARM_NO = 141;                 ! Make it 141

    !
    ! Remove the parameter from the table vector, always succeeds.
    !

    REMOVE_PARAMETER (.EDB_QE, .ENTITY_TYPE, .PARM_NO, $true);

    return $TRUE;
    end;				! End of NML$CLR_VDB_PARAMETER
%global_routine ('NML$FIND_NDB', CKT_ENTITY_ID) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Searches the NODE entity volatile data base for the node
!       which has the service circuit parameter corresponding to the
!       CIRCUIT entity specified as an argument.
!
! FORMAL PARAMETERS
!
!	CKT_ENTITY_ID - Pointer to circuit entity id.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Pointer to the node entity id if the node is found;
!       0 if not found.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         NDB_QE: ref NODE_DB_BLOCK;

    $SHOW_NDB

    NDB_QE = NMU$QUEUE_SCAN (QH_NODE_PARAMETERS, .CKT_ENTITY_ID, SVC_CKT_MATCH);

    if .NDB_QE neq 0
    then return ch$ptr (NDB_QE[NDB_ENTITY_ID],,8)
    else return 0;

    end;				! End of NML$FIND_NDB
%routine ('SELECT_LOGGING', EDB_QE : ref ENTITY_DB_BLOCK, PBF : ref PBF_BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No filters supported yet.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    selectone .PBF [PBF_SELECTOR] of
        set
        [-1]:
            ;
        [otherwise]:
            begin
            literal ON = 0, OFF = 1, HOLD = 2;
            local STATE;

            NML$GET_VDB_PARAMETER (LOGGING_,
                                   ch$ptr (EDB_QE[EDB_ENTITY_ID],,8),
                                   0,
                                   STATE);
            selectone .STATE of
                set
                [ON, HOLD]:
                    ;
                [otherwise]:
                    return 0;
                tes;
            end;
        tes;

    if (.PBF [PBF_LEN_ADR] = ..PBF [PBF_LEN_ADR] - 1) geq 0
    then
        ch$wchar_a (ch$rchar (ch$ptr (EDB_QE[EDB_ENTITY_ID],,8)),
                    .PBF [PBF_BUF_PTR_ADR]);

    return 0
    end;				! End of SELECT_LOGGING
%routine ('SELECT_MODULE', EDB_QE : ref ENTITY_DB_BLOCK, PBM : ref PBM_BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No filters supported yet.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin
    local LEN;

    selectone .PBM [PBM_SELECTOR] of
        set
        [-1]:
            ;
        [otherwise]:
            return 0;
        tes;

    LEN = ch$rchar (ch$ptr (EDB_QE[EDB_ENTITY_ID],,8)) + 1;

    if (.PBM [PBM_LEN_ADR] = ..PBM [PBM_LEN_ADR] - .LEN) geq 0
    then
        .PBM [PBM_BUF_PTR_ADR] = ch$move (.LEN,
                                          ch$ptr (EDB_QE[EDB_ENTITY_ID],,8),
                                          ..PBM [PBM_BUF_PTR_ADR]);

    return 0
    end;				! End of SELECT_MODULE
%routine ('VDB_READ', FUNCTION, TYPE, ENTITY, QUALIFIER, SELECTOR, LENGTH, BP_ADDR, ERR_DETAIL) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Performs the NML NICE read function for NML volatile parameters.
!
! FORMAL PARAMETERS
!
!	FUNCTION  - Code to denote whether the specified parameter is to be
!                   defined or purged.
!       TYPE      - The NML entity type number of the entity to which the
!                   parameter pertains.
!       ENTITY    - Character sequence pointer to the entity id.
!       QUALIFIER - An optional character sequence pointer to a qualifier in
!                   parameter format.
!       SELECTOR  - For the return function, the class of entities to return.
!       LENGTH    - The address of a variable to be updated with the length
!                   of the data returned in the buffer.
!       BP_ADDR   - The address of a character sequence pointer to 
!                   the parameter buffer.
!       ERR_DETAIL- The address of a variable in which to return the
!		    error detail field for the response message if this
!		    request fails.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NML specified NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         RESULT,
         EDB_QE: ref ENTITY_DB_BLOCK;

    $SHOW_EDB

    if (EDB_QE = GET_EXISTING_ENTITY_DB (.TYPE, .ENTITY)) eql 0
    then RESULT = (if ENTITY_IS_VALID (.TYPE, .ENTITY)
                   then NICE$_SUC
                   else begin
			.ERR_DETAIL = .TYPE;
			$NICE$ERR_URC
			end)
    else begin
         %if $X25 and not $MCB
         %then

         if .TYPE eql MODULE_
         then begin
              RESULT = READ_QUALIFIED_ENTITY (.EDB_QE,
                                              .FUNCTION,
                                              .TYPE,
                                              .ENTITY,
                                              .QUALIFIER,
                                              .SELECTOR,
                                              .LENGTH,
                                              .BP_ADDR);

              return .RESULT;
              end;

         %fi

         RESULT = READ_ENTITY (.EDB_QE,
                               .FUNCTION,
                               .TYPE,
                               .ENTITY,
                               .QUALIFIER,
                               .SELECTOR,
                               .LENGTH,
                               .BP_ADDR);
         end;

    return .RESULT;
    end;				! End of VDB_READ
%if $X25 and not $MCB %then
%routine ('READ_QUALIFIED_ENTITY', EDB_QE, FUNCTION, TYPE, ENTITY, QUALIFIER, SELECTOR, LENGTH, POINTER) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Perform the read information function for a specific entity
!       in the volatile data base which has qualifier sub-queues.
!
! FORMAL PARAMETERS
!
!	EDB_QE    - Address of the entity data base entry.
!	FUNCTION  - Code to denote whether a straight read parameters/counters
!                   operation or a show and zero counters is performed.
!       TYPE      - The NML entity type number of the entity to which the
!                   parameter pertains.
!       ENTITY    - Character sequence pointer to the entity id.
!       QUALIFIER - An optional character sequence pointer to a qualifier in
!                   parameter format.
!       SELECTOR  - For the return function, the class of entities to return.
!       LENGTH    - The address of a variable to be updated with the length
!                   of the data returned in the buffer.
!       POINTER   - The address of a character sequence pointer to 
!                   the parameter buffer.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        EDB_QE: ref ENTITY_DB_BLOCK;

    local
        QUALIFIER_QUEUE: ref Q_HEADER,
        ENTRY: ref ENTITY_DB_BLOCK;

    QUALIFIER_QUEUE = EDB_QE[EDB_QUALIFIER_QUEUE]; ! Get qualified queue header

    if .QUALIFIER eql 0
    then begin                          ! Read default existing queue

         ! If the queue length (number of entries) is not 1,
         ! i.e. the queue does not have any entries or more than one

         if NMU$QUEUE_LENGTH (.QUALIFIER_QUEUE) neq 1
         then begin                     ! Return list of network names
              local NEXT: ref Q_ENTRY;

              NEXT = .QUALIFIER_QUEUE[Q_FORWARD];
              while ((ENTRY = .NEXT) neq .QUALIFIER_QUEUE)
              do begin
                 NEXT = .NEXT[Q_FORWARD];
                 READ_QUALIFIER (.ENTRY, .LENGTH, .POINTER);
                 end;

              return NICE$_SUC;
              end;

         ENTRY = .QUALIFIER_QUEUE[Q_FORWARD]; ! Default qualified queue
         end
    else begin                          ! Read specific queue
         local ID_STRING, COUNT: $SIGNED_BYTE_VALUE;

         ID_STRING = ch$plus (.QUALIFIER, 2);
         COUNT = ch$rchar (.ID_STRING); ! Get the count byte

         if .COUNT[VALUE] lss 0         ! If count byte is negative ....
         then begin                     ! Read KNOWN qualified queues
              local RESULT, NEXT: ref Q_ENTRY;

              NEXT = .QUALIFIER_QUEUE[Q_FORWARD];
              RESULT = NICE$_SUC;

              while (.RESULT eql NICE$_SUC)
              and ((ENTRY = .NEXT) neq .QUALIFIER_QUEUE)
              do begin
                 NEXT = .NEXT[Q_FORWARD];
                 READ_QUALIFIER (.ENTRY, .LENGTH, .POINTER);
                 RESULT = READ_ENTITY (.ENTRY,
                                       .FUNCTION,
                                       .TYPE,
                                       .ENTITY,
                                       .QUALIFIER,
                                       .SELECTOR,
                                       .LENGTH,
                                       .POINTER);
                 end;

              return .RESULT;
              end
         else begin                     ! Read specific qualified queue
              ENTRY = NMU$QUEUE_SCAN (.QUALIFIER_QUEUE,
                                      .ID_STRING,
                                      NON_NODE_ID_MATCH);

              if .ENTRY eql 0           ! No data base for specified qualifier
              then return NICE$_SUC;
              end;
         end;

    READ_QUALIFIER (.ENTRY, .LENGTH, .POINTER);

    return READ_ENTITY (.ENTRY,
                        .FUNCTION,
                        .TYPE,
                        .ENTITY,
                        .QUALIFIER,
                        .SELECTOR,
                        .LENGTH,
                        .POINTER);
    end;				! End of READ_QUALIFIED_ENTITY
%fi
%sbttl ''
%if $X25 and not $MCB %then
%routine ('READ_QUALIFIER', ENTRY, LENGTH, POINTER) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Perform the read qualifier for a specific qualifier queue
!       in the volatile data base.
!
! FORMAL PARAMETERS
!
!	ENTRY   Address of the entity data base entry.
!       LENGTH  The address of a variable to be updated with the length
!               of the data returned in the buffer.
!       POINTER The address of a character sequence pointer to 
!               the parameter buffer.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        ENTRY: ref ENTITY_DB_BLOCK;

    local
        VAL;

    VAL = 1110;                         ! NETWORK parameter number
    PUTW (VAL, .POINTER);

    PUTB (%O'100', .POINTER);           ! Data type byte

    VAL = ch$rchar (ch$ptr (ENTRY[EDB_QUALIFIER],,8)) + 1;
    .POINTER = ch$move (.VAL,           ! Network name string
                        ch$ptr (ENTRY[EDB_QUALIFIER],,8),
                        ..POINTER);

    .LENGTH = ..LENGTH - .VAL - 3;      ! Remaining length of the buffer

    return;
    end;                                ! End of READ_QUALIFIER
%fi
%routine ('READ_ENTITY', EDB_QE, FUNCTION, TYPE, ENTITY, QUALIFIER, SELECTOR, LENGTH, BP_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Perform the read information function for a specific entity
!       in the volatile data base.
!
! FORMAL PARAMETERS
!
!	EDB_QE    - Address of the entity data base entry.
!	FUNCTION  - Code to denote whether a straight read parameters/counters
!                   operation or a show and zero counters is performed.
!       TYPE      - The NML entity type number of the entity to which the
!                   parameter pertains.
!       ENTITY    - Character sequence pointer to the entity id.
!       QUALIFIER - An optional character sequence pointer to a qualifier in
!                   parameter format.
!       SELECTOR  - For the return function, the class of entities to return.
!       LENGTH    - The address of a variable to be updated with the length
!                   of the data returned in the buffer.
!       BP_ADDR   - The address of a character sequence pointer to 
!                   the parameter buffer.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    local
         PVB_QE: ref $NML$PVB_ENTRY_BLOCK;

    selectone .FUNCTION of
        set
        [%bliss36($NTSHO)
         %bliss16(N$FSHO)]:               ! Show parameters
            begin
            case .SELECTOR from SUMMARY_ to EVENTS_ of
                set
                [SUMMARY_, STATUS_, CHARACTERISTICS_]: 
                    READ_PARAMETERS (.EDB_QE, .TYPE, .SELECTOR,
                                     .LENGTH, .BP_ADDR);
                [COUNTERS_]:
                    READ_COUNTERS (.EDB_QE, .TYPE, .SELECTOR,
                                   .LENGTH, .BP_ADDR);
                [EVENTS_]:
                    READ_FILTERS (.EDB_QE, .TYPE, .QUALIFIER,
                                  .LENGTH, .BP_ADDR);
                tes
            end;

        [%bliss36($NTSZC)
         %bliss16(N$FSZC)]:             ! Show and zero counters
            READ_COUNTERS (.EDB_QE, .TYPE, .SELECTOR,
                           .LENGTH, .BP_ADDR);
        [otherwise]:
            $NICE$ERR_MPE;
        tes

    end;				! End of READ_ENTITY
%routine ('READ_PARAMETERS', EDB_QE, TYPE, SELECTOR, LENGTH, BP_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Reads all of the NML parameters out of the volatile
!       data base for an entity.
!
! FORMAL PARAMETERS
!
!	EDB_QE    - Address of the entity data base entry.
!       TYPE      - The NML entity type number of the entity to which the
!                   parameter pertains.
!       SELECTOR  - For the return function, the class of entities to return.
!       LENGTH    - The address of a variable to be updated with the length
!                   of the data returned in the buffer.
!       BP_ADDR   - The address of a character sequence pointer to 
!                   the parameter buffer.
!
! IMPLICIT INPUTS
!
!	When called, the contents of the address passed as LENGTH
!	specifies the characters currently available in the buffer.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	The contents of LENGTH are updated.
!
!--

    begin

    map
        EDB_QE: ref ENTITY_DB_BLOCK;

    label
        DISPLAY_CHECK;

    literal
	CPARM_STATE = 0;                ! Circuit STATE

    !
    ! If parameter count is zero or a parameter vector is not currently
    ! allocated there is nothing to show.
    !

    if ((.EDB_QE[EDB_PARAMETER_ALLOCATION] eql 0) ! They better all be in
    and (.EDB_QE[EDB_PARAMETER_VECTOR] eql 0)) ! agreement.
    or (.EDB_QE[EDB_PARAMETER_COUNT] eql 0)
    then return NICE$_SUC;

    !
    ! Otherwise, if the count is non-zero and a parameter vector is
    ! allocated, then search through the vector for each parameter
    ! in the volatile data base and place a formatted entry in the
    ! buffer representing its current value.
    !

    begin

    local
        PVB_QE: ref $NML$PVB_ENTRY_BLOCK;

    PVB_QE = .EDB_QE[EDB_PARAMETER_VECTOR];

    decru N from .EDB_QE[EDB_PARAMETER_COUNT] to 1
    do begin
DISPLAY_CHECK:
       begin                            ! DISPLAY_CHECK
       local L;

       case .SELECTOR from SUMMARY_ to COUNTERS_ of
           set
           [STATUS_]:
               if not NML$STATUS (.TYPE, .PVB_QE[PE_NUMBER])
               then leave DISPLAY_CHECK;
           [SUMMARY_]:
               if not NML$SUMMARY (.TYPE, .PVB_QE[PE_NUMBER])
               then leave DISPLAY_CHECK;
           [CHARACTERISTICS_]:
               if not NML$CHARACTERISTIC (.TYPE, .PVB_QE[PE_NUMBER])
               then leave DISPLAY_CHECK;
           [inrange]:
               return NICE$_MPE;
           tes;
%if $MCB
%then
       selectone .TYPE of
           set
           [LINE_, CIRCUIT_]:
               if .PVB_QE[PE_NUMBER] eql CPARM_STATE
               then leave DISPLAY_CHECK;
           [otherwise]:
               ;
           tes;
%fi

       !
       ! If the parameter buffer length is 3 or less, we can't fill in
       ! any data in the buffer.
       !

       if ..LENGTH leq 3 then return NICE$_REE;

       L = READ_PARAMETER_DATA (.TYPE, .PVB_QE, ..LENGTH-3, .BP_ADDR) + 3;

       if ..LENGTH lss .L then return $NICE$ERR_REE;

       .LENGTH = ..LENGTH - .L
       end;                             ! DISPLAY_CHECK
       PVB_QE = vector [.PVB_QE, PVB_ENTRY_SIZE];
       end;

    end;

    if (.TYPE eql LOGGING_) and (.SELECTOR eql CHARACTERISTICS_)
    then READ_FILTERS (.EDB_QE, .TYPE, 0, .LENGTH, .BP_ADDR);

    return NICE$_SUC;
    end;				! End of READ_PARAMETERS
%routine ('READ_COUNTERS', EDB_QE, TYPE, SELECTOR, LENGTH, BP_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No counters are supported at this level.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    return $TRUE;
    end;				! End of READ_COUNTERS
%routine ('READ_FILTERS', EDB_QE, TYPE, QUALIFIER, LENGTH, BP_ADDR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No filters supported yet.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    local
        PBF : PBF_BLOCK,
        FDB : ref FDB_BLOCK,
        NODE_PTR;

%if NML$CFG_FILTERS
%then

    PBF [PBF_LEN_ADR] = .LENGTH;
    PBF [PBF_BUF_PTR_ADR] = .BP_ADDR;
    PBF [PBF_SINK] = ch$rchar (ch$ptr (EDB_QE [EDB_ENTITY_ID],, 8));

    if (NODE_PTR = .QUALIFIER) eql 0
    then begin
         FDB = NMU$QUEUE_SCAN (QH_LOGGING_FILTERS,
                               NMU$NETWORK_LOCAL (),
                               NODE_ID_MATCH);
         if .FDB neq 0
         then if READ_FILTER (.FDB, PBF) neq 0
              then return $FALSE;
         end
    else begin
         if (FDB = ch$rchar_a (NODE_PTR)) lequ 127
         then begin
              local NODE_BUF : block [NODE_ID_BUFFER_SIZE];

              if .FDB eql 0
              then begin
                   local NODE_ADR;

                   if (NODE_ADR = GETW (NODE_PTR)) eql 0
                   then begin
                        ch$move (NODE_ID_BUFFER_LENGTH,
                                 NMU$NETWORK_LOCAL (),
                                 ch$ptr (NODE_BUF,, 8));
                        NODE_PTR = 0;
                        end
                   else begin
                        NODE_PTR = ch$ptr (NODE_BUF,, 8);
                        PUTW (NODE_ADR, NODE_PTR);
                        PUTB (0, NODE_PTR);
                        end;
                   end
              else begin
                   NODE_PTR = ch$ptr (NODE_BUF,, 8);
                   PUTB (0, NODE_PTR);
                   PUTB (0, NODE_PTR);
                   ch$move (.FDB + 1, .QUALIFIER, .NODE_PTR);
                   end;

              if .NODE_PTR neq 0
              then begin
                   NODE_PTR = NODE_ID_BUFFER_LENGTH;
                   $NML$MAP_NODE_ID (NODE_PTR, ch$ptr (NODE_BUF,, 8));
                   end;

              FDB = NMU$QUEUE_SCAN (QH_LOGGING_FILTERS,
                                    ch$ptr (NODE_BUF,, 8),
                                    NODE_ID_MATCH);
              if .FDB neq 0
              then if READ_FILTER (.FDB, PBF) neq 0
                   then return $false;
              end
         else if NMU$QUEUE_SCAN (QH_LOGGING_FILTERS, PBF, READ_FILTER) neq 0
              then return $FALSE;
         end;

    return $TRUE
%else
    return $false
%fi
    end;				! End of READ_FILTERS
%routine ('READ_FILTER', FDB : ref FDB_BLOCK, PBF : ref PBF_BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No filters supported yet.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin
    PBF [PBF_NODE_ID_PTR] = ch$ptr (FDB [FDB_NODE_ID],, 8);

%if NML$CFG_FILTERS
%then

    selectone .PBF [PBF_SINK] of
        set
        [CONSOLE_]:
            NMU$QUEUE_SCAN (FDB [FDB_CONSOLE_FILTERS], .PBF, READ_FILTER_SINK);
        [FILE_]:
            NMU$QUEUE_SCAN (FDB [FDB_FILE_FILTERS], .PBF, READ_FILTER_SINK);
        [MONITOR_]:
            NMU$QUEUE_SCAN (FDB [FDB_MONITOR_FILTERS], .PBF, READ_FILTER_SINK);
        tes

%else
    0
%fi
    end;				! End of READ_FILTER
%routine ('READ_FILTER_SINK', FDBS : ref FDBS_BLOCK, PBF : ref PBF_BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No filters supported yet.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin
%if NML$CFG_FILTERS
%then
    PBF [PBF_ENTITY_PTR] = ch$ptr (FDBS [FDBS_ENTITY],, 8);
    NMU$QUEUE_SCAN (FDBS [FDBS_MASKS], .PBF, READ_FILTER_MASKS)
%else
    0
%fi
    end;				! End of READ_FILTER_SINK
%routine ('READ_FILTER_MASKS', FDBM : ref FDBM_BLOCK, PBF : ref PBF_BLOCK) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       No filters supported yet.
!
! FORMAL PARAMETERS
!
!	NONE.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    bind
        PE = PBF[PBF_PE] : $NML$PVB_ENTRY_BLOCK;

    local
        MASK : ref block field (MASK_BITS);

%if NML$CFG_FILTERS
%then

    MASK = FDBM[FDBM_MASKS];

    incr TYPE from .FDBM[FDBM_LOW] to .FDBM[FDBM_HIGH]
    do begin
       local LNG, PTR;

       LNG = 0;                         ! Copy BITVECTOR into 4 bytes
       PTR = ch$ptr (PBF[PBF_MASK],, 8);
       PUT32 (MASK[MASK_BITS], PTR);
       LNG = 0;                         ! Check if house is full or empty
       PTR = ch$ptr (PBF[PBF_MASK],, 8);
       decru CNT from 4 to 1 do LNG = .LNG + ch$rchar_a (PTR);
       if .LNG neq 0
       then begin
            if .LNG eql 4*255
            then LNG = -1
            else LNG = 4; %(for now)%

            if .PBF[PBF_NODE_ID_PTR] neq 0
            then begin
                 local L;

                 PE[PE_NUMBER] = 200;
                 PE[PE_ADDRESS] = .PBF[PBF_NODE_ID_PTR];
                 L = READ_PARAMETER_DATA (LOGGING_,
                                          PE,
                                          (..PBF[PBF_LEN_ADR] - 3),
                                          .PBF[PBF_BUF_PTR_ADR]) + 3;
                 if ..PBF[PBF_LEN_ADR] lss .L then return NICE$_REE;

                 .PBF[PBF_LEN_ADR] = ..PBF[PBF_LEN_ADR] + .L;
                 PBF[PBF_NODE_ID_PTR] = 0;
                 end;

            %(record ENTITY TYPE from FDBS[FDBS_ENTITY])%

            if .LNG gtr 0
            then begin %(record EVENT CLASS from 0^14 + .TYPE)%
                 0 %(record EVENT MASK from LNG and MASK[MASK_BITS])%
                 end
            else begin
                 0 %(record EVENT CLASS from 2^14 + .TYPE)%
                 end;
            end;

       MASK = vector [.MASK, MASK_SIZE];
       end;
%fi

    return 0
    end;				! End of READ_FILTER_MASKS
%routine ('VDB_CHANGE', FUNCTION, TYPE, QUALIFIER, ENTITY, LENGTH, POINTER, ERR_DETAIL) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Performs the NML NICE change function for NML volatile parameters.
!
! FORMAL PARAMETERS
!
!	FUNCTION  - Code to denote whether the specified parameter is to be
!                   set or cleared.
!       TYPE      - The NML entity type number of the entity to which the
!                   parameter pertains.
!       QUALIFIER - An optional character sequence pointer to a qualifier in
!                   parameter format.
!       ENTITY    - Character sequence pointer to the entity id.
!       LENGTH    - The length of the parameter data passed in the
!		    parameter buffer.
!       POINTER   - A character sequence pointer to the parameter buffer.
!       ERR_DETAIL- The address of a variable in which to return the
!		    error detail field for the response message if this
!		    request fails.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NML specified NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         EDB_QE: ref ENTITY_DB_BLOCK;

    selectone .FUNCTION of
        set
        [%bliss36($NTSET) %bliss16(N$FSET)]: ! SET parameter
            begin
            if (EDB_QE = GET_EXISTING_ENTITY_DB (.TYPE, .ENTITY)) eql 0
            then begin                  ! Could not locate data base entry
                 if not ENTITY_IS_VALID (.TYPE, .ENTITY) ! Is entity valid ?
                 then begin
		      .ERR_DETAIL = .TYPE;
		      return $NICE$ERR_URC; ! No, return error
		      end;

                 if (EDB_QE = SET_ENTITY_DB (.TYPE, .ENTITY)) eql 0
                 then return $NICE$ERR_NRE; ! Try to create data base entry

                 %if $X25 and not $MCB
                 %then

                 if .TYPE eql MODULE_   ! Initialize queue for network entries
                 then NMU$QUEUE_RESET (EDB_QE[EDB_QUALIFIER_QUEUE]);

                 %fi
                 end;

            selectone .TYPE of          ! Put the parameter entry into
                set                     ! the parameter data vector.
                [NODE_E]:
                    begin
                    local PTR;

                    PTR = .POINTER;     ! Get local copy of pointer
                    if GETW (PTR) eql 110 ! SERVICE CIRCUIT
                    then begin          ! Check if circuit already assigned
                         if (PTR = NML$FIND_NDB (.PTR)) neq 0
                         then
			     if not ch$eql (9, .PTR, 9, .ENTITY)
			     then begin
				  .ERR_DETAIL = CIRCUIT_;
				  return $NICE$ERR_CWS;
				  end;
                         end;

                    return INSERT_PARAMETER (.EDB_QE, .TYPE, .POINTER, $false);
                    end;

                %if $X25 and not $MCB   ! MODULE X25-ACCESS volatile data base
                %then                   ! exists in the TOPS only

                [MODULE_]:
                    return SET_QUALIFIED_ENTITY (.EDB_QE,
                                                 .TYPE,
                                                 .QUALIFIER,
                                                 .POINTER);
                %fi

                [otherwise]:
                    return INSERT_PARAMETER (.EDB_QE, .TYPE, .POINTER, $false);
                tes;
            end;

        [%bliss36($NTCLR) %bliss16(N$FCLR)]: ! CLEAR parameter
            begin
            if (EDB_QE = GET_EXISTING_ENTITY_DB (.TYPE, .ENTITY)) eql 0
            then begin
		 .ERR_DETAIL = .TYPE;
		 return $NICE$ERR_URC;
		 end
            else selectone .TYPE of
                     set
                     [MODULE_]:
                         %if $X25 and not $MCB %then
                         return REMOVE_QUALIFIED_PARAMETER (.EDB_QE,
                                                            .TYPE,
                                                            .QUALIFIER,
                                                            .POINTER,
                                                            .LENGTH,
                                                            $false);
                         %else
			 begin
			 .ERR_DETAIL = .TYPE;
                         return $NICE$ERR_URC;
			 end;
                         %fi

                     [otherwise]:
                         REMOVE_PARAMETER (.EDB_QE,
                                           .TYPE,
                                           (if .LENGTH gtr 0
                                            then GETW_NA (.POINTER)
                                            else -1), ! Zero implies ALL
                                           $false);
                     tes;
            end;

        [otherwise]:
            return $NICE$ERR_UFO;
        tes;

    return NICE$_SUC;
    end;				! End of VDB_CHANGE
%if $X25 and not $MCB %then
%routine ('SET_QUALIFIED_ENTITY', EDB_QE, ENTITY, QUALIFIER, PARAMETER) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Set the parameter entry in the qualified sub queues.
!
! FORMAL PARAMETERS
!
!	EDB_QE          Address of the qualified entity data base structure to
!                       which the parameter is to be inserted.
!       ENTITY          The entity type number to which the parameter applies.
!       QUALIFIER       A character sequence pointer to the qualifier
!                       parameter.
!       PARAMETER       A character sequence pointer to the parameter to
!                       be inserted.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        EDB_QE: ref ENTITY_DB_BLOCK;

    local
        QH_QUALIFIER: ref Q_HEADER,
        QE_QUALIFIER: ref ENTITY_DB_BLOCK;

    QH_QUALIFIER = EDB_QE[EDB_QUALIFIER_QUEUE];

    if .QUALIFIER eql 0
    then begin                          ! Use default existing qualifier queue
         if NMU$QUEUE_LENGTH (.QH_QUALIFIER) eql 1 ! Queue has only 1 entry ?
         then QE_QUALIFIER = .QH_QUALIFIER[Q_FORWARD] ! Yes, default queue
         else return $NICE$ERR_PAM;     ! No, expecting qualifier name
         end
    else begin                          ! Use specific qualifier queue
         local ID_STRING, COUNT: $SIGNED_BYTE_VALUE;

         ID_STRING = ch$plus (.QUALIFIER, 2); ! Get qualifier id string
         COUNT = ch$rchar (.ID_STRING); ! Get count byte

         if .COUNT[VALUE] lss 0         ! If count byte is negative ....
         then begin                     ! Set KNOWN qualified queues
              local RESULT, NEXT: ref Q_ENTRY;

              NEXT = .QH_QUALIFIER[Q_FORWARD];
              RESULT = NICE$_SUC;

              while (.RESULT eql NICE$_SUC)
              and ((QE_QUALIFIER = .NEXT) neq .QH_QUALIFIER)
              do begin
                 NEXT = .NEXT[Q_FORWARD];
                 RESULT = INSERT_PARAMETER (.QE_QUALIFIER,
                                            .ENTITY,
                                            .PARAMETER,
                                            $false);
                 end;

              return .RESULT;
              end
         else begin                     ! Set specific qualified queue
              QE_QUALIFIER = NMU$QUEUE_SCAN (.QH_QUALIFIER,
                                             .ID_STRING,
                                             NON_NODE_ID_MATCH);

              if .QE_QUALIFIER eql 0    ! Does entry exist ?
              then begin                ! No, create new entry for qualifier
                   QE_QUALIFIER = NMU$MEMORY_GET (ENTITY_DB_BLOCK_ALLOCATION);

                   if .QE_QUALIFIER eql 0 ! Fail to allocate memory
                   then return $NICE$ERR_NRE;

                   ch$move ((.COUNT[VALUE] + 1),
                            .ID_STRING,
                            ch$ptr (QE_QUALIFIER[EDB_QUALIFIER],,8));

                   NMU$QUEUE_INSERT (.QH_QUALIFIER, .QE_QUALIFIER);
                   end;
              end;
         end;

    return INSERT_PARAMETER (.QE_QUALIFIER, .ENTITY, .PARAMETER, $false);
    end;				! End of SET_QUALIFIED_ENTITY
%fi
%sbttl ''
%routine ('SET_NODE_ENTITY', NDB_QE: ref NODE_DB_BLOCK, ENTITY_PTR) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Sets up the entity id portion of an EDB for NODE entity.
!
! FORMAL PARAMETERS
!
!	NDB_QE - Address of the NDB Queue Entry.
!       ENTITY_PTR - Pointer to the NODE id.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         NODE_PTR,
         NODE_ADDR;

    NODE_ADDR = GETW (ENTITY_PTR);
    NODE_PTR = ch$ptr (NDB_QE[NDB_ENTITY_ID],,8);
    PUTW (NODE_ADDR, NODE_PTR);
    ch$move ((ch$rchar (.ENTITY_PTR) + 1), .ENTITY_PTR, .NODE_PTR);

    end;				! End of SET_NODE_ENTITY
%routine ('GET_EXISTING_ENTITY_DB', ENTITY_TYPE, ENTITY_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Searches the volatile data base for the specified entity,
!	and if found, returns the address of the entity data block.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - Entity type number.
!       ENTITY_PTR  - Character pointer to entity id.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	The address of the entity data block if the entity exists
!	    in the volatile data base.
!       Otherwise, 0.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
	QUEUE,
	MATCH_ROUTINE;

    !
    ! Determine the queue to which this entity belongs and the routine
    ! to be used for matching the entity id.
    !

    if GET_VDB_ENTITY_QUEUE (.ENTITY_TYPE, QUEUE, MATCH_ROUTINE)
    then NMU$QUEUE_SCAN (.QUEUE, .ENTITY_PTR, .MATCH_ROUTINE)
    else 0

    end;				! End of GET_EXISTING_ENTITY_DB
%routine ('SET_ENTITY_DB', ENTITY_TYPE, ENTITY_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Allocate and initialize an entry in the data base.
!       Returns the address of the entry in all cases.
!
! FORMAL PARAMETERS
!
!       ENTITY_TYPE - The entity type number.
!       ENTITY_PTR - A character sequence pointer to the entity id
!                    to be created.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Address of the entity data base block.
!	0 if no insufficient resources for data base creation.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         QHEADER,
         EDB_QE: ref ENTITY_DB_BLOCK;

    selectone .ENTITY_TYPE of
        set
        [NODE_E]:
            begin
            if (EDB_QE = NMU$MEMORY_GET (ENTITY_DB_BLOCK_ALLOCATION)) eql 0
            then return 0;

            SET_NODE_ENTITY (.EDB_QE, .ENTITY_PTR);
            end;

        [LINE_,
         CIRCUIT_,
         LOGGING_,
         MODULE_]:
            begin
            if (EDB_QE = NMU$MEMORY_GET (ENTITY_DB_BLOCK_ALLOCATION)) eql 0
            then return 0;

            ch$move ((ch$rchar (.ENTITY_PTR) + 1), ! Copy entity id
                     .ENTITY_PTR,
                     ch$ptr (EDB_QE[EDB_ENTITY_ID],,8));
            end;

        [otherwise]:                    ! NOT supported entity
            begin
            TASK_ERROR ('Invalid entity for data base creation');
            return 0;
            end;
        tes;

    if GET_VDB_ENTITY_QUEUE (.ENTITY_TYPE, QHEADER, 0) ! Get queue header
    then NMU$QUEUE_INSERT (.QHEADER, .EDB_QE) ! Insert the entity in data base.
    else begin                          ! No queue header for this entity
         TASK_ERROR ('Missing queue for data base creation');
         return 0;
         end;

    return .EDB_QE;                     ! Return address of entry
    end;				! End of SET_ENTITY_DB
%routine ('ENTITY_IS_VALID', ENTITY_TYPE, ENTITY_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Determine if we should allow this entity to be added
!       to the data bases.  In MCB, we ask NMX about LINEs and CIRCUITs.
!       In TOPS20, determine if a DTE is legal.
!
! FORMAL PARAMETERS
!
!       ENTITY_TYPE - The entity type number.
!       ENTITY_PTR - A character sequence pointer to the entity id
!                    to be created.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	$true - if entity is acceptable
!       $false - Don't add this to the data bases!
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         EDB_QE: ref ENTITY_DB_BLOCK;

    selectone .ENTITY_TYPE of
        set
        [NODE_E]:
            begin                    ! Verify existence of entity ....
            EDB_QE = 2;
            return ($NML$SHOW (.ENTITY_TYPE,       ! Returns OCM error
                               .ENTITY_PTR,	   !  if valid entity
                               0,		   !  since buffer is
                               SUMMARY_,	   !  too small.
                               EDB_QE,		   ! Otherwise,
                               ch$ptr (EDB_QE,,8)) !  entity is invalid.
                    eql
			%if $MCB
			%then
			      $NICE$ERR_OCM);      ! in the MCB
			%else
			      $NICE$ERR_REE);      ! in the TOPS
			%fi
            end;

        [MODULE_]:
            return (MODULE_IS_VALID (ch$rchar (.ENTITY_PTR),
                                     ch$plus (.ENTITY_PTR, 1)));

        [LOGGING_]:
            return (GET_EXISTING_ENTITY_DB (.ENTITY_TYPE, .ENTITY_PTR) neq 0);

        [LINE_, CIRCUIT_]:
            begin
            %if $MCB                    ! Verify existence of entity ....
            %then                       ! in the MCB
            EDB_QE = 2;
            return ($NML$SHOW (.ENTITY_TYPE,
                               .ENTITY_PTR,
                               0,
                               SUMMARY_,
                               EDB_QE,
                               ch$ptr (EDB_QE,,8))
                    neq $NICE$ERR_URC);

            %else                       ! in the TOPS
            external routine NMU$DLX_KNOWN_DEVICE;

            return (NMU$DLX_KNOWN_DEVICE (.ENTITY_PTR));
            %fi

            end;

        [otherwise]:
            TASK_ERROR ('Invalid entity for data base creation');
        tes;

    return $FALSE;
    end;				! End of ENTITY_IS_VALID
%routine ('MODULE_IS_VALID', LENGTH, POINTER) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Determine if we should allow this module data base to be handled
!       in this layer.
!
! FORMAL PARAMETERS
!
!       LENGTH          The module name length
!       POINTER         A character sequence pointer to the module name
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	$TRUE           If module is acceptable
!       $FALSE          Otherwise
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    %if $X25
    %then %if $MCB
          %then                         ! These modules are valid in the MCB
          return (ch$eql (.LENGTH,
                          .POINTER,
                          %charcount ('X25-PROTOCOL'),
                          CH$ASCIZ ('X25-PROTOCOL'),
                          0) or
                  ch$eql (.LENGTH,
                          .POINTER,
                          %charcount ('X25-SERVER'),
                          CH$ASCIZ ('X25-SERVER'),
                          0));

          %else                         ! These modules are valid in the TOPS
          return (ch$eql (.LENGTH,
                          .POINTER,
                          %charcount ('X25-ACCESS'),
                          CH$ASCIZ ('X25-ACCESS'),
                          0));
          %fi

    %else
    return $FALSE;                      ! No module is available
    %fi

    end;				! End of MODULE_IS_VALID
%routine ('GET_VDB_ENTITY_QUEUE', ENTITY_TYPE, QUEUE, MATCH_ROUTINE) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine determines the queue in the volatile data base
!       as well as the matching routine associated with the specified
!       entity type.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE     Entity type number.
!       QUEUE           The address in which to return the address of the
!                       queue header for this type of entity.
!       MATCH_ROUTINE   The address in which to return the address
!                       of the associated string matching routine.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	$TRUE   If the volatile data base contains this entity type.
!       $FALSE  Otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
        QUEUE_HEADER,
        QUEUE_MATCH_ROUTINE;

    case .ENTITY_TYPE from NODE_E to MODULE_ of
        set
        [NODE_E]:
            begin
            QUEUE_HEADER = QH_NODE_PARAMETERS;
            QUEUE_MATCH_ROUTINE = NODE_ID_MATCH;
            end;

        [LINE_]:
            begin
            QUEUE_HEADER = QH_LINE_PARAMETERS;
            QUEUE_MATCH_ROUTINE = NON_NODE_ID_MATCH;
            end;

        [LOGGING_]:
            begin
            QUEUE_HEADER = QH_LOGGING_PARAMETERS;
            QUEUE_MATCH_ROUTINE = LOGGING_ID_MATCH;
            end;

        [CIRCUIT_]:
            begin
            QUEUE_HEADER = QH_CIRCUIT_PARAMETERS;
            QUEUE_MATCH_ROUTINE = NON_NODE_ID_MATCH;
            end;

        [MODULE_]: 
            begin
            %if $X25
            %then
            QUEUE_HEADER = QH_MODULE_PARAMETERS;
            QUEUE_MATCH_ROUTINE = NON_NODE_ID_MATCH;

            %else
            return $FALSE;
            %fi

            end;

        [inrange,
         outrange]:
            return $FALSE;
        tes;

!
! If no address is specified do not return value
!

    if .QUEUE neq 0
    then .QUEUE = .QUEUE_HEADER;

    if .MATCH_ROUTINE neq 0
    then .MATCH_ROUTINE = .QUEUE_MATCH_ROUTINE;

    return $TRUE;
    end;				! End of GET_VDB_ENTITY_QUEUE
%routine ('INSERT_PARAMETER', EDB_QE, ENTITY_TYPE, PRM_PTR, PRIVLEDGED) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Inserts a parameter entry into the parameter vector of the
!       data base for an entity.
!
! FORMAL PARAMETERS
!
!	EDB_QE      - The address of the entity data base structure to
!                     which the parameter is to be inserted.
!       ENTITY_TYPE - The entity type number to which the parameter
!		      applies.
!       PRM_PTR     - A character sequence pointer to the parameter to
!                     be inserted.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    local
         PVB: ref $NML$PVB_ENTRY_VECTOR (0),
	 PVB_QE: ref $NML$PVB_ENTRY_BLOCK,
         PARM_NO;

    PARM_NO = GETW (PRM_PTR);

%( Does the parameter apply to this entity?
   Does the entity exist and is it in the ON state?
   If a node entity and the parameter is one which applies to
   an adjacent node, is the node address valid? )%

    if not APPLICABLE (.ENTITY_TYPE, .EDB_QE, .PARM_NO)
    then return $NICE$ERR_PNA;

    if NML$READ_ONLY (.ENTITY_TYPE, .PARM_NO) and not .PRIVLEDGED
    then return $NICE$ERR_PNA;

    !
    ! If this is a counter timer, adjust the counter time data base
    ! to reflect the time change.
    !

    if not NML$COUNTER_TIMER_SET (.PARM_NO,
                                  .ENTITY_TYPE,
                                  EDB_QE[EDB_ENTITY_ID],
				  .PRM_PTR)
    then return $NICE$ERR_IPV;          ! Illegal parameter value

    !
    ! Search through the vector for the location to insert the
    ! parameter.  If the parameter is already in the vector,
    ! simply change its value.  Otherwise, ripple all parameters
    ! numbered higher than the new one up one position in the vector,
    ! and then insert the new parameter.
    !

    PVB = .EDB_QE[EDB_PARAMETER_VECTOR];

    incr N from 0 to .EDB_QE[EDB_PARAMETER_COUNT] - 1
    do begin
       PVB_QE = PVB[.N,0,0,0,0];

       if .PARM_NO leq .PVB_QE[PE_NUMBER]
       then begin
            if .PARM_NO eql .PVB_QE[PE_NUMBER]
            then begin			! Found in table
		 if SET_PARAMETER_DATA (.ENTITY_TYPE, .PRM_PTR, .PVB_QE)
                 then return NICE$_SUC
                 else return $NICE$ERR_REE;
		 end
	    else begin			! Entry not in table
		 if not EXPAND_PVB (.EDB_QE, .N)
                 then return $NICE$ERR_REE;

		 PVB = .EDB_QE[EDB_PARAMETER_VECTOR];
		 PVB_QE = PVB[.N,0,0,0,0];
 		 PVB_QE[PE_NUMBER] = .PARM_NO;
		 if not SET_PARAMETER_DATA (.ENTITY_TYPE, .PRM_PTR, .PVB_QE)
                 then return $NICE$ERR_REE;

		 EDB_QE[EDB_PARAMETER_COUNT] = .EDB_QE[EDB_PARAMETER_COUNT] + 1;
		 return NICE$_SUC;
		 end;
            end;
       end;

    !
    ! If we get here, the parameter could not be inserted within the
    ! vector.  If there were initially no parameters, this will be the
    ! first entry;  otherwise it will be the last entry.
    !

    if not GET_PVB (.EDB_QE)
    then return $NICE$ERR_REE;

    PVB = .EDB_QE[EDB_PARAMETER_VECTOR];
    PVB_QE = PVB[.EDB_QE[EDB_PARAMETER_COUNT],0,0,0,0];
    PVB_QE[PE_NUMBER] = .PARM_NO;

    if not SET_PARAMETER_DATA (.ENTITY_TYPE, .PRM_PTR, .PVB_QE)
    then return $NICE$ERR_REE;

    EDB_QE[EDB_PARAMETER_COUNT] = .EDB_QE[EDB_PARAMETER_COUNT] + 1;

    return NICE$_SUC;
    end;				! End of INSERT_PARAMETER
%routine ('COPY_PARAMETER_VECTOR', OPVB, NPVB, COUNT) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
! Copy a parameter vector.
!
! FORMAL PARAMETERS
!
!	OPVB - The address of the old parameter vector.
!       NPVB - The address of the new parameter vector.
!       COUNT - The number of elements to copy.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
       CNPVB: ref vector,
       COPVB: ref vector;

    CNPVB = .NPVB;
    COPVB = .OPVB;

    decru CNT from (.COUNT*PVB_ENTRY_SIZE) to 1
    do begin
       CNPVB [0] = .COPVB [0];
       CNPVB = CNPVB [1];
       COPVB = COPVB [1];
       end;

    end;				! End of COPY_PARAMETER_VECTOR
%routine ('APPLICABLE', ENTITY_TYPE, EDB_QE, PARM_NO) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Determines whether a parameter, if an NML data base parameter,
!       applies to an entry in the NML data base which represents a
!       specific entity. I.e., if a parameter is applicable to the
!       executor node only, then it could not apply to a data base
!       entry for a remote node.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - The entity type number of this entity.
!       EDB_QE      - The address of the entity data base entry for
!                     particular entity.
!       PARM_NO     - The parameter type number.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	TRUE, if the parameter is applies to this entity;
!       FALSE, otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    case .ENTITY_TYPE from NODE_E to MODULE_ of
        set
        [NODE_E]:
            if NML$EXECUTOR_ONLY (.ENTITY_TYPE, .PARM_NO)
            then begin
                 if .EDB_QE[NDB_NODE_TYPE] eql NDB$EXECUTOR
                 then return $TRUE
                 else return $FALSE;
                 end
            else return $TRUE;

        [LINE_, CIRCUIT_, LOGGING_, MODULE_]:
            return $TRUE;

        [inrange,
         outrange]:
        tes;

    return $FALSE;
    end;				! End of APPLICABLE
%if $X25 and not $MCB %then
%routine ('REMOVE_QUALIFIED_PARAMETER', EDB_QE, ENTITY, QUALIFIER, POINTER, LENGTH, PRIVLEDGED) =

!++
! FUNCTIONAL DESCRIPTION:
!
!       Remove parameters in the qualifier sub queues.
!
! FORMAL PARAMETERS
!
!	EDB_QE          Address of the qualified entity data base structure to
!                       which the parameter is to be inserted.
!       ENTITY          The entity type number to which the parameter applies.
!       QUALIFIER       A character sequence pointer to the qualifier
!                       parameter.
!       POINTER         A character sequence pointer to the parameter to
!                       be inserted.
!       LENGTH          The length of the parameter data passed in the
!                       parameter buffer.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NICE return code.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
        EDB_QE: ref ENTITY_DB_BLOCK;

    local
        PARAMETER,
        QH_QUALIFIER: ref Q_HEADER,
        QE_QUALIFIER: ref ENTITY_DB_BLOCK;

    QH_QUALIFIER = EDB_QE[EDB_QUALIFIER_QUEUE];
    PARAMETER = (if .LENGTH gtr 0       ! Get parameter number
                 then GETW_NA (.POINTER)
                 else -1);              ! Zero length implies ALL

    if .QUALIFIER eql 0
    then begin                          ! Use default existing qualifier queue
         if NMU$QUEUE_LENGTH (.QH_QUALIFIER) eql 1 ! Queue has only 1 entry ?
         then QE_QUALIFIER = .QH_QUALIFIER[Q_FORWARD] ! Yes, default queue
         else return $NICE$ERR_PAM;     ! No, expecting qualifier name
         end
    else begin                          ! Use specific qualifier queue
         local ID_STRING, COUNT: $SIGNED_BYTE_VALUE;

         ID_STRING = ch$plus (.QUALIFIER, 2); ! Get qualifier id string
         COUNT = ch$rchar (.ID_STRING); ! Get count byte

         if .COUNT[VALUE] lss 0         ! If count byte is negative ....
         then begin                     ! Set KNOWN qualified queues
              local NEXT: ref Q_ENTRY;

              NEXT = .QH_QUALIFIER[Q_FORWARD];

              while (QE_QUALIFIER = .NEXT) neq .QH_QUALIFIER
              do begin
                 NEXT = .NEXT[Q_FORWARD];
                 REMOVE_PARAMETER (.QE_QUALIFIER, .ENTITY, .PARAMETER, .PRIVLEDGED);
                 end;

              return NICE$_SUC;
              end
         else begin                     ! Set specific qualified queue
              QE_QUALIFIER = NMU$QUEUE_SCAN (.QH_QUALIFIER,
                                             .ID_STRING,
                                             NON_NODE_ID_MATCH);

              if .QE_QUALIFIER eql 0    ! Does entry exist ?
              then return $NICE$ERR_IPV;
              end;
         end;

    REMOVE_PARAMETER (.QE_QUALIFIER, .ENTITY, .PARAMETER, .PRIVLEDGED);

    return NICE$_SUC;
    end;				! End of REMOVE_QUALIFIED_PARAMETER
%fi
%sbttl ''
%routine ('REMOVE_PARAMETER', EDB_QE, ENTITY_TYPE, PARM_NO, PRIVLEDGED) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Removes a parameter entry from the parameter vector of the
!       data base for an entity.
!
! FORMAL PARAMETERS
!
!	EDB_QE      - The address of the entity data base structure from
!                     which the parameter is to be removed.
!       ENTITY_TYPE - The entity type number to which the parameter applies.
!       PARM_NO     - The parameter number for the parameter to be removed.
!       PRIVLEDGED  - If true, clear the parameter even if not clearable.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    !
    !  Verify that all fields related to the parameter vector are
    !  in agreement.  If there is any indication that there is no
    !  PVB, reset all the fields.
    !

    if (.EDB_QE[EDB_PARAMETER_COUNT] eql 0)
    or (.EDB_QE[EDB_PARAMETER_VECTOR] eql 0)
    or (.EDB_QE[EDB_PARAMETER_ALLOCATION] eql 0)
    then begin
	 RELEASE_PVB (.EDB_QE);
	 return;
	 end;

    !
    ! Otherwise, get the parameter number and check it for applicability.
    !

    if not APPLICABLE (.ENTITY_TYPE, .EDB_QE, .PARM_NO)
    then return $NICE$ERR_PNA

    !
    ! Search through the vector for the parameter to
    ! to be removed and ripple all parameters numbered higher than
    ! the one to be removed down one position in the vector. 
    !

    else begin
         local CNT,
               ENTRY: ref $NML$PVB_ENTRY_BLOCK;

         ENTRY = .EDB_QE[EDB_PARAMETER_VECTOR];
         CNT = .EDB_QE[EDB_PARAMETER_COUNT];

         do begin

            ! Note: ALL (-1) is less than any parameter number

            if .PARM_NO leq .ENTRY[PE_NUMBER]
            then begin
                 if not ((.PARM_NO eql .ENTRY[PE_NUMBER]) or ! parameter #
                         (.PARM_NO lss 0))                   ! ALL
                 then exitloop;         ! No match

                 ! Found parameter or removing all

                 if NML$CLEARABLE (.ENTITY_TYPE, .ENTRY[PE_NUMBER]) or
                    .PRIVLEDGED
                 then begin             ! Check if user can clear parameter

                      ! If this is a counter timer, adjust the counter
                      ! timer data base to reflect the time change.

                      NML$COUNTER_TIMER_CLEAR (.PARM_NO,
                                               .ENTITY_TYPE,
                                               EDB_QE[EDB_ENTITY_ID]);

                      CLEAR_PARAMETER_DATA (.ENTITY_TYPE, .ENTRY);
                      COPY_PARAMETER_VECTOR (vector [.ENTRY, PVB_ENTRY_SIZE],
                                             .ENTRY,
                                             .CNT - 1);
                      EDB_QE[EDB_PARAMETER_COUNT] = .EDB_QE[EDB_PARAMETER_COUNT] - 1;
                      end
                 else begin             ! Move down one entry
                      ENTRY = vector [.ENTRY, PVB_ENTRY_SIZE];
                      end;

                 if .PARM_NO geq 0 then exitloop; ! Done Removing single parameter
                 end
            else				  ! Move down one entry
                 ENTRY = vector [.ENTRY, PVB_ENTRY_SIZE];
            end
         while (CNT = .CNT - 1) neq 0;
         end;

    ! If there are now no more parameters left in the vector, release
    ! storage used by the vector.

    if .EDB_QE[EDB_PARAMETER_COUNT] eql 0
    then RELEASE_PVB (.EDB_QE);

    return;
    end;				! End of REMOVE_PARAMETER
%routine ('RELEASE_PVB', EDB_QE) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Clears all related fields and releases the parameter entry
!       vector block for a specific entity data base structure.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - The address of the entity data base structure from
!                 which the PVB is to be removed.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!   The following fields of the entity data base entry will be cleared:
!         EDB_QE[EDB_PARAMETER_ALLOCATION]
!         EDB_QE[EDB_PARAMETER_VECTOR]
!         EDB_QE[EDB_PARAMETER_COUNT]
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    !
    ! If a parameter vector is not currently allocated there is
    !  no memory to be released.
    !

    if (.EDB_QE[EDB_PARAMETER_ALLOCATION] neq 0) ! They better all be in
    and (.EDB_QE[EDB_PARAMETER_VECTOR] neq 0) ! agreement.
    then NMU$MEMORY_RELEASE (.EDB_QE[EDB_PARAMETER_VECTOR],
                             .EDB_QE[EDB_PARAMETER_ALLOCATION]);

    EDB_QE[EDB_PARAMETER_ALLOCATION] = 0;
    EDB_QE[EDB_PARAMETER_VECTOR] = 0;
    EDB_QE[EDB_PARAMETER_COUNT] = 0;

    return;
    end;				! End of RELEASE_PVB
%routine ('GET_PVB', EDB_QE) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Gets a parameter entry vector block for a specific entity
!	data base structure.  If a parameter vector is already
!	allocated, a new one will not be allocated provided there
!	is enough room for 1 more entry in the existing vector.
!	If there is not enough room, a larger vector will be allocated
!	and the existing entries will be copied to the new vector.
!	The associated fields in the data base structure will be
!	updated.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - The address of the entity data base structure from
!                 which the PVB is to be allocated.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!   The following fields of the entity data base entry will be changed:
!         EDB_QE[EDB_PARAMETER_ALLOCATION]
!         EDB_QE[EDB_PARAMETER_VECTOR]
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    if .EDB_QE[EDB_PARAMETER_ALLOCATION] lss
    ((.EDB_QE[EDB_PARAMETER_COUNT] + 1) * PVB_ENTRY_ALLOCATION)
    then begin
         local COUNT, NPVB: ref $NML$PVB_ENTRY_VECTOR (0);
         bind NEW_ALLOCATION = .EDB_QE[EDB_PARAMETER_ALLOCATION] +
                               PVB_ENTRY_ALLOCATION;

         if (NPVB = NMU$MEMORY_GET (NEW_ALLOCATION)) eql 0
         then return $FALSE;

         COUNT = .EDB_QE[EDB_PARAMETER_COUNT];
         COPY_PARAMETER_VECTOR(.EDB_QE[EDB_PARAMETER_VECTOR],
                               .NPVB,
                               .EDB_QE[EDB_PARAMETER_COUNT]);

         RELEASE_PVB (.EDB_QE);
         EDB_QE[EDB_PARAMETER_VECTOR] = .NPVB;
         EDB_QE[EDB_PARAMETER_ALLOCATION] = NEW_ALLOCATION;
         EDB_QE[EDB_PARAMETER_COUNT] = .COUNT;
         end;

    return $TRUE;
    end;				! End of GET_PVB
%routine ('EXPAND_PVB', EDB_QE, N) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Expands the parameter entry vector block for a specific entity
!	data base structure.  If a parameter vector is already
!	allocated, a new one will not be allocated provided there
!	is enough room for 1 more entry in the existing vector.
!	If there is not enough room, a larger vector will be allocated
!	and the existing entries will be copied to the new vector.
!	In any case, the parameter vector will be opened up and
!	a null entry will be placed in the vector at position N,
!	where N varies from 0 to count-1.
!	The associated fields in the data base structure will be
!	updated.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - The address of the entity data base structure from
!                 which the PVB is to be expanded.
!	N	- The number of the vector entry, where the null
!		  entry is to be placed. (0 <= N < count)
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!   The following fields of the entity data base entry will be changed:
!         EDB_QE[EDB_PARAMETER_ALLOCATION]
!         EDB_QE[EDB_PARAMETER_VECTOR]
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    local
         PVB: ref $NML$PVB_ENTRY_VECTOR (0);

    if .EDB_QE[EDB_PARAMETER_ALLOCATION]
    lss ((.EDB_QE[EDB_PARAMETER_COUNT] + 1) * PVB_ENTRY_ALLOCATION)
    then if not GET_PVB (.EDB_QE)
         then return $FALSE;

    PVB = .EDB_QE[EDB_PARAMETER_VECTOR];
    decr M from .EDB_QE[EDB_PARAMETER_COUNT] - 1 to .N
    do begin
       PVB[.M+1,PE_NUMBER] = .PVB[.M,PE_NUMBER];
       PVB[.M+1,PE_DATA] = .PVB[.M,PE_DATA];
       end;

    PVB[.N,PE_NUMBER] = 0;
    PVB[.N,PE_DATA] = 0;

    return $TRUE;
    end;				! End of EXPAND_PVB
%routine ('SET_PARAMETER_DATA', ENTITY_TYPE, PRM_PTR, PVB_QE) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Stores the data for a parameter in the parameter vector block.
!       The data stored is dependent on the type of data for the 
!       parameter. For coded and binary value parameters the data is
!       stored directly. For image fields the address of a dynamically
!       allocated block containing the image field is stored.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - Entity type number.
!       PRM_PTR     - Pointer to data portion of parameter.
!       PVB_QE      - Address of Parameter Vector Block Queue Entry.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       PVB_QE: ref $NML$PVB_ENTRY_BLOCK;

    local
         DATA_TYPE: block [1] field (DATA_TYPE_FIELDS);

    DATA_TYPE = NML$GET_PDB_DATA_TYPE (.ENTITY_TYPE, .PVB_QE[PE_NUMBER]);

    if .DATA_TYPE[DT_CODED] eql 0       ! Not coded
    then begin
         if .DATA_TYPE[DT_FTYPE] eql 0  ! Binary number
         then begin
              if .DATA_TYPE[DT_LENGTH] eql 0 ! Image field
              then begin
                   if not SET_IMAGE_FIELD (PVB_QE[PE_ADDRESS], .PRM_PTR)
                   then return $FALSE;
                   end
              else begin
                   if .DATA_TYPE[DT_LENGTH] leq %bpval/8
                   then PVB_QE[PE_DATA] = GETN (PRM_PTR, .DATA_TYPE[DT_LENGTH])
                   else begin
                        bind L = .DATA_TYPE[DT_LENGTH],
                             A = ch$allocation (L,8) * %upval;

                        if .PVB_QE[PE_ADDRESS] eql 0
                        then if (PVB_QE[PE_ADDRESS] = NMU$MEMORY_GET (A)) eql 0
                             then return $FALSE;

                        ch$move (L, .PRM_PTR, ch$ptr (.PVB_QE[PE_ADDRESS],,8));
                        end;
                   end;
              end
         else begin                     ! ASCII image field
              if not SET_IMAGE_FIELD (PVB_QE[PE_ADDRESS], .PRM_PTR)
              then return $FALSE;
              end;
         end
    else begin                          ! Coded
         if .DATA_TYPE[DT_FTYPE] eql 0  ! Single field
         then PVB_QE[PE_DATA] = GETN (PRM_PTR, .DATA_TYPE[DT_NUMBER])
         else begin                     ! Multiple field
              if begin                  ! Special cases for mutiple fields of
                 selectone .ENTITY_TYPE of
                     set
                     [NODE_E]:          ! NODE entity
                         selectone .PVB_QE[PE_NUMBER] of
                             set
                             [141]:     ! HOST
                                 $TRUE;
                             [otherwise]:
                                 $FALSE;
                             tes;
                     [MODULE_]:         ! MODULE entity
                         selectone .PVB_QE[PE_NUMBER] of
                             set
                             [320]:     ! NODE
                                 $TRUE;
                             [otherwise]:
                                 $FALSE;
                             tes;
                     [otherwise]:
                         $FALSE;
                     tes
                 end
              then begin
                   local PTR, TEMP;

                   if .PVB_QE[PE_ADDRESS] eql 0
                   then if (PVB_QE[PE_ADDRESS] = NMU$MEMORY_GET (NODE_ID_BUFFER_ALLOCATION)) eql 0
                        then return $FALSE;

                   PTR = ch$ptr (.PVB_QE[PE_ADDRESS],,8);
                   TEMP = GETB (PRM_PTR);
                   if .TEMP eql 0
                   then begin
                        TEMP = GETW (PRM_PTR);
                        PUTW (TEMP, PTR);
                        PUTB (0, PTR);
                        end
                   else begin
                        local ADDR;

                        ADDR = 0;
                        PUTW (ADDR, PTR);
                        PUTB (.TEMP, PTR);
                        ch$move (.TEMP, .PRM_PTR, .PTR);
                        end;

                   PTR = ch$ptr (.PVB_QE[PE_ADDRESS],,8);
                   TEMP = NODE_ID_BUFFER_LENGTH;

                   !
                   ! Map node address so a valid address
                   ! is displayed.
                   !

                   $NML$MAP_NODE_ID (TEMP, .PTR);
                   end
              else PVB_QE[PE_ADDRESS] = 0; ! Unknown multiple parameter
              end;
         end;

    return $TRUE;
    end;				! End of SET_PARAMETER_DATA
%routine ('SET_FILTER', FDB_QE, TYPE, BUF_PTR) =

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

    begin

    TASK_INFO ('INTERNAL ERROR: SET_FILTER routine not coded');

    return $FALSE;
    end;				! End of SET_FILTER
%routine ('SET_IMAGE_FIELD', ADDR, PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Sets an image field in the parameter data base.
!
! FORMAL PARAMETERS
!
!	ADDR - The address within the parameter data base vector which
!              contains the address of the dynamically allocated storage
!              which contains the image string. If zero a block will be
!              allocated.
!
!	PTR  - A pointer to the image field to be set in the data base.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
         XLEN,
         TLEN;

    TLEN = ch$rchar(.PTR) + 1;

    if ..ADDR eql 0
    then .ADDR = NMU$MEMORY_GET ((ch$allocation (.TLEN,8) * %upval))
    else if .TLEN neq (XLEN = ch$rchar (ch$ptr (..ADDR,,8)) + 1)
         then begin
              NMU$MEMORY_RELEASE (..ADDR, (ch$allocation (.XLEN,8) * %upval));
              .ADDR = NMU$MEMORY_GET ((ch$allocation (.TLEN,8) * %upval));
              end;

    if ..ADDR eql 0
    then return $FALSE;

    ch$move (.TLEN, .PTR, ch$ptr (..ADDR,,8));

    return $TRUE;
    end;				! End of SET_IMAGE_FIELD
%routine ('CLEAR_PARAMETER_DATA', ENTITY_TYPE, PVB_QE) : novalue =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Clears the data for a parameter in the parameter vector block.
!       The data stored is dependent on the type of data for the 
!       parameter. For coded and binary value parameters the data is
!       cleared to zero. For image fields the address of a dynamically
!       allocated block containing the image field is used to release
!       the storage containing the image field. The address is then set
!       to zero.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE - Entity type number.
!       PVB_QE      - Address of Parameter Vector Block Queue Entry.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	NONE.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       PVB_QE: ref $NML$PVB_ENTRY_BLOCK;

    local
         DATA_TYPE: block [1] field (DATA_TYPE_FIELDS);

    DATA_TYPE = NML$GET_PDB_DATA_TYPE (.ENTITY_TYPE, .PVB_QE[PE_NUMBER]);

    if .DATA_TYPE[DT_CODED] eql 0       ! Not coded
    then begin
         if .DATA_TYPE[DT_FTYPE] eql 0  ! Binary number
         then begin
              if .DATA_TYPE[DT_LENGTH] eql 0
              then begin                ! Image binary
                   bind L = ch$rchar (ch$ptr (.PVB_QE[PE_ADDRESS],,8)) + 1,
                        A = ch$allocation (L,8) * %upval;

                   NMU$MEMORY_RELEASE (.PVB_QE[PE_ADDRESS], A);
                   PVB_QE[PE_ADDRESS] = 0;
                   end
              else begin
                   if .DATA_TYPE[DT_LENGTH] leq %bpval/8
                   then PVB_QE[PE_DATA] = 0 
                   else begin
                        bind L = .DATA_TYPE[DT_LENGTH],
                             A = ch$allocation (L,8) * %upval;

                        NMU$MEMORY_RELEASE (.PVB_QE[PE_ADDRESS], A);
                        PVB_QE[PE_ADDRESS] = 0;
                        end;
                   end;
              end
         else begin                     ! ASCII image field
              bind L = ch$rchar (ch$ptr (.PVB_QE[PE_ADDRESS],,8)) + 1,
                   A = ch$allocation (L,8) * %upval;

              NMU$MEMORY_RELEASE (.PVB_QE[PE_ADDRESS], A);
              PVB_QE[PE_ADDRESS] = 0;
              end;
         end
    else begin                          ! Coded

         %( N.B. - Do special casing here just like in SET_PARAMETER_DATA.
            Else we gonna mess up storage allocation. )%

         if .DATA_TYPE[DT_FTYPE] eql 0  ! Single field
         then PVB_QE[PE_DATA] = 0
         else begin                     ! Multiple field
              if (.ENTITY_TYPE eql NODE_E) ! Special cases for HOST
              and (.PVB_QE[PE_NUMBER] eql 141)
              then NMU$MEMORY_RELEASE (.PVB_QE[PE_ADDRESS], NODE_ID_BUFFER_ALLOCATION)
              else PVB_QE[PE_ADDRESS] = 0; ! Unknown multiple parameter
              end;
         end;

    end;				! End of CLEAR_PARAMETER_DATA
%routine ('CLEAR_FILTER', FDB_QE, TYPE, PARM_NO) =

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

    begin

    TASK_INFO ('INTERNAL ERROR: CLEAR_FILTER routine not coded');

    return $FALSE;
    end;				! End of CLEAR_FILTER
%routine ('READ_PARAMETER_DATA', ENTITY_TYPE, ENTRY, LENGTH, POINTER) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Reads the data portion of a volatile data base parameter
!       into the parameter buffer.
!
! FORMAL PARAMETERS
!
!	ENTITY_TYPE     Entity type number.
!	ENTRY           The address of the parameter vector block entry
!                       for this parameter.
!       LENGTH          The length of the buffer remaining.
!       POINTER         The address of a character sequence pointer to the
!                       buffer.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	The number of bytes for this parameter excluding data id
!	and datatype bytes.  
!
! SIDE EFFECTS:
!
!	If the parameter will fit in the buffer, it is copied into
!	the buffer.
!
!--

    begin

    macro
         PUTN (VALUE, PTR_ADR, N) =
             begin
             local L, X;

             X = VALUE;
             ch$wchar_a (.X, PTR_ADR);
             incr L from 256 to ((N - 1) * 256) by 256
             do begin
                X = .X / .L;
                ch$wchar_a (.X, PTR_ADR);
                end;

             .L / 256
             end %;

    map
       ENTRY: ref $NML$PVB_ENTRY_BLOCK;

    local
         BUF_PTR,
         BUF_LEN,
         DATA_ID: block [1] field (DATA_ID_FIELDS), ! Data ID 
         DATA_TYPE: block [1] field (DATA_TYPE_FIELDS);

    BUF_PTR = ..POINTER;
    DATA_ID = 0;
    DATA_ID[DI_PARMNO] = .ENTRY[PE_NUMBER]; ! Get parameter number
    DATA_ID[DI_TYPE] = 0;               ! This is a parameter
    DATA_TYPE = NML$GET_PDB_DATA_TYPE (.ENTITY_TYPE, .ENTRY[PE_NUMBER]);

    if .DATA_TYPE[DT_CODED] eql 0       ! Not coded
    then begin
         PUTW (DATA_ID, BUF_PTR);       ! Write data id into buffer
         PUTB (.DATA_TYPE, BUF_PTR);    ! Write data type into buffer
         if .DATA_TYPE[DT_FTYPE] eql 0  ! Binary number
         then begin
              if .DATA_TYPE[DT_LENGTH] eql 0
              then begin                ! Binary image field
                   BUF_LEN = ch$rchar (ch$ptr (.ENTRY[PE_ADDRESS],,8)) + 1;
                   if .LENGTH geq .BUF_LEN
                   then BUF_PTR = ch$move (.BUF_LEN,
                                           ch$ptr (.ENTRY[PE_ADDRESS],,8),
                                           .BUF_PTR);
                   end
              else begin
                   BUF_LEN = .DATA_TYPE[DT_LENGTH];
                   if .DATA_TYPE[DT_LENGTH] leq %bpval/8
                   then begin           ! Data stored in value
                        if .LENGTH geq .BUF_LEN
                        then PUTN (.ENTRY[PE_DATA],
                                   BUF_PTR,
                                   .DATA_TYPE[DT_LENGTH]);
                        end
                   else begin           ! Data stored in buffer
                        BUF_LEN = .DATA_TYPE[DT_LENGTH];
                        if .LENGTH geq .BUF_LEN
                        then BUF_PTR = ch$move (.BUF_LEN,
                                                ch$ptr (.ENTRY[PE_ADDRESS],,8),
                                                .BUF_PTR);
                        end;
                   end;
              end
         else begin                     ! ASCII image field
              BUF_LEN = ch$rchar (ch$ptr (.ENTRY[PE_ADDRESS],,8)) + 1;
              if .LENGTH geq .BUF_LEN
              then BUF_PTR = ch$move (.BUF_LEN,
                                      ch$ptr (.ENTRY[PE_ADDRESS],,8),
                                      .BUF_PTR);
              end;
         end
    else begin                          ! Coded

         %( N.B. - We have to do special casing here for multiple coded
            fields. )%

         if .DATA_TYPE[DT_FTYPE] eql 0  ! Single field
         then begin
              PUTW (DATA_ID, BUF_PTR);  ! Write data id into buffer
              PUTB (.DATA_TYPE, BUF_PTR); ! Write data type into buffer
              BUF_LEN = .DATA_TYPE[DT_NUMBER];
              if .LENGTH geq .BUF_LEN
              then PUTN (.ENTRY[PE_DATA], BUF_PTR, .DATA_TYPE[DT_NUMBER]);
              end
         else begin                     ! Multiple field
              literal
                  DATA_NODE_ID = 1,
                  DATA_VERSION = 2,
                  DATA_EVENTS = 3;

              selectone
                  begin
                  selectone .ENTITY_TYPE of
                      set
                      [NODE_E]:
                          selectone .ENTRY[PE_NUMBER] of
                              set
                              [141]:    ! HOST
                                  begin
                                  DATA_ID = .DATA_ID - 1; ! Read # 140
                                  DATA_NODE_ID
                                  end;
                              [101]:    ! MANAGEMENT VERSION
                                  DATA_VERSION;
                              [otherwise]:
                                  0;
                              tes;

                      [LOGGING_]:
                          selectone .ENTRY[PE_NUMBER] of
                              set
                              [200]:    ! SINK NODE
                                  DATA_NODE_ID;
                              [201]:    ! EVENTS
                                  DATA_EVENTS;
                              [otherwise]:
                                  0;
                              tes;

                      %if $X25
                      %then

                      [MODULE_]:
                          selectone .ENTRY[PE_NUMBER] of
                              set
                              [320]:    ! NODE
                                  DATA_NODE_ID;
                              [otherwise]:
                                  0;
                              tes;

                      %fi

                      [otherwise]:
                          0;
                      tes
                  end of
                  set
                  [DATA_NODE_ID] :      ! Node identification
                      begin
                      local PTR;

                      PTR = ch$ptr (.ENTRY[PE_ADDRESS],,8);
                      PUTW (DATA_ID, BUF_PTR); ! Write data id 
                      PUTB (.DATA_TYPE, BUF_PTR); ! Write data type 

                      BUF_LEN = 6 + 5;	! Assume node name of 6 chars
                      if .LENGTH geq .BUF_LEN
                      then
                        begin
                        !
                        ! Node address
                        !

                          begin
                          literal DATA_TYPE = 0^7 + 0^6 + 0^4 + 2;
                          local NODE_ADDRESS;

                          NODE_ADDRESS = GETW (PTR);
                          PUTB (DATA_TYPE, BUF_PTR); ! Write Data Type
                          PUTW (NODE_ADDRESS, BUF_PTR); ! Write address
                          end;

                        !
                        ! Node name
                        !

                          begin
                          literal DATA_TYPE = 0^7 + 1^6;
                          local NODE_NAME_LENGTH;

                          PUTB (DATA_TYPE, BUF_PTR); ! Write Data Type
                          NODE_NAME_LENGTH = GETB (PTR); ! Get I-length
                          PUTB (.NODE_NAME_LENGTH, BUF_PTR);
                          BUF_PTR = ch$move (.NODE_NAME_LENGTH,
                                             .PTR,
                                             .BUF_PTR);
                          BUF_LEN = .NODE_NAME_LENGTH + 5; ! Real length
                          end;
                        end;
                      end;

                  [DATA_VERSION] :      ! Version number
                      begin
                      external          ! Version numbers defined in NMUSKD
                          NMLVER,       ! Major version
                          DECECO,       ! Minor version
                          USRECO;       ! Customer version

                      PUTW (DATA_ID, BUF_PTR); ! Write data id 
                      PUTB (.DATA_TYPE, BUF_PTR); ! Write data type 
                      BUF_LEN = 6;      ! Six bytes to write excluding
                                        ! data id and data type bytes

                      if .LENGTH geq .BUF_LEN
                      then
                          begin
                          literal DATA_TYPE = 0^7 + 0^6 + 0^4 + 1;

                          PUTB (DATA_TYPE, BUF_PTR); ! Write Data Type
                          PUTB (.NMLVER, BUF_PTR); ! Write version byte
                          PUTB (DATA_TYPE, BUF_PTR); ! Write Data Type
                          PUTB (.DECECO, BUF_PTR); ! Write version byte
                          PUTB (DATA_TYPE, BUF_PTR); ! Write Data Type
                          PUTB (.USRECO, BUF_PTR); ! Write version byte
                          end;

                      end;

                  [otherwise] :
                      BUF_LEN = 0;      ! Unknown multiple parameter
                  tes;
              end;
         end;

    .POINTER = .BUF_PTR;

    return .BUF_LEN;                    ! Return number of bytes written
    end;				! End of READ_PARAMETER_DATA
%routine ('LOGGING_ID_MATCH', EDB_QE, EID_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Makes determination as to whether a particular ENTITY_DB_BLOCK
!       for the LOGGING entity is the one being searched for when called 
!       by NMU$QUEUE_SCAN as an exit routine.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - Address of the LOGGING entity data base block to be tested.
!	EID_PTR - Pointer to the entity id being searched for.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Address of LOGGING entity data base block if it matches the entity id;
!	Zero (0), otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    if ch$rchar (ch$ptr (EDB_QE [EDB_ENTITY_ID],, 8)) eql ch$rchar (.EID_PTR)
    then return .EDB_QE
    else return 0;

    end;				! End of NODE_ID_MATCH
%routine ('NODE_ID_MATCH', EDB_QE, EID_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Makes determination as to whether a particular ENTITY_DB_BLOCK
!       for the NODE entity is the one being searched for when called 
!       by NMU$QUEUE_SCAN as an exit routine.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - Address of the NODE entity data base block to be tested.
!	EID_PTR - Pointer to the entity id being searched for.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Address of NODE entity data base block if it matches the entity id;
!	Zero (0), otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    local
         PTR;

    PTR = ch$ptr (EDB_QE[NDB_ENTITY_ID],,8);

    if GETW (PTR) eql GETW (EID_PTR)
    then return .EDB_QE
    else return 0;

    end;				! End of NODE_ID_MATCH
%routine ('NON_NODE_ID_MATCH', EDB_QE, EID_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Makes determination as to whether a particular ENTITY_DB_BLOCK
!       is the one being searched for when called by NMU$QUEUE_SCAN
!       as an exit routine.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - Address of the entity data base block to be tested.
!	EID_PTR - Pointer to the entity id being searched for.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Address of entity data base entry if it matches the entity id;
!	Zero (0), otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       EDB_QE: ref ENTITY_DB_BLOCK;

    return MATCH_ID (.EDB_QE, ch$ptr (EDB_QE[EDB_ENTITY_ID],,8), .EID_PTR);
    end;				! End of NON_NODE_ID_MATCH
%routine ('SVC_CKT_MATCH', NDB_QE, CKT_ID_PTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Makes determination as to whether a particular NODE_DB_BLOCK
!       contains the circuit id, passed as an argument, as the 
!       SERVICE CIRCUIT parameter by NMU$QUEUE_SCAN as an exit routine.
!
! FORMAL PARAMETERS
!
!	NDB_QE  - Address of the NODE entity data base block to be tested.
!	CKT_ID_PTR - Pointer to the circuit entity id being searched for.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Address of NODE entity data base block if its SERVICE CIRCUIT 
!          parameter matches the circuit entity id;
!	Zero (0), otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    map
       NDB_QE: ref NODE_DB_BLOCK;

    bind
	PVB = NDB_QE[EDB_PARAMETER_VECTOR] : ref $NML$PVB_ENTRY_VECTOR (0);

    local
         ADR_AI_FIELD;

    ADR_AI_FIELD = 0;

    incr N from 0 to .NDB_QE[EDB_PARAMETER_COUNT] - 1
    do begin
       if .PVB[.N,PE_NUMBER] eql 110
       then begin
            ADR_AI_FIELD = .PVB[.N,PE_ADDRESS];
            exitloop;		! Found SERVICE CIRCUIT parameter
            end;
       end;

    if .ADR_AI_FIELD eql 0	! No SERVICE CIRCUIT parameter
    then return 0
    else return MATCH_ID (.NDB_QE, ch$ptr (.ADR_AI_FIELD,,8), .CKT_ID_PTR);

    end;				! End of SVC_CKT_MATCH
%routine ('MATCH_ID', EDB_QE, PTR1, PTR2) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Compares the entity id referenced by pointer 1 with the entity
!       id referenced by pointer 2.  No distinction is made between
!       upper and lower case when comparing the strings.  If the ids
!       match, the address of the entity data block is returned.
!
! FORMAL PARAMETERS
!
!	EDB_QE  - Address of the entity data base block.
!	PTR1 - Pointer to the first entity id.
!	PTR2 - Pointer to the second entity id.
!
! IMPLICIT INPUTS
!
!	NONE.
!
! ROUTINE VALUE:
!
!	Address of entity data base entry if the strings match;
!	Zero (0), otherwise.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    begin

    local
	L;

    if (L = GETB (PTR1)) eql GETB (PTR2)
    then begin
         incr N from 1 to .L
         do begin
            if GETMB (PTR1) neq GETMB (PTR2)
            then return 0;
            end;

         return .EDB_QE;
         end
    else return 0;

    end;				! End of MATCH_ID
end                                     ! End of Module NMLVDB
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:2
! Comment Column:40
! Comment Rounding:+1
! End: