<> <> <> <> DIRECTORY Basics, IntelHex; IntelHexImpl: PROGRAM IMPORTS Basics EXPORTS IntelHex = BEGIN <> iEOF: SIGNAL = CODE; <> ChecksumError: SIGNAL = CODE; BitOp: TYPE = PROC [a, b: UNSPECIFIED] RETURNS [UNSPECIFIED]; And: BitOp = INLINE { RETURN[Basics.BITAND[a,b]]; }; Shift: BitOp = INLINE { RETURN[Basics.BITSHIFT[a,b]]; }; <> WordCk: PROC [c: CARDINAL] RETURNS [CARDINAL] = { v: Basics.BytePair _ LOOPHOLE[c]; RETURN [v.low+v.high]; }; <> CkSum: PROC [c: CARDINAL] RETURNS [CARDINAL] = { v: INTEGER _ And[c, 377B]; v _ -v; v _ And[v, 377B]; RETURN [LOOPHOLE[v, CARDINAL]]; }; ProcessFile: PUBLIC SAFE PROC [in: IntelHex.IStream, out: IntelHex.OStream, errs: IntelHex.PutCharProc] RETURNS [success: BOOLEAN] = TRUSTED { PutS: PROC [s: STRING] = { FOR i: CARDINAL IN [0..s.length) DO errs[s[i]]; ENDLOOP; }; PutL: PROC [s: STRING] = { PutS[s]; PutCR[]; }; PutHexNum: PROC [x: CARDINAL] = { Dig: PROC [y: CARDINAL] RETURNS [CHARACTER] = { y _ And[y, 017B]; IF y < 10 THEN RETURN[y+'0] ELSE RETURN[y-10+'A]; }; errs[Dig[Shift[x, -12]]]; errs[Dig[Shift[x, -8]]]; errs[Dig[Shift[x, -4]]]; errs[Dig[x]]; }; PutCR: PROC = { errs['\n]; }; { ENABLE { iEOF => { PutL["Unexpected end of input file."]; GOTO ReturnFalse; }; ChecksumError => { PutL["Checksum error in input file."]; GOTO ReturnFalse; }; }; inCkecksum: CARDINAL; -- checksum of input record rectype, length, count, frame, bytepos: CARDINAL; <> CkChar: PROC RETURNS[v: CARDINAL] = { IF in.endof[] THEN SIGNAL iEOF; v _ in.get[]; inCkecksum _ inCkecksum+v; }; <> CkWord: PROC RETURNS [CARDINAL] = { v: Basics.BytePair; IF in.endof[] THEN SIGNAL iEOF; v.high _ in.get[]; v.low _ in.get[]; inCkecksum _ inCkecksum+v.high + v.low; RETURN[LOOPHOLE[v, CARDINAL]]; }; CheckChecksum: PROC = { [] _ CkChar[]; IF And[inCkecksum, 377B]#0 THEN SIGNAL ChecksumError; }; <> <> gda: LONG CARDINAL; <> NewDataAddress: PROC [frame, bytepos: CARDINAL] = { gda _ Shift[frame, 4] + bytepos; }; DataByte: PROC [d: CARDINAL] = { out.DataByte[adr: gda, d: d]; gda _ gda+1; }; <> <> <> DumpRepeated: PROC [length: CARDINAL] RETURNS [CARDINAL] = { rptcount, blockcount, nlength: CARDINAL; pos: LONG CARDINAL; rptcount _ CkWord[]; blockcount _ CkWord[]; length _ length-4; IF blockcount = 0 THEN { count: CARDINAL _ CkChar[]; nlength _ length - count - 1; pos _ in.GetPosition[]; THROUGH [0..rptcount) DO in.SetPosition[pos]; THROUGH[0..count) DO DataByte[CkChar[]]; ENDLOOP; ENDLOOP; } ELSE { pos _ in.GetPosition[]; THROUGH [0..rptcount) DO nlength _ length; in.SetPosition[pos]; THROUGH[0..blockcount) DO nlength _ DumpRepeated[nlength]; ENDLOOP; ENDLOOP; }; RETURN [nlength]; }; <> DO inCkecksum _ 0; rectype _ CkChar[]; SELECT rectype FROM 200B, 202B => { length _ CkWord[]; count _ CkChar[]; length _ length - count - 1; THROUGH [0..count) DO [] _ CkChar[]; ENDLOOP; CheckChecksum[]; }; 212B => { modtype: CARDINAL; length _ CkWord[]; modtype _ CkChar[]; SELECT Shift[modtype, -6] FROM 0 => out.PutEndRecord[]; 1, 3 => { frame _ CkWord[]; bytepos _ CkWord[]; out.PutStartRecord[frame: frame, bytepos: bytepos]; out.PutEndRecord[]; }; ENDCASE => { PutS["Invalid end record attributes: "]; PutHexNum[modtype]; PutCR[]; }; CheckChecksum[]; EXIT; -- end of module, stop here }; 204B => { length _ CkWord[]; frame _ CkWord[]; bytepos _ CkChar[]; length _ length - 4; NewDataAddress[frame: frame, bytepos: bytepos]; THROUGH [0..length) DO DataByte[CkChar[]]; ENDLOOP; CheckChecksum[]; }; 206B => { filepos: LONG CARDINAL; length _ CkWord[]; frame _ CkWord[]; bytepos _ CkChar[]; length _ length - 4; filepos _ in.GetPosition[]; NewDataAddress[frame: frame, bytepos: bytepos]; <> <> THROUGH [0..length) DO [] _ CkChar[]; ENDLOOP; CheckChecksum[]; in.SetPosition[filepos]; length _ DumpRepeated[length]; <> IF length#0 THEN { PutL["End PIData, non zero length."]; GOTO ReturnFalse; }; <> [] _ CkChar[]; }; ENDCASE => { PutS["Unknown record type: "]; PutHexNum[rectype]; PutCR[]; length _ CkWord[]; THROUGH [0..length-1) DO [] _ CkChar[]; ENDLOOP; CheckChecksum[]; }; ENDLOOP; RETURN[TRUE]; }; EXITS ReturnFalse => RETURN[FALSE]; }; -- end of ProcessFile END. October 4, 1981 3:06 PM, LStewart; Created December 23, 1981 3:31 PM, LStewart; Suppress duplicate address records 1-Jan-82 21:05:41, L. Stewart, Rewrite with Defs file April 25, 1983 3:44 pm, LCS, CEDAR December 21, 1983 2:49 pm, L. Stewart.pa, Cedar 5