{$T-} program PASREF; {PASCAL cross reference generator using a binary tree. Adapted from Algorithms + Data Structures = Programs, by Niklaus Wirth (pp. 206-210). V1A - Bill Heidebrecht - 16 Sep 77 TRW Systems One Space Park Redondo Beach, CA 90278} const C1 = 12; {length of words} C2 = 12; {numbers per line} C3 = 6; {digits per number} NL = CHR(10); FF = CHR(12); type ALFA = array [1..C1] of CHAR; WORDREF = @WORD; ITEMREF = @ITEM; WORD = record KEY: ALFA; FIRST, LAST: ITEMREF; LEFT, RIGHT: WORDREF end; ITEM = record LNO: INTEGER; NEXT: ITEMREF end; COMPARE = (LT, EQ, GT); var ROOT: WORDREF; K, K1: INTEGER; NCL: INTEGER; {current line number} IDX: ALFA; LST, INFILE: TEXT; FILENAME: array [1..32] of CHAR; DONE, PRINTSOURCE: BOOLEAN; CH: CHAR; function MATCH (W: WORDREF): COMPARE; var I: INTEGER; DIFFERENT: BOOLEAN; B: ALFA; begin MATCH:= EQ; DIFFERENT:= FALSE; B:= W@.KEY; I:= 0; repeat I:= I+1; if IDX[I] # B[I] then begin DIFFERENT:= TRUE; if IDX[I] > B[I] then MATCH:= GT else MATCH:= LT end; until DIFFERENT ! (I>=C1); end; procedure SEARCH (var W1: WORDREF); var W: WORDREF; X: ITEMREF; Q: COMPARE; begin W:= W1; if W = NIL then begin {insert new identifier into tree} NEW(W); NEW(X); with W@ do begin KEY:= IDX; LEFT:= NIL; RIGHT:= NIL; FIRST:= X; LAST:= X; end; X@.LNO:= NCL; X@.NEXT:= NIL; W1:= W end else begin case MATCH(W) of LT: SEARCH(W@.LEFT); GT: SEARCH(W@.RIGHT); EQ: begin {add reference to existing list} NEW(X); X@.LNO:= NCL; X@.NEXT:= NIL; W@.LAST@.NEXT:= X; W@.LAST:= X end end {case} end end; {SEARCH} procedure PRINTTREE (W2: WORDREF); var W: WORDREF; procedure PRINTWORD (W1: WORDREF); var L, LINENO: INTEGER; X: ITEMREF; WA: WORD; begin WA:= W1@; WRITE(LST,' ',WA.KEY); X:= WA.FIRST; L:= 0; repeat if L = C2 then begin L:= 0; WRITE(LST,NL,' ':13) end; L:= L+1; LINENO:= X@.LNO; WRITE(LST,LINENO:C3); X:= X@.NEXT until X = NIL; WRITE(LST,NL) end; {PRINTWORD} begin {PRINTTREE} W:= W2; if W # NIL then begin PRINTTREE(W@.LEFT); PRINTWORD(W); PRINTTREE(W@.RIGHT) end end; {PRINTTREE} procedure INITFILES; var I: INTEGER; CH: CHAR; begin WRITE(OUT,NL,'IN FILE: '); BREAK(OUT); I:= 0; repeat READ(INP,CH); I:= I+1; FILENAME[I]:= CH until CH = NL; FILENAME[I]:= ' '; RESET(INFILE, FILENAME); REWRITE(LST, 'PASREF.OUT '); WRITE(LST,NL); WRITE(OUT,NL,'PRINT INPUT FILE [Y/N]: '); BREAK(OUT); READ(INP,CH); PRINTSOURCE:= CH = 'Y'; WRITE(OUT,NL); BREAK(OUT); end; {INITFILES} procedure NEXTCHAR; begin READ(INFILE,CH); if EOF(INFILE) then begin DONE:= TRUE; CH:= NL end; if PRINTSOURCE then WRITE(LST,CH) end; procedure CHECKEOL; begin if CH = NL then {new line} begin NCL:= NCL+1; if PRINTSOURCE then WRITE(LST, NCL:C3, ' ') end; end; function SPECIALCHAR: BOOLEAN; begin SPECIALCHAR:= FALSE; if (CH<'0') ! (CH>'Z') then SPECIALCHAR:= TRUE else if (CH>'9') & (CH<'A') then SPECIALCHAR:= TRUE; if CH='_' then SPECIALCHAR:= FALSE; end; begin {main program} INITFILES; DONE:= FALSE; ROOT:= NIL; K1:= C1; CH:= NL; NCL:= 0; CHECKEOL; repeat NEXTCHAR; CHECKEOL; if (CH>='A') & (CH<='Z') then begin K:= 0; repeat if K < C1 then begin K:= K+1; IDX[K]:= CH end; NEXTCHAR until SPECIALCHAR ! DONE; if K >= K1 then K1:= K else repeat IDX[K1]:= ' '; K1:= K1-1 until K1 = K; SEARCH(ROOT); CHECKEOL end else begin {check for quote or comment} if CH = '''' then repeat NEXTCHAR; CHECKEOL until (CH = '''') ! DONE else if CH = '{' then repeat NEXTCHAR; CHECKEOL until (CH = '}') ! DONE end until DONE; WRITE(LST,FF,NL); PRINTTREE(ROOT); WRITE(LST,NL); BREAK(LST); WRITE(OUT,'END PASREF',NL); BREAK(OUT) end.