Google
 

Trailing-Edge - PDP-10 Archives - DEC_CMS-20_V1.0_SRC - cms/sources/attrib.bli
There are no other files named attrib.bli in the archive.
MODULE ATTRIB	(
		IDENT = '1',
		%IF
		    %BLISS(BLISS32)
		%THEN
		    LANGUAGE(BLISS32),
		    ADDRESSING_MODE(EXTERNAL=LONG_RELATIVE,
				    NONEXTERNAL=LONG_RELATIVE)
		%ELSE
		    LANGUAGE(BLISS36)
		%FI
		) =
BEGIN

!
!		  	COPYRIGHT (c) 1982 BY
!	      DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
! ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH  LICENSE AND WITH THE
! INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR  ANY  OTHER
! COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
! OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
! TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE  WITHOUT  NOTICE
! AND  SHOULD  NOT  BE  CONSTRUED  AS  A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR  RELIABILITY  OF  ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!

!++
! FACILITY:	CMS Library Processor
!
! ABSTRACT:
!
!	When called with a class name and an element name, find and
!	return the generation requested.
!
! ENVIRONMENT:	VAX/VMS, DS-20
!
! AUTHOR: D. Knight , CREATION DATE: 18-Sep-79
!
!--
!++
!			General Description
!
!	This module is used to access the CMS internal file ATF.
!	ATF contains all of the class related information for a
!	single library.  Each entry contains the following information.
!
!		1.  A single line entry containing the class
!		    name.
!
!		2.  One line for each element marked with the particular
!		    class which contains the element name and the
!		    generation of the element which is marked with
!		    the particular class.
!
!	All classes are stored in alphabetic order.  All element
!	references within each class are stored alphabetically also.
!
!--
!
! TABLE OF CONTENTS
!

FORWARD ROUTINE
	GETATR,				!get specified class
	GETNATR,			!get next class
	SETATR,				!set up for class calls
	GETCLS;				! get classes a particular 
					! generation of an element
					! belongs to

!
! INCLUDE FILES:
!

%if %bliss(bliss32) %then
    LIBRARY 'SYS$LIBRARY:STARLET';
%else
    REQUIRE 'jsys:';
%fi

LIBRARY 'XPORT:';

REQUIRE 'SCONFG:';

REQUIRE 'BLISSX:';

REQUIRE 'COMUSR:';

REQUIRE 'HOSUSR:';

!
! MACROS:
!

!
! EQUATED SYMBOLS:
!

LITERAL
	ATR_TAB_SIZ=1500;		!attribute table size in characters

!
! OWN STORAGE:
!

OWN
	ATR_END_PTR,			!pointer to end of table
	ATR_TAB_PTR,			!pointer to head of table
	ATR_T_SIZ,			!Current attribute table size
	ATR_T_PTR;			!working table pointer

!
! EXTERNAL REFERENCES:
!

EXTERNAL ROUTINE
	BADLIB,				!error in user's library
	badxpo,				!error in user's library
	BUG;				!Bug in code
