<> <> <<>> <> DIRECTORY Basics USING [CompareInt, Comparison], Commander USING [CommandProc, Register], IO USING [BreakProc, Close, EndOf, GetLineRope, GetTokenRope, int, PutF, RIS, rope, STREAM], ExpertPinRead USING [PinInfo, PinInfoList, PinTable, ReadPinFile], FS USING [Error, FileInfo, StreamOpen], List USING [Compare, CompareProc, Comparison, LORA, Merge, Sort, UniqueSort], Rope USING [Cat, Compare, Equal, Fetch, Length, ROPE, Substr], SymTab USING [Create, Fetch, EachPairAction, Pairs, Ref, Store]; ExpertPageList: CEDAR PROGRAM IMPORTS Basics, Commander, ExpertPinRead, List, FS, IO, Rope, SymTab = BEGIN ROPE: TYPE = Rope.ROPE; Entry: TYPE = REF EntryRep; EntryRep: TYPE = RECORD [ refDes: ROPE, part: ROPE ]; PartTable: TYPE = SymTab.Ref; RefDesList: TYPE = List.LORA; PageList: TYPE = List.LORA; PositionTable: TYPE = SymTab.Ref; RefInt: TYPE = REF INT; TokenProc1: IO.BreakProc ~ { -- Takes any character different from SP for the name IF char = ' THEN RETURN [sepr]; RETURN [other]; }; IsNext: PROC [r1, r2: ROPE] RETURNS [next: BOOL _ FALSE] ~ { comp: List.Comparison; x1, x2, mul: INT; len1: INT _ Rope.Length[r1]; len2: INT _ Rope.Length[r2]; x1 _ 0; mul _ 1; WHILE len1 # 0 AND '0 <= Rope.Fetch[r1, len1-1] AND Rope.Fetch[r1, len1-1] <= '9 DO x1 _ x1 + mul * (Rope.Fetch[r1, len1-1] - '0); len1 _ len1 - 1; mul _ mul * 10; ENDLOOP; x2 _ 0; mul _ 1; WHILE len2 # 0 AND '0 <= Rope.Fetch[r2, len2-1] AND Rope.Fetch[r2, len2-1] <= '9 DO x2 _ x2 + mul * (Rope.Fetch[r2, len2-1] - '0); len2 _ len2 - 1; mul _ mul * 10; ENDLOOP; r1 _ Rope.Substr[r1, 0, len1]; r2 _ Rope.Substr[r2, 0, len2]; comp _ Rope.Compare[r1, r2, FALSE]; IF comp # equal THEN RETURN; IF (x1 + 1) = x2 THEN next _ TRUE; }; Compare: List.CompareProc ~ { comp: List.Comparison; x1, x2, mul: INT; r1, r2: ROPE; len1, len2: INT; IF ISTYPE[ref1, Entry] THEN { entry1: Entry _ NARROW[ref1]; entry2: Entry _ NARROW[ref2]; RETURN Compare[entry1.refDes, entry2.refDes]; }; r1 _ NARROW[ref1]; r2 _ NARROW[ref2]; len1 _ Rope.Length[r1]; len2 _ Rope.Length[r2]; x1 _ 0; mul _ 1; WHILE len1 # 0 AND '0 <= Rope.Fetch[r1, len1-1] AND Rope.Fetch[r1, len1-1] <= '9 DO x1 _ x1 + mul * (Rope.Fetch[r1, len1-1] - '0); len1 _ len1 - 1; mul _ mul * 10; ENDLOOP; x2 _ 0; mul _ 1; WHILE len2 # 0 AND '0 <= Rope.Fetch[r2, len2-1] AND Rope.Fetch[r2, len2-1] <= '9 DO x2 _ x2 + mul * (Rope.Fetch[r2, len2-1] - '0); len2 _ len2 - 1; mul _ mul * 10; ENDLOOP; r1 _ Rope.Substr[r1, 0, len1]; r2 _ Rope.Substr[r2, 0, len2]; comp _ Rope.Compare[r1, r2, FALSE]; IF comp # equal THEN RETURN Rope.Compare[r1, r2, FALSE]; RETURN Basics.CompareInt[x1, x2]; }; ReadPartFile: PROC [file: ROPE] RETURNS [completeEntryList: List.LORA] ~ { x: List.LORA; line, refDes: ROPE; inLine: IO.STREAM; in: IO.STREAM _ FS.StreamOpen[file]; x _ NIL; WHILE NOT IO.EndOf[in] DO line _ IO.GetLineRope[in]; inLine _ IO.RIS[line]; refDes _ IO.GetTokenRope[inLine, TokenProc1].token; x _ CONS[refDes, x]; ENDLOOP; completeEntryList _ List.Sort[x, Compare]; }; <<>> Merge: PROC [pageList: PageList, page: INT] RETURNS [newPageList: PageList] ~ { tempPageList, tempPageList2: PageList; refPage: RefInt _ NEW [INT]; refPage^ _ page; tempPageList _ CONS[refPage, NIL]; tempPageList2 _ List.Merge[pageList, tempPageList, List.Compare]; newPageList _ List.UniqueSort[tempPageList2]; }; ExpertPageListProc: Commander.CommandProc = BEGIN FileExistence: PROC [fileName: ROPE] RETURNS [found: BOOLEAN _ TRUE] ~ { [] _ FS.FileInfo[fileName ! FS.Error => { IF error.group = user THEN { IO.PutF[cmd.out, "%g\n", IO.rope[error.explanation]]; found _ FALSE; CONTINUE; }; }]; }; Pages: SymTab.EachPairAction ~ { FOR l: ExpertPinRead.PinInfoList _ NARROW[val], l.rest UNTIL l = NIL DO newPageList: PageList; pinInfo: ExpertPinRead.PinInfo _ l.first; refDes: ROPE _ pinInfo.refDes; pageNumber: INT _ pinInfo.pageNumber; IF SymTab.Fetch[positionTable, refDes].found THEN { pageList: PageList _ NARROW[SymTab.Fetch[positionTable, refDes].val]; newPageList _ Merge[pageList, pageNumber]; } ELSE { refPage: RefInt _ NEW [INT]; refPage^ _ pageNumber; newPageList _ CONS[refPage, NIL]; }; [] _ SymTab.Store[positionTable, refDes, newPageList]; ENDLOOP; }; out: IO.STREAM; refDes, savedRefDes1, savedRefDes2: ROPE; pageList: PageList; refPage: RefInt; page, savedPage, savedPage2: INT; completeEntryList: List.LORA; positionTable: PositionTable; pinTable: ExpertPinRead.PinTable; stream: IO.STREAM _ IO.RIS[cmd.commandLine]; file: ROPE _ IO.GetTokenRope[stream].token; pinListFile: ROPE _ Rope.Cat[file, ".pinlist"]; partListFile: ROPE _ Rope.Cat[file, ".partlist"]; pageListFile: ROPE _ Rope.Cat[file, ".pagelist"]; IF NOT FileExistence[pinListFile] THEN GO TO fail; IF NOT FileExistence[partListFile] THEN GO TO fail; IO.PutF[cmd.out, "Reading %g\n", IO.rope[pinListFile]]; pinTable _ ExpertPinRead.ReadPinFile[pinListFile]; IO.PutF[cmd.out, "Reading %g\n", IO.rope[partListFile]]; completeEntryList _ ReadPartFile[partListFile]; IO.PutF[cmd.out, "Sorting the page numbers\n"]; positionTable _ SymTab.Create[]; [] _ SymTab.Pairs[pinTable, Pages]; IO.PutF[cmd.out, "Writing %g\n", IO.rope[pageListFile]]; out _ FS.StreamOpen[pageListFile, $create]; IO.PutF[out, "%g\n\tShows on which page each part appears\n\n", IO.rope[pageListFile]]; savedPage _ 0; savedPage2 _ 0; FOR l: List.LORA _ completeEntryList, l.rest UNTIL l = NIL DO refDes _ NARROW[l.first]; pageList _ NARROW[SymTab.Fetch[positionTable, refDes].val]; refPage _ NARROW[pageList.first]; page _ refPage^; IF page = savedPage AND IsNext[savedRefDes2, refDes] AND pageList.rest = NIL THEN { savedRefDes2 _ refDes; } ELSE { IF savedPage # 0 THEN { IF Rope.Equal[savedRefDes1, savedRefDes2] THEN { IO.PutF[out, "%g\t\tpage %g", IO.rope[savedRefDes1], IO.int[savedPage]]; } ELSE { IO.PutF[out, "%g-%g\tpage %g", IO.rope[savedRefDes1], IO.rope[savedRefDes2], IO.int[savedPage]]; }; IF savedPage2 # 0 THEN { IO.PutF[out, ", %g\n", IO.int[savedPage2]]; } ELSE { IO.PutF[out, "\n"]; }; }; savedRefDes1 _ refDes; savedRefDes2 _ refDes; savedPage _ page; IF pageList.rest # NIL THEN { refPage _ NARROW[pageList.rest.first]; savedPage2 _ refPage^; } ELSE { savedPage2 _ 0; }; }; ENDLOOP; IF Rope.Equal[savedRefDes1, savedRefDes2] THEN { IO.PutF[out, "%g\t\tpage %g\n", IO.rope[savedRefDes1], IO.int[savedPage]]; } ELSE { IO.PutF[out, "%g-%g\tpage %g\n", IO.rope[savedRefDes1], IO.rope[savedRefDes2], IO.int[savedPage]]; }; IF savedPage2 # 0 THEN { IO.PutF[out, ", %g\n", IO.int[savedPage2]]; } ELSE { IO.PutF[out, "\n"]; }; IO.Close[out]; EXITS fail => result _ $Failed; END; Commander.Register[ key: "ExpertPageList", proc: ExpertPageListProc, doc: "Read a .pinlist file and generates a .pagelist file\n"]; END.