home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol081 / xref.pas < prev    next >
Pascal/Delphi Source File  |  1984-04-29  |  6KB  |  261 lines

  1. { Cross-reference generator for Pascal/Z programs.  Cross references
  2.   lower case identifiers, ignores comments enclosed in braces and
  3.   quoted strings.  }
  4.  
  5. { Author:   Peter Grogono }
  6.  
  7. {$M- inhibit multiply/divide check }
  8. {$R- inhibit range/bound check }
  9. {$S- inhibit stack overflow check }
  10. {$U- inhibit range/bound check for parameters }
  11.  
  12. program xref;
  13.  
  14. const
  15.  
  16. {$ICONSTS.PAS }
  17.  
  18. namelen = 8;                   { Significant length of identifier }
  19. filenamelen = 14;              { For i/o file names }
  20. extin = '.PPP';                { Default input file extension }
  21. extout = '.XRT';               { Default output extension }
  22. maxwidth = 80;                 { Maximum width of output line }
  23. minspace = 100;                { Abandon if < minspace bytes free}
  24.  
  25. type
  26.  
  27. {$ITYPES.PAS }
  28.  
  29. nametype = string namelen;
  30. fntype = string filenamelen;
  31.  
  32. itemptr = ^ itemrecord;
  33. entryptr = ^ entryrecord;
  34.  
  35. itemrecord = record
  36. line : integer;
  37. next : itemptr
  38. end; { itemrecord }
  39.  
  40. entryrecord = record
  41. name : nametype;
  42. items : itemptr;
  43. left, right : entryptr
  44. end; { entryrecord }
  45.  
  46. var
  47.  
  48. infilename, outfilename : fntype;
  49. infile, outfile : text;
  50.  
  51. roots : array ['a'..'z'] of entryptr;
  52. name : nametype;
  53. line, oldline, symcount, entcount : integer;
  54. ch : char;
  55. maxent, entlen : byte;
  56. spaceleft : boolean;
  57.  
  58. {$IPROCS.PAS }
  59. {$IGETFILES.PAS }
  60.  
  61. { Read one character from the input file; check for end of file; count lines }
  62.  
  63. procedure getchar;
  64.  
  65. begin
  66. if eof(infile) then ch := blank
  67. else
  68. if eoln(infile) then
  69. begin readln(infile,ch); line := line + 1 end
  70. else read(infile,ch)
  71. end; { getchar }
  72.  
  73. { Read an identifier from the input file; ignore names that start
  74.   with an upper case letter, comments, quoted strings, and other
  75.   characters. }
  76.  
  77. procedure getname;
  78.  
  79. var
  80. done : boolean;
  81.  
  82. begin
  83. done := false;
  84. repeat
  85. if ch in ['a'..'z'] then
  86. begin
  87. setlength(name,0); oldline := line;
  88. while ch in ['a'..'z','A'..'Z','0'..'9','_'] do
  89. begin
  90. if length(name) < namelen then append(name,ch);
  91. getchar
  92. end; { while }
  93. done := true
  94. end
  95. else
  96. if ch = '{' then
  97. begin repeat getchar until (ch = '}') or eof(infile); getchar end
  98. else
  99. if ch = '''' then
  100. begin repeat getchar until (ch = '''') or eof(infile); getchar end
  101. else getchar
  102. until done or eof(infile)
  103. end; { getname }
  104.  
  105. { Store a name in one of the binary trees.  The tree is chosen according
  106.   to the first letter of the name.  The tree is searched with a REPEAT
  107.   loop rather than by recursion for speed.  }
  108.  
  109. procedure storename;
  110.  
  111. var
  112. entry : entryptr;
  113. item : itemptr;
  114. entered : boolean;
  115.  
  116. { Make an entry in the symbol table.  }
  117.  
  118. procedure makentry (var entry : entryptr);
  119.  
  120. var
  121. tempentry : entryptr;
  122. tempitem : itemptr;
  123.  
  124. begin
  125. new(tempitem);
  126. tempitem^.line := oldline;
  127. tempitem^.next := nil;
  128. new(tempentry);
  129. tempentry^.name := name;
  130. tempentry^.items := tempitem;
  131. tempentry^.left := nil;
  132. tempentry^.right := nil;
  133. entry := tempentry;
  134. symcount := symcount + 1;
  135. entered := true
  136. end; { makentry }
  137.  
  138. begin { storename }
  139. entry := roots[name[1]]; entered := false;
  140. repeat
  141. if name < entry^.name then
  142. if entry^.left = nil then makentry(entry^.left)
  143. else entry := entry^.left
  144. else
  145. if name > entry^.name then
  146. if entry^.right = nil then makentry(entry^.right)
  147. else entry := entry^.right
  148. else { name matched }
  149. begin
  150. if entry^.items^.line <> line then
  151. begin
  152. new(item);
  153. item^.line := oldline;
  154. item^.next := entry^.items;
  155. entry^.items := item
  156. end;
  157. entered := true
  158. end
  159. until entered;
  160. entcount := entcount + 1
  161. end; { storename }
  162.  
  163. { Print a tree given its root.  The list of line numbers associated with
  164.   an identifier is LIFO and must be reversed before printing.  }
  165.  
  166. procedure print (entry : entryptr);
  167.  
  168. var
  169. forwards, backwards, temp : itemptr;
  170. entcount : byte;
  171.  
  172. begin
  173. if entry <> nil then
  174. begin
  175. print(entry^.left);
  176. if length(entry^.name) > 0 then
  177. begin
  178. write(outfile,entry^.name,blank:namelen+2-length(entry^.name));
  179. forwards := nil; backwards := entry^.items;
  180. while backwards <> nil do { reverse list }
  181. begin
  182. temp := backwards; backwards := temp^.next;
  183. temp^.next := forwards; forwards := temp
  184. end; { while }
  185. entcount := 0;
  186. while forwards <> nil do
  187. begin
  188. if entcount >= maxent then
  189. begin writeln(outfile); write(outfile,blank:namelen+2); entcount := 0 end;
  190. write(outfile,forwards^.line:entlen); entcount := entcount + 1;
  191. forwards := forwards^.next
  192. end; { while }
  193. writeln(outfile)
  194. end;
  195. print(entry^.right)
  196. end
  197. end; { print }
  198.  
  199. { Main program }
  200.  
  201. begin
  202.  
  203. { Open files }
  204.  
  205. getfilenames(extin,extout);
  206. writeln('Reading from ',infilename);
  207. reset(infilename,infile);
  208. if eof(infile) then writeln(infilename,' is empty.')
  209. else
  210. begin
  211. writeln('Writing to   ',outfilename);
  212. reset(infilename,infile);
  213. rewrite(outfilename,outfile);
  214.  
  215. { Initialize 26 binary trees.  Storename requires dummy entries.  }
  216.  
  217.  
  218. for ch := 'a' to 'z' do
  219. begin
  220. new(roots[ch]);
  221. setlength(roots[ch]^.name,0);
  222. roots[ch]^.items := nil;
  223. roots[ch]^.left := nil;
  224. roots[ch]^.right := nil
  225. end; { for }
  226.  
  227. { Initialize counters and space flag }
  228.  
  229. symcount := 0; entcount := 0; spaceleft := true;
  230.  
  231. { Initialize input procedures }
  232.  
  233. line := 1; getchar; getname;
  234.  
  235. { Scan the program }
  236.  
  237. while spaceleft and not eof(infile) do
  238. begin 
  239. if (0 < space) and (space < minspace) then
  240. begin writeln('Memory exhausted at line ',line:1); spaceleft := false end;
  241. storename; getname 
  242. end; { while }
  243.  
  244. { Define output layout }
  245.  
  246. entlen := 3;
  247. if line > 99 then entlen := 4;
  248. if line > 999 then entlen := 5;
  249. maxent := (maxwidth - namelen - 2) div entlen;
  250.  
  251. { Print the tree }
  252.  
  253. for ch := 'a' to 'z' do print(roots[ch]);
  254.  
  255. { Display report }
  256.  
  257. writeln(line-1:1,' lines read, ',symcount:1,' symbols stored, ',
  258. entcount:1,' entries recorded.');
  259. if space > 0 then writeln('Space left: ',space:1,' bytes.')
  260. end
  261. end. { xref }