-- File: JDSmoduleImpl.mesa
-- last edit by:
-- Nagata, April 7, 1982; converted to Trinity
-- Glenn, September 10, 1981 5:56 PM
-- Changed the Kanji convert of GET to ignore JDSBOR char in that field 9/10/81
-- Added PhonicToJDS procedure to this module 7/23/81
-- Changed the CATcode default value from: 22B to: 26B (4 new Catcodes)
DIRECTORY
CharDefs USING [Char],
Environment USING [Block],
Heap USING [FreeNode, MakeNode, systemZone],
JDSmoduleDefs,
JDSPosDefs USING [GetCatValue, GetPosValue],
JDStoOISDefs USING [JDStoOIS, lastJDSKanji, UNDF],
MStream USING [EndOf],
OISDictDataDefs USING [Entry],
Stream USING [Block, Byte, CompletionCode, defaultObject, GetByte, GetPosition,
GetWord, Handle, InputOptions, Object, PutBlock, PutByte, SendAttention,
SetPosition, SetSST, SubSequenceType, WaitForAttention, Word];
JDSmoduleImpl: MONITOR IMPORTS Heap, JDSPosDefs, JDStoOISDefs, MStream, Stream
EXPORTS JDSmoduleDefs =
BEGIN
-- TYPEs
streamZone: UNCOUNTED ZONE = Heap.systemZone;
Handle: TYPE = Stream.Handle;
BoxObject: TYPE = RECORD [base: LONG CARDINAL, bytecount: CARDINAL];
BoxPtr: TYPE = LONG POINTER TO ARRAY [0..0) OF BoxObject;
Box: BoxPtr ← NIL;
jdsStreamObject: TYPE = MACHINE DEPENDENT RECORD [
defaultObject: Stream.Object, clientSH: Stream.Handle, jdsPtr: jdsFileObject];
StreamJDSObject: TYPE = LONG POINTER TO jdsStreamObject;
jdsObject: TYPE = RECORD [
jdspage: ARRAY [0..30] OF CARDINAL, -- page directory of JDS file
numofboxes: CARDINAL ← 0, -- count of number of boxes in page
wordsperbox: CARDINAL ← 0, -- count of words per box (+ tabsets)
wordcount: CARDINAL ← 0, -- count of total text words in page
wordsread: CARDINAL ← 0, -- count of total words read so far
textwordsread: CARDINAL ← 0, -- count of total text chars read so far
pageno: CARDINAL ← 0, -- index to JDS.jdspage array
boxno: CARDINAL ← 0, -- index to BoxObjects
boxtextbytesread: CARDINAL ← 0, -- count of text bytes read from box
recordsmade: CARDINAL ← 0, -- count of records (16 words) built/read *
wurd: CARDINAL ← 0, -- JDS text character (in sequence)
curpage: LONG CARDINAL ← 0, -- current page index
curbyteindx: LONG CARDINAL ← 0, -- current stream byte index
topoftext: LONG CARDINAL ← 0, -- Starting index of JDS text in file
pagetextstart: LONG CARDINAL ← 0, -- current page start of text index
startofpage: BOOLEAN ← TRUE, -- flag page change
startofbox: BOOLEAN ← TRUE]; -- flag box change
jdsFileObject: TYPE = LONG POINTER TO jdsObject;
-- Constant declarations
maxjdspages: CARDINAL = 30;
jdspagesize: CARDINAL = 16;
boxOffset: LONG CARDINAL = 22;
jdsfilecheckword: CARDINAL = 12345B;
JDSEOR: CARDINAL = 10000B;
JDSBOR: CARDINAL = 46B;
JDSBLK: CARDINAL = 375B;
NULLCHAR: CharDefs.Char = [ 177B, 377B];
UNDFCHAR: CharDefs.Char = [0, 201B];
-- PUBLIC SIGNALS
endOfJDS: PUBLIC SIGNAL = CODE;
-- PUBLIC PROCEDURES
create: PUBLIC PROCEDURE [h: Handle] RETURNS [hJDS: Handle] =
BEGIN
i: CARDINAL;
sH: StreamJDSObject;
sH ← streamZone.NEW[
jdsStreamObject ← [
defaultObject: Stream.defaultObject, clientSH: h, jdsPtr: NIL]];
sH.defaultObject.options ← [TRUE, FALSE, FALSE, FALSE, FALSE, TRUE];
sH.defaultObject.getByte ← getByte;
sH.defaultObject.putByte ← putByte;
sH.defaultObject.getWord ← getWord; -- plug in my own proc
sH.defaultObject.get ← get; -- plug in my own proc
sH.defaultObject.put ← put;
sH.defaultObject.delete ← delete;
sH.defaultObject.setSST ← setSST;
sH.defaultObject.sendAttention ← sendAttention;
sH.defaultObject.waitAttention ← waitAttention;
sH.clientSH ← h;
sH.jdsPtr ← streamZone.NEW[jdsObject];
Stream.SetPosition[h, 0];
IF MStream.EndOf[h] THEN ERROR;
FOR i IN [0..256) DO
sH.jdsPtr.wurd ← Stream.GetWord[h];
IF i <= maxjdspages THEN sH.jdsPtr.jdspage[i] ← sH.jdsPtr.wurd;
sH.jdsPtr.wordsread ← sH.jdsPtr.wordsread + 1;
ENDLOOP;
IF sH.jdsPtr.jdspage[0] # jdsfilecheckword THEN ERROR; -- not graceful !
sH.jdsPtr.startofpage ← TRUE;
sH.jdsPtr.startofbox ← TRUE;
sH.jdsPtr.pageno ← 0;
sH.jdsPtr.curpage ← 0;
sH.jdsPtr.curbyteindx ← Stream.GetPosition[h];
sH.jdsPtr.topoftext ← sH.jdsPtr.curbyteindx;
sH.jdsPtr.recordsmade ← 0;
RETURN[LOOPHOLE[sH, Handle]];
END;
topOfJDS: PUBLIC PROCEDURE [sH: Stream.Handle] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
sh.jdsPtr.startofpage ← TRUE;
sh.jdsPtr.startofbox ← TRUE;
sh.jdsPtr.pageno ← 0;
sh.jdsPtr.curpage ← 0;
sh.jdsPtr.recordsmade ← 0;
sh.jdsPtr.curbyteindx ← sh.jdsPtr.topoftext;
Stream.SetPosition[sh.clientSH, sh.jdsPtr.topoftext];
END;
getByte: PROCEDURE [sH: Stream.Handle] RETURNS [byte: Stream.Byte] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
RETURN[Stream.GetByte[sh.clientSH]];
END;
putByte: PROCEDURE [sH: Stream.Handle, byte: Stream.Byte] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
Stream.PutByte[sh.clientSH, byte];
END;
put: PROCEDURE [
sH: Stream.Handle, block: Stream.Block, endRecord: BOOLEAN] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
Stream.PutBlock[sh.clientSH, block, endRecord];
END;
get: PROCEDURE [
sH: Stream.Handle, block: Stream.Block, options: Stream.InputOptions]
RETURNS [
bytesTransferred: CARDINAL, why: Stream.CompletionCode,
sst: Stream.SubSequenceType] =
BEGIN -- Reads a JDS file and creates a formatted Master Entry/record.
wurd: CARDINAL;
i, oiscode: CARDINAL ← 0;
tempindex: LONG CARDINAL;
done: BOOLEAN ← FALSE;
newrec: BOOLEAN ← FALSE;
eor: BOOLEAN ← FALSE;
sh: StreamJDSObject ← LOOPHOLE[sH];
JDS: jdsFileObject ← sh.jdsPtr;
RP: LONG POINTER TO OISDictDataDefs.Entry ← LOOPHOLE[block.blockPointer];
BEGIN -- Dummy Block to contain the Exit clause
ENABLE endOfJDS => BEGIN why ← endOfStream; GOTO fini; END;
IF (block.stopIndexPlusOne MOD 2) # 0 THEN ERROR; -- using words NOT bytes
bytesTransferred ← 0;
-- Conditional needed for Show Top flag ...reset to JDS.topoftext
Stream.SetPosition[sh.clientSH, JDS.curbyteindx];
-- get Start of JDS record (".")
UNTIL JDS.wurd = JDSBOR DO JDS.wurd ← getWord[sH]; ENDLOOP;
-- Initialize record
RP↑.notdel ← TRUE;
RP↑.notMarked ← TRUE;
RP↑.kanjiCodeSet ← OIS;
RP↑.kanaCodeSet ← PhonicCodes;
RP↑.logicalDict ← 0;
-- get KANA chars with 377B-fill (minus 1)
FOR i IN [0..13] DO
IF done THEN RP↑.kana[i] ← 377B
ELSE
BEGIN
JDS.wurd ← getWord[sH];
IF JDS.wurd = JDSEOR THEN {
eor ← newrec ← done ← TRUE; RP↑.kana[i] ← 377B; }
ELSE
-- IF JDS.wurd = JDSBOR THEN {newrec ← done ← TRUE; RP↑.kana[i] ← 377B;} ELSE
IF JDS.wurd = JDSBLK THEN {done ← TRUE; RP↑.kana[i] ← 377B; }
ELSE RP↑.kana[i] ← JDSToPhonic[JDS.wurd];
END;
ENDLOOP;
done ← FALSE;
i ← 0;
IF newrec THEN GOTO dunatkanji;
-- get Kanji chars with 177777B-fill (minus 1)
UNTIL JDS.wurd # JDSBLK DO JDS.wurd ← getWord[sH]; ENDLOOP;
FOR i IN [0..6] DO
IF done THEN RP↑.kanji[i] ← NULLCHAR
ELSE
BEGIN
IF JDS.wurd = JDSEOR THEN {
RP↑.kanji[i] ← NULLCHAR; eor ← newrec ← done ← TRUE; }
ELSE
IF JDS.wurd = JDSBLK THEN {RP↑.kanji[i] ← NULLCHAR; done ← TRUE; }
ELSE {
IF JDS.wurd IN [1..JDStoOISDefs.lastJDSKanji] THEN
{ oiscode ← JDStoOISDefs.JDStoOIS[JDS.wurd];
IF oiscode = JDStoOISDefs.UNDF THEN
RP↑.kanji[i] ← UNDFCHAR
ELSE RP↑.kanji[i] ← LOOPHOLE[oiscode, CharDefs.Char];}
ELSE RP↑.kanji[i] ← UNDFCHAR; };
IF NOT done THEN JDS.wurd ← getWord[sH];
END;
ENDLOOP;
done ← FALSE;
i ← 0;
IF newrec THEN GOTO dunatfreq;
-- get Frequency code value from character (0 - 9, default = 0)
UNTIL JDS.wurd # JDSBLK DO wurd ← getWord[sH]; ENDLOOP;
IF JDS.wurd = JDSEOR THEN {eor ← TRUE; GOTO dunatfreq; }
ELSE
IF JDS.wurd = JDSBOR THEN GOTO dunatfreq
ELSE RP↑.freq ← IF JDS.wurd IN [216B..227B] THEN JDS.wurd - 216B ELSE 0;
-- get Part Of Speech code value from characters (0 - 244, default = 0)
wurd ← getWord[sH]; -- get the next word(s)
UNTIL JDS.wurd # JDSBLK DO wurd ← getWord[sH]; ENDLOOP;
IF JDS.wurd = JDSEOR THEN {eor ← TRUE; GOTO dunatpos; }
ELSE
-- IF JDS.wurd = JDSBOR THEN GOTO dunatpos ELSE
RP↑.pos ← JDSPosDefs.GetPosValue[wurd, getWord[sH]];
-- get Catagory code value from character (0 - 25B, default = 26B)
wurd ← getWord[sH]; -- get the next word(s)
UNTIL JDS.wurd # JDSBLK DO JDS.wurd ← getWord[sH]; ENDLOOP;
IF JDS.wurd = JDSEOR THEN {eor ← TRUE; GOTO dunatcat; }
ELSE
IF JDS.wurd = JDSBOR THEN GOTO dunatcat
ELSE RP↑.cat ← JDSPosDefs.GetCatValue[JDS.wurd];
-- get End of JDS record (CR)
done ← FALSE;
i ← 0;
IF NOT eor THEN
UNTIL JDS.wurd = JDSEOR DO
BEGIN
JDS.wurd ← getWord[sH];
IF JDS.wurd = JDSBOR THEN -- No CR for this record...reset;
BEGIN
tempindex ← Stream.GetPosition[sh.clientSH];
tempindex ← tempindex - 2;
Stream.SetPosition[sh.clientSH, tempindex];
GOTO fini;
END;
END;
ENDLOOP;
GOTO fini;
-- fills the rest of the incomplete record with default values
EXITS -- flagging the last unused byte with a "?" (6)
dunatkanji =>
BEGIN
IF eor THEN -- No CR for this record...reset;
BEGIN
tempindex ← Stream.GetPosition[sh.clientSH];
tempindex ← tempindex - 2;
Stream.SetPosition[sh.clientSH, tempindex];
END;
FOR i IN [0..6] DO RP↑.kanji[i] ← NULLCHAR; ENDLOOP;
RP↑.freq ← RP↑.pos ← 0;
RP↑.cat ← 26B;
JDS.recordsmade ← JDS.recordsmade + 1;
bytesTransferred ← bytesTransferred + 32;
END;
dunatfreq =>
BEGIN
IF eor THEN -- No CR for this record...reset;
BEGIN
tempindex ← Stream.GetPosition[sh.clientSH];
tempindex ← tempindex - 2;
Stream.SetPosition[sh.clientSH, tempindex];
END;
RP↑.freq ← RP↑.pos ← 0;
RP↑.cat ← 26B;
JDS.recordsmade ← JDS.recordsmade + 1;
bytesTransferred ← bytesTransferred + 32;
END;
dunatpos =>
BEGIN
IF eor THEN -- No CR for this record...reset;
BEGIN
tempindex ← Stream.GetPosition[sh.clientSH];
tempindex ← tempindex - 2;
Stream.SetPosition[sh.clientSH, tempindex];
END;
RP↑.pos ← 0;
RP↑.cat ← 26B;
JDS.recordsmade ← JDS.recordsmade + 1;
bytesTransferred ← bytesTransferred + 32;
END;
dunatcat =>
BEGIN
RP↑.cat ← 26B;
JDS.recordsmade ← JDS.recordsmade + 1;
bytesTransferred ← bytesTransferred + 32;
END;
fini =>
BEGIN
JDS.recordsmade ← JDS.recordsmade + 1;
bytesTransferred ← bytesTransferred + 32;
END;
END; -- Dummy Block to contain the EXITS clause
IF MStream.EndOf[sh.clientSH] THEN why ← endOfStream
ELSE JDS.curbyteindx ← Stream.GetPosition[sh.clientSH];
RETURN[bytesTransferred, why, sst];
END;
getWord: PRIVATE PROCEDURE [sH: Stream.Handle] RETURNS [word: Stream.Word] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
JDS: jdsFileObject ← sh.jdsPtr;
IF JDS.startofpage THEN
BEGIN
JDS.pageno ← JDS.pageno + 1;
IF JDS.pageno > maxjdspages THEN SIGNAL endOfJDS
ELSE IF JDS.jdspage[JDS.pageno] = 0 THEN RETURN[getWord[sH]];
JDS.curpage ← LONG[512]*LONG[JDS.jdspage[JDS.pageno]];
IF JDS.textwordsread > 0 THEN Heap.FreeNode[p: Box]; -- Flush old boxes
Stream.SetPosition[sh.clientSH, JDS.curpage]; -- Start of page
JDS.numofboxes ← Stream.GetWord[sh.clientSH];
JDS.wordsperbox ← Stream.GetWord[sh.clientSH];
JDS.wordsperbox ← JDS.wordsperbox + Stream.GetWord[sh.clientSH];
JDS.curbyteindx ← JDS.curpage + 6; -- update byte stream indx
Box ← AllocateBoxes[JDS];
LoadBoxPtrs[sh.clientSH, JDS];
JDS.wordcount ← Stream.GetWord[sh.clientSH]; -- Total Text wordcount of Page
JDS.curbyteindx ← JDS.curbyteindx + 2; -- set to start page text (bytes)
JDS.pagetextstart ← JDS.curbyteindx; -- set to start page text (bytes)
JDS.wordsread ← 4 + (JDS.numofboxes*JDS.wordsperbox);
JDS.textwordsread ← 0;
JDS.boxno ← 0;
JDS.startofpage ← FALSE;
JDS.startofbox ← TRUE;
RETURN[getWord[sH]];
END
ELSE
IF JDS.startofbox THEN
BEGIN
IF JDS.boxno >= JDS.numofboxes THEN
BEGIN JDS.startofpage ← TRUE; RETURN[getWord[sH]]; END;
JDS.curbyteindx ← JDS.pagetextstart + Box[JDS.boxno].base;
Stream.SetPosition[sh.clientSH, JDS.curbyteindx];
JDS.boxtextbytesread ← 0;
JDS.startofbox ← FALSE;
RETURN[getWord[sH]];
END
ELSE
BEGIN
DO
IF JDS.wordsread >= 256*16 THEN -- End of Page ?
BEGIN JDS.startofpage ← TRUE; RETURN[getWord[sH]]; END;
IF JDS.textwordsread >= JDS.wordcount THEN -- End of Page Text ?
BEGIN JDS.startofpage ← TRUE; RETURN[getWord[sH]]; END;
IF JDS.boxtextbytesread >= Box[JDS.boxno].bytecount THEN -- End of Box Text ?
BEGIN
JDS.startofbox ← TRUE;
JDS.boxno ← JDS.boxno + 1;
RETURN[getWord[sH]];
END;
JDS.wurd ← Stream.GetWord[sh.clientSH]; -- Get JDS word
JDS.wordsread ← JDS.wordsread + 1;
JDS.textwordsread ← JDS.textwordsread + 1;
JDS.boxtextbytesread ← JDS.boxtextbytesread + 2;
IF JDS.wurd IN [1..6624B] OR JDS.wurd = 10000B THEN RETURN[JDS.wurd]
ELSE RETURN[JDS.wurd ← 201B];
ENDLOOP;
END;
END;
delete: PROCEDURE [sH: Stream.Handle] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
streamZone.FREE[@sh.jdsPtr];
streamZone.FREE[@sh];
END;
setSST: PROCEDURE [sH: Stream.Handle, sst: Stream.SubSequenceType] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
Stream.SetSST[sh.clientSH, sst];
END;
sendAttention: PROCEDURE [sH: Stream.Handle, byte: Stream.Byte] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
Stream.SendAttention[sh.clientSH, byte];
END;
waitAttention: PROCEDURE [sH: Stream.Handle] RETURNS [byte: Stream.Byte] =
BEGIN
sh: StreamJDSObject ← LOOPHOLE[sH];
RETURN[Stream.WaitForAttention[sh.clientSH]];
END;
AllocateBoxes: PRIVATE PROCEDURE [JDS: jdsFileObject] RETURNS [p: BoxPtr] =
BEGIN -- Allocates space for Box records and initiates
i: CARDINAL;
p ← Heap.MakeNode[n: SIZE[BoxObject]*JDS.numofboxes];
FOR i IN [0..JDS.numofboxes) DO p[i].base ← 0; p[i].bytecount ← 0; ENDLOOP;
RETURN[p];
END;
LoadBoxPtrs: PRIVATE PROCEDURE [sH: Stream.Handle, JDS: jdsFileObject] =
BEGIN -- Reads in the Box Text pointers and counts
i: CARDINAL;
bytesperbox, indx: LONG CARDINAL;
bytesperbox ← JDS.wordsperbox*2;
IF MStream.EndOf[sH] THEN ERROR;
indx ← JDS.curbyteindx + boxOffset;
FOR i IN [0..JDS.numofboxes) DO
Stream.SetPosition[sH, indx]; -- 12th word of box
Box[i].base ← Stream.GetWord[sH];
Box[i].bytecount ← Stream.GetWord[sH];
indx ← indx + bytesperbox;
ENDLOOP;
JDS.curbyteindx ← JDS.curbyteindx + (bytesperbox*JDS.numofboxes);
Stream.SetPosition[sH, JDS.curbyteindx]; -- get total text wordcount
END;
JDSToPhonic: PROC [JDSCode: CARDINAL] RETURNS [Phonic: [0..377B]] =
BEGIN
Phonic ←
SELECT JDSCode FROM
IN [400B..523B] => JDSCode - 400B, -- kana
IN [216B..227B] => JDSCode - 36B, -- digits
IN [230B..261B] => JDSCode - 7B, -- UpperCase Romaji
IN [262B..313B] => JDSCode - 21B, -- lowercase Romaji
= 41B => 377B, -- blank
= 42B, =44 => 131B, -- comma
= 43B, =45B => 132B, -- period
= 157B => 321B, -- yen sign
= 160B => 144B, -- dollar sign
ENDCASE => 152B; -- asterix default
END;
END.