{ MODULE 7 Postmortem Diagnostics In principle, the production of source-related diagnostics entails the construction of a 'data map' containing a description of all types, emumeration constants, variables, parameters, and blocks declared in the program, together with a 'code map' that allows a source-program line number to be deduced from an object program address. The data map is constructed by procedure Filescope which systemat- ically traverses the identifier and type sub-tables making each entry available to the procedures Fileid and Filetype respec- tively. The linkages that exist between and within these tables may be preserved by recasting them in terms of unique serial numbers assigned to each data-item to be filed. Serial numbers are allocated in a monotonically increasing sequence by procedures Iserialise and Tserialise to each new identifier or type table entry. The standard types are serialised and filed by procedure FileStdTypes during the initialisation phase of the compiler. The code map is constructed by making the source program line number available to the code generator by means of a call to pro- cedure Flowpoint immediately prior to analysis of each statement in a block. The underlying mechanisms involved in creating the data map and the code map are described in Module .... } program DiagnosticHandler; #include "globals.h" procedure FlowPoint(SourceLine: Scalar); visible; begin end; procedure FileAType(TheType: TypEntry); begin end; procedure FileId(Id, NextId: IdEntry); begin end; procedure ISerialise(Id: IdEntry); visible; begin if Id <> nil then begin Id^.Serial := NextSerial; NextSerial := NextSerial + 1 end end { iserialise }; procedure TSerialise(Typ: TypEntry); visible; begin if Typ <> nil then begin Typ^.Serial := NextSerial; NextSerial := NextSerial + 1 end end { tserialise }; procedure FileScope(BlockId: IdEntry); visible; var PreviousVar: IdEntry; ThisType: TypEntry; procedure FileLocalVars(Entry: IdEntry); begin if Entry <> nil then with Entry^ do begin FileLocalVars(RightLink); if Klass = Vars then begin FileId(Entry, PreviousVar); PreviousVar := Entry end; FileLocalVars(LeftLink) end end { filelocalvars }; begin { filescope } with Display[BlockLevel] do begin { file types } ThisType := TypeChain; while ThisType <> nil do begin FileAType(ThisType); ThisType := ThisType^.Next end; { file local variables, including formal parameters } PreviousVar := nil; FileLocalVars(Locals); { file block } FileId(BlockId, PreviousVar) end end { filescope }; procedure InitDiagnostics; visible; begin end; procedure FileStdTypes; visible; { ... which have not yet been serialised } begin NextSerial := NilSerial + 1; TSerialise(IntType); FileAType(IntType); TSerialise(RealType); FileAType(RealType); TSerialise(CharType); FileAType(CharType); { serialise boolean constants } with BoolType^ do begin ISerialise(FirstConst); ISerialise(FirstConst^.SuccId) end; TSerialise(BoolType); FileAType(BoolType); TSerialise(TextType); FileAType(TextType) end { filestdtypes }; procedure EndDiagnostics; visible; begin end; begin { end of module } end.