<<-- T1FileOps.Mesa>> <<-- written by Bill Paxton December 1980>> <<-- last written by Paxton; July 11, 1983 11:20 am>> T1FileOps: CEDAR DEFINITIONS = BEGIN Op: TYPE = CHARACTER; endOfFile: Op = 0C; startNode: Op = endOfFile+1; <<-- length of typename in next byte. text for type name follows that.>> <<-- enter in typename table>> <<-- and assign it the next number>> startNodeFirst: Op = startNode+1; startNodeLast: Op = startNodeFirst+numTypes; <<-- these opcodes encode previously seen typename so don't need to repeat it>> <<-- find typename in op-startNodeFirst of type table>> <<-- other information follows same as for startNode>> terminalTextNode: Op = startNodeLast+1; terminalTextNodeFirst: Op = terminalTextNode+1; terminalTextNodeLast: Op = terminalTextNodeFirst+numTypes; <<-- these opcodes are for nodes without children so can skip endNode opcode>> <<-- identical to startNodeFirst..startNodeLast, except implies no children>> <<-- find type name in op-startNodeFirst of type table>> <<-- other information follows same as for startNode>> otherNode: Op = terminalTextNodeLast+1; <<-- for "other" type of nodes>> <<-- length of typename in next byte. text for type name follows that.>> <<-- enter in typename table >> <<-- and assign it the next number>> otherNodeShort: Op = otherNode+1; <<-- like otherNode, but followed by a typename code number instead of length+text>> otherNodeSpecs: Op = otherNodeShort+1; <<-- gives "variety" and specifications for immediately previous "other" type node>> <<-- length of variety name follows in next byte(s). then text of name>> <<-- enter in property name table and assign next number>> <<-- length of specs text in next byte(s)>> <<-- specs follow that>> otherNodeSpecsShort: Op = otherNodeSpecs+1; <<-- like otherNodeSpecs, but followed by a propname code number instead of length+text>> prop: Op = otherNodeSpecsShort+1; <<-- specifies property for current node>> <<-- property specs are stored on file as a rope>> <<-- length of property name follows in next byte(s). then text of name>> <<-- enter in property name table and assign next number>> <<-- length of property specs rope in next byte(s)>> <<-- followed by text for property specs rope>> propShort: Op = prop+1; <<-- like prop, but followed by a propname code number instead of length+text>> endNode: Op = propShort+1; <<-- end current node and go back to adding to its parent. >> rope: Op = endNode+1; <<-- this op declares rope for most recently started node>> <<-- length of text for the node in next byte(s).>> <<-- actual text comes from text block>> <<-- followed by a CR which is not included in the length>> comment: Op = rope+1; <<-- identical to rope except implies text stored in comment area of file>> runs: Op = comment+1; <<-- this op preceeds definition of looks for most recently started node>> <<-- number of runs in following byte(s)>> <<-- have at most 1 runs op per node. if omit, then no special looks.>> looks: Op = runs+1; <<-- looks vector in following 4 bytes.>> <<-- enter vector in looks table.>> <<-- and assign it the next number>> <<-- length of run in next byte(s).>> looksFirst: Op = looks+1; looksLast: Op = looksFirst+numLooks; <<-- these ops encode previously encountered looks so don't need to repeat>> <<-- find looks in looks table[op-looksFirst].>> <<-- length of run in the next byte(s).>> look1: Op = looksLast+1; <<-- like looks op, except has single look char instead of 4 byte looks vector>> look2: Op = look1+1; <<-- like looks1, except has two looks chars>> look3: Op = look2+1; <<-- like look2, except has three looks chars>> numTypes: CARDINAL = 70; <<-- max number of entries in the type table for the file>> <<-- others must be given in long form>> TypeIndex: TYPE = [0..numTypes); numLooks: CARDINAL = 50; <<-- max number of entries in a look table>> <<-- others must be given in long form>> <<-- each entry in a look table is a distinct vector of 32 bits>> LooksIndex: TYPE = [0..numLooks); numProps: CARDINAL = 50; <<-- max number of entries in a prop table>> PropIndex: TYPE = [0..numProps); <<-- lengths are given in as few bytes as possible according to following scheme>> <<-- first bit of each byte tells if 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>> IntBytes: TYPE = MACHINE DEPENDENT RECORD [ first (0:9..15): [0..127] _ 0, -- first byte written on file second (0:2..8): [0..127] _ 0, -- second byte written thirdBottom (0:0..1): [0..3] _ 0, -- bottom bits of third byte written thirdTop (1:11..15): [0..31] _ 0, -- top bits of third byte written fourth (1:4..10): [0..127] _ 0, -- fourth byte written unused (1:0..3): [0..15] _ 0 -- these are always 0 ]; LengthByte: TYPE = MACHINE DEPENDENT RECORD [ unused (0:0..7): [0..255] _ 0, others (0:8..8): BOOLEAN _ FALSE, -- tells if other bytes are present data (0:9..15): [0..127] _ 0]; ThirdByte: TYPE = MACHINE DEPENDENT RECORD [ unused (0:0..7): [0..255] _ 0, others (0:8..8): BOOLEAN _ FALSE, dataTop (0:9..13): [0..31] _ 0, -- top 5 bits of data dataBottom (0:14..15): [0..3] _ 0 -- bottom 2 bits of data ]; <<-- ***** the following defines the trailer bytes that form the Tioga password>> commentHeaderId: ARRAY [0..fileIdSize) OF CHARACTER = [0C,0C]; controlHeaderId: ARRAY [0..fileIdSize) OF CHARACTER = [235C,312C]; controlTrailerId: ARRAY [0..fileIdSize) OF CHARACTER = [205C,227C]; fileIdSize: NAT = 2; numTrailerLengths: NAT = 3; -- endSize: NAT = fileIdSize+numTrailerLengths*4; -- trailer plus three lengths END. Tioga file format is as follows: == == characters from (non-comment) nodes in display order with a CR after each node == == == byte length of == characters from comment nodes in display order with a CR after each node == == == == [..bytes..] as defined above Thus start with double 0's which can serve to mark end of . == byte length of == == gives length of == == [..bytes..] as defined above == byte address in file for start of comments == sequence of control bytes and control text. The last thing in the file is the . Thus to read a file, first check the and read the byte address for the . We also read the saved as a double check. The saved is a 4 byte checksum of the data part of the file. This lets us read the where we double check to make sure we have a valid file by reading the and the . Then we go to the , checking the and reading the . Finally, we check that ++ = . The , , and 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, terminalTextNode, otherNode, otherNodeShort, or something in the startNodeFirst..startNodeLast range or in the terminalTextNodeFirst..terminalTextNodeLast 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 rather than 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.