home *** CD-ROM | disk | FTP | other *** search
- { Cross-reference generator for Pascal/Z programs. Cross references
- lower case identifiers, ignores comments enclosed in braces and
- quoted strings. }
-
- { Author: Peter Grogono }
-
- {$M- inhibit multiply/divide check }
- {$R- inhibit range/bound check }
- {$S- inhibit stack overflow check }
- {$U- inhibit range/bound check for parameters }
-
- program xref;
-
- const
-
- {$ICONSTS.PAS }
-
- namelen = 8; { Significant length of identifier }
- filenamelen = 14; { For i/o file names }
- extin = '.PPP'; { Default input file extension }
- extout = '.XRT'; { Default output extension }
- maxwidth = 80; { Maximum width of output line }
- minspace = 100; { Abandon if < minspace bytes free}
-
- type
-
- {$ITYPES.PAS }
-
- nametype = string namelen;
- fntype = string filenamelen;
-
- itemptr = ^ itemrecord;
- entryptr = ^ entryrecord;
-
- itemrecord = record
- line : integer;
- next : itemptr
- end; { itemrecord }
-
- entryrecord = record
- name : nametype;
- items : itemptr;
- left, right : entryptr
- end; { entryrecord }
-
- var
-
- infilename, outfilename : fntype;
- infile, outfile : text;
-
- roots : array ['a'..'z'] of entryptr;
- name : nametype;
- line, oldline, symcount, entcount : integer;
- ch : char;
- maxent, entlen : byte;
- spaceleft : boolean;
-
- {$IPROCS.PAS }
- {$IGETFILES.PAS }
-
- { Read one character from the input file; check for end of file; count lines }
-
- procedure getchar;
-
- begin
- if eof(infile) then ch := blank
- else
- if eoln(infile) then
- begin readln(infile,ch); line := line + 1 end
- else read(infile,ch)
- end; { getchar }
-
- { Read an identifier from the input file; ignore names that start
- with an upper case letter, comments, quoted strings, and other
- characters. }
-
- procedure getname;
-
- var
- done : boolean;
-
- begin
- done := false;
- repeat
- if ch in ['a'..'z'] then
- begin
- setlength(name,0); oldline := line;
- while ch in ['a'..'z','A'..'Z','0'..'9','_'] do
- begin
- if length(name) < namelen then append(name,ch);
- getchar
- end; { while }
- done := true
- end
- else
- if ch = '{' then
- begin repeat getchar until (ch = '}') or eof(infile); getchar end
- else
- if ch = '''' then
- begin repeat getchar until (ch = '''') or eof(infile); getchar end
- else getchar
- until done or eof(infile)
- end; { getname }
-
- { Store a name in one of the binary trees. The tree is chosen according
- to the first letter of the name. The tree is searched with a REPEAT
- loop rather than by recursion for speed. }
-
- procedure storename;
-
- var
- entry : entryptr;
- item : itemptr;
- entered : boolean;
-
- { Make an entry in the symbol table. }
-
- procedure makentry (var entry : entryptr);
-
- var
- tempentry : entryptr;
- tempitem : itemptr;
-
- begin
- new(tempitem);
- tempitem^.line := oldline;
- tempitem^.next := nil;
- new(tempentry);
- tempentry^.name := name;
- tempentry^.items := tempitem;
- tempentry^.left := nil;
- tempentry^.right := nil;
- entry := tempentry;
- symcount := symcount + 1;
- entered := true
- end; { makentry }
-
- begin { storename }
- entry := roots[name[1]]; entered := false;
- repeat
- if name < entry^.name then
- if entry^.left = nil then makentry(entry^.left)
- else entry := entry^.left
- else
- if name > entry^.name then
- if entry^.right = nil then makentry(entry^.right)
- else entry := entry^.right
- else { name matched }
- begin
- if entry^.items^.line <> line then
- begin
- new(item);
- item^.line := oldline;
- item^.next := entry^.items;
- entry^.items := item
- end;
- entered := true
- end
- until entered;
- entcount := entcount + 1
- end; { storename }
-
- { Print a tree given its root. The list of line numbers associated with
- an identifier is LIFO and must be reversed before printing. }
-
- procedure print (entry : entryptr);
-
- var
- forwards, backwards, temp : itemptr;
- entcount : byte;
-
- begin
- if entry <> nil then
- begin
- print(entry^.left);
- if length(entry^.name) > 0 then
- begin
- write(outfile,entry^.name,blank:namelen+2-length(entry^.name));
- forwards := nil; backwards := entry^.items;
- while backwards <> nil do { reverse list }
- begin
- temp := backwards; backwards := temp^.next;
- temp^.next := forwards; forwards := temp
- end; { while }
- entcount := 0;
- while forwards <> nil do
- begin
- if entcount >= maxent then
- begin writeln(outfile); write(outfile,blank:namelen+2); entcount := 0 end;
- write(outfile,forwards^.line:entlen); entcount := entcount + 1;
- forwards := forwards^.next
- end; { while }
- writeln(outfile)
- end;
- print(entry^.right)
- end
- end; { print }
-
- { Main program }
-
- begin
-
- { Open files }
-
- getfilenames(extin,extout);
- writeln('Reading from ',infilename);
- reset(infilename,infile);
- if eof(infile) then writeln(infilename,' is empty.')
- else
- begin
- writeln('Writing to ',outfilename);
- reset(infilename,infile);
- rewrite(outfilename,outfile);
-
- { Initialize 26 binary trees. Storename requires dummy entries. }
-
-
- for ch := 'a' to 'z' do
- begin
- new(roots[ch]);
- setlength(roots[ch]^.name,0);
- roots[ch]^.items := nil;
- roots[ch]^.left := nil;
- roots[ch]^.right := nil
- end; { for }
-
- { Initialize counters and space flag }
-
- symcount := 0; entcount := 0; spaceleft := true;
-
- { Initialize input procedures }
-
- line := 1; getchar; getname;
-
- { Scan the program }
-
- while spaceleft and not eof(infile) do
- begin
- if (0 < space) and (space < minspace) then
- begin writeln('Memory exhausted at line ',line:1); spaceleft := false end;
- storename; getname
- end; { while }
-
- { Define output layout }
-
- entlen := 3;
- if line > 99 then entlen := 4;
- if line > 999 then entlen := 5;
- maxent := (maxwidth - namelen - 2) div entlen;
-
- { Print the tree }
-
- for ch := 'a' to 'z' do print(roots[ch]);
-
- { Display report }
-
- writeln(line-1:1,' lines read, ',symcount:1,' symbols stored, ',
- entcount:1,' entries recorded.');
- if space > 0 then writeln('Space left: ',space:1,' bytes.')
- end
- end. { xref }