MailParse.mesa
Copyright Ó 1985, 1989, 1991 by Xerox Corporation. All rights reserved.
based on MailParseDefs.mesa of Brotz, March 3, 1983 8:32 PM
Last Edited by: Willie-sue, August 4, 1989 1:23:41 pm PDT
Doug Terry, October 21, 1988 3:33:27 pm PDT
Doug Wyatt, March 7, 1985 10:42:40 am PST
DIRECTORY
MailBasics USING [RName],
Rope USING [ROPE];
MailParse: CEDAR DEFINITIONS
= BEGIN
ROPE: TYPE = Rope.ROPE;
RName: TYPE = MailBasics.RName;
General Note: The organization of this interface is motivated by RFC 822,
"Standard for the Format of Arpa Network Text Messages", August 13, 1982.
Types and Constants
ParseErrorCode: TYPE = {none, badFieldName, badFieldBody, truncated};
ParseHandle: TYPE = REF ParseInfo;
Instances of this type represent independent instances of the parser. This
permits multiple clients of this interface to be using the parser implementation
at the same time.
ParseInfo: TYPE;
endOfInput: CHAR = 203C;
This character should be returned by the client's "next" procedure (see InitializeParse)
when the end of the input is reached.
endOfList: CHAR = 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: PROC RETURNS [ph: 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".
FinalizeParse: PROC [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: PROC [ph: ParseHandle, next: PROC RETURNS [CHAR]]
RETURNS [fieldName: 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,
as "fieldName". 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).
Upon return, fieldName is NIL if no field names remain in the header.
If the header field ends prematurely or illegal header charactersare encountered,
ParseError[badFieldName] is raised.
GetFieldBody: PROC [ph: ParseHandle, next: PROC RETURNS [CHAR],
suppressBody: BOOL ¬ FALSE, suppressWhiteSpace: BOOL ¬ FALSE]
RETURNS [fieldBody: ROPE];
The (remainder of the) current field body is read using "next" (see InitializeParse)
and is returned as "fieldBody". If the field body terminates before a CR is seen,
ParseError[badFieldBody] is raised. Upon return, "fieldBody" 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.
IF suppressBody is TRUE, then no fieldBody is generated
NameList: PROC [ph: ParseHandle, transport: ATOM, next: PROC RETURNS[CHAR],
proc: PROC[rName: RName] RETURNS[nameToWrite: ROPE],
write: PROC [ROPE] ¬ NIL];
ParseNameList expects to read characters using "next" (see InitializeParse) for a structured field body consisting of a list of recipient names. ParseNameList eliminate leading white space, then scans for a comma that does not appear inside quote marks, and calls the registered NameProcs until one claims to recognize the name; if none do, then ParseError[badFieldBody] is raised.
If proc returns nameToWrite # NIL and write # NIL, then nameToWrite gets written.
It is legitimate for the "proc" routine to raise a signal that causes ParseNameList to be unwound.
ParseNameProc: TYPE ~ PROC[uninterpreted: ROPE] RETURNS [recognized: BOOL, rName: RName];
if the name is really a fileName (for private DL's, then rName will be: [$file, fileName]
RegisterNameProc: PROC[which: ATOM, nameProc: ParseNameProc];
ConvertNameProc: TYPE ~ PROC[rName: RName] RETURNS[changed: BOOL, converted: RName];
RegisterConvertNameProc: PROC[convertProc: ConvertNameProc];
END.