Google
 

Trailing-Edge - PDP-10 Archives - DEC_CMS-20_V1.0_SRC - cms/sources/values.bli
There are no other files named values.bli in the archive.
module values (	! Recognize and process STEP qualifier values.
		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:
!
!	This module contains routines that analyze qualifier values for
!	CMS commands.  The principal routine, RECVAL, sees if a given
!	qualifier takes a value, and if so, calls other routines to
!	recognize and analyze it.
!
! Environment: Transportable
!
! Author:  Earl Van Horn	Creation Date:  June, 1979
!
!--
!
! Table of Contents:
!

forward routine
    check_date,			! Check the syntax of a date.
    recval,			! Recognize a qualifier's value, if any.
    required_eql,		! Eat up a required colon or equal sign.
    required_lexeme ;		! Obtain a required lexeme qualifier.

!
! Include Files:
!
%if %bliss(bliss32)

%then library 'sys$library:starlet';

%else require 'jsys:';

%fi

library 'XPORT:' ;
require 'BLISSX:' ;
require 'COMUSR:' ;		! Declarations for the user of the
				! language processor.
require 'LANGME:' ;		! Declarations internal to the language
				! processor.

!
! Macros:
!

!
! Equated Symbols:
!
bind
    chars_for_eql = lit( %bliss32(':=') %bliss36(':') %bliss16(':=') ) ;
			! Address of the descriptor of a string of the
			! characters that are allowed to separate a qualifier
			! from its value.

!
! Own Storage:
!

!
! External References:
!

external literal
	s_badvar,
	s_datebad,
	s_dayerr,
	s_eqlreq,
	s_hyphtwo,
	s_ilchar,
	s_invqual,
	s_montherr,
	s_nomondig,
	s_not20cent,
	s_noyearlet,
	s_valnotall,
	s_yearerr;

external routine
    bug,			! Report a bug.
    codspl,			! Return descriptor of spelling for code.
    ers,			! Report a user mistake.
    genexp,			! Recognize a generation expression.
    gennum,			! Check syntax of a generation number.
    genpri,			! Check syntax of a generation primary.
    nxtlex,			! Obtain the next lexeme.
    peekch ;			! Look ahead to the next command character.
routine check_date(a_lexeme, a_description) =

!++
! Functional Description:
!
!	This routine checks that the given lexeme is a valid date, and
!	returns TRUE if it is.  The given description is a phrase describing
!	what the lexeme is supposed to be, for use in error messages.
!
!	The lexeme must have the form:
!
!	    [digit] digit "-" letter letter letter "-" ["19"] digit digit
!
!	It is assumed that letters have already been converted to upper case.
!
! Formal Parameters:
!
!	a_lexeme:	Address of a descriptor of the lexeme whose syntax
!			is to be checked.
!	a_description:	Address of a descriptor of what the lexeme is supposed
!			to be, for use in error messages.
!
! Implicit Inputs:
!
!	None
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	TRUE if the lexeme has the syntax given above.
!	FALSE means the user has been told of his mistake.
!
! Side Effects:
!
!	None
!
!--

    begin	! CHECK_DATE
    bind
	lexeme = .a_lexeme : desc_block,
	description = .a_description : desc_block ;

    local
	day_digits,	! Number of digits seen in the day.
	hyphens,	! Number of hyphens encountered so far.
	month_letters,	! Number of letters seen in the month.
	p_this,		! Pointer to current character being checked.
	year_digits ;	! Number of digits seen in the year.

    ! Initialize to scan the lexeme.
    hyphens = 0 ;
    day_digits = 0 ;
    month_letters = 0 ;
    year_digits = 0 ;
    p_this = .lexeme[desc_ptr] ;

    ! Scan the lexeme from left to right.
    incr i from 1 to .lexeme[desc_len] do
	begin	! Examine one character and advance to the next.
	selectone ch$rchar(.p_this) of
	    set	! Examine one character.

	    [%c'-']:
		begin		! Hyphen.
		hyphens = .hyphens + 1 ;
		if .hyphens geq 3
		then
		    begin	! Too many hyphens.
		    ers(s_hyphtwo,cat('Your ', description, ' ', lexeme,
			' should have two hyphens')) ;
		    return false ;
		    end ;	! Too many hyphens.
		end ;		! Hyphen.

	    [%c'0' to %c'9']:
		selectone .hyphens of
		    set		! Digit action.
		    [0]:
			day_digits = .day_digits + 1 ;
		    [1]:
			begin	! Digits in month.
			ers(s_nomondig,cat('Your ', description, ' ', lexeme,
			   ' should not have a digit in the month'));
			return false ;
			end ;	! Digits in month.
		    [2]:
			year_digits = .year_digits + 1 ;
		    [otherwise]:
			bug(cat('CHECK_DATE hyphen error for digits of ',
				lexeme)) ;

		    tes ;	! Digit action.

	    [%c'A' to %c'Z']:
		selectone .hyphens of
		    set		! Letter action.
		    [0]:
			begin	! Leading letter.
			ers(s_datebad,cat('Your ', description, ' ', lexeme,
			   ' should have a form like: [d]d-mmm-19yy')) ;
			return false ;
			end ;	! Leading letter.
		    [1]:
			month_letters = .month_letters + 1 ;
		    [2]:
			begin	! Letter in year.
			ers(s_noyearlet,cat('Your ', description, ' ', lexeme,
			   ' should not have a letter in the year'));
			return false ;
			end ;	! Letter in year.
		    [otherwise]:
			bug(cat('CHECK_DATE hyphen error for letters of  ',
				lexeme)) ;
		    tes ;	! Letter action.

	    [otherwise]:
		begin		! Invalid character in date.
		ers(s_ilchar,cat('Your ', description, ' ', lexeme,
		    ' may not contain "', (1, .p_this), '"')) ;
		return false ;
		end ;		! Invalid character in date.

	    tes ;		! Examine one character.

	p_this = ch$plus(.p_this, 1) ;
	end ;	! Examine one character and advance to the next.

    if .hyphens lss 2
    then
	begin	! Not enough hyphens.
	ers(s_hyphtwo,cat('Your ', description, ' ', lexeme,
		' should have two hyphens')) ;
	return false ;
	end ;	! Not enough hyphens.

    if .day_digits lss 1 or .day_digits gtr 2
    then
	begin	! Day error.
	ers(s_dayerr,cat('Your ', description, ' ', lexeme,
	    ' should have a day of one or two digits')) ;
	return false ;
	end ;	! Day error.

    if .month_letters neq 3
    then
	begin	! Month error.
	ers(s_montherr,cat('Your ', description, ' ', lexeme,
	    ' should have a month of three letters')) ;
	return false ;
	end ;	! Month error.

    if .year_digits neq 2 and .year_digits neq 4
    then
	begin	! Year size error
	ers(s_yearerr,cat('Your ', description, ' ', lexeme,
	    ' should have a year of two or four digits')) ;
	return false ;
	end ;	! Year size error.

    if .year_digits eql 4
    then
	if ch$neq(2, ch$plus(.lexeme[desc_ptr], .lexeme[desc_len] - 4),
		len_comma_ptr('19'))
	then
	    begin	! Century error.
	    ers(s_not20cent,cat('In your ', description, ' ', lexeme,
		' the four-digit year should begin with "19"')) ;
	     return false ;
	    end ;	! Century error.

    true
    end ;	! CHECK_DATE
global routine recval(a_user_string, a_qua) =

!++
! Functional Description:
!
!	This routine determines whether a qualifer whose block is qiven
!	takes an optional or mandatory value.  If it does, the value is
!	obtained from the beginning of the user string, and is removed from
!	the user string.
!
! Formal Parameters:
!
!	a_user_string:	Address of a descriptor of the unprocessed characters
!			in the user's command string.  If the qualifier takes
!			a value, then a leading colon or equal sign indicates
!			that the user supplied a value.  The descriptor is
!			advanced beyond the value by NXTLEX.
!	a_qua:		Address of a qualifier block for the qualifier whose
!			value is to be looked for.
!
! Implicit Inputs:
!
!	None
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	TRUE is returned if the user made no mistake, otherwise FALSE.
!
! Side Effects:
!
!	None
!
!--

    begin	! RECVAL
    bind
	user_string = .a_user_string : desc_block,
	qua = .a_qua : qualifier_block ;

    ! Initialize the descriptor for the qualifier value.
    $str_desc_init(descriptor = qua[qua_value], string = (0, k_null)) ;

    ! Treat each qualifier separately.
    selectone .qua[qua_code] of
	set	! Examine the qualifier code.

	[k_all_qual, k_append_qual, k_brief_qual, k_class_qual,
	 k_delete_qual, k_if_absent_qual, k_if_present_qual, k_keep_qual,
	 k_nohistory_qual, k_nonotes_qual, k_parallel_qual, 
	 k_recover_qual, k_reserve_qual, k_supersede_qual, k_unusual_qual,
	 K_log_qual,k_nolog_qual,k_repair_qual,k_read_qual,k_noread_qual,
	 k_noappend_qual,k_nooutput_qual,k_nokeep_qual,k_noreserve_qual,
	 k_noparallel_qual,k_nomerge_qual,k_nosupersede_qual,k_novariant_qual,
	 k_noclass_qual,k_noformat_qual,k_nobrief_qual,k_nounusual_qual,
	 k_norecover_qual,k_norepair_qual,k_nodelete_qual]:
	    begin	! No value allowed.
	    if peekch(user_string, chars_for_eql)
	    then
		begin	! User tried to give a value.
		ers(s_valnotall,cat(codspl(.qua[qua_code]),
				 ' does not take a value')) ;
		return false ;
		end ;	! User tried to give a value.
	    end ;	! No value allowed.

	[k_output_qual]:
	    begin	! Optional file specification.
	    if peekch(user_string, chars_for_eql)
	    then
		begin	! User supplied an optional file specification.

		! Eat up the colon or equal sign.
		if not nxtlex(user_string, k_normal_lex, k_null,
				qua[qua_value])
		then
		    bug(lit('NXTLEX found no delimiter for /OUTPUT')) ;

		! Take the next lexeme as a file specification.
		if not nxtlex(user_string, k_file_spec_lex,
				codspl(k_file_spec_syn), qua[qua_value])
		then
		    return false ;
		end ;	! User supplied an optional file specification.
	    end ;	! Optional file specification.

	[k_gen_qual, k_merge_qual]:
	    begin	! Required generation expression.

	    ! Get the delimiter.
	    if not required_eql(user_string, k_gen_exp_syn, qua)
	    then
		return false ;

	    ! Recognize the generation expression.
	    if not genexp(user_string, k_gen_exp_syn, qua[qua_value],
						      qua[qua_a_tree])
	    then
		return false ;

	    end ;	! Required generation expression.
	    
	[k_from_qual]:
	    begin	! Required generation primary.
	    if not required_lexeme(user_string, k_normal_lex,
						k_gen_pri_syn, qua)
	    then
		return false ;

	    ! Make sure it has the right syntax.
	    if not genpri(qua[qua_value], codspl(k_gen_pri_syn))
	    then
		return false ;

	    end ;	! Required generation primary.

	[k_variant_qual]:
	    begin	! Required variant letter.
	    if not required_lexeme(user_string, k_normal_lex,
						k_var_let_syn, qua)
	    then
		return false ;

	    ! Make sure it is only one character.
	    if .qua[qua_value_len] gtr 1
	    then
		begin	! Variant value too long.
		ers(s_badvar,cat(qua[qua_value], ' is invalid because ',
			codspl(.qua[qua_code]), ' needs a single letter')) ;
		return false ;
		end ;	! Variant value too long.

	    ! Make sure it is a letter.
	    if ch$rchar(.qua[qua_value_ptr]) lss %c'A'
	    or ch$rchar(.qua[qua_value_ptr]) gtr %c'Z'
	    then
		begin	! Not a letter.
		ers(s_badvar,cat( qua[qua_value], ' is invalid because ',
		    codspl(.qua[qua_code]), ' needs a letter')) ;
		return false ;
		end ;	! Not a letter.

	    end ;	! Required variant letter.

	[k_position_qual, k_width_qual]:
	    begin	! Required non-negative integer.
	    local
		p_this ;	! Pointer to current character being examined.

	    ! Get the lexeme that is the qualifier value.
	    if not required_lexeme(user_string, k_normal_lex,
						k_char_pos_syn, qua)
	    then
		return false ;

	    ! Make sure it is a non-negative integer.
	    p_this = .qua[qua_value_ptr] ;
	    incr i from 1 to .qua[qua_value_len] do
		begin	! Examine one digit and advance to the next.
		if ch$rchar(.p_this) lss %c'0' or ch$rchar(.p_this) gtr %c'9'
		then
		    begin	! Non-digit.
		    ers(s_invqual,cat(qua[qua_value], ' is invalid because ',
				codspl(.qua[qua_code]),
				' needs a non-negative integer')) ;
		    return false ;
		    end ;	! Non-digit.
		p_this = ch$plus(.p_this, 1) ;
		end ;	! Examine one digit and advance to the next.

	    end ;	! Required non-negative integer.

	[k_history_qual, k_notes_qual]:
	    begin	! Required insertion pattern.
	    if not required_lexeme(user_string, k_quotation_lex,
						k_ins_pat_syn, qua)
	    then
		return false ;
	    end ;	! Required insertion pattern.

	[k_format_qual]:
	    begin	! Required format string.
	    if not required_lexeme(user_string, k_quotation_lex,
						k_format_syn, qua)
	    then
		return false ;
	    end ;	! Required format string.

	[k_since_qual]:
	    begin	! Required date.

	    ! Get the date string.
	    if not required_lexeme(user_string, k_normal_lex, k_date_syn, qua)
	    then
		return false ;

	    ! Check it for proper form.
	    if not check_date(qua[qua_value], codspl(k_date_syn))
	    then
		return false ;

	    end ;	! Required date.

	[otherwise]:
	    bug(cat(codspl(.qua[qua_code]), ' is not handled by RECVAL')) ;

	tes ;	! Examine the qualifier code.

    true
    end ;	! RECVAL
routine required_eql(a_user_string, syntax, a_qua) =

!++
! Functional Description:
!
!	This routine looks for a ":" or "=" as the next thing in the user's
!	command string.  The user string descriptor is advanced beyond this
!	delimiter by calling NXTLEX.
!
!	If the delimiter is not present, the user is told of his mistake,
!	and FALSE is returned.  The given syntactic category and the QUA_CODE
!	in the given qualifier block are used for messages.
!
! Formal Parameters:
!
!	a_user_string:	Address of a descriptor of the unprocessed characters
!			in the user's command string.  NXTLEX will advance
!			the descriptor just beyond the value found.
!	syntax:		Integer code giving the syntactic category of the
!			qualifier's value, for use in error messages.  These
!			codes are defined in COMUSR.REQ.
!	a_qua:		Address of a qualifier block for this qualifier.
!			The QUA_CODE field is used for messages.
!
! Implicit Inputs:
!
!	None
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	TRUE is returned if the user made no mistake, otherwise false.
!
! Side Effects:
!
!	None
!
!--

    begin	! REQUIRED_EQL
    bind
	user_string = .a_user_string : desc_block,
	qua = .a_qua : qualifier_block ;

    ! Look for the colon or equal sign.
    if not peekch(user_string, chars_for_eql)
    then
	begin	! Missing colon or equal sign.
	ers(s_eqlreq,cat(codspl(.qua[qua_code]),
	    	%string(' needs "' %bliss32(, '=" or "'), ':" followed by '),
		codspl(.syntax))) ;
	return false ;
	end ;	! Missing colon or equal sign.

    ! Eat up the colon or equal sign.
    if not nxtlex(user_string, k_normal_lex, k_null, qua[qua_value])
    then
	bug(cat('NXTLEX gave REQUIRED_EQL no delimiter at ',
		user_string)) ;

    true
    end ;	! REQUIRED_EQL
routine required_lexeme(a_user_string, lexical_rule, syntax, a_qua) =

!++
!
! Functional Description:
!
!	This routine looks for a ":" or "=" followed by a qualifier value
!	as the next things in the user's command string.  The value must
!	be present and satisfy the given lexical rule.  If these requirements
!	are not met, the user is told of his mistake, and FALSE is returned.
!	The given syntactic category and the QUA_CODE in the given qualifier
!	block are used for messages.  If the user made no mistake, the
!	QUA_VALUE descriptor in the qualifier block is made to denote
!	the value that was found.  The user string descriptor is advanced
!	beyond the value by NXTLEX.
!
! Formal Parameters:
!
!	a_user_string:	Address of a descriptor of the unprocessed characters
!			in the user's command string.  NXTLEX will advance
!			the descriptor beyond the value found.
!	lexical_rule:	Integer code giving the lexical rule to be satisfied
!			by the value.  These codes are defined in LANGME.REQ.
!	syntax:		Integer code giving the syntactic category of the
!			value, for use in error messages.  These codes are
!			defined in COMUSR.REQ.
!	a_qua:		Address of a qualifier block for this qualifier.
!			The QUA_CODE field is used for messages, and the
!			QUA_VALUE field is stored into.
!
! Implicit Inputs:
!
!	None
!
! Implicit Outputs:
!
!	None
!
! Routine Value:
! Completion Codes:
!
!	TRUE is returned if the user made no mistake, otherwise false.
!
! Side Effects:
!
!	None
!
!--

    begin	! REQUIRED_LEXEME
    bind
	user_string = .a_user_string : desc_block,
	qua = .a_qua : qualifier_block ;

    ! Eat up the delimiter.
    if not required_eql(user_string, .syntax, qua)
    then
	return false ;

    ! Get the required value.
    if not nxtlex(user_string, .lexical_rule, codspl(.syntax), qua[qua_value])
    then
	return false ;

    true
    end ;	! REQUIRED_LEXEME
end				! Module VALUES
eludom