GLOBAL ROUTINE GETATR (ELMLEN,ELMPTR,GENLEN,GENPTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Using the attribute string supplied to SETATR, fetch the
!	generation number which corresponds to the
!	specified attribute.
!
! FORMAL PARAMETERS
!
!	ELMLEN - length of element name.
!	ELMPTR - pointer to element name.
!	GENLEN - address of cell where generation length is stored
!	GENPTR - Character pointer to area where generation number is to be stored
!
! IMPLICIT INPUTS
!
!	The attribute data is stored in the table pointed to by ATR_TAB_PTR as retrieved from
!	the file ATF.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	TRUE - an entry was found
!	FALSE - No entry was found
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    BEGIN

    LOCAL
	EL_LEN,
	EL_BUF : VECTOR[CH$ALLOCATION(EL_NAM_SIZE)],
	FIRST,
	TMP_LEN,
	TMP_BUF : VECTOR[CH$ALLOCATION(GEN_SIZE)];

    FIRST=TRUE;

    !Try to find a matching element name
    WHILE
	GETNATR(.FIRST,EL_LEN,CH$PTR(EL_BUF),TMP_LEN,CH$PTR(TMP_BUF))
    DO
	BEGIN

	FIRST=FALSE;

	IF
	    CH$EQL(.ELMLEN,.ELMPTR,.EL_LEN,CH$PTR(EL_BUF))
	THEN
	    BEGIN
	    CH$MOVE(.TMP_LEN,CH$PTR(TMP_BUF),.GENPTR);
	    .GENLEN=.TMP_LEN;
	    RETURN TRUE
	    END

	END;

    FALSE

    END;				!End of GETATR
GLOBAL ROUTINE GETNATR (FIRST,ELMLEN,ELMPTR,GENLEN,GENPTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Using the attribute string supplied to SETATR, fetch the
!	generation number which corresponds to the
!	next attribute in the list.
!
! FORMAL PARAMETERS
!
!	FIRST - if TRUE, start at the beginning of the list.
!		if FALSE, continue from where left off after last
!		GETNATR call.
!	ELMLEN - address of cell where length of element name is to be stored
!	ELMPTR - character pointer to area where element name is to be stored
!	GENLEN - address of cell where length of generation is to be stored
!		 (area must be EL_NAM_SIZ characters long)
!	GENPTR - character pointer to area where generation is to be stored
!		 (area must be GEN_SIZE characters long)
!
! IMPLICIT INPUTS
!
!	The attribute data is stored in the table pointed to by ATR_TAB_PTR as retrieved from
!	the file ATF.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	TRUE - An entry was found
!	FALSE - No entry was found
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    BEGIN

    LOCAL
	COUNT,
	TXT_PTR;

    IF
	NOT .FIRST AND
	.ATR_T_PTR EQL 0
    THEN
	BUG(LIT('GETNATR not initialized'));

    !Initialize if starting over
    IF
	.FIRST
    THEN
	ATR_T_PTR=.ATR_TAB_PTR;

    !Make sure there is more text
    IF
	CH$DIFF(.ATR_END_PTR,.ATR_T_PTR) LEQ 0
    THEN
	!End of text
	BEGIN
	ATR_T_PTR=0;
	RETURN FALSE
	END;

    !Pick up the character count
    COUNT=CH$RCHAR_A(ATR_T_PTR);

    !Get the element name
    .ELMLEN=0;

    TXT_PTR=.ELMPTR;

    REPEAT
	BEGIN

	LOCAL
	    CHARACTER;

	CHARACTER=CH$RCHAR_A(ATR_T_PTR);
	COUNT=.COUNT-1;

	IF
	    .CHARACTER EQL %C' '
	THEN
	    EXITLOOP;

	if
	    ..elmlen geq el_nam_size
	then
	    bug(lit('Element name table overflow in GETNATR'));

	CH$WCHAR_A(.CHARACTER,TXT_PTR);
	.ELMLEN=..ELMLEN+1

	END;

    !Make sure the name is non-zero in length
    IF
	..ELMLEN EQL 0
    THEN
	BADLIB(LIT('Zero length class name'));

    !Get the generation
    .GENLEN=0;

    TXT_PTR=.GENPTR;

    if
	.count gtr gen_size
    then
	bug(lit('Generation number table overflow in GETNATR'));

    UNTIL
	.COUNT EQL 0
    DO
	BEGIN
	CH$WCHAR_A(CH$RCHAR_A(ATR_T_PTR),TXT_PTR);
	COUNT=.COUNT-1;
	.GENLEN=..GENLEN+1
	END;

    !It must exist
    IF
	..GENLEN EQL 0
    THEN
	BADLIB(LIT('Zero length generation number'));

    TRUE

    END;				!End of GETNATR
GLOBAL ROUTINE SETATR (ATRLEN,ATRPTR) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Initialize the attribute table with the attribute
!	specified in the argument.
!
! FORMAL PARAMETERS
!
!	ATRLEN - length of attribute string.
!	ATRPTR - pointer to attribute string.
!
! IMPLICIT INPUTS
!
!	The attribute data is contained in the file ATF.
!
! ROUTINE VALUE:
! COMPLETION CODES:
!
!	TRUE - Attribute information was found
!	FALSE - no such attribute.
!
! SIDE EFFECTS:
!
!	NONE.
!
!--

    BEGIN

    LOCAL
	$IO_BLOCK_DECL(ATR);		!declare iobs etc

    !Initialize IOB
    $IO_BLOCK_INIT(ATR);

    !make sure starting pointer is also clear
    atr_t_ptr=0;

    !Find the file, set no such attribute if not found
    IF
	NOT $STEP_OPEN(IOB=ATR_IOB,FILE_SPEC=(%STRING(LIB,ATF)),OPTIONS=INPUT,FAILURE=0)
    THEN
	RETURN FALSE;

    !Find the correct attribute
    UNTIL
	$step_get(IOB=ATR_IOB) EQL step$_eof
    DO
	BEGIN

	LOCAL
	    ATRPNT,
	    CLS_NM_LGT;

	ATRPNT=.ATR_IOB[IOB$A_STRING];

	CLS_NM_LGT=0;

	!Get length of class name only
	UNTIL
	    CH$RCHAR(CH$PLUS(.ATR_IOB[IOB$A_STRING],.CLS_NM_LGT)) EQL %C' ' OR
	    .CLS_NM_LGT EQL .ATR_IOB[IOB$H_STRING]
	DO
	    CLS_NM_LGT=.CLS_NM_LGT+1;

	!If this attribute is correct, build the attribute table
	IF
	    CH$RCHAR(.ATRPNT) NEQ %C' ' AND
	    CH$EQL(.CLS_NM_LGT,.ATR_IOB[IOB$A_STRING],.ATRLEN,.ATRPTR)
	THEN
	    BEGIN

	    !Initialize table
	    $XPO_GET_MEM(CHARACTERS=ATR_TAB_SIZ,RESULT=ATR_TAB_PTR);
	    ATR_T_SIZ=ATR_TAB_SIZ;
	    ATR_END_PTR=.ATR_TAB_PTR;

	    !Get contents of attribute list
	    REPEAT
		BEGIN

		!Get a line
		IF
		    $step_get(IOB=ATR_IOB) EQL step$_eof
		THEN
		    BEGIN
		    IF
			CH$DIFF(.ATR_END_PTR,.ATR_TAB_PTR) EQL 0
		    THEN
			!Attribute does not exist
			BEGIN
			$XPO_FREE_MEM(STRING=(ATR_TAB_SIZ,.ATR_TAB_PTR));
			RETURN FALSE
			END
		    ELSE
			EXITLOOP
		    END;

		ATRPNT=.ATR_IOB[IOB$A_STRING];

		!Non blank first character means end of list
		IF
		    CH$RCHAR_A(ATRPNT) NEQ %C' '
		THEN
		    EXITLOOP;

		!Make sure there is room
		IF
		    CH$DIFF(CH$PLUS(.ATR_END_PTR,.ATR_IOB[IOB$H_STRING]),
			CH$PLUS(.ATR_TAB_PTR,.ATR_T_SIZ)) GEQ 0
		THEN
		    !Get more room by reallocating the table
		    BEGIN

		    LOCAL
			T_PTR;

		    !Specify how much more is needed
		    ATR_T_SIZ=.ATR_T_SIZ+ATR_TAB_SIZ;

		    !Allocate new storage block
		    $XPO_GET_MEM(CHARACTERS=.ATR_T_SIZ,RESULT=T_PTR);

		    !Move data from old to new table
		    ATR_END_PTR=CH$MOVE(CH$DIFF(.ATR_END_PTR,.ATR_TAB_PTR),
					.ATR_TAB_PTR,.T_PTR);

		    !Release old table
		    $XPO_FREE_MEM(STRING=(.ATR_T_SIZ-ATR_TAB_SIZ,.ATR_TAB_PTR));

		    !Point to new table
		    ATR_TAB_PTR=.T_PTR

		    END;

		!Now store the data
		CH$WCHAR_A(.ATR_IOB[IOB$H_STRING]-1,ATR_END_PTR);
		ATR_END_PTR=CH$MOVE(.ATR_IOB[IOB$H_STRING]-1,.ATRPNT,.ATR_END_PTR)

		END;

	    !Terminate the file
	    $step_close(IOB=ATR_IOB);

	    RETURN TRUE
	    END;

	IF
	    CH$RCHAR(.ATRPNT) NEQ %C' ' AND
	    CH$GTR(.CLS_NM_LGT,.ATR_IOB[IOB$A_STRING],.ATRLEN,.ATRPTR)
	THEN
	    EXITLOOP

	END;

    !Close the working file
    $step_close(IOB=ATR_IOB);

    FALSE

    END;				!End of SETATR
GLOBAL ROUTINE GETCLS(GEN_LEN,GEN_PTR,ELM_LEN,ELM_PTR,A_DESC_OUT) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine examines the class file to find all the classes that
!	a particular generation of an element belongs. This routine also
!	supports a wild card character (*) for the generation number in
!	in the generation string.  This means a class is found if the element
!	name matches regardless of the generation number.
!
! FORMAL PARAMETERS:
!
!	GEN_LEN		    Length of generation string.
!
!	GEN_PTR		    Pointer to generation string.
!
!	ELM_LEN		    Length of element string.
!	
!	ELM_PTR		    Pointer to element string.
!
!	A_DESC_OUT	    Address of a descriptor that points to where
!			    output string is located.  This is assumed to
!			    to have been initialized by the calling routine.
!			    The output string consist of a concatentation of
!			    all the classes that the particular generation of
!			    the element belongs and are separated by blank
!			    delimiters.  The storage for this output string is
!			    allocated within this routine.
!
! IMPLICIT INPUTS:
!
!	
!
! IMPLICIT OUTPUTS:
!
!	
!
! ROUTINE VALUE and
! COMPLETION CODES:
!
!	TRUE = Element belongs to at least one class.
!	FALSE = Element does not belong to any class.
!
! SIDE EFFECTS:
!
!	
!
!--
    BEGIN
    
    LITERAL
	N_ALLOC_FAC = 120;		! allocation factor for string expansion

	!+
	!    WARNING: The above value should be of sufficient size to 
	!	satisfy the request with one allocation.  That is to say its
	!	size should be at least as big as the maximum class name size
	! 	plus one(for the blank delimiter).
	!+

    BIND
	D_OUT=.A_DESC_OUT:DESC_BLOCK ;	! desc provided by caller(initialized)
	
    LOCAL
	$IO_BLOCK_DECL(ATR),		! file iob

	A_MEM_BLK,			! address of memory block
	CLS_CNT,			! number of classes found
	
	D_ELM: DESC_BLOCK,		! Desc of element string in file
	D_GEN: DESC_BLOCK,		! desc of generation string in file
	
	F_ELM_REC,			! Previous record was element record
	F_MAT_BOTH,			! Both element and gen match input
	F_1ST_ALL,			! first allocation of memory
	
	L_ELM_REC,			! current work length in element rec
	L_REM_OUT,			! remaining length in output area
	L_SAV_CLS,			! length of current class + blank
	L_VAL_STR,			! length of valid string in buf so far
	
	P_ELM_REC,			! current work pointer on element rec
	P_NXT_SPC,			! pointer to next space available
	P_SAV_CLS,			! pointer to current class in out area
	status;
	
    ! initialize iob
    $IO_BLOCK_INIT(ATR) ;
	
    ! open class file
    IF
	(status=$STEP_OPEN(IOB=ATR_IOB,FILE_SPEC=(%STRING(LIB,ATF)),
	 OPTIONS=INPUT,FAILURE=0)) NEQ step$_NORMAL
    THEN
	badxpo(.status,CAT('Unable to open class file')) ;
		
    ! initialize variables
    L_REM_OUT = 0;
    CLS_CNT = 0 ;
    F_1ST_ALL = FALSE ;
    F_MAT_BOTH = FALSE ;
    F_ELM_REC = FALSE ;
    
    UNTIL
	$step_get(IOB=ATR_IOB) EQL step$_eof
    DO
	BEGIN	    ! read class file loop

	LOCAL
	    CLS_NM_LGT;

	CLS_NM_LGT=0;

	!Get length of class name only
	UNTIL
	    CH$RCHAR(CH$PLUS(.ATR_IOB[IOB$A_STRING],.CLS_NM_LGT)) EQL %C' ' OR
	    .CLS_NM_LGT EQL .ATR_IOB[IOB$H_STRING]
	DO
	    CLS_NM_LGT=.CLS_NM_LGT+1;
	
	IF
	    (CH$RCHAR(.ATR_IOB[IOB$A_STRING]) NEQ %C' ')
	THEN
	    BEGIN	! non-blank means class record
	    
	    IF
		NOT .F_MAT_BOTH AND .F_1ST_ALL
	    THEN
		BEGIN	! no match,backup
		
		!+
		!	When there was no match among previous elements
		!	the output buffer is backed up to where last class
		!	string started so it over written by the next 
		!	valid match.
		!+
		
		L_REM_OUT = .L_REM_OUT + .L_SAV_CLS ;
		P_NXT_SPC = .P_SAV_CLS ;
		END ;	! no match,backup

	    IF 
		.F_ELM_REC
	    THEN
		BEGIN	    ! last rec was elm rec
		F_ELM_REC = FALSE ;
		
		IF
		    .F_MAT_BOTH
		THEN
		    BEGIN	! match
		    CLS_CNT = .CLS_CNT + 1 ;
		    F_MAT_BOTH = FALSE ;
		    END ;	! match
		
		END ;	    ! last rec was elm rec
	    
	    IF
		.L_REM_OUT EQL 0 OR
		.L_REM_OUT LSS (.CLS_NM_LGT+1)
	    THEN
		BEGIN	    ! allocation required
		IF
		    NOT .F_1ST_ALL
		THEN
		    BEGIN	    ! first allocation
		    D_OUT[DESC_LEN] = N_ALLOC_FAC ;
		    $XPO_GET_MEM(CHARACTERS=N_ALLOC_FAC,
				 RESULT=D_OUT[DESC_PTR]) ;
		    F_1ST_ALL = TRUE ;
		    L_REM_OUT = N_ALLOC_FAC ;
		    P_NXT_SPC = .D_OUT[DESC_PTR] ;
		    END	    ! first allocation
		ELSE
		    BEGIN	    ! 2nd + subsequent allocations
		    
		    !+
		    !   When another block is required it is allocated.  the 
		    !   string from the previous block is moved to the new 
		    !   block and the old block is released. Each new block
		    !   represents a character expansion by a factor of 
		    !	N_ALLOC_FAC over the old block.
		    !+
		    
		    $XPO_GET_MEM(CHARACTERS=(.D_OUT[DESC_LEN]+N_ALLOC_FAC),
			 	RESULT=A_MEM_BLK) ;    ! allocate new block
		    L_VAL_STR = .D_OUT[DESC_LEN]-.L_REM_OUT ;
		    P_NXT_SPC = CH$MOVE(.L_VAL_STR,.D_OUT[DESC_PTR],
					.A_MEM_BLK) ;   ! actual str len+ptr
		    !update remaining length and free old block
		    L_REM_OUT = .D_OUT[DESC_LEN] + N_ALLOC_FAC - .L_VAL_STR ;
		    $XPO_FREE_MEM(STRING=(.D_OUT[DESC_LEN],.D_OUT[DESC_PTR])) ;
		    
		    ! reset descriptor to new block
		    D_OUT[DESC_LEN] = .L_VAL_STR + .L_REM_OUT ;
		    D_OUT[DESC_PTR] = .A_MEM_BLK ;
		    END ;	    ! 2nd + subsequent allocation
		    
		END ;   ! allocation required

	    ! move new class to out buffer
	    P_NXT_SPC = CH$MOVE(.CLS_NM_LGT,.ATR_IOB[IOB$A_STRING],
				.P_NXT_SPC) ;
	    CH$WCHAR_A(%C' ',P_NXT_SPC) ;	    !put blank after class
	    L_REM_OUT = .L_REM_OUT - .CLS_NM_LGT - 1 ;

	    ! save len + ptr in case backup required
	    L_SAV_CLS = .CLS_NM_LGT+1;
	    P_SAV_CLS = CH$PLUS(.P_NXT_SPC,-.L_SAV_CLS) ;
	    
	    END 	! non-blank means class record
	ELSE
	    BEGIN	! blank means element gen record
	    
	    IF
		NOT .F_ELM_REC
	    THEN
		F_ELM_REC = TRUE ;
		
	    IF
		NOT .F_MAT_BOTH
	    THEN
		BEGIN	    ! no match yet
		! set up descriptor to point element in record
		D_ELM[DESC_PTR] = CH$PLUS(.ATR_IOB[IOB$A_STRING],1) ;
		P_ELM_REC = CH$FIND_CH(.ATR_IOB[IOB$H_STRING]-1,
				       .D_ELM[DESC_PTR],%C' ') ;
		D_ELM[DESC_LEN] = CH$DIFF(.P_ELM_REC,.D_ELM[DESC_PTR]) ;
		
		! set up generation descriptor
		P_ELM_REC = CH$PLUS(.P_ELM_REC,1) ;
		D_GEN[DESC_PTR] = .P_ELM_REC ;
		L_ELM_REC = .ATR_IOB[IOB$H_STRING] - .D_ELM[DESC_LEN] -2 ;
		P_ELM_REC = CH$FIND_CH(.L_ELM_REC,.D_GEN[DESC_PTR],%C' ') ;
		
		IF
		    (CH$FAIL(.P_ELM_REC) EQL 1 )
		THEN
		    ! nothing beyond generation number
		    D_GEN[DESC_LEN] = .L_ELM_REC 
		ELSE
		    D_GEN[DESC_LEN] = CH$DIFF(.P_ELM_REC,.D_GEN[DESC_PTR]) ;
		    
		IF
		    CH$RCHAR(.GEN_PTR) EQL %C'*'
		THEN
		    BEGIN	! wild card gen number

		    IF
			CH$EQL(.ELM_LEN,.ELM_PTR,LEN_COMMA_PTR(D_ELM),%C' ')
		    THEN
			F_MAT_BOTH = TRUE ;

		    END		! wild card gen number
		ELSE
		    BEGIN	! compare both element and generation

		    IF
			CH$EQL(.GEN_LEN,.GEN_PTR,LEN_COMMA_PTR(D_GEN),%C' ') AND
			CH$EQL(.ELM_LEN,.ELM_PTR,LEN_COMMA_PTR(D_ELM),%C' ')
		    THEN
			F_MAT_BOTH = TRUE ;
		    
		    END ;	! compare both element and generation

		END ;	    ! no match yet
		
	    END ;	! blank means element gen record
	    
	END ;	    ! read file loop
	
    ! end of file - verify that last class was valid
    IF
	NOT .F_MAT_BOTH
    THEN
	L_REM_OUT = .L_REM_OUT + .L_SAV_CLS 
    ELSE
	! last record matches
	CLS_CNT = .CLS_CNT + 1 ;
	
    !reset output descriptor to actual string length
    D_OUT[DESC_LEN] = .D_OUT[DESC_LEN] - .L_REM_OUT ;
    
    ! close class file before returning
    $step_close(IOB=ATR_IOB) ;
	    
    IF
	.CLS_CNT EQL 0
    THEN
	RETURN FALSE ;
	
	
    TRUE
    END;
END				!End of Module ATTRIB
ELUDOM