system.pp 38 KB

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