1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-04-20 00:43:22 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

567 lines
14 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
! PH4:<GLINDELL>NMUQUE.BLI.7 21-Nov-83 17:21:45, Edit by GLINDELL
!
! Ident 4.
! Add routine NMU$QUEUE_NEXT that returns the next entry of a queue
!
! NET:<VOBA.NML.DEVELOPMENT>NMUQUE.BLI.3 25-Mar-82 17:59:35, Edit by VOBA
!
! Ident 3.
! Add routine NMU$QUEUE_LENGTH to return the length (number of entries) of
! a queue.
!
! NET:<VOBA.NML.DEVELOPMENT>NMUQUE.BLI.5 4-Mar-82 14:19:09, Edit by VOBA
!
! Ident 2.
! Clean up code and update copyright date.
!
!NET:<DECNET20-V3P1.BASELEVEL-2.SOURCES>NMUQUE.BLI.4 12-Aug-81 10:47:34, Edit by JENNESS
!
! Update copyright notice.
! Clean up code, update to current coding conventions.
%title 'NMUQUE -- General Queue Management'
module NMUQUE (
ident = 'X00.04'
) =
begin
! COPYRIGHT (C) 1981, 1982 BY
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS 01754
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A SINGLE
! COMPUTER SYSTEM AND MAY BE COPIED ONLY 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
! EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE
! TERMS. TITLE TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES
! REMAIN IN DEC.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
!
!++
! Facility: LSG DECnet Network Management
!
! Abstract:
!
! This set of routines provides a primitives for
! manipulating queues. The only requirement for
! using this set of routines is that the queue overhead
! information must be defined at the very beginning
! of any entry made to a queue.
!
! Environment: TOPS10 and TOPS20 user mode, MCB RSX task level
!
! Author: Steven M. Jenness, Creation date: 19 August 1980
!
!--
!
! INCLUDE FILES
!
library 'MXNLIB'; ! All needed definitions
!
! TABLE OF CONTENTS
!
forward routine
NMU$QUEUE_MANAGER; ! Global entry definitions
%global_routine ('NMU$QUEUE_RESET', QUEUE: ref Q_HEADER) : novalue =
!++
! Functional description:
!
! This routine resets a queue header to the null
! state.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value: none
! Side effects:
!
! All pointers in the queue header point to
! the header itself (empty queue).
!
!--
begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
UNLOCK (QUEUE[Q_SEMAPHORE]);
end; ! End of NMU$QUEUE_RESET
%global_routine ('NMU$QUEUE_INSERT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =
!++
! Functional description:
!
! This routine inserts an entry to the end of
! a queue.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .ENTRY Address of entry data. The queueing information
! is stored starting at this address. A block
! of length Q_ENTRY_SIZE must be reserved.
!
! Routine value:
!
! $true if queue becomes non-empty with this insert
! $false if queue was previously non-empty
!
! Side effects:
!
! The forward pointer of the last item on the queue and
! the reverse pointer of the queue header are changed to
! point to the new entry.
!
!--
begin
local
LAST_ENTRY : ref Q_ENTRY,
RET_VAL;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Check for queue empty and set empty transition
! flag.
!
RET_VAL = (.QUEUE eql .QUEUE[Q_REVERSE]); ! Check for non-empty
!
! Insert entry onto end of queue and
! update pointers.
!
LAST_ENTRY = .QUEUE[Q_REVERSE];
ENTRY[Q_REVERSE] = .LAST_ENTRY;
ENTRY[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .ENTRY;
LAST_ENTRY[Q_FORWARD] = .ENTRY;
!
! Unlock the queue.
!
UNLOCK (QUEUE[Q_SEMAPHORE]);
!
! Return empty to non-empty transition flag.
!
return .RET_VAL;
end; ! End of NMU$QUEUE_INSERT
%global_routine ('NMU$QUEUE_REMOVE', QUEUE: ref Q_HEADER) =
!++
! Functional description:
!
! This routine removes the first entry on a queue.
! If the queue is empty a zero (0) value is returned.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value:
!
! Non-empty queue Address of entry (after queue information)
! Empty queue Zero (0)
!
! Side effects:
!
! The forward pointer of the queue header and the
! reverse pointer of the second entry (if any) are
! changed to point to each other.
!--
begin
local
ENTRY : ref Q_ENTRY,
NEXT_ENTRY : ref Q_ENTRY;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Get address of first entry on the queue.
!
ENTRY = .QUEUE[Q_FORWARD];
!
! Check for empty queue, return zero if empty.
! If entry found...
! unlink from queue
! fixup queue around hole made by removal
! clear queue linkage in removed entry.
!
if .ENTRY eql .QUEUE
then ENTRY = 0
else begin
NEXT_ENTRY = .ENTRY[Q_FORWARD];
QUEUE[Q_FORWARD] = .NEXT_ENTRY;
NEXT_ENTRY[Q_REVERSE] = .QUEUE;
ENTRY[Q_FORWARD] = 0;
ENTRY[Q_REVERSE] = 0;
end;
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock the queue
return .ENTRY; ! Return address of entry found, if any
end; ! End of NMU$QUEUE_REMOVE
%global_routine ('NMU$QUEUE_EXTRACT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =
!++
! Functional description:
!
! This routine handles extraction of an entry from a place
! in a queue other than the beginning. This requires "knowing"
! the address of the queue entry before calling this routine.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .ENTRY Address of entry (after queue information)
!
! Routine value:
!
! $true Entry was found on the queue and extracted
! $false Entry was not found on the queue
!
! Side effects:
!
! The links of the queue entries before and after the
! entry to be extracted are updated to point to each
! other.
!
!--
begin
local
NEXT_ENTRY : ref Q_ENTRY,
PREVIOUS_ENTRY : ref Q_ENTRY,
SEARCH : ref Q_ENTRY,
RET_VAL;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Loop until the entry is found.
!
SEARCH = .QUEUE[Q_FORWARD];
while (.SEARCH neq .ENTRY) and (.SEARCH neq .QUEUE)
do SEARCH = .SEARCH[Q_FORWARD];
if .SEARCH eql .ENTRY ! Found entry ?
then begin ! Yes, extract it and return true
NEXT_ENTRY = .ENTRY[Q_FORWARD];
PREVIOUS_ENTRY = .ENTRY[Q_REVERSE];
NEXT_ENTRY[Q_REVERSE] = .PREVIOUS_ENTRY;
PREVIOUS_ENTRY[Q_FORWARD] = .NEXT_ENTRY;
RET_VAL = $TRUE;
end
else RET_VAL = $FALSE; ! No, return false
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock queue
return .RET_VAL; ! Return result of extraction
end; ! End of NMU$QUEUE_EXTRACT
%global_routine ('NMU$QUEUE_LENGTH', QUEUE: ref Q_HEADER) =
!++
! Functional description:
!
! This routine returns the length (number of entries) of a queue.
!
! Formal parameters:
!
! .QUEUE Address of queue header
!
! Routine value:
!
! The length (number of entries) of the queue.
!
! Side effects: none
!
!--
begin
local
ENTRY,
RESULT,
NEXT : ref Q_ENTRY;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Return length of 0
!
RESULT = 0;
if .(.QUEUE) neq 0
then begin
NEXT = .QUEUE[Q_FORWARD]; ! Set first entry to the queue
while (ENTRY = .NEXT) neq .QUEUE
do begin ! Scan queue until end of queue
RESULT = .RESULT + 1;
NEXT = .NEXT[Q_FORWARD];
end;
end;
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock the queue
return .RESULT; ! Return the result of scanning
end; ! End of NMU$QUEUE_LENGTH
%global_routine ('NMU$QUEUE_SCAN', QUEUE: ref Q_HEADER, DATA, S_RTN) =
!++
! Functional description:
!
! This routine facilitates scanning a queue. The S_RTN
! parameter specifies a routine that is to be called with
! the DATA parameter and each ENTRY. When the return
! from the S_RTN is non-zero or the queue runs out, the
! scanning stops.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .DATA Data to be passed to each S_RTN call
! .S_RTN Scanning routine to be called for each entry
!
! Routine value:
!
! The value of S_RTN if it ever returns a non-zero value.
! Zero if the queue runs out before non-zero from S_RTN.
!
! Side effects: none
!
!--
begin
bind routine
SCAN_ROUTINE = .S_RTN;
local
ENTRY,
RESULT,
NEXT : ref Q_ENTRY;
!
! Lock the queue from concurrently running processes.
!
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
!
! If the queue header is zero ... queue is empty.
! Initialize the queue header.
!
if .(.QUEUE) eql 0
then begin
QUEUE[Q_FORWARD] = .QUEUE;
QUEUE[Q_REVERSE] = .QUEUE;
end;
!
! Clear the result value and point to the
! first entry on the queue.
!
RESULT = 0;
NEXT = .QUEUE[Q_FORWARD];
!
! Scan queue until end of queue or the scan
! routine returns a non zero value.
!
while (ENTRY = .NEXT) neq .QUEUE
do begin
NEXT = .NEXT[Q_FORWARD];
UNLOCK (QUEUE[Q_SEMAPHORE]);
if (RESULT = SCAN_ROUTINE (.ENTRY, .DATA)) neq 0
then exitloop;
while not LOCK (QUEUE[Q_SEMAPHORE])
do 1;
end;
UNLOCK (QUEUE[Q_SEMAPHORE]); ! Unlock the queue
return .RESULT; ! Return the result of scanning
end; ! End of NMU$QUEUE_SCAN
%global_routine ('NMU$QUEUE_SCAN_EXTRACT', ENTRY: ref Q_ENTRY) : novalue =
!++
! Functional description:
!
! This routine is used to extract a queue entry from
! a queue while scanning the queue. It is assumed
! that the only queue being worked on is the one being
! scanned. It also is assumed that the entry being
! extracted is the one currently being looked at by
! the scanning routine.
!
! ANY OTHER USE OF THIS ROUTINE CAN GIVE UNPREDICTABLE
! RESULTS!
!
! Formal parameters:
!
! .ENTRY Address of queue entry to remove.
!
! Routine value: none
! Side effects: none
!
!--
begin
local
NEXT_ENTRY : ref Q_ENTRY,
PREVIOUS_ENTRY : ref Q_ENTRY;
NEXT_ENTRY = .ENTRY[Q_FORWARD];
PREVIOUS_ENTRY = .ENTRY[Q_REVERSE];
NEXT_ENTRY[Q_REVERSE] = .PREVIOUS_ENTRY;
PREVIOUS_ENTRY[Q_FORWARD] = .NEXT_ENTRY;
end; ! End of NMU$QUEUE_SCAN_EXTRACT
%global_routine ('NMU$QUEUE_NEXT', QUEUE: ref Q_HEADER, ENTRY: ref Q_ENTRY) =
!++
!
! Functional description:
!
! This routine will return the next entry in a queue.
!
! At the first call, ENTRY should be zero. The routine will then return
! the first element. On successive calls, ENTRY should be the entry
! returned on the previous call. NMU$QUEUE_NEXT will return the next
! entry or 0 at the end of the queue.
!
! Formal parameters:
!
! .QUEUE Address of queue header
! .ENTRY Address of entry
!
! Routine value:
!
! 0 End of queue
! ENTRY Address of next entry in queue
!
!--
begin
local RESULT;
if ..QUEUE eql 0
then return 0 ! No queue at all
else begin
! Lock the queue from concurrently running processes
while not LOCK(QUEUE[Q_SEMAPHORE]) do 1;
if .ENTRY eql 0
then RESULT = .QUEUE[Q_FORWARD] ! First entry
else RESULT = .ENTRY[Q_FORWARD]; ! Get next entry
if .RESULT eql .QUEUE
then RESULT = 0; ! At end of queue
! Unlock the queue
UNLOCK(QUEUE[Q_SEMAPHORE]);
end;
return .RESULT;
end; ! End of NMU$QUEUE_NEXT
end ! End of module NMUQUE
eludom
! Local Modes:
! Mode:BLISS
! Auto Save Mode:2
! Comment Column:40
! Comment Rounding:+1
! End: