-- File: GVMailParse.mesa
-- Based on MailParse by Levin: 15-Jan-81 8:48:28
-- Contents: version of MailParse for Cedar using Ropes, etc.

-- Last edited by:
-- Willie-Sue, January 21, 1983 10:40 am

DIRECTORY MailParse, Rope;

GVMailParse: CEDAR DEFINITIONS
IMPORTS MailParse =

BEGIN

ROPE: TYPE = Rope.ROPE;

-- General Note: The organization of this interface is motivated by RFC 733,
-- "Standard for the Format of Arpa Network Text Messages", November 21, 1977.
-- Syntactic entities enclosed in meta-linguistic brackets (e.g., <atom>) are
-- taken from this document (where they appear unbracketed), as is much of the
-- general terminology.


-- Types and Constants --

ParseErrorCode: TYPE = MailParse.ParseErrorCode;
ParseHandle: TYPE = MailParse.ParseHandle;
NameInfo: TYPE = MailParse.NameInfo;
NameType: TYPE = MailParse.NameType;
BracketType: TYPE = MailParse.BracketType;

endOfInput: CHARACTER = 203C;
-- this character should be returned by the client's 'next' procedure (see
-- InitializeParse) when the end of the input is reached. The client's 'backup'
-- procedure may be called after endOfInput has been returned by the 'next'
-- procedure, and a subsequent call of 'next' should again produce endOfInput.

endOfList: CHARACTER = 204C;
-- this character may be used as an "invisible delimiter" terminating a list of
-- names. It has no other effect.

-- Signals --

ParseError: ERROR [code: ParseErrorCode];

-- Procedures --

InitializeParse: PROCEDURE [next: PROCEDURE RETURNS [CHARACTER],
backup: PROCEDURE, notifyTruncation: BOOLEANFALSE] RETURNS [ParseHandle];
-- Initializes the header parser, and returns a ParseHandle which is to be passed to
-- all other procedures of this interface. Subsequent invocations of GetFieldName,
-- GetFieldBody, and ParseNameList will obtain their input using 'next'. The
-- procedure 'backup' is occasionally called by the parser to "back up" the input
-- sequence. The client should be prepared to back up no less than 10 characters.
-- If 'notifyTruncation' is TRUE, GetFieldName and GetFieldBody will raise
-- ParseError[truncated] if the string they are collecting overflows the string
-- provided. (The signal is not raised until the entire field name or body has
-- been scanned.) If 'notifyTruncation' is FALSE, this signal is suppressed.

FinalizeParse: PROCEDURE [pH: ParseHandle];
-- Finalizes the parser instance specified by 'pH'. This procedure must be
-- called when the client has finished parsing, either because of normal
-- completion or because some error has occurred. After calling this procedure,
-- 'pH' is no longer meaningful and must not be reused. Note: FinalizeParse may
-- not be called while a call to ParseNameList is pending (for the same ParseHandle).

GetFieldName: PROCEDURE [pH: ParseHandle] RETURNS [found: BOOLEAN, fieldNameOut: ROPE];
-- GetFieldName presumes that 'next' (see InitializeParse) is positioned to read the
-- first character of a field name and returns the field name, without the
-- terminating colon, in 'fieldNameOut'. GetFieldName leaves 'next' ready to
-- return the first character following the colon (or, if the end of the message
-- header has been reached, the character (if any) after the two CRs that normally
-- terminate the header). If the field name is too long, the behavior of
-- GetFieldName depends upon the 'notifyTruncation' parameter passed to
-- InitializeParse. Upon return, 'found' is FALSE if no field names remain in the
-- header. If the header field ends prematurely or illegal header characters are
-- encountered, ParseError[badFieldName] is raised.

