-- MailParsePrivate.mesa
-- Last edited by Levin: 19-Feb-81  9:23:09
--  Willie-Sue:  3-Mar-82 10:34:34

DIRECTORY
  MailParse USING [NameInfo, NameType];

MailParsePrivate: DEFINITIONS =

  BEGIN

  -- Some special characters specified by RFC 733 --

  openComment: CHARACTER = '(;
  closeComment: CHARACTER = ');
  quoteNext: CHARACTER = '\\;
  stringQuote: CHARACTER = '";
  nameSeparator: CHARACTER = ',;


  -- Inter-module communication --

  ParseHandle: TYPE = LONG POINTER TO ParseInfo;

  ParseInfo: TYPE = RECORD [
    nextChar: PROCEDURE RETURNS [CHARACTER],
    backUp: PROCEDURE,
    write: PROCEDURE [CHARACTER] ← NULL,
    process: PROCEDURE [STRING, STRING, STRING, MailParse.NameInfo]
      RETURNS [BOOLEAN] ← NULL,
    lexHead: Lexeme ← NIL,
    dotLex, atLex: Lexeme ← NULL,
    simpleName, registry, arpaHost: STRING ← NIL,
    bufferList, cache: CharBuffer ← NIL,
    nameInfo: MailParse.NameInfo ← NULL,
    lexStart: CharIndex ← NULL,
    freeLexHead, tagLexList, preludeLexList: Lexeme ← NIL,
    signalTruncation: BOOLEAN,
    nameOutput, outputThisLevel, suppressWhiteSpace, scanningTag: BOOLEAN ← NULL,
    cantFinalize, recordingChars: BOOLEAN ← FALSE,
    nameSeen: BOOLEAN ← NULL,	-- hack used only to detect MSG dl names (like CSL:)
    spaceState: SpaceState ← NULL,
    curLexType: LexemeType ← NULL,
    preludeOut: CharIndex ← 0];

  SpaceState: TYPE = {initial, white, black};

  TagOrPrelude: TYPE = {tag, prelude};


  -- Procedures for name list parsing and output --

  RecurForBrackets: PROCEDURE [pH: ParseHandle, opener, terminator: CHARACTER];

  AccumulateComment: PROCEDURE [pH: ParseHandle];

  AccumulateQuotedString: PROCEDURE [pH: ParseHandle];

  AccumulateFileName: PROCEDURE [pH: ParseHandle];

  AccumulateTagOrPrelude: PROCEDURE [pH: ParseHandle] RETURNS [TagOrPrelude];

  ParseList: PROCEDURE [pH: ParseHandle, terminator: CHARACTER];

  BuildMSGdlAtom: PROCEDURE [pH: ParseHandle];

  OutputName: PROCEDURE [pH: ParseHandle];

  SyntaxError: ERROR;


  -- Lexeme Handling Utilities --


  Lexeme: TYPE = POINTER TO Lex;

  Lex: TYPE = RECORD [
    next, prev: Lexeme, type: LexemeType, length: [0..17777B], start: CharIndex];

  LexemeType: TYPE = {atom, dot, at, space, prelude, null, head};

  Magnitude: TYPE = {none, one, many};

  InitializeLexicalStorage: PROCEDURE [pH: ParseHandle];

  FinalizeLexicalStorage: PROCEDURE [pH: ParseHandle];

  ResetLexicalStorage: PROCEDURE [pH: ParseHandle];

  LexemeCount: PROCEDURE [pH: ParseHandle] RETURNS [Magnitude];

  EmptyLexemeListOrSpace: PROCEDURE [pH: ParseHandle] RETURNS [BOOLEAN];

  MakeLexeme: PROCEDURE [
    pH: ParseHandle, type: LexemeType, start: CharIndex ← 0, length: CARDINAL ← 0]
    RETURNS [lex: Lexeme];

  MakeLexemeFromString: PROCEDURE [pH: ParseHandle, type: LexemeType, s: STRING]
    RETURNS [lex: Lexeme];

  MaybeNewLexeme: PROCEDURE [pH: ParseHandle, new: LexemeType];

  TerminateLexeme: PROCEDURE [pH: ParseHandle] = INLINE {MaybeNewLexeme[pH, null]};

  AppendLexemeValue: PROCEDURE [pH: ParseHandle, s: STRING, lex: Lexeme];

  FlushLexemeList: PROCEDURE [pH: ParseHandle] = INLINE
    {DiscardLexemeList[pH, RemoveLexemeList[pH]]};

  RemoveLexemeList: PROCEDURE [pH: ParseHandle] RETURNS [head: Lexeme];

  DiscardLexemeList: PROCEDURE [pH: ParseHandle, head: Lexeme];

  AddLexeme: PROCEDURE [pH: ParseHandle, lex: Lexeme, where: Lexeme ← NIL];

  DeleteLexeme: PROCEDURE [pH: ParseHandle, lex: Lexeme];

  AppendSublistToString: PROCEDURE [pH: ParseHandle, s: STRING, first, last: Lexeme]
    RETURNS [nameType: MailParse.NameType];


  -- Character Handling Utilities --

  CharIndex: TYPE = CARDINAL;

  maxCharsPerBuffer: CARDINAL = 512 - 2 * SIZE[CharBufferHeader];

  CharBuffer: TYPE = POINTER TO CharBufferContents;

  CharBufferHeader: TYPE = RECORD [
    next, prev: CharBuffer, first: CharIndex, count: CARDINAL];

  CharBufferContents: TYPE = RECORD [
    header: CharBufferHeader, chars: PACKED ARRAY [0..maxCharsPerBuffer) OF CHARACTER];


  EndOfInput: SIGNAL;


  Get: PROCEDURE [pH: ParseHandle] RETURNS [char: CHARACTER];

  GetNaked: PROCEDURE [pH: ParseHandle] RETURNS [char: CHARACTER] = INLINE
    -- obtains next input character without any special interpretation.
    {RETURN[pH.nextChar[]]};

  InitializeCharacterStorage: PROCEDURE [pH: ParseHandle];

  FinalizeCharacterStorage: PROCEDURE [pH: ParseHandle];

  ResetCharacterStorage: PROCEDURE [pH: ParseHandle] = INLINE
    {TruncateCharacterStorage[pH, 0]};

  TruncateCharacterStorage: PROCEDURE [pH: ParseHandle, killFrom: CharIndex];

  ReadFromStore: PROCEDURE [pH: ParseHandle, index: CharIndex] RETURNS [CHARACTER];

  WriteToStore: PROCEDURE [pH: ParseHandle, char: CHARACTER];

  GetPosition: PROCEDURE [pH: ParseHandle] RETURNS [CharIndex];

  AddBuffer: PROCEDURE [pH: ParseHandle, first: CharIndex, prev: CharBuffer]
    RETURNS [CharBuffer];

  LoadCache: PROCEDURE [pH: ParseHandle, index: CharIndex];

  DeleteSuccessorBuffers: PROCEDURE [b: CharBuffer];


  END.