t_msdos.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman
  3. This unit implements support import,export,link routines
  4. for the (i8086) MS-DOS 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. ****************************************************************************
  17. }
  18. unit t_msdos;
  19. {$i fpcdefs.inc}
  20. {$define USE_LINKER_WLINK}
  21. interface
  22. implementation
  23. uses
  24. SysUtils,
  25. cutils,cfileutl,cclasses,
  26. globtype,globals,systems,verbose,cscript,
  27. fmodule,i_msdos,
  28. link,cpuinfo,
  29. aasmbase,aasmcnst,symbase,symdef,
  30. omfbase,ogbase,ogomf,owomflib;
  31. type
  32. { Borland TLINK support }
  33. TExternalLinkerMsDosTLink=class(texternallinker)
  34. private
  35. Function WriteResponseFile(isdll:boolean) : Boolean;
  36. public
  37. constructor Create;override;
  38. procedure SetDefaultInfo;override;
  39. function MakeExecutable:boolean;override;
  40. end;
  41. { the ALINK linker from http://alink.sourceforge.net/ }
  42. TExternalLinkerMsDosALink=class(texternallinker)
  43. private
  44. Function WriteResponseFile(isdll:boolean) : Boolean;
  45. public
  46. constructor Create;override;
  47. procedure SetDefaultInfo;override;
  48. function MakeExecutable:boolean;override;
  49. end;
  50. { the (Open) Watcom linker }
  51. TExternalLinkerMsDosWLink=class(texternallinker)
  52. private
  53. Function WriteResponseFile(isdll:boolean) : Boolean;
  54. Function PostProcessExecutable(const fn:string) : Boolean;
  55. public
  56. constructor Create;override;
  57. procedure SetDefaultInfo;override;
  58. function MakeExecutable:boolean;override;
  59. end;
  60. { TInternalLinkerMsDos }
  61. TInternalLinkerMsDos=class(tinternallinker)
  62. private
  63. function GetTotalSizeForSegmentClass(aExeOutput: TExeOutput; const SegClass: string): QWord;
  64. protected
  65. function GetCodeSize(aExeOutput: TExeOutput): QWord;override;
  66. function GetDataSize(aExeOutput: TExeOutput): QWord;override;
  67. function GetBssSize(aExeOutput: TExeOutput): QWord;override;
  68. procedure DefaultLinkScript;override;
  69. public
  70. constructor create;override;
  71. end;
  72. { tmsdostai_typedconstbuilder }
  73. tmsdostai_typedconstbuilder = class(ttai_lowleveltypedconstbuilder)
  74. protected
  75. procedure add_link_ordered_symbol(sym: tasmsymbol; const secname: TSymStr); override;
  76. public
  77. class function get_vectorized_dead_strip_custom_section_name(const basename: TSymStr; st: tsymtable; options: ttcasmlistoptions; out secname: TSymStr): boolean; override;
  78. class function is_smartlink_vectorized_dead_strip: boolean; override;
  79. end;
  80. {****************************************************************************
  81. tmsdostai_typedconstbuilder
  82. ****************************************************************************}
  83. procedure tmsdostai_typedconstbuilder.add_link_ordered_symbol(sym: tasmsymbol; const secname: TSymStr);
  84. begin
  85. if (tf_smartlink_library in target_info.flags) and is_smartlink_vectorized_dead_strip then
  86. begin
  87. with current_module.linkorderedsymbols do
  88. if (Last=nil) or (TCmdStrListItem(Last).Str<>secname) then
  89. current_module.linkorderedsymbols.concat(secname);
  90. end;
  91. end;
  92. class function tmsdostai_typedconstbuilder.get_vectorized_dead_strip_custom_section_name(const basename: TSymStr; st: tsymtable; options: ttcasmlistoptions; out secname: TSymStr): boolean;
  93. begin
  94. result:=(tf_smartlink_library in target_info.flags) and is_smartlink_vectorized_dead_strip;
  95. if not result then
  96. exit;
  97. if tcalo_vectorized_dead_strip_start in options then
  98. secname:='1_START'
  99. else if tcalo_vectorized_dead_strip_item in options then
  100. secname:='2_ITEM'
  101. else if tcalo_vectorized_dead_strip_end in options then
  102. secname:='3_END'
  103. else
  104. secname:='4_INV';
  105. secname:=make_mangledname(basename,st,secname);
  106. end;
  107. class function tmsdostai_typedconstbuilder.is_smartlink_vectorized_dead_strip: boolean;
  108. begin
  109. {$ifdef USE_LINKER_WLINK}
  110. result:=inherited or (tf_smartlink_library in target_info.flags);
  111. {$else}
  112. result:=inherited and not (cs_link_extern in current_settings.globalswitches);
  113. {$endif USE_LINKER_WLINK}
  114. end;
  115. {****************************************************************************
  116. TExternalLinkerMsDosTLink
  117. ****************************************************************************}
  118. Constructor TExternalLinkerMsDosTLink.Create;
  119. begin
  120. Inherited Create;
  121. { allow duplicated libs (PM) }
  122. SharedLibFiles.doubles:=true;
  123. StaticLibFiles.doubles:=true;
  124. end;
  125. procedure TExternalLinkerMsDosTLink.SetDefaultInfo;
  126. begin
  127. with Info do
  128. begin
  129. ExeCmd[1]:='tlink $OPT $RES';
  130. end;
  131. end;
  132. Function TExternalLinkerMsDosTLink.WriteResponseFile(isdll:boolean) : Boolean;
  133. Var
  134. linkres : TLinkRes;
  135. s : string;
  136. begin
  137. WriteResponseFile:=False;
  138. { Open link.res file }
  139. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  140. { Add all options to link.res instead of passing them via command line:
  141. DOS command line is limited to 126 characters! }
  142. { add objectfiles, start with prt0 always }
  143. LinkRes.Add(GetShortName(FindObjectFile('prt0','',false)) + ' +');
  144. while not ObjectFiles.Empty do
  145. begin
  146. s:=ObjectFiles.GetFirst;
  147. if s<>'' then
  148. LinkRes.Add(GetShortName(s) + ' +');
  149. end;
  150. LinkRes.Add(', ' + maybequoted(current_module.exefilename));
  151. { Write and Close response }
  152. linkres.writetodisk;
  153. LinkRes.Free;
  154. WriteResponseFile:=True;
  155. end;
  156. function TExternalLinkerMsDosTLink.MakeExecutable:boolean;
  157. var
  158. binstr,
  159. cmdstr : TCmdStr;
  160. success : boolean;
  161. begin
  162. if not(cs_link_nolink in current_settings.globalswitches) then
  163. Message1(exec_i_linking,current_module.exefilename);
  164. { Write used files and libraries and our own tlink script }
  165. WriteResponsefile(false);
  166. { Call linker }
  167. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  168. Replace(cmdstr,'$RES','@'+maybequoted(outputexedir+Info.ResName));
  169. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  170. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  171. { Remove ReponseFile }
  172. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  173. DeleteFile(outputexedir+Info.ResName);
  174. MakeExecutable:=success; { otherwise a recursive call to link method }
  175. end;
  176. {****************************************************************************
  177. TExternalLinkerMsDosALink
  178. ****************************************************************************}
  179. { TExternalLinkerMsDosALink }
  180. function TExternalLinkerMsDosALink.WriteResponseFile(isdll: boolean): Boolean;
  181. Var
  182. linkres : TLinkRes;
  183. s : string;
  184. begin
  185. WriteResponseFile:=False;
  186. { Open link.res file }
  187. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  188. { Add all options to link.res instead of passing them via command line:
  189. DOS command line is limited to 126 characters! }
  190. { add objectfiles, start with prt0 always }
  191. LinkRes.Add(maybequoted(FindObjectFile('prt0','',false)));
  192. while not ObjectFiles.Empty do
  193. begin
  194. s:=ObjectFiles.GetFirst;
  195. if s<>'' then
  196. LinkRes.Add(maybequoted(s));
  197. end;
  198. LinkRes.Add('-oEXE');
  199. LinkRes.Add('-o ' + maybequoted(current_module.exefilename));
  200. { Write and Close response }
  201. linkres.writetodisk;
  202. LinkRes.Free;
  203. WriteResponseFile:=True;
  204. end;
  205. constructor TExternalLinkerMsDosALink.Create;
  206. begin
  207. Inherited Create;
  208. { allow duplicated libs (PM) }
  209. SharedLibFiles.doubles:=true;
  210. StaticLibFiles.doubles:=true;
  211. end;
  212. procedure TExternalLinkerMsDosALink.SetDefaultInfo;
  213. begin
  214. with Info do
  215. begin
  216. ExeCmd[1]:='alink $OPT $RES';
  217. end;
  218. end;
  219. function TExternalLinkerMsDosALink.MakeExecutable: boolean;
  220. var
  221. binstr,
  222. cmdstr : TCmdStr;
  223. success : boolean;
  224. begin
  225. if not(cs_link_nolink in current_settings.globalswitches) then
  226. Message1(exec_i_linking,current_module.exefilename);
  227. { Write used files and libraries and our own tlink script }
  228. WriteResponsefile(false);
  229. { Call linker }
  230. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  231. Replace(cmdstr,'$RES','@'+maybequoted(outputexedir+Info.ResName));
  232. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  233. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  234. { Remove ReponseFile }
  235. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  236. DeleteFile(outputexedir+Info.ResName);
  237. MakeExecutable:=success; { otherwise a recursive call to link method }
  238. end;
  239. {****************************************************************************
  240. TExternalLinkerMsDosWLink
  241. ****************************************************************************}
  242. { TExternalLinkerMsDosWLink }
  243. function TExternalLinkerMsDosWLink.WriteResponseFile(isdll: boolean): Boolean;
  244. Var
  245. linkres : TLinkRes;
  246. s : string;
  247. begin
  248. WriteResponseFile:=False;
  249. { Open link.res file }
  250. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,true);
  251. { Add all options to link.res instead of passing them via command line:
  252. DOS command line is limited to 126 characters! }
  253. LinkRes.Add('option quiet');
  254. if cs_debuginfo in current_settings.moduleswitches then
  255. begin
  256. if target_dbg.id in [dbg_dwarf2,dbg_dwarf3,dbg_dwarf4] then
  257. LinkRes.Add('debug dwarf')
  258. else if target_dbg.id=dbg_codeview then
  259. LinkRes.Add('debug codeview')
  260. else
  261. LinkRes.Add('debug watcom all');
  262. if cs_link_separate_dbg_file in current_settings.globalswitches then
  263. LinkRes.Add('option symfile');
  264. end;
  265. { add objectfiles, start with prt0 always }
  266. case current_settings.x86memorymodel of
  267. mm_tiny: LinkRes.Add('file ' + maybequoted(FindObjectFile('prt0t','',false)));
  268. mm_small: LinkRes.Add('file ' + maybequoted(FindObjectFile('prt0s','',false)));
  269. mm_medium: LinkRes.Add('file ' + maybequoted(FindObjectFile('prt0m','',false)));
  270. mm_compact: LinkRes.Add('file ' + maybequoted(FindObjectFile('prt0c','',false)));
  271. mm_large: LinkRes.Add('file ' + maybequoted(FindObjectFile('prt0l','',false)));
  272. mm_huge: LinkRes.Add('file ' + maybequoted(FindObjectFile('prt0h','',false)));
  273. end;
  274. while not ObjectFiles.Empty do
  275. begin
  276. s:=ObjectFiles.GetFirst;
  277. if s<>'' then
  278. LinkRes.Add('file ' + maybequoted(s));
  279. end;
  280. while not StaticLibFiles.Empty do
  281. begin
  282. s:=StaticLibFiles.GetFirst;
  283. if s<>'' then
  284. LinkRes.Add('library '+MaybeQuoted(s));
  285. end;
  286. if apptype=app_com then
  287. LinkRes.Add('format dos com')
  288. else
  289. LinkRes.Add('format dos');
  290. if current_settings.x86memorymodel=mm_tiny then
  291. LinkRes.Add('order clname CODE clname DATA clname BSS')
  292. else
  293. LinkRes.Add('order clname CODE clname FAR_DATA clname BEGDATA segment _NULL segment _AFTERNULL clname DATA clname BSS clname STACK clname HEAP');
  294. if (cs_link_map in current_settings.globalswitches) then
  295. LinkRes.Add('option map='+maybequoted(ChangeFileExt(current_module.exefilename,'.map')));
  296. LinkRes.Add('name ' + maybequoted(current_module.exefilename));
  297. { Write and Close response }
  298. linkres.writetodisk;
  299. LinkRes.Free;
  300. WriteResponseFile:=True;
  301. end;
  302. constructor TExternalLinkerMsDosWLink.Create;
  303. begin
  304. Inherited Create;
  305. { allow duplicated libs (PM) }
  306. SharedLibFiles.doubles:=true;
  307. StaticLibFiles.doubles:=true;
  308. end;
  309. procedure TExternalLinkerMsDosWLink.SetDefaultInfo;
  310. begin
  311. with Info do
  312. begin
  313. ExeCmd[1]:='wlink $OPT $RES';
  314. end;
  315. end;
  316. function TExternalLinkerMsDosWLink.MakeExecutable: boolean;
  317. var
  318. binstr,
  319. cmdstr : TCmdStr;
  320. success : boolean;
  321. begin
  322. if not(cs_link_nolink in current_settings.globalswitches) then
  323. Message1(exec_i_linking,current_module.exefilename);
  324. { Write used files and libraries and our own tlink script }
  325. WriteResponsefile(false);
  326. { Call linker }
  327. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  328. Replace(cmdstr,'$RES','@'+maybequoted(outputexedir+Info.ResName));
  329. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  330. success:=DoExec(FindUtil(utilsprefix+BinStr),cmdstr,true,false);
  331. { Post process }
  332. if success then
  333. success:=PostProcessExecutable(current_module.exefilename);
  334. { Remove ReponseFile }
  335. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  336. DeleteFile(outputexedir+Info.ResName);
  337. MakeExecutable:=success; { otherwise a recursive call to link method }
  338. end;
  339. { In far data memory models, this function sets the MaxAlloc value in the DOS MZ
  340. header according to the difference between HeapMin and HeapMax. We have to do
  341. this manually, because WLink sets MaxAlloc to $FFFF and there seems to be no
  342. way to specify a different value with a linker option. }
  343. function TExternalLinkerMsDosWLink.PostProcessExecutable(const fn: string): Boolean;
  344. var
  345. f: file;
  346. minalloc,maxalloc: Word;
  347. heapmin_paragraphs, heapmax_paragraphs: Integer;
  348. begin
  349. { nothing to do in the near data memory models }
  350. if current_settings.x86memorymodel in x86_near_data_models then
  351. exit(true);
  352. { .COM files are not supported in the far data memory models }
  353. if apptype=app_com then
  354. internalerror(2014062501);
  355. { open file }
  356. assign(f,fn);
  357. {$push}{$I-}
  358. reset(f,1);
  359. if ioresult<>0 then
  360. Message1(execinfo_f_cant_open_executable,fn);
  361. { read minalloc }
  362. seek(f,$A);
  363. BlockRead(f,minalloc,2);
  364. if source_info.endian<>target_info.endian then
  365. minalloc:=SwapEndian(minalloc);
  366. { calculate the additional number of paragraphs needed }
  367. heapmin_paragraphs:=(heapsize + 15) div 16;
  368. heapmax_paragraphs:=(maxheapsize + 15) div 16;
  369. maxalloc:=min(minalloc-heapmin_paragraphs+heapmax_paragraphs,$FFFF);
  370. { write maxalloc }
  371. seek(f,$C);
  372. if source_info.endian<>target_info.endian then
  373. maxalloc:=SwapEndian(maxalloc);
  374. BlockWrite(f,maxalloc,2);
  375. close(f);
  376. {$pop}
  377. if ioresult<>0 then;
  378. Result:=true;
  379. end;
  380. {****************************************************************************
  381. TInternalLinkerMsDos
  382. ****************************************************************************}
  383. function TInternalLinkerMsDos.GetTotalSizeForSegmentClass(
  384. aExeOutput: TExeOutput; const SegClass: string): QWord;
  385. var
  386. objseclist: TFPObjectList;
  387. objsec: TOmfObjSection;
  388. i: Integer;
  389. begin
  390. Result:=0;
  391. objseclist:=TMZExeOutput(aExeOutput).MZFlatContentSection.ObjSectionList;
  392. for i:=0 to objseclist.Count-1 do
  393. begin
  394. objsec:=TOmfObjSection(objseclist[i]);
  395. if objsec.ClassName=SegClass then
  396. Inc(Result,objsec.Size);
  397. end;
  398. end;
  399. function TInternalLinkerMsDos.GetCodeSize(aExeOutput: TExeOutput): QWord;
  400. begin
  401. Result:=GetTotalSizeForSegmentClass(aExeOutput,'CODE');
  402. end;
  403. function TInternalLinkerMsDos.GetDataSize(aExeOutput: TExeOutput): QWord;
  404. begin
  405. Result:=GetTotalSizeForSegmentClass(aExeOutput,'DATA')+
  406. GetTotalSizeForSegmentClass(aExeOutput,'FAR_DATA');
  407. end;
  408. function TInternalLinkerMsDos.GetBssSize(aExeOutput: TExeOutput): QWord;
  409. begin
  410. Result:=GetTotalSizeForSegmentClass(aExeOutput,'BSS');
  411. end;
  412. procedure TInternalLinkerMsDos.DefaultLinkScript;
  413. var
  414. s: TCmdStr;
  415. begin
  416. { add objectfiles, start with prt0 always }
  417. case current_settings.x86memorymodel of
  418. mm_tiny: LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile('prt0t','',false)));
  419. mm_small: LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile('prt0s','',false)));
  420. mm_medium: LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile('prt0m','',false)));
  421. mm_compact: LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile('prt0c','',false)));
  422. mm_large: LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile('prt0l','',false)));
  423. mm_huge: LinkScript.Concat('READOBJECT ' + maybequoted(FindObjectFile('prt0h','',false)));
  424. end;
  425. while not ObjectFiles.Empty do
  426. begin
  427. s:=ObjectFiles.GetFirst;
  428. if s<>'' then
  429. LinkScript.Concat('READOBJECT ' + maybequoted(s));
  430. end;
  431. LinkScript.Concat('GROUP');
  432. while not StaticLibFiles.Empty do
  433. begin
  434. s:=StaticLibFiles.GetFirst;
  435. if s<>'' then
  436. LinkScript.Concat('READSTATICLIBRARY '+MaybeQuoted(s));
  437. end;
  438. LinkScript.Concat('ENDGROUP');
  439. LinkScript.Concat('EXESECTION .MZ_flat_content');
  440. if current_settings.x86memorymodel=mm_tiny then
  441. begin
  442. LinkScript.Concat(' OBJSECTION _TEXT||CODE');
  443. LinkScript.Concat(' OBJSECTION *||CODE');
  444. LinkScript.Concat(' OBJSECTION *||DATA');
  445. LinkScript.Concat(' SYMBOL _edata');
  446. LinkScript.Concat(' OBJSECTION *||BSS');
  447. LinkScript.Concat(' SYMBOL _end');
  448. end
  449. else
  450. begin
  451. LinkScript.Concat(' OBJSECTION _TEXT||CODE');
  452. LinkScript.Concat(' OBJSECTION *||CODE');
  453. LinkScript.Concat(' OBJSECTION *||FAR_DATA');
  454. LinkScript.Concat(' OBJSECTION _NULL||BEGDATA');
  455. LinkScript.Concat(' OBJSECTION _AFTERNULL||BEGDATA');
  456. LinkScript.Concat(' OBJSECTION *||BEGDATA');
  457. LinkScript.Concat(' OBJSECTION *||DATA');
  458. LinkScript.Concat(' SYMBOL _edata');
  459. LinkScript.Concat(' OBJSECTION *||BSS');
  460. LinkScript.Concat(' SYMBOL _end');
  461. LinkScript.Concat(' OBJSECTION *||STACK');
  462. LinkScript.Concat(' OBJSECTION *||HEAP');
  463. end;
  464. LinkScript.Concat('ENDEXESECTION');
  465. if (cs_debuginfo in current_settings.moduleswitches) and
  466. (target_dbg.id in [dbg_dwarf2,dbg_dwarf3,dbg_dwarf4]) then
  467. begin
  468. LinkScript.Concat('EXESECTION .debug_info');
  469. LinkScript.Concat(' OBJSECTION .DEBUG_INFO||DWARF');
  470. LinkScript.Concat('ENDEXESECTION');
  471. LinkScript.Concat('EXESECTION .debug_abbrev');
  472. LinkScript.Concat(' OBJSECTION .DEBUG_ABBREV||DWARF');
  473. LinkScript.Concat('ENDEXESECTION');
  474. LinkScript.Concat('EXESECTION .debug_line');
  475. LinkScript.Concat(' OBJSECTION .DEBUG_LINE||DWARF');
  476. LinkScript.Concat('ENDEXESECTION');
  477. LinkScript.Concat('EXESECTION .debug_aranges');
  478. LinkScript.Concat(' OBJSECTION .DEBUG_ARANGES||DWARF');
  479. LinkScript.Concat('ENDEXESECTION');
  480. end;
  481. LinkScript.Concat('ENTRYNAME ..start');
  482. end;
  483. constructor TInternalLinkerMsDos.create;
  484. begin
  485. inherited create;
  486. CArObjectReader:=TOmfLibObjectReader;
  487. CExeOutput:=TMZExeOutput;
  488. CObjInput:=TOmfObjInput;
  489. end;
  490. {*****************************************************************************
  491. Initialize
  492. *****************************************************************************}
  493. initialization
  494. ctai_typedconstbuilder:=tmsdostai_typedconstbuilder;
  495. RegisterLinker(ld_int_msdos,TInternalLinkerMsDos);
  496. {$if defined(USE_LINKER_TLINK)}
  497. RegisterLinker(ld_msdos,TExternalLinkerMsDosTLink);
  498. {$elseif defined(USE_LINKER_ALINK)}
  499. RegisterLinker(ld_msdos,TExternalLinkerMsDosALink);
  500. {$elseif defined(USE_LINKER_WLINK)}
  501. RegisterLinker(ld_msdos,TExternalLinkerMsDosWLink);
  502. {$else}
  503. {$fatal no linker defined}
  504. {$endif}
  505. RegisterTarget(system_i8086_msdos_info);
  506. end.