GetFieldBody: PROCEDURE [pH: ParseHandle, suppressWhiteSpace: BOOLEANFALSE]
RETURNS[fieldBodyOut: ROPE];
-- The (remainder of the) current field body is read using 'next' (see
-- InitializeParse) and is returned in 'fieldBodyOut'. If the field
-- body is too long, the behavior GetFieldBody depends upon the 'notifyTruncation'
-- parameter passed to InitializeParse. If the field body
-- terminates before a CR is seen, ParseError[badFieldBody] is raised. Upon
-- return, 'fieldBodyOut' has no initial or terminal white space (blanks and tabs)
-- and, if 'suppressWhiteSpace' is TRUE, each internal run of white space has
-- been replaced by a single blank. ArpaNet folding conventions are also observed.

ParseNameList: PROCEDURE [
pH: ParseHandle,
process: PROCEDURE [ROPE, ROPE, ROPE, NameInfo] RETURNS [BOOLEAN],
write: PROCEDURE [CHARACTER] ← NIL, suppressWhiteSpace: BOOLEANFALSE];
-- ParseNameList expects to read characters using 'next' (see InitializeParse)
-- for a structured field body consisting of a list of recipient names. For each
-- such name encountered, it will call 'process', passing it three string arguments
-- that designate the simple name, registry, and Arpanet host. The simple name is
-- always non-empty. If the registry and/or host is absent, a string of length
-- zero (not NIL) is passed. The string parameters are free from leading, trailing,
-- and excess internal white space, and are guaranteed to be at least
-- 'maxRecipientLength' characters in length. The 'process' routine has a fourth
-- parameter which provides additional information about the name being supplied
-- (see the description of the NameInfo type, above, for details). The registry
-- and Arpanet host parameters may (but not the simple name) be changed by
-- 'process' to alter the qualification of the simple name. This operates as
-- follows: If 'process' returns TRUE, ParseNameList will output the complete
-- name, with potentially altered qualification, by calling 'write'
-- successively with each character. ParseNameList will attempt to preserve the
-- original format of the name as much as possible, including bracketing, comments,
-- and white space, unless 'suppressWhiteSpace' is TRUE. In the latter case,
-- non-significant white space will be eliminated and significant white space
-- (outside of quoted strings) will be replaced by a single space. If 'process'
-- returns FALSE or if 'write' is defaulted, no output occurs. ParseNameList
-- assumes responsibility for outputing appropriate separators (commas) and
-- brackets, based on the values returned by succesive invocations of 'process'.
-- If any syntax errors are detected during parsing, ParseError[badFieldBody] is
-- raised. It is legitimate for the 'process' routine to raise a signal that
-- causes ParseNameList to be unwound.

GetListOrGroupName: PROCEDURE [pH: ParseHandle] RETURNS[ROPE];
-- This procedure can only reasonably be called from inside the 'process'
-- procedure passed to ParseNameList. The <phrase> that introduces the current
-- list or group is read using 'next' (see InitializeParse) and is returned in
-- 'name'. If the name is too long, the behavior of GetListOrGroupName depends
-- upon the 'notifyTruncation' parameter passed to InitializeParse. Upon return,
-- 'name' has no initial or terminal white space (blanks and tabs) and each
-- internal run of white space has been replaced by a single blank. If
-- GetListOrGroupName is called at an inappropriate time (e.g., when
-- NameInfo.nesting = none), the empty string is returned.

GetTag: PROCEDURE [pH: ParseHandle] RETURNS[ROPE];
-- This procedure can only reasonably be called from inside the 'process'
-- procedure passed to ParseNameList. The <atom> appearing within colons that
-- introduces the current name is read using 'next' (see InitializeParse) and is
-- returned in 'tag'. (If a sequence of such atoms, each within colons,
-- precedes the current name, GetTag constructs a <phrase> consisting of this
-- sequence of atoms separated by spaces and returns it in 'tag'. If the atom is
-- too long, the behavior of GetTag depends upon the 'notifyTruncation' parameter
-- passed to InitializeParse. Upon return, 'tag' has no initial or terminal white
-- space (blanks and tabs). If GetTag is called at an inappropriate time
-- (e.g., when NameInfo.hasTag = FALSE), the empty string is returned.


END.