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:
BOOL←
FALSE]
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.STREAM ← IO.noWhereStream;
Commander.Register[key:"BitFormat", proc: BitFormat, doc: bitFormatDoc];
Commander.Register[key:"BitFormatFlat", proc: BitFormatFlat, doc: bitFormatFlatDoc];
END.