symppu.inc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl, Pierre Muller
  4. Implementation of the reading of PPU Files for the symtable
  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. const
  19. {$ifdef FPC}
  20. ppubufsize=32768;
  21. {$ELSE}
  22. {$IFDEF USEOVERLAY}
  23. ppubufsize=512;
  24. {$ELSE}
  25. ppubufsize=4096;
  26. {$ENDIF}
  27. {$ENDIF}
  28. {*****************************************************************************
  29. PPU Writing
  30. *****************************************************************************}
  31. procedure writebyte(b:byte);
  32. begin
  33. current_ppu^.putbyte(b);
  34. end;
  35. procedure writeword(w:word);
  36. begin
  37. current_ppu^.putword(w);
  38. end;
  39. procedure writelong(l:longint);
  40. begin
  41. current_ppu^.putlongint(l);
  42. end;
  43. procedure writereal(d:bestreal);
  44. begin
  45. current_ppu^.putreal(d);
  46. end;
  47. procedure writestring(const s:string);
  48. begin
  49. current_ppu^.putstring(s);
  50. end;
  51. procedure writenormalset(var s); {You cannot pass an array[0..31] of byte!}
  52. begin
  53. current_ppu^.putdata(s,sizeof(tnormalset));
  54. end;
  55. procedure writecontainer(var p:tstringcontainer;id:byte;hold,strippath:boolean);
  56. var
  57. hcontainer : tstringcontainer;
  58. s : string;
  59. begin
  60. if hold then
  61. hcontainer.init;
  62. while not p.empty do
  63. begin
  64. s:=p.get;
  65. if strippath then
  66. current_ppu^.putstring(SplitFileName(s))
  67. else
  68. current_ppu^.putstring(s);
  69. if hold then
  70. hcontainer.insert(s);
  71. end;
  72. current_ppu^.writeentry(id);
  73. if hold then
  74. p:=hcontainer;
  75. end;
  76. procedure writeposinfo(const p:tfileposinfo);
  77. begin
  78. current_ppu^.putword(p.fileindex);
  79. current_ppu^.putlongint(p.line);
  80. current_ppu^.putword(p.column);
  81. end;
  82. procedure writedefref(p : pdef);
  83. begin
  84. if p=nil then
  85. current_ppu^.putlongint($ffffffff)
  86. else
  87. begin
  88. if p^.owner^.symtabletype=staticsymtable then
  89. current_ppu^.putword($fffe)
  90. else if (p^.owner=aktrecordsymtable) then
  91. current_ppu^.putword($ffff)
  92. else if p^.owner^.unitid>$8000 then
  93. current_ppu^.putword(p^.owner^.unitid)
  94. else
  95. current_ppu^.putword(p^.owner^.unitid);
  96. current_ppu^.putword(p^.indexnb);
  97. end;
  98. end;
  99. procedure writesymref(p : psym);
  100. begin
  101. if p=nil then
  102. current_ppu^.putlongint($ffffffff)
  103. else
  104. begin
  105. if p^.owner^.symtabletype=staticsymtable then
  106. current_ppu^.putword($fffe)
  107. else if (p^.owner=aktrecordsymtable) then
  108. current_ppu^.putword($ffff)
  109. else if p^.owner^.unitid>$8000 then
  110. current_ppu^.putword(p^.owner^.unitid)
  111. else
  112. current_ppu^.putword(p^.owner^.unitid);
  113. current_ppu^.putword(p^.indexnb);
  114. end;
  115. end;
  116. procedure writesourcefiles;
  117. var
  118. hp : pinputfile;
  119. begin
  120. { second write the used source files }
  121. current_ppu^.do_crc:=false;
  122. hp:=current_module^.sourcefiles^.files;
  123. while assigned(hp) do
  124. begin
  125. { only name and extension }
  126. current_ppu^.putstring(hp^.name^);
  127. hp:=hp^.ref_next;
  128. end;
  129. current_ppu^.writeentry(ibsourcefiles);
  130. current_ppu^.do_crc:=true;
  131. end;
  132. procedure writeusedunit;
  133. var
  134. hp : pused_unit;
  135. begin
  136. numberunits;
  137. hp:=pused_unit(current_module^.used_units.first);
  138. while assigned(hp) do
  139. begin
  140. {$ifdef Double_checksum}
  141. current_ppu^.do_interface_crc:=hp^.in_interface;
  142. {$endif Double_checksum}
  143. current_ppu^.putstring(hp^.name^);
  144. current_ppu^.do_crc:=false;
  145. {$ifndef Double_checksum}
  146. { the checksum should not affect the crc of this unit ! (PFV) }
  147. current_ppu^.putlongint(hp^.checksum);
  148. {$else Double_checksum}
  149. if hp^.in_interface then
  150. current_ppu^.putlongint(hp^.checksum)
  151. else
  152. current_ppu^.putlongint(hp^.interface_checksum);
  153. {$endif def Double_checksum}
  154. current_ppu^.do_crc:=true;
  155. current_ppu^.putbyte(byte(hp^.in_interface));
  156. hp:=pused_unit(hp^.next);
  157. end;
  158. {$ifdef Double_checksum}
  159. current_ppu^.do_interface_crc:=true;
  160. {$endif Double_checksum}
  161. current_ppu^.writeentry(ibloadunit);
  162. end;
  163. procedure writeunitas(const s : string;unittable : punitsymtable;only_crc : boolean);
  164. begin
  165. Message1(unit_u_ppu_write,s);
  166. { create unit flags }
  167. with Current_Module^ do
  168. begin
  169. if (((cs_create_staticlib in aktmoduleswitches) or
  170. (cs_smartlink in aktmoduleswitches)) and
  171. (SplitName(ppufilename^)<>SplitName(staticlibfilename^))) or
  172. ((cs_create_sharedlib in aktmoduleswitches) and
  173. (SplitName(ppufilename^)<>SplitName(sharedlibfilename^))) then
  174. flags:=flags or uf_in_library;
  175. if cs_smartlink in aktmoduleswitches then
  176. flags:=flags or uf_smartlink;
  177. {$ifdef GDB}
  178. if cs_gdb_dbx in aktglobalswitches then
  179. flags:=flags or uf_has_dbx;
  180. {$endif GDB}
  181. if target_os.endian=endian_big then
  182. flags:=flags or uf_big_endian;
  183. if cs_browser in aktmoduleswitches then
  184. flags:=flags or uf_has_browser;
  185. if cs_local_browser in aktmoduleswitches then
  186. flags:=flags or uf_local_browser;
  187. end;
  188. {$ifdef Test_Double_checksum_write}
  189. If only_crc then
  190. Assign(CRCFile,s+'.INT')
  191. else
  192. Assign(CRCFile,s+'.IMP');
  193. Rewrite(CRCFile);
  194. {$endif def Test_Double_checksum_write}
  195. { open ppufile }
  196. current_ppu:=new(pppufile,init(s));
  197. if not current_ppu^.create then
  198. Message(unit_f_ppu_cannot_write);
  199. {$ifdef Double_checksum}
  200. current_ppu^.crc_only:=only_crc;
  201. {$ifdef Test_Double_checksum}
  202. if only_crc then
  203. begin
  204. new(current_ppu^.crc_test);
  205. end
  206. else
  207. begin
  208. current_ppu^.crc_test:=Current_Module^.crc_array;
  209. current_ppu^.crc_index:=Current_Module^.crc_size;
  210. end;
  211. {$endif def Test_Double_checksum}
  212. {$endif Double_checksum}
  213. current_ppu^.change_endian:=source_os.endian<>target_os.endian;
  214. { write symbols and definitions }
  215. unittable^.writeasunit;
  216. { flush to be sure }
  217. current_ppu^.flush;
  218. { create and write header }
  219. current_ppu^.header.size:=current_ppu^.size;
  220. current_ppu^.header.checksum:=current_ppu^.crc;
  221. {$ifdef Double_checksum}
  222. current_module^.interface_crc:=current_ppu^.interface_crc;
  223. {$endif def Double_checksum}
  224. current_ppu^.header.compiler:=wordversion;
  225. current_ppu^.header.cpu:=word(target_cpu);
  226. current_ppu^.header.target:=word(target_info.target);
  227. current_ppu^.header.flags:=current_module^.flags;
  228. current_ppu^.writeheader;
  229. { save crc in current_module also }
  230. current_module^.crc:=current_ppu^.crc;
  231. {$ifdef Double_checksum}
  232. current_module^.interface_crc:=current_ppu^.interface_crc;
  233. if only_crc then
  234. begin
  235. {$ifdef Test_Double_checksum}
  236. Current_Module^.crc_array:=current_ppu^.crc_test;
  237. current_ppu^.crc_test:=nil;
  238. Current_Module^.crc_size:=current_ppu^.crc_index;
  239. {$endif def Test_Double_checksum}
  240. closecurrentppu;
  241. end;
  242. {$ifdef Test_Double_checksum_write}
  243. close(CRCFile);
  244. {$endif Test_Double_checksum_write}
  245. {$endif def Double_checksum}
  246. end;
  247. procedure closecurrentppu;
  248. begin
  249. {$ifdef Test_Double_checksum}
  250. if assigned(current_ppu^.crc_test) then
  251. dispose(current_ppu^.crc_test);
  252. {$endif Test_Double_checksum}
  253. { close }
  254. current_ppu^.close;
  255. dispose(current_ppu,done);
  256. current_ppu:=nil;
  257. end;
  258. {*****************************************************************************
  259. PPU Reading
  260. *****************************************************************************}
  261. function readbyte:byte;
  262. begin
  263. readbyte:=current_ppu^.getbyte;
  264. if current_ppu^.error then
  265. Message(unit_f_ppu_read_error);
  266. end;
  267. function readword:word;
  268. begin
  269. readword:=current_ppu^.getword;
  270. if current_ppu^.error then
  271. Message(unit_f_ppu_read_error);
  272. end;
  273. function readlong:longint;
  274. begin
  275. readlong:=current_ppu^.getlongint;
  276. if current_ppu^.error then
  277. Message(unit_f_ppu_read_error);
  278. end;
  279. function readreal : bestreal;
  280. begin
  281. readreal:=current_ppu^.getreal;
  282. if current_ppu^.error then
  283. Message(unit_f_ppu_read_error);
  284. end;
  285. function readstring : string;
  286. begin
  287. readstring:=current_ppu^.getstring;
  288. if current_ppu^.error then
  289. Message(unit_f_ppu_read_error);
  290. end;
  291. procedure readnormalset(var s); {You cannot pass an array [0..31] of byte.}
  292. begin
  293. current_ppu^.getdata(s,sizeof(tnormalset));
  294. if current_ppu^.error then
  295. Message(unit_f_ppu_read_error);
  296. end;
  297. procedure readcontainer(var p:tstringcontainer);
  298. begin
  299. while not current_ppu^.endofentry do
  300. p.insert(current_ppu^.getstring);
  301. end;
  302. procedure readposinfo(var p:tfileposinfo);
  303. begin
  304. p.fileindex:=current_ppu^.getword;
  305. p.line:=current_ppu^.getlongint;
  306. p.column:=current_ppu^.getword;
  307. end;
  308. function readdefref : pdef;
  309. var
  310. hd : pdef;
  311. begin
  312. longint(hd):=current_ppu^.getword;
  313. longint(hd):=longint(hd) or (longint(current_ppu^.getword) shl 16);
  314. readdefref:=hd;
  315. end;
  316. function readsymref : psym;
  317. var
  318. hd : psym;
  319. begin
  320. longint(hd):=current_ppu^.getword;
  321. longint(hd):=longint(hd) or (longint(current_ppu^.getword) shl 16);
  322. readsymref:=hd;
  323. end;
  324. procedure readsourcefiles;
  325. var
  326. temp,hs : string;
  327. incfile_found : boolean;
  328. ppufiletime,
  329. source_time : longint;
  330. hp : pinputfile;
  331. begin
  332. ppufiletime:=getnamedfiletime(current_module^.ppufilename^);
  333. current_module^.sources_avail:=true;
  334. while not current_ppu^.endofentry do
  335. begin
  336. hs:=current_ppu^.getstring;
  337. temp:='';
  338. if (current_module^.flags and uf_in_library)<>0 then
  339. begin
  340. current_module^.sources_avail:=false;
  341. temp:=' library';
  342. end
  343. else if pos('Macro ',hs)=1 then
  344. begin
  345. { we don't want to find this file }
  346. { but there is a problem with file indexing !! }
  347. temp:='';
  348. end
  349. else
  350. begin
  351. { check the date of the source files }
  352. Source_Time:=GetNamedFileTime(current_module^.path^+hs);
  353. incfile_found:=false;
  354. if (Source_Time=-1) then
  355. begin
  356. temp:=search(hs,includesearchpath,incfile_found);
  357. if incfile_found then
  358. begin
  359. hs:=temp+hs;
  360. Source_Time:=GetNamedFileTime(hs);
  361. end
  362. end
  363. else
  364. hs:=current_module^.path^+hs;
  365. if Source_Time=-1 then
  366. begin
  367. current_module^.sources_avail:=false;
  368. temp:=' not found';
  369. end
  370. else
  371. begin
  372. { time newer? But only allow if the file is not searched
  373. in the include path (PFV), else you've problems with
  374. units which use the same includefile names }
  375. if incfile_found then
  376. temp:=' found'
  377. else
  378. begin
  379. temp:=' time '+filetimestring(source_time);
  380. if (source_time>ppufiletime) then
  381. begin
  382. current_module^.do_compile:=true;
  383. temp:=temp+' *'
  384. end;
  385. end;
  386. end;
  387. new(hp,init(hs));
  388. { the indexing is wrong here PM }
  389. current_module^.sourcefiles^.register_file(hp);
  390. end;
  391. Message1(unit_u_ppu_source,hs+temp);
  392. end;
  393. { main source is always the last }
  394. stringdispose(current_module^.mainsource);
  395. current_module^.mainsource:=stringdup(hs);
  396. { the indexing is corrected here PM }
  397. current_module^.sourcefiles^.inverse_register_indexes;
  398. { check if we want to rebuild every unit, only if the sources are
  399. available }
  400. if do_build and current_module^.sources_avail then
  401. current_module^.do_compile:=true;
  402. end;
  403. procedure readloadunit;
  404. var
  405. hs : string;
  406. checksum : longint;
  407. in_interface : boolean;
  408. begin
  409. while not current_ppu^.endofentry do
  410. begin
  411. hs:=current_ppu^.getstring;
  412. checksum:=current_ppu^.getlongint;
  413. in_interface:=(current_ppu^.getbyte<>0);
  414. current_module^.used_units.concat(new(pused_unit,init_to_load(hs,checksum,in_interface)));
  415. end;
  416. end;
  417. procedure load_interface;
  418. var
  419. b : byte;
  420. begin
  421. { read interface part }
  422. repeat
  423. b:=current_ppu^.readentry;
  424. case b of
  425. ibmodulename : begin
  426. stringdispose(current_module^.modulename);
  427. current_module^.modulename:=stringdup(current_ppu^.getstring);
  428. end;
  429. ibsourcefiles : readsourcefiles;
  430. ibloadunit : readloadunit;
  431. iblinksharedlibs : readcontainer(current_module^.LinkSharedLibs);
  432. iblinkstaticlibs : readcontainer(current_module^.LinkStaticLibs);
  433. iblinkunitfiles : readcontainer(current_module^.LinkUnitFiles);
  434. iblinkofiles : readcontainer(current_module^.LinkOFiles);
  435. ibendinterface : break;
  436. else
  437. Message1(unit_f_ppu_invalid_entry,tostr(b));
  438. end;
  439. until false;
  440. end;
  441. {
  442. $Log$
  443. Revision 1.35 1999-04-07 15:39:35 pierre
  444. + double_checksum code added
  445. Revision 1.34 1999/03/02 13:49:19 peter
  446. * renamed loadunit_int -> loadunit
  447. Revision 1.33 1999/02/23 18:29:25 pierre
  448. * win32 compilation error fix
  449. + some work for local browser (not cl=omplete yet)
  450. Revision 1.32 1999/02/22 13:07:08 pierre
  451. + -b and -bl options work !
  452. + cs_local_browser ($L+) is disabled if cs_browser ($Y+)
  453. is not enabled when quitting global section
  454. * local vars and procedures are not yet stored into PPU
  455. Revision 1.31 1999/02/16 00:48:25 peter
  456. * save in the ppu if linked with obj file instead of using the
  457. library flag, so the .inc files are also checked
  458. Revision 1.30 1999/02/05 08:54:30 pierre
  459. + linkofiles splitted inot linkofiles and linkunitfiles
  460. because linkofiles must be stored with directory
  461. to enabled linking of different objects with same name
  462. in a different directory
  463. Revision 1.29 1999/01/20 10:16:46 peter
  464. * don't update crc when writing objs,libs and sources
  465. Revision 1.28 1999/01/12 14:25:35 peter
  466. + BrowserLog for browser.log generation
  467. + BrowserCol for browser info in TCollections
  468. * released all other UseBrowser
  469. Revision 1.27 1998/12/08 10:18:14 peter
  470. + -gh for heaptrc unit
  471. Revision 1.26 1998/11/26 14:36:02 peter
  472. * set also library flag if smartlinking and outputname is different
  473. Revision 1.25 1998/10/26 09:35:47 peter
  474. * don't count includefiles which are found in the includepath for a
  475. recompile.
  476. Revision 1.24 1998/10/20 08:06:59 pierre
  477. * several memory corruptions due to double freemem solved
  478. => never use p^.loc.location:=p^.left^.loc.location;
  479. + finally I added now by default
  480. that ra386dir translates global and unit symbols
  481. + added a first field in tsymtable and
  482. a nextsym field in tsym
  483. (this allows to obtain ordered type info for
  484. records and objects in gdb !)
  485. Revision 1.23 1998/10/16 13:37:24 florian
  486. + switch -FD added to specify the path for utilities
  487. Revision 1.22 1998/10/14 13:38:24 peter
  488. * fixed path with staticlib/objects in ppufiles
  489. Revision 1.21 1998/10/14 10:45:10 pierre
  490. * ppu problems for m68k fixed (at least in cross compiling)
  491. * one last memory leak for sysamiga fixed
  492. * the amiga RTL compiles now completely !!
  493. Revision 1.20 1998/10/13 13:10:30 peter
  494. * new style for m68k/i386 infos and enums
  495. Revision 1.19 1998/10/08 23:29:07 peter
  496. * -vu shows unit info, -vt shows tried/used files
  497. Revision 1.18 1998/09/28 16:57:27 pierre
  498. * changed all length(p^.value_str^) into str_length(p)
  499. to get it work with and without ansistrings
  500. * changed sourcefiles field of tmodule to a pointer
  501. Revision 1.17 1998/09/22 17:13:53 pierre
  502. + browsing updated and developed
  503. records and objects fields are also stored
  504. Revision 1.16 1998/09/22 15:40:56 peter
  505. * some extra ifdef GDB
  506. Revision 1.15 1998/09/21 08:45:23 pierre
  507. + added vmt_offset in tobjectdef.write for fututre use
  508. (first steps to have objects without vmt if no virtual !!)
  509. + added fpu_used field for tabstractprocdef :
  510. sets this level to 2 if the functions return with value in FPU
  511. (is then set to correct value at parsing of implementation)
  512. THIS MIGHT refuse some code with FPU expression too complex
  513. that were accepted before and even in some cases
  514. that don't overflow in fact
  515. ( like if f : float; is a forward that finally in implementation
  516. only uses one fpu register !!)
  517. Nevertheless I think that it will improve security on
  518. FPU operations !!
  519. * most other changes only for UseBrowser code
  520. (added symtable references for record and objects)
  521. local switch for refs to args and local of each function
  522. (static symtable still missing)
  523. UseBrowser still not stable and probably broken by
  524. the definition hash array !!
  525. Revision 1.14 1998/09/01 07:54:24 pierre
  526. * UseBrowser a little updated (might still be buggy !!)
  527. * bug in psub.pas in function specifier removed
  528. * stdcall allowed in interface and in implementation
  529. (FPC will not yet complain if it is missing in either part
  530. because stdcall is only a dummy !!)
  531. Revision 1.13 1998/08/17 10:10:11 peter
  532. - removed OLDPPU
  533. Revision 1.12 1998/08/17 09:17:53 peter
  534. * static/shared linking updates
  535. Revision 1.11 1998/08/16 20:32:49 peter
  536. * crcs of used units are not important for the current crc, reduces the
  537. amount of recompiles
  538. Revision 1.10 1998/08/13 10:57:30 peter
  539. * constant sets are now written correctly to the ppufile
  540. Revision 1.9 1998/08/11 15:31:41 peter
  541. * write extended to ppu file
  542. * new version 0.99.7
  543. Revision 1.8 1998/08/10 14:50:29 peter
  544. + localswitches, moduleswitches, globalswitches splitting
  545. Revision 1.7 1998/07/14 14:47:07 peter
  546. * released NEWINPUT
  547. Revision 1.6 1998/07/07 11:20:14 peter
  548. + NEWINPUT for a better inputfile and scanner object
  549. Revision 1.5 1998/06/24 14:48:39 peter
  550. * ifdef newppu -> ifndef oldppu
  551. Revision 1.4 1998/06/16 08:56:32 peter
  552. + targetcpu
  553. * cleaner pmodules for newppu
  554. Revision 1.3 1998/06/13 00:10:17 peter
  555. * working browser and newppu
  556. * some small fixes against crashes which occured in bp7 (but not in
  557. fpc?!)
  558. Revision 1.2 1998/05/28 14:40:28 peter
  559. * fixes for newppu, remake3 works now with it
  560. Revision 1.1 1998/05/27 19:45:09 peter
  561. * symtable.pas splitted into includefiles
  562. * symtable adapted for $ifdef NEWPPU
  563. }