symppu.inc 21 KB

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