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