TiogaFileFormat.mesa
Copyright Ó 1985, 1986, 1988, 1991 by Xerox Corporation. All rights reserved.
written by Bill Paxton December 1980
Michael Plass, March 14, 1985 11:56:00 am PST
Doug Wyatt, October 15, 1991 3:33 pm PDT
TiogaFileFormat: CEDAR DEFINITIONS = BEGIN
Op: TYPE ~ MACHINE DEPENDENT {
endOfFile(endOfFileCode),
startNode(startNodeCode),
followed by <formatName: Text>
startNodeFirst(startNodeFirstCode),
startNodeLast(startNodeLastCode),
these specify formatIndex = (op-startNodeFirst)
startLeaf(startLeafCode),
like startNode, but for a node with no children
followed by <formatName: Text>
startLeafFirst(startLeafFirstCode),
startLeafLast(startLeafLastCode),
these specify formatIndex = (op-startLeafFirst)
prop(propCode),
followed by <propName: Text> <propSpecs: Text>
propShort(propShortCode),
followed by <propIndex: Byte> <propSpecs: Text>
endNode(endNodeCode),
end current node and go back up to parent
dataRope(dataRopeCode),
followed by <len: Len>
text comes from data part: len chars plus a newline char
commentRope(commentRopeCode),
followed by <len: Len>
text comes from comment part: len chars plus a newline char
runs(runsCode),
followed by <numRuns: Len>, then that many runs
looks(looksCode),
followed by <looks: Looks> <runLen: Len>
looksFirst(looksFirstCode),
looksLast(looksLastCode),
these specify looksIndex = (op-looksFirstCode)
followed by <runLen: Len>
look1(look1Code),
followed by <look1: Char> <runLen: Len>
look2(look2Code),
followed by <look1: Char> <look2: Char> <runLen: Len>
look3(look3Code),
followed by <look1: Char> <look2: Char> <look3: Char> <runLen: Len>
(BYTE.LAST)
};
numFormats: CARDINAL = 70;
max number of entries in the format table for the file
others must be given in long form
numProps: CARDINAL = 50;
max number of entries in the prop table
numLooks: CARDINAL = 50;
max number of entries in the look table
endOfFileCode: BYTE ~ 0;
startNodeCode: BYTE ~ endOfFileCode+1;
startNodeFirstCode: BYTE ~ startNodeCode+1;
startNodeLastCode: BYTE ~ startNodeFirstCode+numFormats;
startLeafCode: BYTE ~ startNodeLastCode+1;
startLeafFirstCode: BYTE ~ startLeafCode+1;
startLeafLastCode: BYTE ~ startLeafFirstCode+numFormats;
otherNodeCode: BYTE ~ startLeafLastCode+1; -- unused
otherNodeShortCode: BYTE ~ otherNodeCode+1;
otherNodeSpecsCode: BYTE ~ otherNodeShortCode+1;
otherNodeSpecsShortCode: BYTE ~ otherNodeSpecsCode+1;
propCode: BYTE ~ otherNodeSpecsShortCode+1;
propShortCode: BYTE ~ propCode+1;
endNodeCode: BYTE ~ propShortCode+1;
dataRopeCode: BYTE ~ endNodeCode+1;
commentRopeCode: BYTE ~ dataRopeCode+1;
runsCode: BYTE ~ commentRopeCode+1;
looksCode: BYTE ~ runsCode+1;
looksFirstCode: BYTE ~ looksCode+1;
looksLastCode: BYTE ~ looksFirstCode+numLooks;
look1Code: BYTE ~ looksLastCode+1;
look2Code: BYTE ~ look1Code+1;
look3Code: BYTE ~ look2Code+1;
lengths are given in as few bytes as possible according to following scheme
high order bit of each byte tells whether other bytes follow (up to 4 bytes max)
concat other 7 bits of bytes with leading 0's to form length
thus can represent lengths up to 2**28-1 if use 4 bytes
lengths of 127 or less fit in 1 byte
lengths in [128..4095] fit in 2 bytes
See TiogaFileIO for further information.
END.
Tioga file format is as follows:
<file> == <data> <comments> <control>
<data> == characters from (non-comment) nodes in display order with a CR after each node
<comments> == <comments-header> <comments-text>
<comments-header> == <commentHeaderId> <comments-length>
<comments-length> == byte length of <comments>
<comments-text> == characters from comment nodes in display order with a CR after each node
<control> == <control-header> <control-info> <control-trailer>
<control-header> == <controlHeaderId> <control-length>
<commentHeaderId> == <controlHeaderId> == [..bytes..] as defined above
Thus <comments> start with double 0's which can serve to mark end of <data>.
<control-length> == byte length of <control>
<control-trailer> == <file-props> <controlTrailerId>
<file-props-length> <data-length> <file-length>
<file-props-length> == gives length of <file-props>
<file-prop> == <propIdByte> <valueLengthByte> <propValueBytes>
<controlTrailerId> == [..bytes..] as defined above
<comments-start> == byte address in file for start of comments
<control-info> == sequence of control bytes and control text.
The last thing in the file is the <control-trailer>. Thus to read a file, first
check the <controlTrailerId> and read the byte address for the <data-length>.
We also read the saved <file-length> as a double check.
The saved <data-stamp> is a 4 byte checksum of the data part of the file.
This lets us read the <comments-header> where we double check to make sure we
have a valid file by reading the <commentHeaderId> and the <comments-length>.
Then we go to the <control-header>, checking the <controlHeaderId> and reading
the <control-length>. Finally, we check that
<control-length>+<comments-length>+<data-length> = <file-length>.
The <data>, <comments>, and <control> are written node by node starting at the root.
For each node the following steps are taken:
1. Output a start node control byte of the appropriate sort.
either startNode, startLeaf, otherNode, otherNodeShort, or
something in the startNodeFirst..startNodeLast range or
in the startLeafFirst..startLeafLast range.
2. Output the properties, if any, of the node.
if the value is a rope, output ropeProp or ropePropShort
else if the value is a node, output nodeProp or nodePropShort.
then output the value itself
text for props is put in <control> rather than <data>
3. Output the contents of the node.
for a text node, first write the runs info, if any, and then the rope.
if it is a comment node, then the text goes in comments,
else it goes in data.
for other varieties of node, write otherNodeSpecs or otherNodeSpecsShort
followed by the text of the specifications.
4. Output the children of the node, if any, in the same manner
5. Output an endNode byte, unless this is a terminal text node
Following the end of the root node, there is an endOfFile byte.