t_os2.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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,
  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. aout_init;
  247. tmp2:=func;
  248. if profile_flag and not (copy(func,1,4)='_16_') then
  249. begin
  250. {sym_entry:=aout_sym(func,n_text+n_ext,0,0,aout_text_size);}
  251. sym_mcount:=aout_sym('__mcount',n_ext,0,0,0);
  252. {Use, say, "_$U_DosRead" for "DosRead" to import the
  253. non-profiled function.}
  254. tmp2:='__$U_'+func;
  255. sym_import:=aout_sym(tmp2,n_ext,0,0,0);
  256. aout_text_byte($55); {push ebp}
  257. aout_text_byte($89); {mov ebp, esp}
  258. aout_text_byte($e5);
  259. aout_text_byte($e8); {call _mcount}
  260. fixup_mcount:=aout_text_size;
  261. aout_text_dword(0-(aout_text_size+4));
  262. aout_text_byte($5d); {pop ebp}
  263. aout_text_byte($e9); {jmp _$U_DosRead}
  264. fixup_import:=aout_text_size;
  265. aout_text_dword(0-(aout_text_size+4));
  266. aout_treloc(fixup_mcount,sym_mcount,1,2,1);
  267. aout_treloc (fixup_import, sym_import,1,2,1);
  268. end;
  269. str(seq_no,tmp1);
  270. tmp1:='IMPORT#'+tmp1;
  271. if name='' then
  272. begin
  273. str(index,tmp3);
  274. tmp3:=func+'='+module+'.'+tmp3;
  275. end
  276. else
  277. tmp3:=func+'='+module+'.'+name;
  278. aout_sym(tmp2,n_imp1+n_ext,0,0,0);
  279. aout_sym(tmp3,n_imp2+n_ext,0,0,0);
  280. aout_finish;
  281. write_ar(tmp1,aout_size);
  282. aout_write;
  283. finish_ar;
  284. inc(seq_no);
  285. end;
  286. procedure timportlibos2.generatelib;
  287. begin
  288. close(out_file);
  289. end;
  290. {****************************************************************************
  291. TLinkeros2
  292. ****************************************************************************}
  293. Constructor TLinkeros2.Create;
  294. begin
  295. Inherited Create;
  296. { allow duplicated libs (PM) }
  297. SharedLibFiles.doubles:=true;
  298. StaticLibFiles.doubles:=true;
  299. end;
  300. procedure TLinkeros2.SetDefaultInfo;
  301. begin
  302. with Info do
  303. begin
  304. ExeCmd[1]:='ld $OPT -o $EXE.out @$RES';
  305. ExeCmd[2]:='emxbind -b $STRIP $APPTYPE $RSRC -k$STACKKB -h$HEAPMB -o $EXE.exe $EXE.out -aim -s$DOSHEAPKB';
  306. ExeCmd[3]:='del $EXE.out';
  307. end;
  308. end;
  309. Function TLinkeros2.WriteResponseFile(isdll:boolean) : Boolean;
  310. Var
  311. linkres : TLinkRes;
  312. i : longint;
  313. HPath : TStringListItem;
  314. s : string;
  315. begin
  316. WriteResponseFile:=False;
  317. { Open link.res file }
  318. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  319. { Write path to search libraries }
  320. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  321. while assigned(HPath) do
  322. begin
  323. LinkRes.Add('-L'+HPath.Str);
  324. HPath:=TStringListItem(HPath.Next);
  325. end;
  326. HPath:=TStringListItem(LibrarySearchPath.First);
  327. while assigned(HPath) do
  328. begin
  329. LinkRes.Add('-L'+HPath.Str);
  330. HPath:=TStringListItem(HPath.Next);
  331. end;
  332. { add objectfiles, start with prt0 always }
  333. LinkRes.AddFileName(FindObjectFile('prt0',''));
  334. while not ObjectFiles.Empty do
  335. begin
  336. s:=ObjectFiles.GetFirst;
  337. if s<>'' then
  338. LinkRes.AddFileName(s);
  339. end;
  340. { Write staticlibraries }
  341. { No group !! This will not work correctly PM }
  342. While not StaticLibFiles.Empty do
  343. begin
  344. S:=StaticLibFiles.GetFirst;
  345. LinkRes.AddFileName(s)
  346. end;
  347. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  348. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  349. While not SharedLibFiles.Empty do
  350. begin
  351. S:=SharedLibFiles.GetFirst;
  352. i:=Pos(target_info.sharedlibext,S);
  353. if i>0 then
  354. Delete(S,i,255);
  355. LinkRes.Add('-l'+s);
  356. end;
  357. { Write and Close response }
  358. linkres.writetodisk;
  359. LinkRes.Free;
  360. WriteResponseFile:=True;
  361. end;
  362. function TLinkeros2.MakeExecutable:boolean;
  363. var
  364. binstr,
  365. cmdstr : string;
  366. success : boolean;
  367. i : longint;
  368. AppTypeStr,
  369. StripStr: string[40];
  370. RsrcStr : string;
  371. begin
  372. if not(cs_link_extern in aktglobalswitches) then
  373. Message1(exec_i_linking,current_module.exefilename^);
  374. { Create some replacements }
  375. if (cs_link_strip in aktglobalswitches) then
  376. StripStr := '-s'
  377. else
  378. StripStr := '';
  379. if (usewindowapi) or (AppType = app_gui) then
  380. AppTypeStr := '-p'
  381. else if AppType = app_fs then
  382. AppTypeStr := '-f'
  383. else AppTypeStr := '-w';
  384. if not (Current_module.ResourceFiles.Empty) then
  385. RsrcStr := '-r ' + Current_module.ResourceFiles.GetFirst
  386. else
  387. RsrcStr := '';
  388. (* Only one resource file supported, discard everything else
  389. (should be already empty anyway, however. *)
  390. Current_module.ResourceFiles.Clear;
  391. { Write used files and libraries }
  392. WriteResponseFile(false);
  393. { Call linker }
  394. success:=false;
  395. for i:=1 to 3 do
  396. begin
  397. SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
  398. if binstr<>'' then
  399. begin
  400. Replace(cmdstr,'$HEAPMB',tostr((maxheapsize+1048575) shr 20));
  401. {Size of the stack when an EMX program runs in OS/2.}
  402. Replace(cmdstr,'$STACKKB',tostr((stacksize+1023) shr 10));
  403. {When an EMX program runs in DOS, the heap and stack share the
  404. same memory pool. The heap grows upwards, the stack grows downwards.}
  405. Replace(cmdstr,'$DOSHEAPKB',tostr((stacksize+maxheapsize+1023) shr 10));
  406. Replace(cmdstr,'$STRIP',StripStr);
  407. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  408. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  409. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  410. Replace(cmdstr,'$RSRC',RsrcStr);
  411. Replace(cmdstr,'$EXE',current_module.exefilename^);
  412. if i<>3 then
  413. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false)
  414. else
  415. success:=DoExec(binstr,cmdstr,(i=1),true);
  416. (* We still want to have the PPAS script complete, right?
  417. if not success then
  418. break;
  419. *)
  420. end;
  421. end;
  422. { Remove ReponseFile }
  423. if (success) and not(cs_link_extern in aktglobalswitches) then
  424. RemoveFile(outputexedir+Info.ResName);
  425. MakeExecutable:=success; { otherwise a recursive call to link method }
  426. end;
  427. {*****************************************************************************
  428. Initialize
  429. *****************************************************************************}
  430. const
  431. res_emxbind_info : tresinfo =
  432. (
  433. id : res_emxbind;
  434. resbin : 'emxbind';
  435. rescmd : '-b -r $RES $OBJ'
  436. (* Not really used - see TLinkeros2.SetDefaultInfo in t_os2.pas. *)
  437. );
  438. const
  439. target_i386_os2_info : ttargetinfo =
  440. (
  441. target : target_i386_OS2;
  442. name : 'OS/2 via EMX';
  443. shortname : 'OS2';
  444. flags : [tf_need_export];
  445. cpu : i386;
  446. unit_env : 'OS2UNITS';
  447. extradefines : '';
  448. sourceext : '.pas';
  449. pasext : '.pp';
  450. exeext : '.exe';
  451. defext : '.def';
  452. scriptext : '.cmd';
  453. smartext : '.sl';
  454. unitext : '.ppo';
  455. unitlibext : '.ppl';
  456. asmext : '.so2';
  457. objext : '.oo2';
  458. resext : '.res';
  459. resobjext : '.oor';
  460. sharedlibext : '.ao2';
  461. staticlibext : '.ao2';
  462. staticlibprefix : '';
  463. sharedlibprefix : '';
  464. sharedClibext : 'dll';
  465. staticClibext : '.a';
  466. staticClibprefix : '';
  467. sharedClibprefix : '';
  468. Cprefix : '_';
  469. newline : #13#10;
  470. dirsep : '\';
  471. files_case_relevent : false;
  472. assem : as_i386_as_aout;
  473. assemextern : as_i386_as_aout;
  474. link : ld_i386_os2;
  475. linkextern : ld_i386_os2;
  476. ar : ar_gnu_ar;
  477. res : res_emxbind;
  478. script : script_dos;
  479. endian : endian_little;
  480. alignment :
  481. (
  482. procalign : 4;
  483. loopalign : 4;
  484. jumpalign : 0;
  485. constalignmin : 0;
  486. constalignmax : 1;
  487. varalignmin : 0;
  488. varalignmax : 1;
  489. localalignmin : 0;
  490. localalignmax : 1;
  491. paraalign : 4;
  492. recordalignmin : 0;
  493. recordalignmax : 2;
  494. maxCrecordalign : 4
  495. );
  496. size_of_pointer : 4;
  497. size_of_longint : 4;
  498. heapsize : 256*1024;
  499. maxheapsize : 32768*1024;
  500. stacksize : 256*1024;
  501. DllScanSupported:true;
  502. use_bound_instruction : false;
  503. use_function_relative_addresses : false
  504. );
  505. initialization
  506. RegisterLinker(ld_i386_os2,TLinkerOS2);
  507. RegisterImport(target_i386_os2,TImportLibOS2);
  508. RegisterRes(res_emxbind_info);
  509. RegisterTarget(target_i386_os2_info);
  510. end.
  511. {
  512. $Log$
  513. Revision 1.11 2001-09-18 11:32:00 michael
  514. * Fixes win32 linking problems with import libraries
  515. * LINKLIB Libraries are now looked for using C file extensions
  516. * get_exepath fix
  517. Revision 1.10 2001/09/17 21:29:16 peter
  518. * merged netbsd, fpu-overflow from fixes branch
  519. Revision 1.9 2001/08/07 18:47:15 peter
  520. * merged netbsd start
  521. * profile for win32
  522. Revision 1.8 2001/07/01 20:16:20 peter
  523. * alignmentinfo record added
  524. * -Oa argument supports more alignment settings that can be specified
  525. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  526. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  527. required alignment and the maximum usefull alignment. The final
  528. alignment will be choosen per variable size dependent on these
  529. settings
  530. Revision 1.7 2001/06/28 19:46:25 peter
  531. * added override and virtual for constructors
  532. Revision 1.6 2001/06/03 15:15:32 peter
  533. * dllprt0 stub for linux shared libs
  534. * pass -init and -fini for linux shared libs
  535. * libprefix splitted into staticlibprefix and sharedlibprefix
  536. Revision 1.5 2001/06/02 19:22:44 peter
  537. * extradefines field added
  538. Revision 1.4 2001/04/18 22:02:04 peter
  539. * registration of targets and assemblers
  540. Revision 1.3 2001/04/13 01:22:22 peter
  541. * symtable change to classes
  542. * range check generation and errors fixed, make cycle DEBUG=1 works
  543. * memory leaks fixed
  544. Revision 1.2 2001/02/27 19:40:05 hajny
  545. * a.out deleted upon successful binding
  546. Revision 1.1 2001/02/26 19:43:11 peter
  547. * moved target units to subdir
  548. Revision 1.7 2001/01/20 18:32:52 hajny
  549. + APPTYPE support under OS/2, app_fs, GetEnvPChar for OS/2
  550. Revision 1.6 2000/12/25 00:07:30 peter
  551. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  552. tlinkedlist objects)
  553. Revision 1.5 2000/09/24 15:06:31 peter
  554. * use defines.inc
  555. Revision 1.4 2000/09/20 19:38:34 peter
  556. * fixed staticlib filename and unitlink instead of otherlinky
  557. Revision 1.3 2000/08/27 16:11:54 peter
  558. * moved some util functions from globals,cobjects to cutils
  559. * splitted files into finput,fmodule
  560. Revision 1.2 2000/07/13 11:32:50 michael
  561. + removed logs
  562. }