<> <> <> <> <> <> DIRECTORY Basics USING [bytesPerWord], CommandUtil USING [GetRootName], FS USING [StreamOpen], IO USING [Close, EndOfStream, GetBlock, GetLength, PutBlock, SetIndex, STREAM, UnsafeGetBlock], PGSConDefs USING [objectVersion, sourceVersion, FixupBcdHeader, WriteBcdHeader], Rope USING [Equal, Find, Length, ROPE], TableCommand USING [CreateTime, GenerateVersion]; ModuleMaker: PROGRAM IMPORTS CommandUtil, FS, IO, PGSConDefs, Rope, TableCommand EXPORTS TableCommand = { bytesPerWord: NAT = Basics.bytesPerWord; <> CreateBCDStream: PUBLIC PROC [ in: IO.STREAM, modId, interfaceId: Rope.ROPE, altoCode: BOOL _ FALSE] RETURNS [output: IO.STREAM] = { modRoot, interfaceRoot: Rope.ROPE; PGSConDefs.sourceVersion _ [0, 0, LOOPHOLE[TableCommand.CreateTime[in]]]; PGSConDefs.objectVersion _ TableCommand.GenerateVersion[]; modRoot _ CommandUtil.GetRootName[modId]; output _ FS.StreamOpen[modId, $create]; <> interfaceRoot _ CommandUtil.GetRootName[interfaceId]; PGSConDefs.WriteBcdHeader[ outStream: output, tableId: modRoot, binaryId: modId, interfaceId: IF Rope.Equal[interfaceRoot, "SELF", FALSE] THEN NIL ELSE interfaceRoot, fileId: NIL, -- for now altoCode: altoCode]; RETURN }; FinishBcdStream: PUBLIC PROC = { PGSConDefs.FixupBcdHeader[] }; <> CheckForBr: PROC [name: Rope.ROPE] RETURNS [BOOL] = { index: INT ~ Rope.Find[s1: name, s2: ".BR", case: FALSE]; IF index < 0 THEN RETURN[FALSE]; RETURN[name.Length[] = index + 3]; }; GetWord: PROC[stream: IO.STREAM] RETURNS[word: CARDINAL _ 0] = { base: LONG POINTER ~ @word; IF stream.UnsafeGetBlock[[base: base, count: bytesPerWord]]=2 THEN RETURN ELSE ERROR IO.EndOfStream[stream]; }; SetWordIndex: PROC[stream: IO.STREAM, wordIndex: INT] = { stream.SetIndex[wordIndex*bytesPerWord]; }; CreateSegmentStream: PROC [segmentId: Rope.ROPE] RETURNS [in: IO.STREAM, byteCount: INT] = { in _ FS.StreamOpen[segmentId]; IF CheckForBr[segmentId] THEN { words: CARDINAL; SetWordIndex[in, 7]; words _ GetWord[in]; SetWordIndex[in, words]; words _ GetWord[in]; byteCount _ words*bytesPerWord; } ELSE byteCount _ in.GetLength[]; }; <> WriteSegment: PROC [in, out: IO.STREAM, count: INT] = { bufferBytes: NAT ~ 512; buffer: REF TEXT ~ NEW[TEXT[bufferBytes]]; bytesRemaining: INT _ count*bytesPerWord; WHILE bytesRemaining>0 DO bytesRequested: NAT ~ MIN[bytesRemaining, bufferBytes]; bytesRead: NAT ~ in.GetBlock[block: buffer, count: bytesRequested]; out.PutBlock[block: buffer, count: bytesRead]; bytesRemaining _ bytesRemaining-bytesRead; IF bytesRead