t_nwl.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. {
  2. Copyright (c) 1998-2004 by Peter Vreman
  3. This unit implements support import,export,link routines
  4. for the (i386) Netware libc target
  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. Currently generating NetWare-NLM's only work under Linux and win32.
  17. (see http://home.arcor.de/armin.diehl/fpcnw for binutils working
  18. with win32) while not included in fpc-releases.
  19. The following compiler-swiches are supported for NetWare:
  20. $DESCRIPTION : NLM-Description, will be displayed at load-time
  21. $M : For Stack-Size, Heap-Size will be ignored
  22. 32K is the accepted minimum
  23. $VERSION x.x.x : Sets Major, Minor and Revision
  24. $SCREENNAME : Sets the ScreenName
  25. $THREADNAME : Sets current threadname
  26. Additional parameters for the nlmvonv-inputfile can be passed with
  27. -k, i.e. -kREENTRANT will add the option REENTRANT to the nlmconv
  28. inputfile. A ; will be converted into a newline
  29. Exports will be handled like in win32:
  30. procedure bla; cdecl;
  31. begin
  32. end;
  33. exports foo name 'Bar';
  34. The path to the import-Files must be specified by the library-path.
  35. All external modules are defined as autoload. (Note: the import-files have
  36. to be in unix-format for exe2nlm)
  37. By default, the most import files are included in freepascal.
  38. e.g. function getgrnam(name:Pchar):Pgroup;cdecl;external 'libc' 'getgrnam';
  39. sets IMPORT @libc.imp and MODULE libc.
  40. To avoid setting the autoload, use ! in the name, e.g.
  41. procedure EnterDebugger;cdecl;external '!netware' name 'EnterDebugger';
  42. Function simply defined as external work without generating autoload and
  43. IMPORT but you will get a warning from nlmconv.
  44. If you dont have nlmconv, compile gnu-binutils with
  45. ./configure --enable-targets=i386-netware
  46. make all
  47. Debugging is possible with gdb and a converter from gdb to ndi available
  48. at http://home.arcor.de/armin.diehl/gdbnw
  49. A sample program:
  50. Program Hello;
  51. (*$DESCRIPTION HelloWorldNlm*)
  52. (*$VERSION 1.2.3*)
  53. (*$ScreenName Hello*)
  54. (*$M 60000,60000*)
  55. begin
  56. writeLn ('hello world');
  57. end.
  58. compile with:
  59. ppc386 -Tnetwlibc hello
  60. Libraries are supported but this needs at least netware 5.1 sp6,
  61. 6.0 sp3 or netware 6.5
  62. In case there is a xdc file with the same name as the nlm name,
  63. this file will be used for nlmconv. Otherwise a temp xdc will
  64. be created and used.
  65. ****************************************************************************
  66. }
  67. unit t_nwl;
  68. {$i fpcdefs.inc}
  69. interface
  70. implementation
  71. {$ifdef netwlibc}
  72. {$define netware}
  73. {$endif}
  74. uses
  75. cutils,
  76. verbose,systems,globtype,globals,
  77. symconst,script,
  78. fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
  79. import,export,link,i_nwl,ogbase
  80. {$ifdef netware} ,dos {$endif}
  81. ;
  82. type
  83. timportlibnetwlibc=class(timportlib)
  84. procedure generatelib;override;
  85. end;
  86. texportlibnetwlibc=class(texportlib)
  87. procedure preparelib(const s : string);override;
  88. procedure exportprocedure(hp : texported_item);override;
  89. procedure exportvar(hp : texported_item);override;
  90. procedure generatelib;override;
  91. end;
  92. tlinkernetwlibc=class(texternallinker)
  93. private
  94. NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
  95. Function WriteResponseFile(isdll:boolean) : Boolean;
  96. public
  97. constructor Create;override;
  98. procedure SetDefaultInfo;override;
  99. function MakeNetwareLoadableModule (isLib : boolean):boolean;
  100. function MakeExecutable:boolean;override;
  101. function MakeSharedLibrary:boolean;override;
  102. end;
  103. Const tmpLinkFileName = '~link~tmp.o';
  104. minStackSize = 32768;
  105. {*****************************************************************************
  106. TIMPORTLIBNETWARE
  107. *****************************************************************************}
  108. procedure timportlibnetwlibc.generatelib;
  109. var
  110. i : longint;
  111. ImportLibrary : TImportLibrary;
  112. begin
  113. for i:=0 to current_module.ImportLibraryList.Count-1 do
  114. begin
  115. ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
  116. current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
  117. end;
  118. end;
  119. {*****************************************************************************
  120. TEXPORTLIBNETWARE
  121. *****************************************************************************}
  122. procedure texportlibnetwlibc.preparelib(const s:string);
  123. begin
  124. end;
  125. procedure texportlibnetwlibc.exportprocedure(hp : texported_item);
  126. var
  127. hp2 : texported_item;
  128. begin
  129. { first test the index value }
  130. if (hp.options and eo_index)<>0 then
  131. begin
  132. Comment(V_Error,'can''t export with index under netware');
  133. exit;
  134. end;
  135. { use pascal name is none specified }
  136. if (hp.options and eo_name)=0 then
  137. begin
  138. hp.name:=stringdup(hp.sym.name);
  139. hp.options:=hp.options or eo_name;
  140. end;
  141. { now place in correct order }
  142. hp2:=texported_item(current_module._exports.first);
  143. while assigned(hp2) and
  144. (hp.name^>hp2.name^) do
  145. hp2:=texported_item(hp2.next);
  146. { insert hp there !! }
  147. if assigned(hp2) and (hp2.name^=hp.name^) then
  148. begin
  149. { this is not allowed !! }
  150. Message1(parser_e_export_name_double,hp.name^);
  151. exit;
  152. end;
  153. if hp2=texported_item(current_module._exports.first) then
  154. current_module._exports.insert(hp)
  155. else if assigned(hp2) then
  156. begin
  157. hp.next:=hp2;
  158. hp.previous:=hp2.previous;
  159. if assigned(hp2.previous) then
  160. hp2.previous.next:=hp;
  161. hp2.previous:=hp;
  162. end
  163. else
  164. current_module._exports.concat(hp);
  165. end;
  166. procedure texportlibnetwlibc.exportvar(hp : texported_item);
  167. begin
  168. hp.is_var:=true;
  169. exportprocedure(hp);
  170. end;
  171. procedure texportlibnetwlibc.generatelib;
  172. var
  173. hp2 : texported_item;
  174. begin
  175. hp2:=texported_item(current_module._exports.first);
  176. while assigned(hp2) do
  177. begin
  178. if (not hp2.is_var) and
  179. (hp2.sym.typ=procsym) then
  180. begin
  181. { the manglednames can already be the same when the procedure
  182. is declared with cdecl }
  183. if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
  184. begin
  185. {$ifdef i386}
  186. { place jump in al_procedures }
  187. current_asmdata.asmlists[al_procedures].concat(Tai_align.Create_op(4,$90));
  188. current_asmdata.asmlists[al_procedures].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
  189. current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_sym(A_JMP,S_NO,current_asmdata.RefAsmSymbol(tprocsym(hp2.sym).first_procdef.mangledname)));
  190. current_asmdata.asmlists[al_procedures].concat(Tai_symbol_end.Createname(hp2.name^));
  191. {$endif i386}
  192. end;
  193. end
  194. else
  195. //Comment(V_Error,'Exporting of variables is not supported under netware');
  196. Message1(parser_e_no_export_of_variables_for_target,'netware');
  197. hp2:=texported_item(hp2.next);
  198. end;
  199. end;
  200. {*****************************************************************************
  201. TLINKERNETWARE
  202. *****************************************************************************}
  203. Constructor TLinkerNetwlibc.Create;
  204. begin
  205. Inherited Create;
  206. end;
  207. procedure TLinkerNetwlibc.SetDefaultInfo;
  208. begin
  209. with Info do
  210. begin
  211. {$ifndef netware}
  212. ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
  213. ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
  214. {$else}
  215. {for running on netware we need absolute pathes since ld has another working directory}
  216. ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
  217. ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
  218. {$endif}
  219. end;
  220. end;
  221. Function TLinkerNetwlibc.WriteResponseFile(isdll:boolean) : Boolean;
  222. Var
  223. linkres : TLinkRes;
  224. i : longint;
  225. s,s2,s3 : string;
  226. ProgNam : string [80];
  227. NlmNam : string [80];
  228. hp2 : texported_item; { for exports }
  229. p : byte;
  230. begin
  231. WriteResponseFile:=False;
  232. ProgNam := current_module.exefilename^;
  233. i:=Pos(target_info.exeext,ProgNam);
  234. if i>0 then
  235. Delete(ProgNam,i,255);
  236. NlmNam := ProgNam + target_info.exeext;
  237. { Open link.res file }
  238. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
  239. NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
  240. p := Pos ('"', Description);
  241. while (p > 0) do
  242. begin
  243. delete (Description,p,1);
  244. p := Pos ('"', Description);
  245. end;
  246. if Description <> '' then
  247. NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
  248. NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
  249. p := Pos ('"', nwscreenname);
  250. while (p > 0) do
  251. begin
  252. delete (nwscreenname,p,1);
  253. p := Pos ('"', nwscreenname);
  254. end;
  255. p := Pos ('"', nwthreadname);
  256. while (p > 0) do
  257. begin
  258. delete (nwthreadname,p,1);
  259. p := Pos ('"', nwthreadname);
  260. end;
  261. p := Pos ('"', nwcopyright);
  262. while (p > 0) do
  263. begin
  264. delete (nwcopyright,p,1);
  265. p := Pos ('"', nwcopyright);
  266. end;
  267. if nwscreenname <> '' then
  268. NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
  269. if nwthreadname <> '' then
  270. NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
  271. if nwcopyright <> '' then
  272. NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
  273. if stacksize < minStackSize then stacksize := minStackSize;
  274. str (stacksize, s);
  275. NLMConvLinkFile.Add ('STACKSIZE '+s);
  276. {$ifndef netware}
  277. NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
  278. {$else}
  279. NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
  280. {$endif}
  281. { add objectfiles, start with nwpre always }
  282. LinkRes.Add ('INPUT(');
  283. s2 := FindObjectFile('nwplibc','',false);
  284. if s2 = '' then
  285. s2 := FindObjectFile('libcpre.gcc','',false);
  286. Comment (V_Debug,'adding Object File '+s2);
  287. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  288. if isDll then {needed to provide main}
  289. s2 := FindObjectFile('nwl_dlle','',false)
  290. else
  291. s2 := FindObjectFile('nwl_main','',false);
  292. Comment (V_Debug,'adding Object File '+s2);
  293. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  294. { main objectfiles, add to linker input }
  295. while not ObjectFiles.Empty do
  296. begin
  297. s:=ObjectFiles.GetFirst;
  298. if s<>'' then
  299. begin
  300. s2 := FindObjectFile (s,'',false);
  301. Comment (V_Debug,'adding Object File '+s2);
  302. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  303. end;
  304. end;
  305. LinkRes.Add (')');
  306. { output file (nlm), add to nlmconv }
  307. {$ifndef netware}
  308. NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
  309. {$else}
  310. NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
  311. {$endif}
  312. { start and stop-procedures }
  313. NLMConvLinkFile.Add ('START _LibCPrelude');
  314. NLMConvLinkFile.Add ('EXIT _LibCPostlude');
  315. NLMConvLinkFile.Add ('CHECK _LibCCheckUnload');
  316. NLMConvLinkFile.Add ('REENTRANT'); { needed by older libc versions }
  317. if not (cs_link_strip in aktglobalswitches) then
  318. begin
  319. NLMConvLinkFile.Add ('DEBUG');
  320. Comment(V_Debug,'DEBUG');
  321. end;
  322. { Write staticlibraries }
  323. if not StaticLibFiles.Empty then
  324. begin
  325. LinkRes.Add ('GROUP(');
  326. While not StaticLibFiles.Empty do
  327. begin
  328. S:=lower (StaticLibFiles.GetFirst);
  329. if s<>'' then
  330. begin
  331. {ad: that's a hack !
  332. whith -XX we get the .a files as static libs (in addition to the
  333. imported libraries}
  334. if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
  335. begin
  336. S2 := FindObjectFile(s,'',false);
  337. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  338. Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
  339. end else
  340. begin
  341. i:=Pos(target_info.staticlibext,S);
  342. if i>0 then
  343. Delete(S,i,255);
  344. S := S + '.imp'; S2 := '';
  345. librarysearchpath.FindFile(S,S2);
  346. {$ifdef netware}
  347. Comment(V_Debug,'IMPORT @'+s2);
  348. s2 := FExpand (S2);
  349. {$endif}
  350. NLMConvLinkFile.Add('IMPORT @'+S2);
  351. Comment(V_Debug,'IMPORT @'+s2);
  352. end;
  353. end
  354. end;
  355. LinkRes.Add (')');
  356. end;
  357. if not SharedLibFiles.Empty then
  358. begin
  359. While not SharedLibFiles.Empty do
  360. begin
  361. {becuase of upper/lower case mix, we may get duplicate
  362. names but nlmconv ignores that.
  363. Here we are setting the import-files for nlmconv. I.e. for
  364. the module libc or libc.nlm we add IMPORT @libc.imp and also
  365. the module libc.nlm (autoload)
  366. If a lib name begins with !, only the IMPORT will be generated
  367. ? may it be better to set autoload's via StaticLibFiles ? }
  368. S:=lower (SharedLibFiles.GetFirst);
  369. if s<>'' then
  370. begin
  371. s2:=s;
  372. i:=Pos(target_info.sharedlibext,S);
  373. if i>0 then
  374. Delete(S,i,255);
  375. if s[1] = '!' then
  376. begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp inlcuded in libc ndk
  377. delete (s,1,1);
  378. S := S + '.imp';
  379. librarysearchpath.FindFile(S,S3);
  380. {$ifdef netware}
  381. Comment(V_Debug,'IMPORT @'+S3);
  382. S3 := FExpand (S3);
  383. {$endif}
  384. NLMConvLinkFile.Add('IMPORT @'+S3);
  385. Comment(V_Debug,'IMPORT @'+S3);
  386. end else
  387. begin
  388. S := S + '.imp';
  389. librarysearchpath.FindFile(S,S3);
  390. {$ifdef netware}
  391. Comment(V_Debug,'IMPORT @'+S3);
  392. S3 := FExpand (S3);
  393. {$endif}
  394. NLMConvLinkFile.Add('IMPORT @'+S3);
  395. NLMConvLinkFile.Add('MODULE '+s2);
  396. Comment(V_Debug,'MODULE '+S2);
  397. Comment(V_Debug,'IMPORT @'+S3);
  398. end;
  399. end
  400. end;
  401. end;
  402. { write exports }
  403. hp2:=texported_item(current_module._exports.first);
  404. while assigned(hp2) do
  405. begin
  406. if not hp2.is_var then
  407. begin
  408. { Export the Symbol }
  409. Comment(V_Debug,'EXPORT '+hp2.name^);
  410. NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
  411. end
  412. else
  413. { really, i think it is possible }
  414. {Comment(V_Error,'Exporting of variables is not supported under netware');}
  415. Message1(parser_e_no_export_of_variables_for_target,'netware');
  416. hp2:=texported_item(hp2.next);
  417. end;
  418. { Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
  419. linkres.writetodisk;
  420. LinkRes.Free;
  421. { pass options from -k to nlmconv, ; is interpreted as newline }
  422. s := ParaLinkOptions;
  423. while(Length(s) > 0) and (s[1] = ' ') do
  424. delete (s,1,1);
  425. p := pos ('"',s);
  426. while p > 0 do
  427. begin
  428. delete (s,p,1);
  429. p := pos ('"',s);
  430. end;
  431. p := pos (';',s);
  432. while p > 0 do
  433. begin
  434. s2 := copy(s,1,p-1);
  435. comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
  436. NLMConvLinkFile.Add(s2);
  437. delete (s,1,p);
  438. p := pos (';',s);
  439. end;
  440. if s <> '' then
  441. begin
  442. comment (V_Debug,'adding "'+s+'" to nlmvonv input');
  443. NLMConvLinkFile.Add(s);
  444. end;
  445. WriteResponseFile:=True;
  446. end;
  447. Const
  448. xdc : Array[0..127] of char = (
  449. 'B','A','G','F',#2,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  450. #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#2,#0,#0,#0,#0,#0,#0,#0,#16,#0,#0,
  451. #0,#7,'M','P','K','_','B','a','g',#0,#0,#0,#0,#0,#0,#0,#0,#11,'M','T',
  452. ' ','S','a','f','e',' ','N','L','M',#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  453. #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  454. #0,#0,#0,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0);
  455. function TLinkerNetwlibc.MakeNetwareLoadableModule (isLib : boolean):boolean;
  456. var
  457. binstr : String;
  458. cmdstr : TcmdStr;
  459. xdcname : string;
  460. success : boolean;
  461. StripStr : string[2];
  462. xdcpresent,usexdc : boolean;
  463. f : file;
  464. begin
  465. if not(cs_link_nolink in aktglobalswitches) then
  466. Message1(exec_i_linking,current_module.exefilename^);
  467. { Create some replacements }
  468. StripStr:='';
  469. if (cs_link_strip in aktglobalswitches) then
  470. StripStr:='-s';
  471. { Write used files and libraries and create Headerfile for
  472. nlmconv in NLMConvLinkFile }
  473. WriteResponseFile(isLib);
  474. if isLib then
  475. NLMConvLinkFile.Add('FLAG_ON 1024'); {0x400 Specifies whether the NLM is a shared library.}
  476. { if we have a xdc file, dont touch it, otherwise create a new
  477. one and remove it after nlmconv }
  478. xdcname := ForceExtension(current_module.exefilename^,'.xdc');
  479. xdcpresent := FileExists (xdcname);
  480. if not xdcpresent then
  481. begin
  482. assign (f,xdcname);
  483. rewrite(f,1);
  484. if ioresult = 0 then
  485. begin
  486. blockwrite (f,xdc,sizeof(xdc));
  487. close(f);
  488. usexdc := (IOResult = 0);
  489. end else
  490. usexdc := false;
  491. end else
  492. usexdc := true;
  493. if usexdc then
  494. NLMConvLinkFile.Add('XDCDATA '+xdcname);
  495. { Call linker, this will generate a new object file that will be passed
  496. to nlmconv. Otherwise we could not create nlms without debug info }
  497. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  498. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
  499. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  500. Replace(cmdstr,'$STRIP',StripStr);
  501. Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
  502. Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
  503. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  504. { Remove ReponseFile }
  505. if (success) and not(cs_link_nolink in aktglobalswitches) then
  506. RemoveFile(outputexedir+Info.ResName);
  507. { Call nlmconv }
  508. if success then
  509. begin
  510. NLMConvLinkFile.writetodisk;
  511. NLMConvLinkFile.Free;
  512. SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
  513. Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
  514. Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
  515. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  516. if (success) and not(cs_link_nolink in aktglobalswitches) then
  517. begin
  518. RemoveFile(outputexedir+'n'+Info.ResName);
  519. RemoveFile(outputexedir+tmpLinkFileName);
  520. if not xdcpresent then
  521. if usexdc then
  522. RemoveFile (xdcname);
  523. end;
  524. end;
  525. MakeNetwareLoadableModule:=success; { otherwise a recursive call to link method }
  526. end;
  527. function TLinkerNetwlibc.MakeExecutable:boolean;
  528. begin
  529. MakeExecutable := MakeNetwareLoadableModule (false);
  530. end;
  531. function TLinkerNetwlibc.MakeSharedLibrary:boolean;
  532. begin
  533. MakeSharedLibrary := MakeNetwareLoadableModule (true);
  534. end;
  535. {*****************************************************************************
  536. Initialize
  537. *****************************************************************************}
  538. initialization
  539. RegisterExternalLinker(system_i386_netwlibc_info,TLinkerNetwlibc);
  540. RegisterImport(system_i386_netwlibc,TImportLibNetwlibc);
  541. RegisterExport(system_i386_netwlibc,TExportLibNetwlibc);
  542. RegisterTarget(system_i386_netwlibc_info);
  543. end.