<<>> <<-- AISChangeHeaderImpl.mesa>> <> <> DIRECTORY AISFileFormat, AISIO, Args, Basics, Commander, FS, IO, Rope; AISChangeHeaderImpl: CEDAR PROGRAM IMPORTS AISIO, Args, Basics, Commander, FS, IO ~ BEGIN <> <<>> wordsHeader: INT ¬ AISFileFormat.wordsPerAISPage; Card: PROC [h: CARD16] RETURNS [b: Basics.HWORD] ~ {b ¬ Basics.HFromCard16[h]}; WriteBytes: UNSAFE PROC [out: IO.STREAM, base: LONG POINTER, bytes: INT] ~ UNCHECKED { IO.UnsafePutBlock[out, [base: LOOPHOLE[base], count: bytes]]; }; WriteInfo: PROC [out: IO.STREAM, info: AISIO.Info] ~ { WritePartHeader: PROC [type: AISFileFormat.PartType, nBytesInPart: INT] ~ { nWordsTotal: INT ¬ (nBytesInPart+AISFileFormat.byteSizePartHeader)/2; part: MACHINE DEPENDENT RECORD [ c: PartHeader, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[PartHeader] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]]; part.c ¬ [type, nWordsTotal/256, nWordsTotal MOD 256]; IF type = nil THEN part.c.lengthHi ¬ part.c.lengthLo ¬ 0; TRUSTED {WriteBytes[out, @part, AISFileFormat.byteSizePartHeader]}; }; PartHeader: TYPE ~ AISFileFormat.PartHeader; UCACoding: TYPE ~ AISFileFormat.UCACoding; AttributeHeader: TYPE ~ AISFileFormat.AttributeHeader; RasterPart: TYPE ~ AISFileFormat.RasterPart; header: MACHINE DEPENDENT RECORD [ c: AttributeHeader, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[AttributeHeader] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]]; raster: MACHINE DEPENDENT RECORD [ c: RasterPart, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[RasterPart] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]]; uca: MACHINE DEPENDENT RECORD [ c: UCACoding, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[UCACoding] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]]; header.c ¬ [AISFileFormat.passwordValue, Card[wordsHeader]]; raster.c ¬ [info.raster.scanCount, info.raster.scanLength, Card[3], Card[1], 0, uca, AISFileFormat.nil]; uca.c ¬ [info.uca.bitsPerSample, info.uca.wordsPerScanLine, AISFileFormat.nil, AISFileFormat.nil]; TRUSTED {WriteBytes[out, @header, AISFileFormat.byteSizeAttributeHeader]}; WritePartHeader[raster, AISFileFormat.byteSizeRasterPart+AISFileFormat.byteSizeUCACoding]; TRUSTED {WriteBytes[out, @raster, AISFileFormat.byteSizeRasterPart]}; TRUSTED {WriteBytes[out, @uca, AISFileFormat.byteSizeUCACoding]}; IF info.placement # NIL THEN { part: MACHINE DEPENDENT RECORD [ c: AISFileFormat.PlacementPart, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[UCACoding] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]]; part.c ¬ info.placement­; WritePartHeader[placement, AISFileFormat.byteSizePlacementPart]; TRUSTED {WriteBytes[out, @part, AISFileFormat.byteSizePlacementPart]}; }; IF info.photometry # NIL THEN { part: MACHINE DEPENDENT RECORD [ c: AISFileFormat.PhotometryPart, p: PACKED ARRAY [0..(BITS[WORD]-(BITS[UCACoding] MOD BITS[WORD])) MOD BITS[WORD]) OF [0..1]]; part.c ¬ info.photometry­; WritePartHeader[photometry, AISFileFormat.byteSizePhotometryPart]; TRUSTED {WriteBytes[out, @part, AISFileFormat.byteSizePhotometryPart]}; }; IF info.comments # NIL THEN { -- ugh -- }; WritePartHeader[nil, 0]; -- end header }; AISChangeHeaderCmd: Commander.CommandProc = { inA, outA, xA, yA, bppA, numberScanlinesA, pixelsPerLineA, commentA: Args.Arg; [inA, outA, xA, yA, bppA, numberScanlinesA, pixelsPerLineA, commentA] ¬ Args.ArgsGet[cmd, "%ss-placement%ii-bitsPerPixel%i-numberScanlines%i-pixelsPerLine%i-comment%s-wordsPerLine%i" ! Args.Error => {msg ¬ reason; CONTINUE}]; IF msg # NIL THEN RETURN[$Failure, msg] ELSE { info: AISIO.Info ¬ AISIO.ReadInfo[inA.rope]; buffer: REF TEXT ¬ NEW[TEXT[1024]]; in: IO.STREAM ¬ FS.StreamOpen[inA.rope ! FS.Error => GOTO Bad]; out: IO.STREAM ¬ FS.StreamOpen[outA.rope, $create]; IF xA.ok OR yA.ok THEN { IF info.placement = NIL THEN info.placement ¬ NEW[AISFileFormat.PlacementPart]; IF xA.ok THEN info.placement.xLeft ¬ Basics.HFromInt16[xA.int]; IF yA.ok THEN info.placement.yBottom ¬ Basics.HFromInt16[yA.int]; }; IF bppA.ok THEN info.uca.bitsPerSample ¬ Basics.HFromInt16[bppA.int]; IF numberScanlinesA.ok THEN info.raster.scanCount ¬ Basics.HFromInt16[numberScanlinesA.int]; IF pixelsPerLineA.ok THEN { info.raster.scanLength ¬ Basics.HFromInt16[pixelsPerLineA.int]; info.uca.wordsPerScanLine ¬ Basics.HFromInt16[pixelsPerLineA.int/2+(pixelsPerLineA.int MOD 2)]; }; IF commentA.ok THEN info.comments ¬ CONS[commentA.rope, info.comments]; WriteInfo[out, info]; IO.SetIndex[in, wordsHeader]; IO.SetIndex[out, wordsHeader]; DO nBytes: INT ¬ IO.GetBlock[in, buffer]; IF nBytes = 0 THEN EXIT; IO.PutBlock[out, buffer]; ENDLOOP; IO.Close[in]; IO.Close[out]; EXITS Bad => RETURN[$Failure, "can't open file"]; }; }; usage: Rope.ROPE ¬ "\nAISChangeHeader [-option] options include: -placement -bitsPerPixel -numberScanlines -pixelsPerLine -comment "; Commander.Register["AISChangeHeader", AISChangeHeaderCmd, usage]; END.