-- 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.