t_os2.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Daniel Mantione
  4. Portions Copyright (c) 1998-2000 Eberhard Mattes
  5. Unit to write out import libraries and def files for OS/2
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. {
  20. A lot of code in this unit has been ported from C to Pascal from the
  21. emximp utility, part of the EMX development system. Emximp is copyrighted
  22. by Eberhard Mattes. Note: Eberhard doesn't know much about the Pascal
  23. port, please send questions to Daniel Mantione
  24. <[email protected]>.
  25. }
  26. unit t_os2;
  27. {$i defines.inc}
  28. interface
  29. implementation
  30. uses
  31. {$ifdef Delphi}
  32. sysutils,
  33. dmisc,
  34. {$else Delphi}
  35. strings,
  36. dos,
  37. {$endif Delphi}
  38. cutils,cclasses,
  39. globtype,comphook,systems,symsym,
  40. globals,verbose,fmodule,script,
  41. import,link,comprsrc;
  42. type
  43. timportlibos2=class(timportlib)
  44. procedure preparelib(const s:string);override;
  45. procedure importprocedure(const func,module:string;index:longint;const name:string);override;
  46. procedure generatelib;override;
  47. end;
  48. tlinkeros2=class(tlinker)
  49. private
  50. Function WriteResponseFile(isdll:boolean) : Boolean;
  51. public
  52. constructor Create;override;
  53. procedure SetDefaultInfo;override;
  54. function MakeExecutable:boolean;override;
  55. end;
  56. const profile_flag:boolean=false;
  57. const n_ext = 1;
  58. n_abs = 2;
  59. n_text = 4;
  60. n_data = 6;
  61. n_bss = 8;
  62. n_imp1 = $68;
  63. n_imp2 = $6a;
  64. type reloc=packed record {This is the layout of a relocation table
  65. entry.}
  66. address:longint; {Fixup location}
  67. remaining:longint;
  68. {Meaning of bits for remaining:
  69. 0..23: Symbol number or segment
  70. 24: Self-relative fixup if non-zero
  71. 25..26: Fixup size (0: 1 byte, 1: 2, 2: 4 bytes)
  72. 27: Reference to symbol or segment
  73. 28..31 Not used}
  74. end;
  75. nlist=packed record {This is the layout of a symbol table entry.}
  76. strofs:longint; {Offset in string table}
  77. typ:byte; {Type of the symbol}
  78. other:byte; {Other information}
  79. desc:word; {More information}
  80. value:longint; {Value (address)}
  81. end;
  82. a_out_header=packed record
  83. magic:word; {Magic word, must be $0107}
  84. machtype:byte; {Machine type}
  85. flags:byte; {Flags}
  86. text_size:longint; {Length of text, in bytes}
  87. data_size:longint; {Length of initialized data, in bytes}
  88. bss_size:longint; {Length of uninitialized data, in bytes}
  89. sym_size:longint; {Length of symbol table, in bytes}
  90. entry:longint; {Start address (entry point)}
  91. trsize:longint; {Length of relocation info for text, bytes}
  92. drsize:longint; {Length of relocation info for data, bytes}
  93. end;
  94. ar_hdr=packed record
  95. ar_name:array[0..15] of char;
  96. ar_date:array[0..11] of char;
  97. ar_uid:array[0..5] of char;
  98. ar_gid:array[0..5] of char;
  99. ar_mode:array[0..7] of char;
  100. ar_size:array[0..9] of char;
  101. ar_fmag:array[0..1] of char;
  102. end;
  103. var aout_str_size:longint;
  104. aout_str_tab:array[0..2047] of byte;
  105. aout_sym_count:longint;
  106. aout_sym_tab:array[0..5] of nlist;
  107. aout_text:array[0..63] of byte;
  108. aout_text_size:longint;
  109. aout_treloc_tab:array[0..1] of reloc;
  110. aout_treloc_count:longint;
  111. aout_size:longint;
  112. seq_no:longint;
  113. ar_member_size:longint;
  114. out_file:file;
  115. procedure write_ar(const name:string;size:longint);
  116. var ar:ar_hdr;
  117. time:datetime;
  118. dummy:word;
  119. numtime:longint;
  120. tmp:string[19];
  121. begin
  122. ar_member_size:=size;
  123. fillchar(ar.ar_name,sizeof(ar.ar_name),' ');
  124. move(name[1],ar.ar_name,length(name));
  125. getdate(time.year,time.month,time.day,dummy);
  126. gettime(time.hour,time.min,time.sec,dummy);
  127. packtime(time,numtime);
  128. str(numtime,tmp);
  129. fillchar(ar.ar_date,sizeof(ar.ar_date),' ');
  130. move(tmp[1],ar.ar_date,length(tmp));
  131. ar.ar_uid:='0 ';
  132. ar.ar_gid:='0 ';
  133. ar.ar_mode:='100666'#0#0;
  134. str(size,tmp);
  135. fillchar(ar.ar_size,sizeof(ar.ar_size),' ');
  136. move(tmp[1],ar.ar_size,length(tmp));
  137. ar.ar_fmag:='`'#10;
  138. blockwrite(out_file,ar,sizeof(ar));
  139. end;
  140. procedure finish_ar;
  141. var a:byte;
  142. begin
  143. a:=0;
  144. if odd(ar_member_size) then
  145. blockwrite(out_file,a,1);
  146. end;
  147. procedure aout_init;
  148. begin
  149. aout_str_size:=sizeof(longint);
  150. aout_sym_count:=0;
  151. aout_text_size:=0;
  152. aout_treloc_count:=0;
  153. end;
  154. function aout_sym(const name:string;typ,other:byte;desc:word;
  155. value:longint):longint;
  156. begin
  157. if aout_str_size+length(name)+1>sizeof(aout_str_tab) then
  158. Do_halt($da);
  159. if aout_sym_count>=sizeof(aout_sym_tab) div sizeof(aout_sym_tab[0]) then
  160. Do_halt($da);
  161. aout_sym_tab[aout_sym_count].strofs:=aout_str_size;
  162. aout_sym_tab[aout_sym_count].typ:=typ;
  163. aout_sym_tab[aout_sym_count].other:=other;
  164. aout_sym_tab[aout_sym_count].desc:=desc;
  165. aout_sym_tab[aout_sym_count].value:=value;
  166. strPcopy(@aout_str_tab[aout_str_size],name);
  167. aout_str_size:=aout_str_size+length(name)+1;
  168. aout_sym:=aout_sym_count;
  169. inc(aout_sym_count);
  170. end;
  171. procedure aout_text_byte(b:byte);
  172. begin
  173. if aout_text_size>=sizeof(aout_text) then
  174. Do_halt($da);
  175. aout_text[aout_text_size]:=b;
  176. inc(aout_text_size);
  177. end;
  178. procedure aout_text_dword(d:longint);
  179. type li_ar=array[0..3] of byte;
  180. begin
  181. aout_text_byte(li_ar(d)[0]);
  182. aout_text_byte(li_ar(d)[1]);
  183. aout_text_byte(li_ar(d)[2]);
  184. aout_text_byte(li_ar(d)[3]);
  185. end;
  186. procedure aout_treloc(address,symbolnum,pcrel,len,ext:longint);
  187. begin
  188. if aout_treloc_count>=sizeof(aout_treloc_tab) div sizeof(reloc) then
  189. Do_halt($da);
  190. aout_treloc_tab[aout_treloc_count].address:=address;
  191. aout_treloc_tab[aout_treloc_count].remaining:=symbolnum+pcrel shl 24+
  192. len shl 25+ext shl 27;
  193. inc(aout_treloc_count);
  194. end;
  195. procedure aout_finish;
  196. begin
  197. while (aout_text_size and 3)<>0 do
  198. aout_text_byte ($90);
  199. aout_size:=sizeof(a_out_header)+aout_text_size+aout_treloc_count*
  200. sizeof(reloc)+aout_sym_count*sizeof(aout_sym_tab[0])+aout_str_size;
  201. end;
  202. procedure aout_write;
  203. var ao:a_out_header;
  204. begin
  205. ao.magic:=$0107;
  206. ao.machtype:=0;
  207. ao.flags:=0;
  208. ao.text_size:=aout_text_size;
  209. ao.data_size:=0;
  210. ao.bss_size:=0;
  211. ao.sym_size:=aout_sym_count*sizeof(aout_sym_tab[0]);
  212. ao.entry:=0;
  213. ao.trsize:=aout_treloc_count*sizeof(reloc);
  214. ao.drsize:=0;
  215. blockwrite(out_file,ao,sizeof(ao));
  216. blockwrite(out_file,aout_text,aout_text_size);
  217. blockwrite(out_file,aout_treloc_tab,sizeof(reloc)*aout_treloc_count);
  218. blockwrite(out_file,aout_sym_tab,sizeof(aout_sym_tab[0])*aout_sym_count);
  219. longint((@aout_str_tab)^):=aout_str_size;
  220. blockwrite(out_file,aout_str_tab,aout_str_size);
  221. end;
  222. procedure timportlibos2.preparelib(const s:string);
  223. {This code triggers a lot of bugs in the compiler.
  224. const armag='!<arch>'#10;
  225. ar_magic:array[1..length(armag)] of char=armag;}
  226. const ar_magic:array[1..8] of char='!<arch>'#10;
  227. var
  228. libname : string;
  229. begin
  230. libname:=FixFileName(s+'.ao2');
  231. seq_no:=1;
  232. current_module.linkunitstaticlibs.add(libname,link_allways);
  233. assign(out_file,current_module.outputpath^+libname);
  234. rewrite(out_file,1);
  235. blockwrite(out_file,ar_magic,sizeof(ar_magic));
  236. end;
  237. procedure timportlibos2.importprocedure(const func,module:string;index:longint;const name:string);
  238. {func = Name of function to import.
  239. module = Name of DLL to import from.
  240. index = Index of function in DLL. Use 0 to import by name.
  241. name = Name of function in DLL. Ignored when index=0;}
  242. var tmp1,tmp2,tmp3:string;
  243. sym_mcount,sym_import:longint;
  244. fixup_mcount,fixup_import:longint;
  245. begin
  246. { force the current mangledname }
  247. aktprocdef.has_mangledname:=true;
  248. aout_init;
  249. tmp2:=func;
  250. if profile_flag and not (copy(func,1,4)='_16_') then
  251. begin
  252. {sym_entry:=aout_sym(func,n_text+n_ext,0,0,aout_text_size);}
  253. sym_mcount:=aout_sym('__mcount',n_ext,0,0,0);
  254. {Use, say, "_$U_DosRead" for "DosRead" to import the
  255. non-profiled function.}
  256. tmp2:='__$U_'+func;
  257. sym_import:=aout_sym(tmp2,n_ext,0,0,0);
  258. aout_text_byte($55); {push ebp}
  259. aout_text_byte($89); {mov ebp, esp}
  260. aout_text_byte($e5);
  261. aout_text_byte($e8); {call _mcount}
  262. fixup_mcount:=aout_text_size;
  263. aout_text_dword(0-(aout_text_size+4));
  264. aout_text_byte($5d); {pop ebp}
  265. aout_text_byte($e9); {jmp _$U_DosRead}
  266. fixup_import:=aout_text_size;
  267. aout_text_dword(0-(aout_text_size+4));
  268. aout_treloc(fixup_mcount,sym_mcount,1,2,1);
  269. aout_treloc (fixup_import, sym_import,1,2,1);
  270. end;
  271. str(seq_no,tmp1);
  272. tmp1:='IMPORT#'+tmp1;
  273. if name='' then
  274. begin
  275. str(index,tmp3);
  276. tmp3:=func+'='+module+'.'+tmp3;
  277. end
  278. else
  279. tmp3:=func+'='+module+'.'+name;
  280. aout_sym(tmp2,n_imp1+n_ext,0,0,0);
  281. aout_sym(tmp3,n_imp2+n_ext,0,0,0);
  282. aout_finish;
  283. write_ar(tmp1,aout_size);
  284. aout_write;
  285. finish_ar;
  286. inc(seq_no);
  287. end;
  288. procedure timportlibos2.generatelib;
  289. begin
  290. close(out_file);
  291. end;
  292. {****************************************************************************
  293. TLinkeros2
  294. ****************************************************************************}
  295. Constructor TLinkeros2.Create;
  296. begin
  297. Inherited Create;
  298. { allow duplicated libs (PM) }
  299. SharedLibFiles.doubles:=true;
  300. StaticLibFiles.doubles:=true;
  301. end;
  302. procedure TLinkeros2.SetDefaultInfo;
  303. begin
  304. with Info do
  305. begin
  306. ExeCmd[1]:='ld $OPT -o $EXE.out @$RES';
  307. ExeCmd[2]:='emxbind -b $STRIP $APPTYPE $RSRC -k$STACKKB -h$HEAPMB -o $EXE.exe $EXE.out -aim -s$DOSHEAPKB';
  308. ExeCmd[3]:='del $EXE.out';
  309. end;
  310. end;
  311. Function TLinkeros2.WriteResponseFile(isdll:boolean) : Boolean;
  312. Var
  313. linkres : TLinkRes;
  314. i : longint;
  315. HPath : TStringListItem;
  316. s : string;
  317. begin
  318. WriteResponseFile:=False;
  319. { Open link.res file }
  320. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  321. { Write path to search libraries }
  322. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  323. while assigned(HPath) do
  324. begin
  325. LinkRes.Add('-L'+HPath.Str);
  326. HPath:=TStringListItem(HPath.Next);
  327. end;
  328. HPath:=TStringListItem(LibrarySearchPath.First);
  329. while assigned(HPath) do
  330. begin
  331. LinkRes.Add('-L'+HPath.Str);
  332. HPath:=TStringListItem(HPath.Next);
  333. end;
  334. { add objectfiles, start with prt0 always }
  335. LinkRes.AddFileName(FindObjectFile('prt0',''));
  336. while not ObjectFiles.Empty do
  337. begin
  338. s:=ObjectFiles.GetFirst;
  339. if s<>'' then
  340. LinkRes.AddFileName(s);
  341. end;
  342. { Write staticlibraries }
  343. { No group !! This will not work correctly PM }
  344. While not StaticLibFiles.Empty do
  345. begin
  346. S:=StaticLibFiles.GetFirst;
  347. LinkRes.AddFileName(s)
  348. end;
  349. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  350. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  351. While not SharedLibFiles.Empty do
  352. begin
  353. S:=SharedLibFiles.GetFirst;
  354. i:=Pos(target_info.sharedlibext,S);
  355. if i>0 then
  356. Delete(S,i,255);
  357. LinkRes.Add('-l'+s);
  358. end;
  359. { Write and Close response }
  360. linkres.writetodisk;
  361. LinkRes.Free;
  362. WriteResponseFile:=True;
  363. end;
  364. function TLinkeros2.MakeExecutable:boolean;
  365. var
  366. binstr,
  367. cmdstr : string;
  368. success : boolean;
  369. i : longint;
  370. AppTypeStr,
  371. StripStr: string[40];
  372. RsrcStr : string;
  373. begin
  374. if not(cs_link_extern in aktglobalswitches) then
  375. Message1(exec_i_linking,current_module.exefilename^);
  376. { Create some replacements }
  377. if (cs_link_strip in aktglobalswitches) then
  378. StripStr := '-s'
  379. else
  380. StripStr := '';
  381. if (usewindowapi) or (AppType = app_gui) then
  382. AppTypeStr := '-p'
  383. else if AppType = app_fs then
  384. AppTypeStr := '-f'
  385. else AppTypeStr := '-w';
  386. if not (Current_module.ResourceFiles.Empty) then
  387. RsrcStr := '-r ' + Current_module.ResourceFiles.GetFirst
  388. else
  389. RsrcStr := '';
  390. (* Only one resource file supported, discard everything else
  391. (should be already empty anyway, however. *)
  392. Current_module.ResourceFiles.Clear;
  393. { Write used files and libraries }
  394. WriteResponseFile(false);
  395. { Call linker }
  396. success:=false;
  397. for i:=1 to 3 do
  398. begin
  399. SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
  400. if binstr<>'' then
  401. begin
  402. Replace(cmdstr,'$HEAPMB',tostr((maxheapsize+1048575) shr 20));
  403. {Size of the stack when an EMX program runs in OS/2.}
  404. Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
  405. {When an EMX program runs in DOS, the heap and stack share the
  406. same memory pool. The heap grows upwards, the stack grows downwards.}
  407. Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+maxheapsize+1023) shr 10));
  408. Replace(cmdstr,'$STRIP',StripStr);
  409. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  410. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  411. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  412. Replace(cmdstr,'$RSRC',RsrcStr);
  413. Replace(cmdstr,'$EXE',current_module.exefilename^);
  414. if i<>3 then
  415. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false)
  416. else
  417. success:=DoExec(binstr,cmdstr,(i=1),true);
  418. (* We still want to have the PPAS script complete, right?
  419. if not success then
  420. break;
  421. *)
  422. end;
  423. end;
  424. { Remove ReponseFile }
  425. if (success) and not(cs_link_extern in aktglobalswitches) then
  426. RemoveFile(outputexedir+Info.ResName);
  427. MakeExecutable:=success; { otherwise a recursive call to link method }
  428. end;
  429. {*****************************************************************************
  430. Initialize
  431. *****************************************************************************}
  432. const
  433. res_emxbind_info : tresinfo =
  434. (
  435. id : res_emxbind;
  436. resbin : 'emxbind';
  437. rescmd : '-b -r $RES $OBJ'
  438. (* Not really used - see TLinkeros2.SetDefaultInfo in t_os2.pas. *)
  439. );
  440. const
  441. target_i386_os2_info : ttargetinfo =
  442. (
  443. target : target_i386_OS2;
  444. name : 'OS/2 via EMX';
  445. shortname : 'OS2';
  446. flags : [tf_need_export];
  447. cpu : i386;
  448. unit_env : 'OS2UNITS';
  449. extradefines : '';
  450. sourceext : '.pas';
  451. pasext : '.pp';
  452. exeext : '.exe';
  453. defext : '.def';
  454. scriptext : '.cmd';
  455. smartext : '.sl';
  456. unitext : '.ppo';
  457. unitlibext : '.ppl';
  458. asmext : '.so2';
  459. objext : '.oo2';
  460. resext : '.res';
  461. resobjext : '.oor';
  462. sharedlibext : '.ao2';
  463. staticlibext : '.ao2';
  464. staticlibprefix : '';
  465. sharedlibprefix : '';
  466. sharedClibext : 'dll';
  467. staticClibext : '.a';
  468. staticClibprefix : '';
  469. sharedClibprefix : '';
  470. Cprefix : '_';
  471. newline : #13#10;
  472. dirsep : '\';
  473. files_case_relevent : false;
  474. assem : as_i386_as_aout;
  475. assemextern : as_i386_as_aout;
  476. link : ld_i386_os2;
  477. linkextern : ld_i386_os2;
  478. ar : ar_gnu_ar;
  479. res : res_emxbind;
  480. script : script_dos;
  481. endian : endian_little;
  482. alignment :
  483. (
  484. procalign : 4;
  485. loopalign : 4;
  486. jumpalign : 0;
  487. constalignmin : 0;
  488. constalignmax : 4;
  489. varalignmin : 0;
  490. varalignmax : 4;
  491. localalignmin : 0;
  492. localalignmax : 4;
  493. paraalign : 4;
  494. recordalignmin : 0;
  495. recordalignmax : 2;
  496. maxCrecordalign : 4
  497. );
  498. size_of_pointer : 4;
  499. size_of_longint : 4;
  500. heapsize : 256*1024;
  501. maxheapsize : 32768*1024;
  502. stacksize : 256*1024;
  503. DllScanSupported:true;
  504. use_bound_instruction : false;
  505. use_function_relative_addresses : false
  506. );
  507. initialization
  508. RegisterLinker(ld_i386_os2,TLinkerOS2);
  509. RegisterImport(target_i386_os2,TImportLibOS2);
  510. RegisterRes(res_emxbind_info);
  511. RegisterTarget(target_i386_os2_info);
  512. end.
  513. {
  514. $Log$
  515. Revision 1.14 2002-01-29 21:27:34 peter
  516. * default alignment changed to 4 bytes for locals and static const,var
  517. Revision 1.12 2002/01/27 12:58:42 hajny
  518. * fix for a problem with importprocedure
  519. Revision 1.11 2001/09/18 11:32:00 michael
  520. * Fixes win32 linking problems with import libraries
  521. * LINKLIB Libraries are now looked for using C file extensions
  522. * get_exepath fix
  523. Revision 1.10 2001/09/17 21:29:16 peter
  524. * merged netbsd, fpu-overflow from fixes branch
  525. Revision 1.9 2001/08/07 18:47:15 peter
  526. * merged netbsd start
  527. * profile for win32
  528. Revision 1.8 2001/07/01 20:16:20 peter
  529. * alignmentinfo record added
  530. * -Oa argument supports more alignment settings that can be specified
  531. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  532. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  533. required alignment and the maximum usefull alignment. The final
  534. alignment will be choosen per variable size dependent on these
  535. settings
  536. Revision 1.7 2001/06/28 19:46:25 peter
  537. * added override and virtual for constructors
  538. Revision 1.6 2001/06/03 15:15:32 peter
  539. * dllprt0 stub for linux shared libs
  540. * pass -init and -fini for linux shared libs
  541. * libprefix splitted into staticlibprefix and sharedlibprefix
  542. Revision 1.5 2001/06/02 19:22:44 peter
  543. * extradefines field added
  544. Revision 1.4 2001/04/18 22:02:04 peter
  545. * registration of targets and assemblers
  546. Revision 1.3 2001/04/13 01:22:22 peter
  547. * symtable change to classes
  548. * range check generation and errors fixed, make cycle DEBUG=1 works
  549. * memory leaks fixed
  550. Revision 1.2 2001/02/27 19:40:05 hajny
  551. * a.out deleted upon successful binding
  552. Revision 1.1 2001/02/26 19:43:11 peter
  553. * moved target units to subdir
  554. Revision 1.7 2001/01/20 18:32:52 hajny
  555. + APPTYPE support under OS/2, app_fs, GetEnvPChar for OS/2
  556. Revision 1.6 2000/12/25 00:07:30 peter
  557. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  558. tlinkedlist objects)
  559. Revision 1.5 2000/09/24 15:06:31 peter
  560. * use defines.inc
  561. Revision 1.4 2000/09/20 19:38:34 peter
  562. * fixed staticlib filename and unitlink instead of otherlinky
  563. Revision 1.3 2000/08/27 16:11:54 peter
  564. * moved some util functions from globals,cobjects to cutils
  565. * splitted files into finput,fmodule
  566. Revision 1.2 2000/07/13 11:32:50 michael
  567. + removed logs
  568. }