system.pp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Watcom
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit system;
  12. INTERFACE
  13. {$ifndef NO_EXCEPTIONS_IN_SYSTEM}
  14. {$define EXCEPTIONS_IN_SYSTEM}
  15. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  16. { include system-independent routine headers }
  17. {$include systemh.inc}
  18. { include heap support headers }
  19. {$include heaph.inc}
  20. {Platform specific information}
  21. type
  22. THandle = Longint;
  23. TThreadID = THandle;
  24. const
  25. LineEnding = #13#10;
  26. { LFNSupport is a variable here, defined below!!! }
  27. DirectorySeparator = '\';
  28. DriveSeparator = ':';
  29. PathSeparator = ';';
  30. { FileNameCaseSensitive is defined separately below!!! }
  31. maxExitCode = 255;
  32. MaxPathLen = 256;
  33. const
  34. { Default filehandles }
  35. UnusedHandle = -1;
  36. StdInputHandle = 0;
  37. StdOutputHandle = 1;
  38. StdErrorHandle = 2;
  39. FileNameCaseSensitive : boolean = false;
  40. CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *)
  41. sLineBreak = LineEnding;
  42. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  43. { Default memory segments (Tp7 compatibility) }
  44. seg0040 = $0040;
  45. segA000 = $A000;
  46. segB000 = $B000;
  47. segB800 = $B800;
  48. var
  49. { Mem[] support }
  50. mem : array[0..$7fffffff] of byte absolute $0:$0;
  51. memw : array[0..$7fffffff div sizeof(word)] of word absolute $0:$0;
  52. meml : array[0..$7fffffff div sizeof(longint)] of longint absolute $0:$0;
  53. { C-compatible arguments and environment }
  54. argc : longint;
  55. argv : ppchar;
  56. envp : ppchar;
  57. dos_argv0 : pchar;
  58. {$ifndef RTLLITE}
  59. { System info }
  60. LFNSupport : boolean;
  61. {$ELSE RTLLITE}
  62. Const
  63. LFNSupport = false;
  64. {$endif RTLLITE}
  65. {
  66. necessary for objects.pas, should be removed (at least from the interface
  67. to the implementation)
  68. }
  69. type
  70. trealregs=record
  71. realedi,realesi,realebp,realres,
  72. realebx,realedx,realecx,realeax : longint;
  73. realflags,
  74. reales,realds,realfs,realgs,
  75. realip,realcs,realsp,realss : word;
  76. end;
  77. function do_write(h:longint;addr:pointer;len : longint) : longint;
  78. function do_read(h:longint;addr:pointer;len : longint) : longint;
  79. procedure syscopyfromdos(addr : sizeuint; len : longint);
  80. procedure syscopytodos(addr : sizeuint; len : longint);
  81. procedure sysrealintr(intnr : word;var regs : trealregs);
  82. var tb:longint;
  83. tb_segment:word;
  84. const tb_offset=0;
  85. tb_size=8192;
  86. IMPLEMENTATION
  87. { include system independent routines }
  88. {$include system.inc}
  89. const
  90. carryflag = 1;
  91. type
  92. tseginfo=packed record
  93. offset : pointer;
  94. segment : word;
  95. end;
  96. var
  97. old_int00 : tseginfo;cvar;
  98. old_int75 : tseginfo;cvar;
  99. {$asmmode ATT}
  100. {*****************************************************************************
  101. Watcom Helpers
  102. *****************************************************************************}
  103. function far_strlen(selector : word;linear_address : sizeuint) : longint;assembler;
  104. asm
  105. movl linear_address,%edx
  106. movl %edx,%ecx
  107. movw selector,%gs
  108. .Larg19:
  109. movb %gs:(%edx),%al
  110. testb %al,%al
  111. je .Larg20
  112. incl %edx
  113. jmp .Larg19
  114. .Larg20:
  115. movl %edx,%eax
  116. subl %ecx,%eax
  117. end;
  118. function get_ds : word;assembler;
  119. asm
  120. movw %ds,%ax
  121. end;
  122. function get_cs : word;assembler;
  123. asm
  124. movw %cs,%ax
  125. end;
  126. function dos_selector : word; assembler;
  127. asm
  128. movw %ds,%ax { no separate selector needed }
  129. end;
  130. procedure alloc_tb; assembler;
  131. { allocate 8kB real mode transfer buffer }
  132. asm
  133. pushl %ebx
  134. movw $0x100,%ax
  135. movw $512,%bx
  136. int $0x31
  137. movw %ax,tb_segment
  138. shll $16,%eax
  139. shrl $12,%eax
  140. movl %eax,tb
  141. popl %ebx
  142. end;
  143. procedure sysseg_move(sseg : word;source : sizeuint;dseg : word;dest : sizeuint;count : longint);
  144. begin
  145. if count=0 then
  146. exit;
  147. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  148. asm
  149. pushl %esi
  150. pushl %edi
  151. pushw %es
  152. pushw %ds
  153. cld
  154. movl count,%ecx
  155. movl source,%esi
  156. movl dest,%edi
  157. movw dseg,%ax
  158. movw %ax,%es
  159. movw sseg,%ax
  160. movw %ax,%ds
  161. movl %ecx,%eax
  162. shrl $2,%ecx
  163. rep
  164. movsl
  165. movl %eax,%ecx
  166. andl $3,%ecx
  167. rep
  168. movsb
  169. popw %ds
  170. popw %es
  171. popl %edi
  172. popl %esi
  173. end
  174. else if (source<dest) then
  175. { copy backward for overlapping }
  176. asm
  177. pushl %esi
  178. pushl %edi
  179. pushw %es
  180. pushw %ds
  181. std
  182. movl count,%ecx
  183. movl source,%esi
  184. movl dest,%edi
  185. movw dseg,%ax
  186. movw %ax,%es
  187. movw sseg,%ax
  188. movw %ax,%ds
  189. addl %ecx,%esi
  190. addl %ecx,%edi
  191. movl %ecx,%eax
  192. andl $3,%ecx
  193. orl %ecx,%ecx
  194. jz .LSEG_MOVE1
  195. { calculate esi and edi}
  196. decl %esi
  197. decl %edi
  198. rep
  199. movsb
  200. incl %esi
  201. incl %edi
  202. .LSEG_MOVE1:
  203. subl $4,%esi
  204. subl $4,%edi
  205. movl %eax,%ecx
  206. shrl $2,%ecx
  207. rep
  208. movsl
  209. cld
  210. popw %ds
  211. popw %es
  212. popl %edi
  213. popl %esi
  214. end;
  215. end;
  216. var psp_selector:word; external name 'PSP_SELECTOR';
  217. procedure setup_arguments;
  218. type
  219. arrayword = array [0..255] of word;
  220. var
  221. proxy_s : string[50];
  222. proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  223. rm_argv : ^arrayword;
  224. argv0len : longint;
  225. useproxy : boolean;
  226. hp : ppchar;
  227. doscmd : string[129]; { Dos commandline copied from PSP, max is 128 chars +1 for terminating zero }
  228. arglen,
  229. count : longint;
  230. argstart,
  231. pc,arg : pchar;
  232. quote : char;
  233. argvlen : longint;
  234. function atohex(s : pchar) : longint;
  235. var
  236. rv : longint;
  237. v : byte;
  238. begin
  239. rv:=0;
  240. while (s^<>#0) do
  241. begin
  242. v:=byte(s^)-byte('0');
  243. if (v > 9) then
  244. dec(v,7);
  245. v:=v and 15; { in case it's lower case }
  246. rv:=(rv shl 4) or v;
  247. inc(longint(s));
  248. end;
  249. atohex:=rv;
  250. end;
  251. procedure allocarg(idx,len:longint);
  252. var oldargvlen:longint;
  253. begin
  254. if idx>=argvlen then
  255. begin
  256. oldargvlen:=argvlen;
  257. argvlen:=(idx+8) and (not 7);
  258. sysreallocmem(argv,argvlen*sizeof(pointer));
  259. fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
  260. argv[idx]:=nil;
  261. end;
  262. ArgV [Idx] := SysAllocMem (Succ (Len));
  263. end;
  264. begin
  265. count:=0;
  266. argc:=1;
  267. argv:=nil;
  268. argvlen:=0;
  269. { load commandline from psp }
  270. sysseg_move(psp_selector, 128, get_ds, longint(@doscmd), 128);
  271. doscmd[length(doscmd)+1]:=#0;
  272. {$IfDef SYSTEM_DEBUG_STARTUP}
  273. Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
  274. {$EndIf }
  275. { create argv[0] }
  276. argv0len:=strlen(dos_argv0);
  277. allocarg(count,argv0len);
  278. move(dos_argv0^,argv[count]^,argv0len);
  279. inc(count);
  280. { setup cmdline variable }
  281. cmdline:=Getmem(argv0len+length(doscmd)+2);
  282. move(dos_argv0^,cmdline^,argv0len);
  283. cmdline[argv0len]:=' ';
  284. inc(argv0len);
  285. move(doscmd[1],cmdline[argv0len],length(doscmd));
  286. cmdline[argv0len+length(doscmd)+1]:=#0;
  287. { parse dos commandline }
  288. pc:=@doscmd[1];
  289. while pc^<>#0 do
  290. begin
  291. { skip leading spaces }
  292. while pc^ in [#1..#32] do
  293. inc(pc);
  294. if pc^=#0 then
  295. break;
  296. { calc argument length }
  297. quote:=' ';
  298. argstart:=pc;
  299. arglen:=0;
  300. while (pc^<>#0) do
  301. begin
  302. case pc^ of
  303. #1..#32 :
  304. begin
  305. if quote<>' ' then
  306. inc(arglen)
  307. else
  308. break;
  309. end;
  310. '"' :
  311. begin
  312. if quote<>'''' then
  313. begin
  314. if pchar(pc+1)^<>'"' then
  315. begin
  316. if quote='"' then
  317. quote:=' '
  318. else
  319. quote:='"';
  320. end
  321. else
  322. inc(pc);
  323. end
  324. else
  325. inc(arglen);
  326. end;
  327. '''' :
  328. begin
  329. if quote<>'"' then
  330. begin
  331. if pchar(pc+1)^<>'''' then
  332. begin
  333. if quote='''' then
  334. quote:=' '
  335. else
  336. quote:='''';
  337. end
  338. else
  339. inc(pc);
  340. end
  341. else
  342. inc(arglen);
  343. end;
  344. else
  345. inc(arglen);
  346. end;
  347. inc(pc);
  348. end;
  349. { copy argument }
  350. allocarg(count,arglen);
  351. quote:=' ';
  352. pc:=argstart;
  353. arg:=argv[count];
  354. while (pc^<>#0) do
  355. begin
  356. case pc^ of
  357. #1..#32 :
  358. begin
  359. if quote<>' ' then
  360. begin
  361. arg^:=pc^;
  362. inc(arg);
  363. end
  364. else
  365. break;
  366. end;
  367. '"' :
  368. begin
  369. if quote<>'''' then
  370. begin
  371. if pchar(pc+1)^<>'"' then
  372. begin
  373. if quote='"' then
  374. quote:=' '
  375. else
  376. quote:='"';
  377. end
  378. else
  379. inc(pc);
  380. end
  381. else
  382. begin
  383. arg^:=pc^;
  384. inc(arg);
  385. end;
  386. end;
  387. '''' :
  388. begin
  389. if quote<>'"' then
  390. begin
  391. if pchar(pc+1)^<>'''' then
  392. begin
  393. if quote='''' then
  394. quote:=' '
  395. else
  396. quote:='''';
  397. end
  398. else
  399. inc(pc);
  400. end
  401. else
  402. begin
  403. arg^:=pc^;
  404. inc(arg);
  405. end;
  406. end;
  407. else
  408. begin
  409. arg^:=pc^;
  410. inc(arg);
  411. end;
  412. end;
  413. inc(pc);
  414. end;
  415. arg^:=#0;
  416. {$IfDef SYSTEM_DEBUG_STARTUP}
  417. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  418. {$EndIf SYSTEM_DEBUG_STARTUP}
  419. inc(count);
  420. end;
  421. argc:=count;
  422. { check for !proxy for long commandlines passed using environment }
  423. hp:=envp;
  424. useproxy:=false;
  425. while assigned(hp^) do
  426. begin
  427. if (hp^[0]=' ') then
  428. begin
  429. proxy_s:=strpas(hp^);
  430. if Copy(proxy_s,1,7)=' !proxy' then
  431. begin
  432. proxy_s[13]:=#0;
  433. proxy_s[18]:=#0;
  434. proxy_s[23]:=#0;
  435. argv[2]:=@proxy_s[9];
  436. argv[3]:=@proxy_s[14];
  437. argv[4]:=@proxy_s[19];
  438. useproxy:=true;
  439. break;
  440. end;
  441. end;
  442. inc(hp);
  443. end;
  444. { check for !proxy for long commandlines passed using commandline }
  445. if (not useproxy) and
  446. (argc > 1) and (far_strlen(get_ds,longint(argv[1])) = 6) then
  447. begin
  448. move(argv[1]^,proxy_s[1],6);
  449. proxy_s[0] := #6;
  450. if (proxy_s = '!proxy') then
  451. useproxy:=true;
  452. end;
  453. { use proxy when found }
  454. if useproxy then
  455. begin
  456. proxy_argc:=atohex(argv[2]);
  457. proxy_seg:=atohex(argv[3]);
  458. proxy_ofs:=atohex(argv[4]);
  459. {$IfDef SYSTEM_DEBUG_STARTUP}
  460. Writeln(stderr,'proxy command line found');
  461. writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs);
  462. {$EndIf SYSTEM_DEBUG_STARTUP}
  463. rm_argv:=SysGetmem(proxy_argc*sizeof(word));
  464. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  465. for count:=0 to proxy_argc - 1 do
  466. begin
  467. lin:=proxy_seg*16+rm_argv^[count];
  468. arglen:=far_strlen(dos_selector,lin);
  469. allocarg(count,arglen);
  470. sysseg_move(dos_selector,lin,get_ds,longint(argv[count]),arglen+1);
  471. {$IfDef SYSTEM_DEBUG_STARTUP}
  472. Writeln(stderr,'arg ',count,' #',rm_argv^[count],'#',arglen,'#',argv[count],'#');
  473. {$EndIf SYSTEM_DEBUG_STARTUP}
  474. end;
  475. SysFreemem(rm_argv);
  476. argc:=proxy_argc;
  477. end;
  478. { create an nil entry }
  479. allocarg(argc,0);
  480. { free unused memory }
  481. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  482. end;
  483. function strcopy(dest,source : pchar) : pchar;assembler;
  484. var
  485. saveeax,saveesi,saveedi : longint;
  486. asm
  487. movl %edi,saveedi
  488. movl %esi,saveesi
  489. {$ifdef REGCALL}
  490. movl %eax,saveeax
  491. movl %edx,%edi
  492. {$else}
  493. movl source,%edi
  494. {$endif}
  495. testl %edi,%edi
  496. jz .LStrCopyDone
  497. leal 3(%edi),%ecx
  498. andl $-4,%ecx
  499. movl %edi,%esi
  500. subl %edi,%ecx
  501. {$ifdef REGCALL}
  502. movl %eax,%edi
  503. {$else}
  504. movl dest,%edi
  505. {$endif}
  506. jz .LStrCopyAligned
  507. .LStrCopyAlignLoop:
  508. movb (%esi),%al
  509. incl %edi
  510. incl %esi
  511. testb %al,%al
  512. movb %al,-1(%edi)
  513. jz .LStrCopyDone
  514. decl %ecx
  515. jnz .LStrCopyAlignLoop
  516. .balign 16
  517. .LStrCopyAligned:
  518. movl (%esi),%eax
  519. movl %eax,%edx
  520. leal 0x0fefefeff(%eax),%ecx
  521. notl %edx
  522. addl $4,%esi
  523. andl %edx,%ecx
  524. andl $0x080808080,%ecx
  525. jnz .LStrCopyEndFound
  526. movl %eax,(%edi)
  527. addl $4,%edi
  528. jmp .LStrCopyAligned
  529. .LStrCopyEndFound:
  530. testl $0x0ff,%eax
  531. jz .LStrCopyByte
  532. testl $0x0ff00,%eax
  533. jz .LStrCopyWord
  534. testl $0x0ff0000,%eax
  535. jz .LStrCopy3Bytes
  536. movl %eax,(%edi)
  537. jmp .LStrCopyDone
  538. .LStrCopy3Bytes:
  539. xorb %dl,%dl
  540. movw %ax,(%edi)
  541. movb %dl,2(%edi)
  542. jmp .LStrCopyDone
  543. .LStrCopyWord:
  544. movw %ax,(%edi)
  545. jmp .LStrCopyDone
  546. .LStrCopyByte:
  547. movb %al,(%edi)
  548. .LStrCopyDone:
  549. {$ifdef REGCALL}
  550. movl saveeax,%eax
  551. {$else}
  552. movl dest,%eax
  553. {$endif}
  554. movl saveedi,%edi
  555. movl saveesi,%esi
  556. end;
  557. var
  558. env_selector:word; external name 'ENV_SELECTOR';
  559. env_size:longint; external name 'ENV_SIZE';
  560. procedure setup_environment;
  561. var env_count : longint;
  562. dos_env,cp : pchar;
  563. begin
  564. env_count:=0;
  565. dos_env:=getmem(env_size);
  566. sysseg_move(env_selector,$0, get_ds, longint(dos_env), env_size);
  567. cp:=dos_env;
  568. while cp ^ <> #0 do
  569. begin
  570. inc(env_count);
  571. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  572. inc(longint(cp)); { skip to next character }
  573. end;
  574. envp := sysgetmem((env_count+1) * sizeof(pchar));
  575. if (envp = nil) then exit;
  576. cp:=dos_env;
  577. env_count:=0;
  578. while cp^ <> #0 do
  579. begin
  580. envp[env_count] := sysgetmem(strlen(cp)+1);
  581. strcopy(envp[env_count], cp);
  582. {$IfDef SYSTEM_DEBUG_STARTUP}
  583. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  584. {$EndIf SYSTEM_DEBUG_STARTUP}
  585. inc(env_count);
  586. while (cp^ <> #0) do
  587. inc(longint(cp)); { skip to NUL }
  588. inc(longint(cp)); { skip to next character }
  589. end;
  590. envp[env_count]:=nil;
  591. longint(cp):=longint(cp)+3;
  592. dos_argv0 := sysgetmem(strlen(cp)+1);
  593. if (dos_argv0 = nil) then halt;
  594. strcopy(dos_argv0, cp);
  595. end;
  596. procedure syscopytodos(addr : sizeuint; len : longint);
  597. begin
  598. if len > tb_size then
  599. HandleError(217);
  600. sysseg_move(get_ds,addr,dos_selector,tb,len);
  601. end;
  602. procedure syscopyfromdos(addr : sizeuint; len : longint);
  603. begin
  604. if len > tb_size then
  605. HandleError(217);
  606. sysseg_move(dos_selector,tb,get_ds,addr,len);
  607. end;
  608. procedure sysrealintr(intnr : word;var regs : trealregs);
  609. begin
  610. regs.realsp:=0;
  611. regs.realss:=0;
  612. asm
  613. pushl %edi
  614. pushl %ebx
  615. pushw %fs
  616. movw intnr,%bx
  617. xorl %ecx,%ecx
  618. movl regs,%edi
  619. movw $0x300,%ax
  620. int $0x31
  621. popw %fs
  622. popl %ebx
  623. popl %edi
  624. end;
  625. end;
  626. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  627. begin
  628. asm
  629. pushl %ebx
  630. movl intaddr,%eax
  631. movl (%eax),%edx
  632. movw 4(%eax),%cx
  633. movl $0x205,%eax
  634. movb vector,%bl
  635. int $0x31
  636. popl %ebx
  637. end;
  638. end;
  639. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  640. begin
  641. asm
  642. pushl %ebx
  643. movb vector,%bl
  644. movl $0x204,%eax
  645. int $0x31
  646. movl intaddr,%eax
  647. movl %edx,(%eax)
  648. movw %cx,4(%eax)
  649. popl %ebx
  650. end;
  651. end;
  652. procedure getinoutres(def : word);
  653. var
  654. regs : trealregs;
  655. begin
  656. regs.realeax:=$5900;
  657. regs.realebx:=$0;
  658. sysrealintr($21,regs);
  659. InOutRes:=lo(regs.realeax);
  660. case InOutRes of
  661. 19 : InOutRes:=150;
  662. 21 : InOutRes:=152;
  663. 32 : InOutRes:=5;
  664. end;
  665. if InOutRes=0 then
  666. InOutRes:=Def;
  667. end;
  668. { Keep Track of open files }
  669. const
  670. max_files = 50;
  671. var
  672. openfiles : array [0..max_files-1] of boolean;
  673. {$ifdef SYSTEMDEBUG}
  674. opennames : array [0..max_files-1] of pchar;
  675. const
  676. free_closed_names : boolean = true;
  677. {$endif SYSTEMDEBUG}
  678. {*****************************************************************************
  679. System Dependent Exit code
  680. *****************************************************************************}
  681. procedure ___exit(exitcode:longint);cdecl;external name '___exit';
  682. procedure do_close(handle : longint);forward;
  683. Procedure system_exit;
  684. var
  685. h : byte;
  686. begin
  687. for h:=0 to max_files-1 do
  688. if openfiles[h] then
  689. begin
  690. {$ifdef SYSTEMDEBUG}
  691. writeln(stderr,'file ',opennames[h],' not closed at exit');
  692. {$endif SYSTEMDEBUG}
  693. if h>=5 then
  694. do_close(h);
  695. end;
  696. { halt is not allways called !! }
  697. { not on normal exit !! PM }
  698. set_pm_interrupt($00,old_int00);
  699. {$ifndef EXCEPTIONS_IN_SYSTEM}
  700. set_pm_interrupt($75,old_int75);
  701. {$endif EXCEPTIONS_IN_SYSTEM}
  702. ___exit(exitcode);
  703. end;
  704. procedure new_int00;
  705. begin
  706. HandleError(200);
  707. end;
  708. {$ifndef EXCEPTIONS_IN_SYSTEM}
  709. procedure new_int75;
  710. begin
  711. asm
  712. xorl %eax,%eax
  713. outb %al,$0x0f0
  714. movb $0x20,%al
  715. outb %al,$0x0a0
  716. outb %al,$0x020
  717. end;
  718. HandleError(200);
  719. end;
  720. {$endif EXCEPTIONS_IN_SYSTEM}
  721. var
  722. __stkbottom : pointer;//###########external name '__stkbottom';
  723. {*****************************************************************************
  724. ParamStr/Randomize
  725. *****************************************************************************}
  726. function paramcount : longint;
  727. begin
  728. paramcount := argc - 1;
  729. end;
  730. function paramstr(l : longint) : string;
  731. begin
  732. if (l>=0) and (l+1<=argc) then
  733. paramstr:=strpas(argv[l])
  734. else
  735. paramstr:='';
  736. end;
  737. procedure randomize;
  738. var
  739. hl : longint;
  740. regs : trealregs;
  741. begin
  742. regs.realeax:=$2c00;
  743. sysrealintr($21,regs);
  744. hl:=lo(regs.realedx);
  745. randseed:=hl*$10000+ lo(regs.realecx);
  746. end;
  747. {*****************************************************************************
  748. OS Memory allocation / deallocation
  749. ****************************************************************************}
  750. function ___sbrk(size:longint):pointer;cdecl; external name '___sbrk';
  751. function SysOSAlloc(size: ptrint): pointer;assembler;
  752. asm
  753. {$ifdef SYSTEMDEBUG}
  754. cmpb $1,accept_sbrk
  755. je .Lsbrk
  756. movl $0,%eax
  757. jmp .Lsbrk_fail
  758. .Lsbrk:
  759. {$endif}
  760. movl size,%eax
  761. pushl %eax
  762. call ___sbrk
  763. addl $4,%esp
  764. {$ifdef SYSTEMDEBUG}
  765. .Lsbrk_fail:
  766. {$endif}
  767. end;
  768. { define HAS_SYSOSFREE}
  769. procedure SysOSFree(p: pointer; size: ptrint);
  770. begin
  771. end;
  772. { include standard heap management }
  773. {$include heap.inc}
  774. {****************************************************************************
  775. Low level File Routines
  776. ****************************************************************************}
  777. procedure AllowSlash(p:pchar);
  778. var
  779. i : longint;
  780. begin
  781. { allow slash as backslash }
  782. for i:=0 to strlen(p) do
  783. if p[i]='/' then p[i]:='\';
  784. end;
  785. procedure do_close(handle : longint);
  786. var
  787. regs : trealregs;
  788. begin
  789. if Handle<=4 then
  790. exit;
  791. regs.realebx:=handle;
  792. if handle<max_files then
  793. begin
  794. openfiles[handle]:=false;
  795. {$ifdef SYSTEMDEBUG}
  796. if assigned(opennames[handle]) and free_closed_names then
  797. begin
  798. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  799. opennames[handle]:=nil;
  800. end;
  801. {$endif SYSTEMDEBUG}
  802. end;
  803. regs.realeax:=$3e00;
  804. sysrealintr($21,regs);
  805. if (regs.realflags and carryflag) <> 0 then
  806. GetInOutRes(lo(regs.realeax));
  807. end;
  808. procedure do_erase(p : pchar);
  809. var
  810. regs : trealregs;
  811. begin
  812. AllowSlash(p);
  813. syscopytodos(longint(p),strlen(p)+1);
  814. regs.realedx:=tb_offset;
  815. regs.realds:=tb_segment;
  816. if LFNSupport then
  817. regs.realeax:=$7141
  818. else
  819. regs.realeax:=$4100;
  820. regs.realesi:=0;
  821. regs.realecx:=0;
  822. sysrealintr($21,regs);
  823. if (regs.realflags and carryflag) <> 0 then
  824. GetInOutRes(lo(regs.realeax));
  825. end;
  826. procedure do_rename(p1,p2 : pchar);
  827. var
  828. regs : trealregs;
  829. begin
  830. AllowSlash(p1);
  831. AllowSlash(p2);
  832. if strlen(p1)+strlen(p2)+3>tb_size then
  833. HandleError(217);
  834. sysseg_move(get_ds,sizeuint(p2),dos_selector,tb,strlen(p2)+1);
  835. sysseg_move(get_ds,sizeuint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  836. regs.realedi:=tb_offset;
  837. regs.realedx:=tb_offset + strlen(p2)+2;
  838. regs.realds:=tb_segment;
  839. regs.reales:=tb_segment;
  840. if LFNSupport then
  841. regs.realeax:=$7156
  842. else
  843. regs.realeax:=$5600;
  844. regs.realecx:=$ff; { attribute problem here ! }
  845. sysrealintr($21,regs);
  846. if (regs.realflags and carryflag) <> 0 then
  847. GetInOutRes(lo(regs.realeax));
  848. end;
  849. function do_write(h:longint;addr:pointer;len : longint) : longint;
  850. var
  851. regs : trealregs;
  852. size,
  853. writesize : longint;
  854. begin
  855. writesize:=0;
  856. while len > 0 do
  857. begin
  858. if len>tb_size then
  859. size:=tb_size
  860. else
  861. size:=len;
  862. syscopytodos(ptrint(addr)+writesize,size);
  863. regs.realecx:=size;
  864. regs.realedx:=tb_offset;
  865. regs.realds:=tb_segment;
  866. regs.realebx:=h;
  867. regs.realeax:=$4000;
  868. sysrealintr($21,regs);
  869. if (regs.realflags and carryflag) <> 0 then
  870. begin
  871. GetInOutRes(lo(regs.realeax));
  872. exit(writesize);
  873. end;
  874. inc(writesize,lo(regs.realeax));
  875. dec(len,lo(regs.realeax));
  876. { stop when not the specified size is written }
  877. if lo(regs.realeax)<size then
  878. break;
  879. end;
  880. Do_Write:=WriteSize;
  881. end;
  882. function do_read(h:longint;addr:pointer;len : longint) : longint;
  883. var
  884. regs : trealregs;
  885. size,
  886. readsize : longint;
  887. begin
  888. readsize:=0;
  889. while len > 0 do
  890. begin
  891. if len>tb_size then
  892. size:=tb_size
  893. else
  894. size:=len;
  895. regs.realecx:=size;
  896. regs.realedx:=tb_offset;
  897. regs.realds:=tb_segment;
  898. regs.realebx:=h;
  899. regs.realeax:=$3f00;
  900. sysrealintr($21,regs);
  901. if (regs.realflags and carryflag) <> 0 then
  902. begin
  903. GetInOutRes(lo(regs.realeax));
  904. do_read:=0;
  905. exit;
  906. end;
  907. syscopyfromdos(ptrint(addr)+readsize,lo(regs.realeax));
  908. inc(readsize,lo(regs.realeax));
  909. dec(len,lo(regs.realeax));
  910. { stop when not the specified size is read }
  911. if lo(regs.realeax)<size then
  912. break;
  913. end;
  914. do_read:=readsize;
  915. end;
  916. function do_filepos(handle : longint) : longint;
  917. var
  918. regs : trealregs;
  919. begin
  920. regs.realebx:=handle;
  921. regs.realecx:=0;
  922. regs.realedx:=0;
  923. regs.realeax:=$4201;
  924. sysrealintr($21,regs);
  925. if (regs.realflags and carryflag) <> 0 then
  926. Begin
  927. GetInOutRes(lo(regs.realeax));
  928. do_filepos:=0;
  929. end
  930. else
  931. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  932. end;
  933. procedure do_seek(handle,pos : longint);
  934. var
  935. regs : trealregs;
  936. begin
  937. regs.realebx:=handle;
  938. regs.realecx:=pos shr 16;
  939. regs.realedx:=pos and $ffff;
  940. regs.realeax:=$4200;
  941. sysrealintr($21,regs);
  942. if (regs.realflags and carryflag) <> 0 then
  943. GetInOutRes(lo(regs.realeax));
  944. end;
  945. function do_seekend(handle:longint):longint;
  946. var
  947. regs : trealregs;
  948. begin
  949. regs.realebx:=handle;
  950. regs.realecx:=0;
  951. regs.realedx:=0;
  952. regs.realeax:=$4202;
  953. sysrealintr($21,regs);
  954. if (regs.realflags and carryflag) <> 0 then
  955. Begin
  956. GetInOutRes(lo(regs.realeax));
  957. do_seekend:=0;
  958. end
  959. else
  960. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  961. end;
  962. function do_filesize(handle : longint) : longint;
  963. var
  964. aktfilepos : longint;
  965. begin
  966. aktfilepos:=do_filepos(handle);
  967. do_filesize:=do_seekend(handle);
  968. do_seek(handle,aktfilepos);
  969. end;
  970. { truncate at a given position }
  971. procedure do_truncate (handle,pos:longint);
  972. var
  973. regs : trealregs;
  974. begin
  975. do_seek(handle,pos);
  976. regs.realecx:=0;
  977. regs.realedx:=tb_offset;
  978. regs.realds:=tb_segment;
  979. regs.realebx:=handle;
  980. regs.realeax:=$4000;
  981. sysrealintr($21,regs);
  982. if (regs.realflags and carryflag) <> 0 then
  983. GetInOutRes(lo(regs.realeax));
  984. end;
  985. const
  986. FileHandleCount : longint = 20;
  987. function Increase_file_handle_count : boolean;
  988. var
  989. regs : trealregs;
  990. begin
  991. Inc(FileHandleCount,10);
  992. regs.realebx:=FileHandleCount;
  993. regs.realeax:=$6700;
  994. sysrealintr($21,regs);
  995. if (regs.realflags and carryflag) <> 0 then
  996. begin
  997. Increase_file_handle_count:=false;
  998. Dec (FileHandleCount, 10);
  999. end
  1000. else
  1001. Increase_file_handle_count:=true;
  1002. end;
  1003. function dos_version : word;
  1004. var
  1005. regs : trealregs;
  1006. begin
  1007. regs.realeax := $3000;
  1008. sysrealintr($21,regs);
  1009. dos_version := regs.realeax
  1010. end;
  1011. procedure do_open(var f;p:pchar;flags:longint);
  1012. {
  1013. filerec and textrec have both handle and mode as the first items so
  1014. they could use the same routine for opening/creating.
  1015. when (flags and $100) the file will be append
  1016. when (flags and $1000) the file will be truncate/rewritten
  1017. when (flags and $10000) there is no check for close (needed for textfiles)
  1018. }
  1019. var
  1020. regs : trealregs;
  1021. action : longint;
  1022. Avoid6c00 : boolean;
  1023. begin
  1024. AllowSlash(p);
  1025. { check if Extended Open/Create API is safe to use }
  1026. Avoid6c00 := lo(dos_version) < 7;
  1027. { close first if opened }
  1028. if ((flags and $10000)=0) then
  1029. begin
  1030. case filerec(f).mode of
  1031. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  1032. fmclosed : ;
  1033. else
  1034. begin
  1035. inoutres:=102; {not assigned}
  1036. exit;
  1037. end;
  1038. end;
  1039. end;
  1040. { reset file handle }
  1041. filerec(f).handle:=UnusedHandle;
  1042. action:=$1;
  1043. { convert filemode to filerec modes }
  1044. case (flags and 3) of
  1045. 0 : filerec(f).mode:=fminput;
  1046. 1 : filerec(f).mode:=fmoutput;
  1047. 2 : filerec(f).mode:=fminout;
  1048. end;
  1049. if (flags and $1000)<>0 then
  1050. action:=$12; {create file function}
  1051. { empty name is special }
  1052. if p[0]=#0 then
  1053. begin
  1054. case FileRec(f).mode of
  1055. fminput :
  1056. FileRec(f).Handle:=StdInputHandle;
  1057. fminout, { this is set by rewrite }
  1058. fmoutput :
  1059. FileRec(f).Handle:=StdOutputHandle;
  1060. fmappend :
  1061. begin
  1062. FileRec(f).Handle:=StdOutputHandle;
  1063. FileRec(f).mode:=fmoutput; {fool fmappend}
  1064. end;
  1065. end;
  1066. exit;
  1067. end;
  1068. { real dos call }
  1069. syscopytodos(longint(p),strlen(p)+1);
  1070. {$ifndef RTLLITE}
  1071. if LFNSupport then
  1072. regs.realeax := $716c { Use LFN Open/Create API }
  1073. else
  1074. regs.realeax:=$6c00;
  1075. {$endif RTLLITE}
  1076. if Avoid6c00 then
  1077. regs.realeax := $3d00 + (flags and $ff) { For now, map to Open API }
  1078. else
  1079. regs.realeax := $6c00; { Use Extended Open/Create API }
  1080. if byte(regs.realeax shr 8) = $3d then
  1081. begin { Using the older Open or Create API's }
  1082. if (action and $00f0) <> 0 then
  1083. regs.realeax := $3c00; { Map to Create/Replace API }
  1084. regs.realds := tb_segment;
  1085. regs.realedx := tb_offset;
  1086. end
  1087. else
  1088. begin { Using LFN or Extended Open/Create API }
  1089. regs.realedx := action; { action if file does/doesn't exist }
  1090. regs.realds := tb_segment;
  1091. regs.realesi := tb_offset;
  1092. regs.realebx := $2000 + (flags and $ff); { file open mode }
  1093. end;
  1094. regs.realecx := $20; { file attributes }
  1095. sysrealintr($21,regs);
  1096. {$ifndef RTLLITE}
  1097. if (regs.realflags and carryflag) <> 0 then
  1098. if lo(regs.realeax)=4 then
  1099. if Increase_file_handle_count then
  1100. begin
  1101. { Try again }
  1102. if LFNSupport then
  1103. regs.realeax := $716c {Use LFN Open/Create API}
  1104. else
  1105. if Avoid6c00 then
  1106. regs.realeax := $3d00+(flags and $ff) {For now, map to Open API}
  1107. else
  1108. regs.realeax := $6c00; {Use Extended Open/Create API}
  1109. if byte(regs.realeax shr 8) = $3d then
  1110. begin { Using the older Open or Create API's }
  1111. if (action and $00f0) <> 0 then
  1112. regs.realeax := $3c00; {Map to Create/Replace API}
  1113. regs.realds := tb_segment;
  1114. regs.realedx := tb_offset;
  1115. end
  1116. else
  1117. begin { Using LFN or Extended Open/Create API }
  1118. regs.realedx := action; {action if file does/doesn't exist}
  1119. regs.realds := tb_segment;
  1120. regs.realesi := tb_offset;
  1121. regs.realebx := $2000+(flags and $ff); {file open mode}
  1122. end;
  1123. regs.realecx := $20; {file attributes}
  1124. sysrealintr($21,regs);
  1125. end;
  1126. {$endif RTLLITE}
  1127. if (regs.realflags and carryflag) <> 0 then
  1128. begin
  1129. GetInOutRes(lo(regs.realeax));
  1130. exit;
  1131. end
  1132. else
  1133. begin
  1134. filerec(f).handle:=lo(regs.realeax);
  1135. {$ifndef RTLLITE}
  1136. { for systems that have more then 20 by default ! }
  1137. if lo(regs.realeax)>FileHandleCount then
  1138. FileHandleCount:=lo(regs.realeax);
  1139. {$endif RTLLITE}
  1140. end;
  1141. if lo(regs.realeax)<max_files then
  1142. begin
  1143. {$ifdef SYSTEMDEBUG}
  1144. if openfiles[lo(regs.realeax)] and
  1145. assigned(opennames[lo(regs.realeax)]) then
  1146. begin
  1147. Writeln(stderr,'file ',opennames[lo(regs.realeax)],'(',lo(regs.realeax),') not closed but handle reused!');
  1148. sysfreememsize(opennames[lo(regs.realeax)],strlen(opennames[lo(regs.realeax)])+1);
  1149. end;
  1150. {$endif SYSTEMDEBUG}
  1151. openfiles[lo(regs.realeax)]:=true;
  1152. {$ifdef SYSTEMDEBUG}
  1153. opennames[lo(regs.realeax)] := sysgetmem(strlen(p)+1);
  1154. move(p^,opennames[lo(regs.realeax)]^,strlen(p)+1);
  1155. {$endif SYSTEMDEBUG}
  1156. end;
  1157. { append mode }
  1158. if ((flags and $100) <> 0) and
  1159. (FileRec (F).Handle <> UnusedHandle) then
  1160. begin
  1161. do_seekend(filerec(f).handle);
  1162. filerec(f).mode:=fmoutput; {fool fmappend}
  1163. end;
  1164. end;
  1165. function do_isdevice(handle:THandle):boolean;
  1166. var
  1167. regs : trealregs;
  1168. begin
  1169. regs.realebx:=handle;
  1170. regs.realeax:=$4400;
  1171. sysrealintr($21,regs);
  1172. do_isdevice:=(regs.realedx and $80)<>0;
  1173. if (regs.realflags and carryflag) <> 0 then
  1174. GetInOutRes(lo(regs.realeax));
  1175. end;
  1176. {*****************************************************************************
  1177. UnTyped File Handling
  1178. *****************************************************************************}
  1179. {$i file.inc}
  1180. {*****************************************************************************
  1181. Typed File Handling
  1182. *****************************************************************************}
  1183. {$i typefile.inc}
  1184. {*****************************************************************************
  1185. Text File Handling
  1186. *****************************************************************************}
  1187. {$i text.inc}
  1188. {*****************************************************************************
  1189. Generic Handling
  1190. *****************************************************************************}
  1191. {$ifdef TEST_GENERIC}
  1192. {$i generic.inc}
  1193. {$endif TEST_GENERIC}
  1194. {*****************************************************************************
  1195. Directory Handling
  1196. *****************************************************************************}
  1197. procedure DosDir(func:byte;const s:string);
  1198. var
  1199. buffer : array[0..255] of char;
  1200. regs : trealregs;
  1201. begin
  1202. move(s[1],buffer,length(s));
  1203. buffer[length(s)]:=#0;
  1204. AllowSlash(pchar(@buffer));
  1205. { True DOS does not like backslashes at end
  1206. Win95 DOS accepts this !!
  1207. but "\" and "c:\" should still be kept and accepted hopefully PM }
  1208. if (length(s)>0) and (buffer[length(s)-1]='\') and
  1209. Not ((length(s)=1) or ((length(s)=3) and (s[2]=':'))) then
  1210. buffer[length(s)-1]:=#0;
  1211. syscopytodos(longint(@buffer),length(s)+1);
  1212. regs.realedx:=tb_offset;
  1213. regs.realds:=tb_segment;
  1214. if LFNSupport then
  1215. regs.realeax:=$7100+func
  1216. else
  1217. regs.realeax:=func shl 8;
  1218. sysrealintr($21,regs);
  1219. if (regs.realflags and carryflag) <> 0 then
  1220. GetInOutRes(lo(regs.realeax));
  1221. end;
  1222. procedure mkdir(const s : string);[IOCheck];
  1223. begin
  1224. If (s='') or (InOutRes <> 0) then
  1225. exit;
  1226. DosDir($39,s);
  1227. end;
  1228. procedure rmdir(const s : string);[IOCheck];
  1229. begin
  1230. if (s = '.' ) then
  1231. InOutRes := 16;
  1232. If (s='') or (InOutRes <> 0) then
  1233. exit;
  1234. DosDir($3a,s);
  1235. end;
  1236. procedure chdir(const s : string);[IOCheck];
  1237. var
  1238. regs : trealregs;
  1239. begin
  1240. If (s='') or (InOutRes <> 0) then
  1241. exit;
  1242. { First handle Drive changes }
  1243. if (length(s)>=2) and (s[2]=':') then
  1244. begin
  1245. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  1246. regs.realeax:=$0e00;
  1247. sysrealintr($21,regs);
  1248. regs.realeax:=$1900;
  1249. sysrealintr($21,regs);
  1250. if byte(regs.realeax)<>byte(regs.realedx) then
  1251. begin
  1252. Inoutres:=15;
  1253. exit;
  1254. end;
  1255. { DosDir($3b,'c:') give Path not found error on
  1256. pure DOS PM }
  1257. if length(s)=2 then
  1258. exit;
  1259. end;
  1260. { do the normal dos chdir }
  1261. DosDir($3b,s);
  1262. end;
  1263. procedure getdir(drivenr : byte;var dir : shortstring);
  1264. var
  1265. temp : array[0..255] of char;
  1266. i : longint;
  1267. regs : trealregs;
  1268. begin
  1269. regs.realedx:=drivenr;
  1270. regs.realesi:=tb_offset;
  1271. regs.realds:=tb_segment;
  1272. if LFNSupport then
  1273. regs.realeax:=$7147
  1274. else
  1275. regs.realeax:=$4700;
  1276. sysrealintr($21,regs);
  1277. if (regs.realflags and carryflag) <> 0 then
  1278. Begin
  1279. GetInOutRes(lo(regs.realeax));
  1280. Dir := char (DriveNr + 64) + ':\';
  1281. exit;
  1282. end
  1283. else
  1284. syscopyfromdos(longint(@temp),251);
  1285. { conversion to Pascal string including slash conversion }
  1286. i:=0;
  1287. while (temp[i]<>#0) do
  1288. begin
  1289. if temp[i]='/' then
  1290. temp[i]:='\';
  1291. dir[i+4]:=temp[i];
  1292. inc(i);
  1293. end;
  1294. dir[2]:=':';
  1295. dir[3]:='\';
  1296. dir[0]:=char(i+3);
  1297. { upcase the string }
  1298. if not FileNameCaseSensitive then
  1299. dir:=upcase(dir);
  1300. if drivenr<>0 then { Drive was supplied. We know it }
  1301. dir[1]:=char(65+drivenr-1)
  1302. else
  1303. begin
  1304. { We need to get the current drive from DOS function 19H }
  1305. { because the drive was the default, which can be unknown }
  1306. regs.realeax:=$1900;
  1307. sysrealintr($21,regs);
  1308. i:= (regs.realeax and $ff) + ord('A');
  1309. dir[1]:=chr(i);
  1310. end;
  1311. end;
  1312. {*****************************************************************************
  1313. SystemUnit Initialization
  1314. *****************************************************************************}
  1315. function CheckLFN:boolean;
  1316. var
  1317. regs : TRealRegs;
  1318. RootName : pchar;
  1319. begin
  1320. { Check LFN API on drive c:\ }
  1321. RootName:='C:\';
  1322. syscopytodos(longint(RootName),strlen(RootName)+1);
  1323. { Call 'Get Volume Information' ($71A0) }
  1324. regs.realeax:=$71a0;
  1325. regs.reales:=tb_segment;
  1326. regs.realedi:=tb_offset;
  1327. regs.realecx:=32;
  1328. regs.realds:=tb_segment;
  1329. regs.realedx:=tb_offset;
  1330. regs.realflags:=carryflag;
  1331. sysrealintr($21,regs);
  1332. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1333. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1334. end;
  1335. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1336. {$define IN_SYSTEM}
  1337. {$i dpmiexcp.pp}
  1338. {$endif EXCEPTIONS_IN_SYSTEM}
  1339. procedure SysInitStdIO;
  1340. begin
  1341. OpenStdIO(Input,fmInput,StdInputHandle);
  1342. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1343. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  1344. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1345. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1346. end;
  1347. function GetProcessID: SizeUInt;
  1348. begin
  1349. GetProcessID := 1;
  1350. end;
  1351. var
  1352. temp_int : tseginfo;
  1353. Begin
  1354. alloc_tb;
  1355. StackLength := InitialStkLen;
  1356. StackBottom := __stkbottom;
  1357. { To be set if this is a GUI or console application }
  1358. IsConsole := TRUE;
  1359. { To be set if this is a library and not a program }
  1360. IsLibrary := FALSE;
  1361. { save old int 0 and 75 }
  1362. get_pm_interrupt($00,old_int00);
  1363. get_pm_interrupt($75,old_int75);
  1364. temp_int.segment:=get_cs;
  1365. temp_int.offset:=@new_int00;
  1366. set_pm_interrupt($00,temp_int);
  1367. {$ifndef EXCEPTIONS_IN_SYSTEM}
  1368. temp_int.offset:=@new_int75;
  1369. set_pm_interrupt($75,temp_int);
  1370. {$endif EXCEPTIONS_IN_SYSTEM}
  1371. { Setup heap }
  1372. InitHeap;
  1373. SysInitExceptions;
  1374. { Setup stdin, stdout and stderr }
  1375. SysInitStdIO;
  1376. { Setup environment and arguments }
  1377. Setup_Environment;
  1378. Setup_Arguments;
  1379. { Use LFNSupport LFN }
  1380. LFNSupport:=CheckLFN;
  1381. if LFNSupport then
  1382. FileNameCaseSensitive:=true;
  1383. { Reset IO Error }
  1384. InOutRes:=0;
  1385. ThreadID := 1;
  1386. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1387. InitDPMIExcp;
  1388. InstallDefaultHandlers;
  1389. {$endif EXCEPTIONS_IN_SYSTEM}
  1390. initvariantmanager;
  1391. initwidestringmanager;
  1392. End.