2
0

browser.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by the FPC development team
  4. Support routines for the browser
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$ifdef TP}
  19. {$N+,E+}
  20. {$endif}
  21. unit browser;
  22. interface
  23. uses
  24. cobjects,files;
  25. const
  26. {$ifdef TP}
  27. logbufsize = 1024;
  28. {$else}
  29. logbufsize = 16384;
  30. {$endif}
  31. type
  32. pref = ^tref;
  33. tref = object
  34. nextref : pref;
  35. posinfo : tfileposinfo;
  36. moduleindex : word;
  37. is_written : boolean;
  38. constructor init(ref:pref;pos:pfileposinfo);
  39. destructor done; virtual;
  40. function get_file_line : string;
  41. end;
  42. pbrowser=^tbrowser;
  43. tbrowser=object
  44. fname : string;
  45. logopen : boolean;
  46. stderrlog : boolean;
  47. f : file;
  48. elements_to_list : pstringqueue;
  49. buf : pchar;
  50. bufidx : longint;
  51. identidx : longint;
  52. constructor init;
  53. destructor done;
  54. procedure setfilename(const fn:string);
  55. procedure createlog;
  56. procedure flushlog;
  57. procedure addlog(const s:string);
  58. procedure addlogrefs(p:pref);
  59. procedure closelog;
  60. procedure ident;
  61. procedure unident;
  62. procedure browse_symbol(const sr : string);
  63. procedure list_elements;
  64. procedure list_debug_infos;
  65. end;
  66. var
  67. browse : tbrowser;
  68. function get_source_file(moduleindex,fileindex : word) : pinputfile;
  69. implementation
  70. uses
  71. comphook,globals,symtable,systems,verbose;
  72. {****************************************************************************
  73. TRef
  74. ****************************************************************************}
  75. constructor tref.init(ref :pref;pos : pfileposinfo);
  76. begin
  77. nextref:=nil;
  78. if assigned(pos) then
  79. posinfo:=pos^;
  80. if assigned(current_module) then
  81. moduleindex:=current_module^.unit_index;
  82. if assigned(ref) then
  83. ref^.nextref:=@self;
  84. is_written:=false;
  85. end;
  86. destructor tref.done;
  87. var
  88. inputfile : pinputfile;
  89. ref : pref;
  90. begin
  91. inputfile:=get_source_file(moduleindex,posinfo.fileindex);
  92. if inputfile<>nil then
  93. dec(inputfile^.ref_count);
  94. ref:=@self;
  95. if assigned(ref^.nextref) then
  96. dispose(ref^.nextref,done);
  97. nextref:=nil;
  98. end;
  99. function tref.get_file_line : string;
  100. var
  101. inputfile : pinputfile;
  102. begin
  103. get_file_line:='';
  104. inputfile:=get_source_file(moduleindex,posinfo.fileindex);
  105. if assigned(inputfile) then
  106. if status.use_gccoutput then
  107. get_file_line:=lower(inputfile^.name^)
  108. +':'+tostr(posinfo.line)+':'+tostr(posinfo.column)+':'
  109. else
  110. get_file_line:=inputfile^.name^
  111. +'('+tostr(posinfo.line)+','+tostr(posinfo.column)+')'
  112. else
  113. if status.use_gccoutput then
  114. get_file_line:='file_unknown:'
  115. +tostr(posinfo.line)+':'+tostr(posinfo.column)+':'
  116. else
  117. get_file_line:='file_unknown('
  118. +tostr(posinfo.line)+','+tostr(posinfo.column)+')'
  119. end;
  120. {****************************************************************************
  121. TBrowser
  122. ****************************************************************************}
  123. constructor tbrowser.init;
  124. begin
  125. fname:=FixFileName('browser.log');
  126. logopen:=false;
  127. elements_to_list:=new(pstringqueue,init);
  128. end;
  129. destructor tbrowser.done;
  130. begin
  131. if logopen then
  132. closelog;
  133. end;
  134. procedure tbrowser.setfilename(const fn:string);
  135. begin
  136. fname:=FixFileName(fn);
  137. end;
  138. procedure tbrowser.createlog;
  139. begin
  140. if logopen then
  141. closelog;
  142. assign(f,fname);
  143. {$I-}
  144. rewrite(f,1);
  145. {$I+}
  146. if ioresult<>0 then
  147. exit;
  148. logopen:=true;
  149. getmem(buf,logbufsize);
  150. bufidx:=0;
  151. identidx:=0;
  152. end;
  153. procedure tbrowser.flushlog;
  154. begin
  155. if logopen then
  156. if not stderrlog then
  157. blockwrite(f,buf^,bufidx)
  158. else
  159. begin
  160. buf[bufidx]:=#0;
  161. {$ifndef TP}
  162. write(stderr,buf);
  163. {$else TP}
  164. write(buf);
  165. {$endif TP}
  166. end;
  167. bufidx:=0;
  168. end;
  169. procedure tbrowser.closelog;
  170. begin
  171. if logopen then
  172. begin
  173. flushlog;
  174. close(f);
  175. freemem(buf,logbufsize);
  176. logopen:=false;
  177. end;
  178. end;
  179. procedure tbrowser.list_elements;
  180. begin
  181. stderrlog:=true;
  182. getmem(buf,logbufsize);
  183. logopen:=true;
  184. while not elements_to_list^.empty do
  185. browse_symbol(elements_to_list^.get);
  186. flushlog;
  187. logopen:=false;
  188. freemem(buf,logbufsize);
  189. stderrlog:=false;
  190. end;
  191. procedure tbrowser.list_debug_infos;
  192. {$ifndef debug}
  193. begin
  194. end;
  195. {$else debug}
  196. var
  197. hp : pmodule;
  198. ff : pinputfile;
  199. begin
  200. hp:=pmodule(loaded_units.first);
  201. while assigned(hp) do
  202. begin
  203. addlog('Unit '+hp^.modulename^+' has index '+tostr(hp^.unit_index));
  204. ff:=hp^.sourcefiles.files;
  205. while assigned(ff) do
  206. begin
  207. addlog('File '+ff^.name^+' index '+tostr(ff^.ref_index));
  208. ff:=ff^.ref_next;
  209. end;
  210. hp:=pmodule(hp^.next);
  211. end;
  212. end;
  213. {$endif debug}
  214. procedure tbrowser.addlog(const s:string);
  215. begin
  216. if not logopen then
  217. exit;
  218. { add ident }
  219. if identidx>0 then
  220. begin
  221. if bufidx+identidx>logbufsize then
  222. flushlog;
  223. fillchar(buf[bufidx],identidx,' ');
  224. inc(bufidx,identidx);
  225. end;
  226. { add text }
  227. if bufidx+length(s)>logbufsize-2 then
  228. flushlog;
  229. move(s[1],buf[bufidx],length(s));
  230. inc(bufidx,length(s));
  231. { add crlf }
  232. buf[bufidx]:=target_os.newline[1];
  233. inc(bufidx);
  234. if length(target_os.newline)=2 then
  235. begin
  236. buf[bufidx]:=target_os.newline[2];
  237. inc(bufidx);
  238. end;
  239. end;
  240. procedure tbrowser.addlogrefs(p:pref);
  241. var
  242. ref : pref;
  243. begin
  244. ref:=p;
  245. Ident;
  246. while assigned(ref) do
  247. begin
  248. Browse.AddLog(ref^.get_file_line);
  249. ref:=ref^.nextref;
  250. end;
  251. Unident;
  252. end;
  253. procedure tbrowser.browse_symbol(const sr : string);
  254. var
  255. sym,symb : psym;
  256. symt : psymtable;
  257. hp : pmodule;
  258. s,ss : string;
  259. p : byte;
  260. procedure next_substring;
  261. begin
  262. p:=pos('.',s);
  263. if p>0 then
  264. begin
  265. ss:=copy(s,1,p-1);
  266. s:=copy(s,p+1,255);
  267. end
  268. else
  269. begin
  270. ss:=s;
  271. s:='';
  272. end;
  273. addlog('substring : '+ss);
  274. end;
  275. begin
  276. s:=sr;
  277. symt:=symtablestack;
  278. next_substring;
  279. if assigned(symt) then
  280. begin
  281. sym:=symt^.search(ss);
  282. if sym=nil then
  283. sym:=symt^.search(upper(ss));
  284. end
  285. else
  286. sym:=nil;
  287. if assigned(sym) and (sym^.typ=unitsym) and (s<>'') then
  288. begin
  289. addlog('Unitsym found !');
  290. symt:=punitsym(sym)^.unitsymtable;
  291. if assigned(symt) then
  292. begin
  293. next_substring;
  294. sym:=symt^.search(ss);
  295. end
  296. else
  297. sym:=nil;
  298. end;
  299. if not assigned(sym) then
  300. begin
  301. symt:=nil;
  302. { try all loaded_units }
  303. hp:=pmodule(loaded_units.first);
  304. while assigned(hp) do
  305. begin
  306. if hp^.modulename^=upper(ss) then
  307. begin
  308. symt:=hp^.symtable;
  309. break;
  310. end;
  311. hp:=pmodule(hp^.next);
  312. end;
  313. if not assigned(symt) then
  314. begin
  315. addlog('!!!Symbol '+ss+' not found !!!');
  316. exit;
  317. end
  318. else
  319. begin
  320. next_substring;
  321. sym:=symt^.search(ss);
  322. if sym=nil then
  323. sym:=symt^.search(upper(ss));
  324. end;
  325. end;
  326. while assigned(sym) and (s<>'') do
  327. begin
  328. next_substring;
  329. case sym^.typ of
  330. typesym :
  331. begin
  332. if ptypesym(sym)^.definition^.deftype in [recorddef,objectdef] then
  333. begin
  334. if ptypesym(sym)^.definition^.deftype=recorddef then
  335. symt:=precdef(ptypesym(sym)^.definition)^.symtable
  336. else
  337. symt:=pobjectdef(ptypesym(sym)^.definition)^.publicsyms;
  338. sym:=symt^.search(ss);
  339. if sym=nil then
  340. sym:=symt^.search(upper(ss));
  341. end;
  342. end;
  343. varsym :
  344. begin
  345. if pvarsym(sym)^.definition^.deftype in [recorddef,objectdef] then
  346. begin
  347. if pvarsym(sym)^.definition^.deftype=recorddef then
  348. symt:=precdef(pvarsym(sym)^.definition)^.symtable
  349. else
  350. symt:=pobjectdef(pvarsym(sym)^.definition)^.publicsyms;
  351. sym:=symt^.search(ss);
  352. if sym=nil then
  353. sym:=symt^.search(upper(ss));
  354. end;
  355. end;
  356. procsym :
  357. begin
  358. symt:=pprocsym(sym)^.definition^.parast;
  359. symb:=symt^.search(ss);
  360. if symb=nil then
  361. symb:=symt^.search(upper(ss));
  362. if not assigned(symb) then
  363. begin
  364. symt:=pprocsym(sym)^.definition^.parast;
  365. sym:=symt^.search(ss);
  366. if symb=nil then
  367. symb:=symt^.search(upper(ss));
  368. end
  369. else
  370. sym:=symb;
  371. end;
  372. {else
  373. sym^.add_to_browserlog;}
  374. end;
  375. end;
  376. if assigned(sym) then
  377. sym^.add_to_browserlog
  378. else
  379. addlog('!!!Symbol '+ss+' not found !!!');
  380. end;
  381. procedure tbrowser.ident;
  382. begin
  383. inc(identidx,2);
  384. end;
  385. procedure tbrowser.unident;
  386. begin
  387. dec(identidx,2);
  388. end;
  389. {****************************************************************************
  390. Helpers
  391. ****************************************************************************}
  392. function get_source_file(moduleindex,fileindex : word) : pinputfile;
  393. var
  394. hp : pmodule;
  395. f : pinputfile;
  396. begin
  397. hp:=pmodule(loaded_units.first);
  398. while assigned(hp) and (hp^.unit_index<>moduleindex) do
  399. hp:=pmodule(hp^.next);
  400. get_source_file:=nil;
  401. if not assigned(hp) then
  402. exit;
  403. f:=pinputfile(hp^.sourcefiles.files);
  404. while assigned(f) do
  405. begin
  406. if f^.ref_index=fileindex then
  407. begin
  408. get_source_file:=f;
  409. exit;
  410. end;
  411. f:=pinputfile(f^.ref_next);
  412. end;
  413. end;
  414. begin
  415. browse.init
  416. end.
  417. {
  418. $Log$
  419. Revision 1.8 1998-09-22 17:13:42 pierre
  420. + browsing updated and developed
  421. records and objects fields are also stored
  422. Revision 1.7 1998/09/21 08:45:05 pierre
  423. + added vmt_offset in tobjectdef.write for fututre use
  424. (first steps to have objects without vmt if no virtual !!)
  425. + added fpu_used field for tabstractprocdef :
  426. sets this level to 2 if the functions return with value in FPU
  427. (is then set to correct value at parsing of implementation)
  428. THIS MIGHT refuse some code with FPU expression too complex
  429. that were accepted before and even in some cases
  430. that don't overflow in fact
  431. ( like if f : float; is a forward that finally in implementation
  432. only uses one fpu register !!)
  433. Nevertheless I think that it will improve security on
  434. FPU operations !!
  435. * most other changes only for UseBrowser code
  436. (added symtable references for record and objects)
  437. local switch for refs to args and local of each function
  438. (static symtable still missing)
  439. UseBrowser still not stable and probably broken by
  440. the definition hash array !!
  441. Revision 1.6 1998/09/01 07:54:16 pierre
  442. * UseBrowser a little updated (might still be buggy !!)
  443. * bug in psub.pas in function specifier removed
  444. * stdcall allowed in interface and in implementation
  445. (FPC will not yet complain if it is missing in either part
  446. because stdcall is only a dummy !!)
  447. Revision 1.5 1998/06/13 00:10:04 peter
  448. * working browser and newppu
  449. * some small fixes against crashes which occured in bp7 (but not in
  450. fpc?!)
  451. Revision 1.4 1998/06/11 10:11:57 peter
  452. * -gb works again
  453. Revision 1.3 1998/05/20 09:42:32 pierre
  454. + UseTokenInfo now default
  455. * unit in interface uses and implementation uses gives error now
  456. * only one error for unknown symbol (uses lastsymknown boolean)
  457. the problem came from the label code !
  458. + first inlined procedures and function work
  459. (warning there might be allowed cases were the result is still wrong !!)
  460. * UseBrower updated gives a global list of all position of all used symbols
  461. with switch -gb
  462. Revision 1.2 1998/04/30 15:59:39 pierre
  463. * GDB works again better :
  464. correct type info in one pass
  465. + UseTokenInfo for better source position
  466. * fixed one remaining bug in scanner for line counts
  467. * several little fixes
  468. }