    .TITLE        GNMPARSETABLE - Parse tables for GNM files
    .IDENT        "V1.1-000"

;++
;  Copyright 1976, 2004 Hewlett-Packard Development Company, L.P.
;
;  Confidential computer software.  Valid license  from  HP  and/or its
;  subsidiaries required for possession, use, or copying.
;
;  Consistent with FAR 12.211 and 12.212, Commercial Computer Software,
;  Computer Software Documentation,  and  Technical Data for Commercial
;  Items  are  licensed to the U.S. Government under vendor's  standard
;  commercial license.
;
;  Neither HP nor any of its subsidiaries shall be liable for technical
;  or editorial errors or omissions contained herein.   The information
;  in  this document is provided  "as is"  without warranty of any kind
;  and is subject  to  change  without  notice.   The warranties for HP
;  products are set forth in the express  limited  warranty  statements
;  accompanying such products.   Nothing herein should be construed  as
;  constituting an additional warranty.
;--
;
;  This Macro32 module is part of the GNM compiler.  
;
;  GNM provides a mechanism for maintaining a common source file for 
;  both OpenVMS messages and for error messages and recovery documentation.  
;
;  The GNM compiler translates the contents of the GNM-format input file 
;  into an output file suitable for processing by the OpenVMS MESSAGE 
;  compiler, and into a second output file intended as input into the
;  OpenVMS DOCUMENT utility.
;
;  The default file extensions used for these two output files are .MSG 
;  and .SDML, respectively.  The default input file extension is .GNM.
;
;  This particular module defines the format, syntax, and processing of 
;  the GNM-format input data file.  This module specifically contains 
;  the tables and keywords referenced by a call to the OpenVMS Run-Time
;  Library (RTL) finite-state parsing routine LIB$TABLE_PARSE, and the
;  state tables here reference a various callback routines (GNM$GB_*) 
;  that process specific portions of the GNM input data.
;

;  Declarations follow...
;
    .PSECT  IMPURE,WRT,NOEXE

;  Load the LIB$TABLE_PARSE definitions.
;
    $CLIDEF
    $TPADEF
    $GNMDEF

    .SBTTL  The GNM compiler state table

;  State Table Implementation Details and Assumptions:
;
;  Because all GNM keywords can exist only at the beginning of a record 
;  in the input file (though potentially with leading whitespace in the
;  record), the callback routines here will regularly read in new records 
;  from the input file, and will reset the contents of the LIB$TABLE_PARSE 
;  argument block accordingly.
;
;  If a syntax error is detected in the input, the parse will fail.
;  That said, the parser will attempt to advance to the next .NAME or 
;  .END keyword, and will attempt to check the syntax of the remainder
;  of the file.  Everything between the syntax error and the record
;  where the next matching keyword is found is ignored. 
;

    $INIT_STATE	    GNM$STATE_TABLE, GNM$KEY_TABLE

    ;  Start to parse the input buffer
    ;
    $STATE  S_START
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  
    ;       find this...    go here...      after calling...
    $TRAN   'COPYRIGHT',    S_START,        GNM$CB_LOADER,,,GNM$K_COPYRIGHT
    $TRAN   'COMPONENT',    S_COMPONENT
    $TRAN   'FACILITY',     S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_FACILITY
    $TRAN   'IDENT',	    S_FACILITY,	    GNM$CB_LOADER,,,GNM$K_IDENT
    $TRAN   'TITLE',	    S_IDENT,	    GNM$CB_LOADER,,,GNM$K_TITLE
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  S_COMPONENT
    ;       find this...    go here...      after calling...
    $TRAN   TPA$_SYMBOL,    S_START,        GNM$CB_LOADER,,,GNM$K_COMPONENT
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  We seem to have found a title keyword.
    ;  We next expect to see an ident or a facility.
    ;
    $STATE  S_IDENT
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE
    ;       find this...    go here...      after calling...
    $TRAN   'COPYRIGHT',    S_IDENT,        GNM$CB_LOADER,,,GNM$K_COPYRIGHT
    $TRAN   'COMPONENT',    S_COMPONENT2
    $TRAN   'FACILITY',     S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_FACILITY
    $TRAN   'IDENT',	    S_FACILITY,	    GNM$CB_LOADER,,,GNM$K_IDENT
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  S_COMPONENT2
    ;       find this...    go here...      after calling...
    $TRAN   TPA$_SYMBOL,    S_START,        GNM$CB_LOADER,,,GNM$K_COMPONENT
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  We found an ident string.
    ;  We next expect to see a facility keyword.
    ;  We must find a facility keyword somewhere in the prolog.
    ;
    $STATE  S_FACILITY
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE
    ;       find this...    go here...      after calling...
    $TRAN   'FACILITY',     S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_FACILITY
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  A facility string has been found; we can now proceed.
    ;  We now expect to see one of the core group of keywords.
    ;
    $STATE  S_COREGROUP
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  
    ;       find this...    go here...      after calling...
    $TRAN   'BASE',	    S_BASE
    $TRAN   'DESTINATION',  S_WHERETO
    $TRAN   'END',	    TPA$_EXIT,      GNM$CB_LOADER,,,GNM$K_END
    $TRAN   'NAME',	    S_NAME
    $TRAN   'PAGE',	    S_MESSAGE,	    GNM$CB_LOADER,,,GNM$K_PAGE
    $TRAN   'SEVERITY',     S_SEVERITY
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  S_NAME
    ;       find this...    go here...      after calling...
    $TRAN   TPA$_SYMBOL,    S_MESSAGE,      GNM$CB_LOADER,,,GNM$K_NAME
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  S_BASE
    ;       find this...    go here...      after calling...
    $TRAN   TPA$_DECIMAL,   S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_BASE
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE  S_SEVERITY
    ;       find this...      go here...      after calling...
    $TRAN   'ERROR',          S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_ERROR
    $TRAN   'FATAL',          S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_FATAL
    $TRAN   'INFORMATIONAL',  S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_INFORMATIONAL
    $TRAN   'SUCCESS',        S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_SUCCESS
    $TRAN   'WARNING',        S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_WARNING
    $TRAN   TPA$_LAMBDA,      S_TRYRECOVERY,  GNM$CB_SYNTAXERR


    ;  We have been asked to route subsequent message group(s) 
    ;  to a particular output destination.  Figure out where.
    ;
    $STATE  S_WHERETO
    ;       find this...    go here...      after calling...
    $TRAN   'ALL',	    S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_DEST_BOTH
    $TRAN   'BOTH',	    S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_DEST_BOTH
    $TRAN   'DOCUMENT',	    S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_DEST_SDML
    $TRAN   'MESSAGE',	    S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_DEST_MSG
    $TRAN   'MSG',	    S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_DEST_MSG
    $TRAN   'SDML',	    S_COREGROUP,    GNM$CB_LOADER,,,GNM$K_DEST_SDML
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  We have entered what should be a named message grouping.
    ;
    $STATE  S_MESSAGE
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE
    ;       find this...    go here...      after calling...
    $TRAN   'MESSAGE',      S_EXPLAN,       GNM$CB_LOADER,,,GNM$K_MESSAGE
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  We are now looking for an .explanation.
    ;
    $STATE  S_EXPLAN
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE
    ;       find this...    go here...      after calling...
    $TRAN   'EXPLANATION',  S_EXPLAN_MORE,  GNM$CB_LOADER,,,GNM$K_EXPLAN

