t_nwl.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  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,aasmcpu,cpubase,symsym,symdef,
  79. import,export,link,i_nwl
  80. {$ifdef netware} ,dos {$endif}
  81. ;
  82. type
  83. timportlibnetwlibc=class(timportlib)
  84. procedure preparelib(const s:string);override;
  85. procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
  86. procedure importvariable(vs:tglobalvarsym;const name,module:string);override;
  87. procedure generatelib;override;
  88. end;
  89. texportlibnetwlibc=class(texportlib)
  90. procedure preparelib(const s : string);override;
  91. procedure exportprocedure(hp : texported_item);override;
  92. procedure exportvar(hp : texported_item);override;
  93. procedure generatelib;override;
  94. end;
  95. tlinkernetwlibc=class(texternallinker)
  96. private
  97. NLMConvLinkFile: TLinkRes; {for second pass, fist pass is ld}
  98. Function WriteResponseFile(isdll:boolean) : Boolean;
  99. public
  100. constructor Create;override;
  101. procedure SetDefaultInfo;override;
  102. function MakeNetwareLoadableModule (isLib : boolean):boolean;
  103. function MakeExecutable:boolean;override;
  104. function MakeSharedLibrary:boolean;override;
  105. end;
  106. Const tmpLinkFileName = '~link~tmp.o';
  107. minStackSize = 32768;
  108. {*****************************************************************************
  109. TIMPORTLIBNETWARE
  110. *****************************************************************************}
  111. procedure timportlibnetwlibc.preparelib(const s : string);
  112. begin
  113. end;
  114. procedure timportlibnetwlibc.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
  115. begin
  116. { insert sharedlibrary }
  117. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  118. end;
  119. procedure timportlibnetwlibc.importvariable(vs:tglobalvarsym;const name,module:string);
  120. begin
  121. { insert sharedlibrary }
  122. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  123. { reset the mangledname and turn off the dll_var option }
  124. vs.set_mangledname(name);
  125. exclude(vs.varoptions,vo_is_dll_var);
  126. end;
  127. procedure timportlibnetwlibc.generatelib;
  128. begin
  129. end;
  130. {*****************************************************************************
  131. TEXPORTLIBNETWARE
  132. *****************************************************************************}
  133. procedure texportlibnetwlibc.preparelib(const s:string);
  134. begin
  135. end;
  136. procedure texportlibnetwlibc.exportprocedure(hp : texported_item);
  137. var
  138. hp2 : texported_item;
  139. begin
  140. { first test the index value }
  141. if (hp.options and eo_index)<>0 then
  142. begin
  143. Comment(V_Error,'can''t export with index under netware');
  144. exit;
  145. end;
  146. { use pascal name is none specified }
  147. if (hp.options and eo_name)=0 then
  148. begin
  149. hp.name:=stringdup(hp.sym.name);
  150. hp.options:=hp.options or eo_name;
  151. end;
  152. { now place in correct order }
  153. hp2:=texported_item(current_module._exports.first);
  154. while assigned(hp2) and
  155. (hp.name^>hp2.name^) do
  156. hp2:=texported_item(hp2.next);
  157. { insert hp there !! }
  158. if assigned(hp2) and (hp2.name^=hp.name^) then
  159. begin
  160. { this is not allowed !! }
  161. Message1(parser_e_export_name_double,hp.name^);
  162. exit;
  163. end;
  164. if hp2=texported_item(current_module._exports.first) then
  165. current_module._exports.insert(hp)
  166. else if assigned(hp2) then
  167. begin
  168. hp.next:=hp2;
  169. hp.previous:=hp2.previous;
  170. if assigned(hp2.previous) then
  171. hp2.previous.next:=hp;
  172. hp2.previous:=hp;
  173. end
  174. else
  175. current_module._exports.concat(hp);
  176. end;
  177. procedure texportlibnetwlibc.exportvar(hp : texported_item);
  178. begin
  179. hp.is_var:=true;
  180. exportprocedure(hp);
  181. end;
  182. procedure texportlibnetwlibc.generatelib;
  183. var
  184. hp2 : texported_item;
  185. begin
  186. hp2:=texported_item(current_module._exports.first);
  187. while assigned(hp2) do
  188. begin
  189. if (not hp2.is_var) and
  190. (hp2.sym.typ=procsym) then
  191. begin
  192. { the manglednames can already be the same when the procedure
  193. is declared with cdecl }
  194. if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
  195. begin
  196. {$ifdef i386}
  197. { place jump in al_code }
  198. asmlist[al_code].concat(Tai_align.Create_op(4,$90));
  199. asmlist[al_code].concat(Tai_symbol.Createname_global(hp2.name^,AT_FUNCTION,0));
  200. asmlist[al_code].concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname,AB_EXTERNAL,AT_FUNCTION)));
  201. asmlist[al_code].concat(Tai_symbol_end.Createname(hp2.name^));
  202. {$endif i386}
  203. end;
  204. end
  205. else
  206. //Comment(V_Error,'Exporting of variables is not supported under netware');
  207. Message1(parser_e_no_export_of_variables_for_target,'netware');
  208. hp2:=texported_item(hp2.next);
  209. end;
  210. end;
  211. {*****************************************************************************
  212. TLINKERNETWARE
  213. *****************************************************************************}
  214. Constructor TLinkerNetwlibc.Create;
  215. begin
  216. Inherited Create;
  217. end;
  218. procedure TLinkerNetwlibc.SetDefaultInfo;
  219. begin
  220. with Info do
  221. begin
  222. {$ifndef netware}
  223. ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T $RES $STRIP -o $TMPOBJ';
  224. ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T$RES';
  225. {$else}
  226. {for running on netware we need absolute pathes since ld has another working directory}
  227. ExeCmd[1]:= FindUtil(utilsprefix+'ld') + ' -Ur -T '+FExpand(outputexedir+Info.ResName)+' $STRIP -o '+Fexpand(outputexedir+tmpLinkFileName);
  228. ExeCmd[2]:= FindUtil(utilsprefix+'nlmconv') + ' -T'+FExpand(outputexedir+'n'+Info.ResName);
  229. {$endif}
  230. end;
  231. end;
  232. Function TLinkerNetwlibc.WriteResponseFile(isdll:boolean) : Boolean;
  233. Var
  234. linkres : TLinkRes;
  235. i : longint;
  236. s,s2,s3 : string;
  237. ProgNam : string [80];
  238. NlmNam : string [80];
  239. hp2 : texported_item; { for exports }
  240. p : byte;
  241. begin
  242. WriteResponseFile:=False;
  243. ProgNam := current_module.exefilename^;
  244. i:=Pos(target_info.exeext,ProgNam);
  245. if i>0 then
  246. Delete(ProgNam,i,255);
  247. NlmNam := ProgNam + target_info.exeext;
  248. { Open link.res file }
  249. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName); {for ld}
  250. NLMConvLinkFile:=TLinkRes.Create(outputexedir+'n'+Info.ResName); {for nlmconv, written in CreateExeFile}
  251. p := Pos ('"', Description);
  252. while (p > 0) do
  253. begin
  254. delete (Description,p,1);
  255. p := Pos ('"', Description);
  256. end;
  257. if Description <> '' then
  258. NLMConvLinkFile.Add('DESCRIPTION "' + Description + '"');
  259. NLMConvLinkFile.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
  260. p := Pos ('"', nwscreenname);
  261. while (p > 0) do
  262. begin
  263. delete (nwscreenname,p,1);
  264. p := Pos ('"', nwscreenname);
  265. end;
  266. p := Pos ('"', nwthreadname);
  267. while (p > 0) do
  268. begin
  269. delete (nwthreadname,p,1);
  270. p := Pos ('"', nwthreadname);
  271. end;
  272. p := Pos ('"', nwcopyright);
  273. while (p > 0) do
  274. begin
  275. delete (nwcopyright,p,1);
  276. p := Pos ('"', nwcopyright);
  277. end;
  278. if nwscreenname <> '' then
  279. NLMConvLinkFile.Add('SCREENNAME "' + nwscreenname + '"');
  280. if nwthreadname <> '' then
  281. NLMConvLinkFile.Add('THREADNAME "' + nwthreadname + '"');
  282. if nwcopyright <> '' then
  283. NLMConvLinkFile.Add('COPYRIGHT "' + nwcopyright + '"');
  284. if stacksize < minStackSize then stacksize := minStackSize;
  285. str (stacksize, s);
  286. NLMConvLinkFile.Add ('STACKSIZE '+s);
  287. {$ifndef netware}
  288. NLMConvLinkFile.Add ('INPUT '+outputexedir+tmpLinkFileName);
  289. {$else}
  290. NLMConvLinkFile.Add ('INPUT '+FExpand(outputexedir+tmpLinkFileName));
  291. {$endif}
  292. { add objectfiles, start with nwpre always }
  293. LinkRes.Add ('INPUT(');
  294. s2 := FindObjectFile('nwplibc','',false);
  295. if s2 = '' then
  296. s2 := FindObjectFile('libcpre.gcc','',false);
  297. Comment (V_Debug,'adding Object File '+s2);
  298. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  299. if isDll then {needed to provide main}
  300. s2 := FindObjectFile('nwl_dlle','',false)
  301. else
  302. s2 := FindObjectFile('nwl_main','',false);
  303. Comment (V_Debug,'adding Object File '+s2);
  304. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  305. { main objectfiles, add to linker input }
  306. while not ObjectFiles.Empty do
  307. begin
  308. s:=ObjectFiles.GetFirst;
  309. if s<>'' then
  310. begin
  311. s2 := FindObjectFile (s,'',false);
  312. Comment (V_Debug,'adding Object File '+s2);
  313. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  314. end;
  315. end;
  316. LinkRes.Add (')');
  317. { output file (nlm), add to nlmconv }
  318. {$ifndef netware}
  319. NLMConvLinkFile.Add ('OUTPUT ' + NlmNam);
  320. {$else}
  321. NLMConvLinkFile.Add ('OUTPUT ' + FExpand(NlmNam));
  322. {$endif}
  323. { start and stop-procedures }
  324. NLMConvLinkFile.Add ('START _LibCPrelude');
  325. NLMConvLinkFile.Add ('EXIT _LibCPostlude');
  326. NLMConvLinkFile.Add ('CHECK _LibCCheckUnload');
  327. NLMConvLinkFile.Add ('REENTRANT'); { needed by older libc versions }
  328. if not (cs_link_strip in aktglobalswitches) then
  329. begin
  330. NLMConvLinkFile.Add ('DEBUG');
  331. Comment(V_Debug,'DEBUG');
  332. end;
  333. { Write staticlibraries }
  334. if not StaticLibFiles.Empty then
  335. begin
  336. LinkRes.Add ('GROUP(');
  337. While not StaticLibFiles.Empty do
  338. begin
  339. S:=lower (StaticLibFiles.GetFirst);
  340. if s<>'' then
  341. begin
  342. {ad: that's a hack !
  343. whith -XX we get the .a files as static libs (in addition to the
  344. imported libraries}
  345. if (pos ('.a',s) <> 0) OR (pos ('.A', s) <> 0) then
  346. begin
  347. S2 := FindObjectFile(s,'',false);
  348. {$ifndef netware} LinkRes.Add (s2); {$else} LinkRes.Add (FExpand(s2)); {$endif}
  349. Comment(V_Debug,'adding Object File (StaticLibFiles) '+S2);
  350. end else
  351. begin
  352. i:=Pos(target_info.staticlibext,S);
  353. if i>0 then
  354. Delete(S,i,255);
  355. S := S + '.imp'; S2 := '';
  356. librarysearchpath.FindFile(S,S2);
  357. {$ifdef netware}
  358. Comment(V_Debug,'IMPORT @'+s2);
  359. s2 := FExpand (S2);
  360. {$endif}
  361. NLMConvLinkFile.Add('IMPORT @'+S2);
  362. Comment(V_Debug,'IMPORT @'+s2);
  363. end;
  364. end
  365. end;
  366. LinkRes.Add (')');
  367. end;
  368. if not SharedLibFiles.Empty then
  369. begin
  370. While not SharedLibFiles.Empty do
  371. begin
  372. {becuase of upper/lower case mix, we may get duplicate
  373. names but nlmconv ignores that.
  374. Here we are setting the import-files for nlmconv. I.e. for
  375. the module libc or libc.nlm we add IMPORT @libc.imp and also
  376. the module libc.nlm (autoload)
  377. If a lib name begins with !, only the IMPORT will be generated
  378. ? may it be better to set autoload's via StaticLibFiles ? }
  379. S:=lower (SharedLibFiles.GetFirst);
  380. if s<>'' then
  381. begin
  382. s2:=s;
  383. i:=Pos(target_info.sharedlibext,S);
  384. if i>0 then
  385. Delete(S,i,255);
  386. if s[1] = '!' then
  387. begin // special, with ! only the imp will be included but no module is autoloaded, needed i.e. for netware.imp inlcuded in libc ndk
  388. delete (s,1,1);
  389. S := S + '.imp';
  390. librarysearchpath.FindFile(S,S3);
  391. {$ifdef netware}
  392. Comment(V_Debug,'IMPORT @'+S3);
  393. S3 := FExpand (S3);
  394. {$endif}
  395. NLMConvLinkFile.Add('IMPORT @'+S3);
  396. Comment(V_Debug,'IMPORT @'+S3);
  397. end else
  398. begin
  399. S := S + '.imp';
  400. librarysearchpath.FindFile(S,S3);
  401. {$ifdef netware}
  402. Comment(V_Debug,'IMPORT @'+S3);
  403. S3 := FExpand (S3);
  404. {$endif}
  405. NLMConvLinkFile.Add('IMPORT @'+S3);
  406. NLMConvLinkFile.Add('MODULE '+s2);
  407. Comment(V_Debug,'MODULE '+S2);
  408. Comment(V_Debug,'IMPORT @'+S3);
  409. end;
  410. end
  411. end;
  412. end;
  413. { write exports }
  414. hp2:=texported_item(current_module._exports.first);
  415. while assigned(hp2) do
  416. begin
  417. if not hp2.is_var then
  418. begin
  419. { Export the Symbol }
  420. Comment(V_Debug,'EXPORT '+hp2.name^);
  421. NLMConvLinkFile.Add ('EXPORT '+hp2.name^);
  422. end
  423. else
  424. { really, i think it is possible }
  425. {Comment(V_Error,'Exporting of variables is not supported under netware');}
  426. Message1(parser_e_no_export_of_variables_for_target,'netware');
  427. hp2:=texported_item(hp2.next);
  428. end;
  429. { Write and Close response for ld, response for nlmconv is in NLMConvLinkFile(not written) }
  430. linkres.writetodisk;
  431. LinkRes.Free;
  432. { pass options from -k to nlmconv, ; is interpreted as newline }
  433. s := ParaLinkOptions;
  434. while(Length(s) > 0) and (s[1] = ' ') do
  435. delete (s,1,1);
  436. p := pos ('"',s);
  437. while p > 0 do
  438. begin
  439. delete (s,p,1);
  440. p := pos ('"',s);
  441. end;
  442. p := pos (';',s);
  443. while p > 0 do
  444. begin
  445. s2 := copy(s,1,p-1);
  446. comment (V_Debug,'adding "'+s2+'" to nlmvonv input');
  447. NLMConvLinkFile.Add(s2);
  448. delete (s,1,p);
  449. p := pos (';',s);
  450. end;
  451. if s <> '' then
  452. begin
  453. comment (V_Debug,'adding "'+s+'" to nlmvonv input');
  454. NLMConvLinkFile.Add(s);
  455. end;
  456. WriteResponseFile:=True;
  457. end;
  458. Const
  459. xdc : Array[0..127] of char = (
  460. 'B','A','G','F',#2,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  461. #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#2,#0,#0,#0,#0,#0,#0,#0,#16,#0,#0,
  462. #0,#7,'M','P','K','_','B','a','g',#0,#0,#0,#0,#0,#0,#0,#0,#11,'M','T',
  463. ' ','S','a','f','e',' ','N','L','M',#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  464. #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,
  465. #0,#0,#0,#0,#0,#0,#1,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0);
  466. function TLinkerNetwlibc.MakeNetwareLoadableModule (isLib : boolean):boolean;
  467. var
  468. binstr : String;
  469. cmdstr : TcmdStr;
  470. xdcname : string;
  471. success : boolean;
  472. StripStr : string[2];
  473. xdcpresent,usexdc : boolean;
  474. f : file;
  475. begin
  476. if not(cs_link_extern in aktglobalswitches) then
  477. Message1(exec_i_linking,current_module.exefilename^);
  478. { Create some replacements }
  479. StripStr:='';
  480. if (cs_link_strip in aktglobalswitches) then
  481. StripStr:='-s';
  482. { Write used files and libraries and create Headerfile for
  483. nlmconv in NLMConvLinkFile }
  484. WriteResponseFile(isLib);
  485. if isLib then
  486. NLMConvLinkFile.Add('FLAG_ON 1024'); {0x400 Specifies whether the NLM is a shared library.}
  487. { if we have a xdc file, dont touch it, otherwise create a new
  488. one and remove it after nlmconv }
  489. xdcname := ForceExtension(current_module.exefilename^,'.xdc');
  490. xdcpresent := FileExists (xdcname);
  491. if not xdcpresent then
  492. begin
  493. assign (f,xdcname);
  494. rewrite(f,1);
  495. if ioresult = 0 then
  496. begin
  497. blockwrite (f,xdc,sizeof(xdc));
  498. close(f);
  499. usexdc := (IOResult = 0);
  500. end else
  501. usexdc := false;
  502. end else
  503. usexdc := true;
  504. if usexdc then
  505. NLMConvLinkFile.Add('XDCDATA '+xdcname);
  506. { Call linker, this will generate a new object file that will be passed
  507. to nlmconv. Otherwise we could not create nlms without debug info }
  508. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  509. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
  510. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  511. Replace(cmdstr,'$STRIP',StripStr);
  512. Replace(cmdstr,'$TMPOBJ',maybequoted(outputexedir+tmpLinkFileName));
  513. Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
  514. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  515. { Remove ReponseFile }
  516. if (success) and not(cs_link_extern in aktglobalswitches) then
  517. RemoveFile(outputexedir+Info.ResName);
  518. { Call nlmconv }
  519. if success then
  520. begin
  521. NLMConvLinkFile.writetodisk;
  522. NLMConvLinkFile.Free;
  523. SplitBinCmd(Info.ExeCmd[2],binstr,cmdstr);
  524. Replace(cmdstr,'$RES',maybequoted(outputexedir+'n'+Info.ResName));
  525. Comment (v_debug,'Executing '+BinStr+' '+cmdstr);
  526. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  527. if (success) and not(cs_link_extern in aktglobalswitches) then
  528. begin
  529. RemoveFile(outputexedir+'n'+Info.ResName);
  530. RemoveFile(outputexedir+tmpLinkFileName);
  531. if not xdcpresent then
  532. if usexdc then
  533. RemoveFile (xdcname);
  534. end;
  535. end;
  536. MakeNetwareLoadableModule:=success; { otherwise a recursive call to link method }
  537. end;
  538. function TLinkerNetwlibc.MakeExecutable:boolean;
  539. begin
  540. MakeExecutable := MakeNetwareLoadableModule (false);
  541. end;
  542. function TLinkerNetwlibc.MakeSharedLibrary:boolean;
  543. begin
  544. MakeSharedLibrary := MakeNetwareLoadableModule (true);
  545. end;
  546. {*****************************************************************************
  547. Initialize
  548. *****************************************************************************}
  549. initialization
  550. RegisterExternalLinker(system_i386_netwlibc_info,TLinkerNetwlibc);
  551. RegisterImport(system_i386_netwlibc,TImportLibNetwlibc);
  552. RegisterExport(system_i386_netwlibc,TExportLibNetwlibc);
  553. RegisterTarget(system_i386_netwlibc_info);
  554. end.