PLAOpsBitFormat.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by Curry, August 11, 1985 5:07:19 pm PDT
DIRECTORY
AMTypes,
Commander,
Convert,
IO,
Interpreter,
PLAOps,
Rope,
RTTypesPrivate;
PLAOpsBitFormat: CEDAR PROGRAM
IMPORTS PLAOps, AMTypes, Convert, Commander, Interpreter, IO, Rope
EXPORTS PLAOps =
BEGIN OPEN PLAOps;
GetRecordRefFormatFromRope: PUBLIC PROC[rec: Rope.ROPE]
RETURNS[ref: REF ANY, format: Format] = {
recTV: AMTypes.TV ← GetRecordTVFromRope[rec]; -- Does NEW
IF recTV=NIL THEN RETURN[NIL, NIL];
TRUSTED{
WITH recTV SELECT FROM
tr: REF RTTypesPrivate.TypedVariableRec =>
WITH head: tr.head SELECT FROM
reference => ref ← head.ref;
ENDCASE => ERROR;
ENDCASE => ERROR};
format ← GetFormatFromTV[recTV]};
GetRecordTVFromRope: PUBLIC PROC[rec: Rope.ROPE] RETURNS[recTV: AMTypes.TV] = {
recOverTV: AMTypes.TV;
noResult:  BOOL;
errorMsg:  Rope.ROPE;
[recOverTV, errorMsg, noResult] ← Interpreter.Evaluate[rec];
IF errorMsg#NIL THEN {comTool.PutF[" %g\n", IO.rope[errorMsg]]; RETURN[NIL]};
recTV  ← AMTypes.New[AMTypes.UnderType[AMTypes.TVToType[recOverTV]]];
SELECT AMTypes.TypeClass[AMTypes.TVType[recTV]] FROM
record, structure => NULL;
ENDCASE  => {comTool.PutF[" %g not a RECORD\n", IO.rope[rec]];RETURN[NIL]}};
GetFormatFromTV: PROC[recTV: AMTypes.TV] RETURNS[format: Format] = {
format ← NEW[FormatRec[AMTypes.NComponents[AMTypes.TVType[recTV]]]];
FOR fldIndex: CARDINAL IN [0..format.size) DO
fldrecTV: AMTypes.TV;
fldTV: AMTypes.TV ← AMTypes.IndexToTV[recTV, fldIndex+1];
fldrecTV ← AMTypes.New[AMTypes.UnderType[AMTypes.TVType[fldTV]]];
format[fldIndex].format ← IF AMTypes.TypeClass[AMTypes.TVType[fldrecTV]]=record
THEN GetFormatFromTV[fldrecTV] ELSE NIL;
format[fldIndex].name ← AMTypes.IndexToName[AMTypes.TVType[recTV], fldIndex+1];
[format[fldIndex].firstBit, format[fldIndex].bitSize] ← TVToFieldBits[fldTV];
ENDLOOP;
RETURN[format]};
TVToFieldBits: PROC[fieldTV: AMTypes.TV] RETURNS[firstBit, bitSize: CARDINAL]=TRUSTED {
tvRef: REF RTTypesPrivate.TypedVariableRec ← NARROW[fieldTV];
WITH tv: tvRef SELECT FROM
entire => RETURN[0,0];
embedded => {
WITH fld: tv.fd SELECT FROM
small => RETURN[16*fld.wordOffset+fld.field.bitFirst, fld.field.bitCount];
large => RETURN[16*fld.wordOffset, fld.size*16];
ENDCASE => ERROR };
constant => RETURN[0, tv.value.size*16];
ENDCASE => ERROR };
BitFormatRope: PUBLIC PROC[record: Rope.ROPE, flatten: BOOLFALSE]
RETURNS[listing: Rope.ROPE] = {
rope:  IO.STREAM  ← IO.ROS[];
sum:  CARDINAL ← 0;
format: Format ← GetRecordRefFormatFromRope[record].format;
IF format=NIL THEN RETURN[NIL];
IF flatten THEN format ← FlattenFormat[format];
rope.PutF["\nBitFormat: %g", IO.rope[record]];
rope.PutRope["\n Index First Size Name"];
FOR i: CARDINAL IN [0..format.size) DO
sum ← sum + format[i].bitSize;
rope.PutF["\n %2g %3g %3g %g",
IO.card[i],
IO.card[format[i].firstBit],
IO.card[format[i].bitSize],
IO.rope[format[i].name]] ENDLOOP;
rope.PutF["\n ---\n BitTotal: %3g\n", IO.card[sum]];
listing ← IO.RopeFromROS[rope] };
BitFormatList: PUBLIC PROC[record: Rope.ROPE]
RETURNS[list: LIST OF Rope.ROPE] = {
format: Format ← GetRecordRefFormatFromRope[record].format;
IF format=NIL THEN RETURN[NIL];
format ← FlattenFormat[format];
FOR i: CARDINAL DECREASING IN [0..format.size) DO
list ← CONS[format[i].name, list] ENDLOOP };
FlattenFormat: PUBLIC PROC
[format: Format, name: Rope.ROPE←NIL, first: CARDINAL𡤀] RETURNS[new: Format] = {
index: CARDINAL ← 0;
list, temp: LIST OF Field;
list ← FlattenFormatList[format];
FOR temp ← list, temp.rest WHILE temp#NIL DO index ← index+1 ENDLOOP;
new ← NEW[ FormatRec[index]];
index ← 0;
FOR temp ← list, temp.rest WHILE temp#NIL DO
new[index] ← temp.first; index ← index+1 ENDLOOP};
FlattenFormatList: PROC
[format: Format, name: Rope.ROPE←NIL, first: CARDINAL𡤀, list: LIST OF Field←NIL]
RETURNS[new: LIST OF Field] = {
IF format=NIL THEN RETURN[list];
new ← list;
FOR i: CARDINAL DECREASING IN [0..format.size) DO
fname: Rope.ROPE ← IF name#NIL
THEN Rope.Cat[name, ".", format[i].name] ELSE format[i].name;
ffirst: CARDINAL ← first+format[i].firstBit;
SELECT TRUE FROM
format[i].bitSize=1 =>
new ← CONS[ [name: fname, format: NIL, firstBit: ffirst, bitSize: 1], new] ;
format[i].format=NIL => {
FOR j: CARDINAL DECREASING IN [0..format[i].bitSize) DO
bitName: Rope.ROPE ← Rope.Cat[fname,".", Convert.RopeFromCard[j]];
new ← CONS[ [name: bitName, format: NIL, firstBit: j+ffirst, bitSize: 1], new]
ENDLOOP };
ENDCASE => new ← FlattenFormatList[format[i].format, fname, ffirst, new];
ENDLOOP};
BitFormat: Commander.CommandProc = {
rec: Rope.ROPE ← DefaultCMDLine[cmd.commandLine, NIL];
comTool ← cmd.out;
IF rec=NIL
THEN cmd.out.PutF [" %g\n",IO.rope[bitFormatDoc]]
ELSE cmd.out.PutRope[BitFormatRope[rec, FALSE]];
comTool ← IO.noWhereStream };
BitFormatFlat: Commander.CommandProc = {
rec: Rope.ROPE ← DefaultCMDLine[cmd.commandLine, NIL];
comTool ← cmd.out;
IF rec=NIL
THEN cmd.out.PutF [" %g\n",IO.rope[bitFormatFlatDoc]]
ELSE cmd.out.PutRope[BitFormatRope[rec, TRUE]];
comTool ← IO.noWhereStream };
comTool ← IO.noWhereStream };
bitFormatDoc:  Rope.ROPE =
"'BitFormat Foo.SomeRecord' displays the size and position of the fields in Foo.SomeRecord";
bitFormatFlatDoc: Rope.ROPE =
"'BitFormatFlat Foo.SomeRecord' displays the size and position of the bits in Foo.SomeRecord";
comTool: IO.STREAMIO.noWhereStream;
Commander.Register[key:"BitFormat",   proc: BitFormat,   doc: bitFormatDoc];
Commander.Register[key:"BitFormatFlat",  proc: BitFormatFlat,  doc: bitFormatFlatDoc];
END.