;???
    $TRAN   'BASE',	    S_BASE,         GNM$CB_DESTMSG
    $TRAN   'DESTINATION',  S_WHERETO,      GNM$CB_DESTMSG
    $TRAN   'END',	    TPA$_EXIT,      GNM$CB_DESTMSG
    $TRAN   'NAME',	    S_NAME,         GNM$CB_DESTMSG
    $TRAN   'SEVERITY',     S_SEVERITY,     GNM$CB_DESTMSG
;???

    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  We are processing an .explanation.  Look for more user
    ;  explanation text, a .user_action keyword, or a leading dot 
    ;  character.  The leading dot implies a keyword follows, and
    ;  specifically a keyword other than the .user_action keyword
    ;  that is the only keyword we are expecting, and that is
    ;  considered a syntax error.
    ;
    $STATE  S_EXPLAN_MORE
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_EXPLAN_MORE,  GNM$CB_LOADER,,,GNM$K_EXPLAN_MORE

    $STATE
    ;       find this...    go here...      after calling...
    $TRAN   'USER_ACTION',  S_USRACT_MORE,  GNM$CB_LOADER,,,GNM$K_USRACT
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  We are processing a .user_action.  Look for more user
    ;  explanation text, one of the core group of keywords,
    ;  or a leading dot character.  The leading dot implies 
    ; a keyword follows, and specifically a keyword other than 
    ;  keywords we are expected.  That is an error, of course.
    ;
    $STATE  S_USRACT_MORE
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_LAMBDA,    S_USRACT_MORE,  GNM$CB_LOADER,,,GNM$K_USRACT_MORE

    $STATE  S_MSGONLY
    ;       find this...    go here...      after calling...
    $TRAN   'BASE',	    S_BASE
    $TRAN   'DESTINATION',  S_WHERETO
    $TRAN   'END',	    TPA$_EXIT
    $TRAN   'NAME',	    S_NAME
    $TRAN   'SEVERITY',     S_SEVERITY
    $TRAN   TPA$_LAMBDA,    S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    ;  If we have reached here, the input file syntax is somehow
    ;  garbled, or we are somehow confused, or both.  Attempt to 
    ;  recover; try to continue processing the remainder of the
    ;  input file.  (We likely will not write (valid) output, but 
    ;  we will attempt to validate syntax further into the input
    ;  file.  This recovery state is simple-minded, seeking only
    ;  the next line starting with an .end or a .name keyword,
    ;  and ignores everything else until one of these is found.
    ;
    $STATE  S_TRYRECOVERY
    ;       find this...    go here...      after calling...
    $TRAN   '.'
    $TRAN   TPA$_EOS,       S_TRYRECOVERY,  GNM$CB_READGNM
    $TRAN   TPA$_ANY,       S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $STATE
    ;       find this...    go here...      after calling...
    $TRAN   'END',	    TPA$_FAIL,      GNM$CB_SYNTAXMSG
    $TRAN   'NAME',	    S_NAME,         GNM$CB_SYNTAXMSG
    $TRAN   TPA$_EOS,       S_TRYRECOVERY,  GNM$CB_READGNM
    $TRAN   TPA$_ANY,       S_TRYRECOVERY,  GNM$CB_SYNTAXERR

    $END_STATE

    .END
