system.pp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577
  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. { include standard heap management }
  778. {$include heap.inc}
  779. {****************************************************************************
  780. Low level File Routines
  781. ****************************************************************************}
  782. procedure AllowSlash(p:pchar);
  783. var
  784. i : longint;
  785. begin
  786. { allow slash as backslash }
  787. for i:=0 to strlen(p) do
  788. if p[i]='/' then p[i]:='\';
  789. end;
  790. procedure do_close(handle : longint);
  791. var
  792. regs : trealregs;
  793. begin
  794. if Handle<=4 then
  795. exit;
  796. regs.realebx:=handle;
  797. if handle<max_files then
  798. begin
  799. openfiles[handle]:=false;
  800. {$ifdef SYSTEMDEBUG}
  801. if assigned(opennames[handle]) and free_closed_names then
  802. begin
  803. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  804. opennames[handle]:=nil;
  805. end;
  806. {$endif SYSTEMDEBUG}
  807. end;
  808. regs.realeax:=$3e00;
  809. sysrealintr($21,regs);
  810. if (regs.realflags and carryflag) <> 0 then
  811. GetInOutRes(lo(regs.realeax));
  812. end;
  813. procedure do_erase(p : pchar);
  814. var
  815. regs : trealregs;
  816. begin
  817. AllowSlash(p);
  818. syscopytodos(longint(p),strlen(p)+1);
  819. regs.realedx:=tb_offset;
  820. regs.realds:=tb_segment;
  821. if LFNSupport then
  822. regs.realeax:=$7141
  823. else
  824. regs.realeax:=$4100;
  825. regs.realesi:=0;
  826. regs.realecx:=0;
  827. sysrealintr($21,regs);
  828. if (regs.realflags and carryflag) <> 0 then
  829. GetInOutRes(lo(regs.realeax));
  830. end;
  831. procedure do_rename(p1,p2 : pchar);
  832. var
  833. regs : trealregs;
  834. begin
  835. AllowSlash(p1);
  836. AllowSlash(p2);
  837. if strlen(p1)+strlen(p2)+3>tb_size then
  838. HandleError(217);
  839. sysseg_move(get_ds,sizeuint(p2),dos_selector,tb,strlen(p2)+1);
  840. sysseg_move(get_ds,sizeuint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  841. regs.realedi:=tb_offset;
  842. regs.realedx:=tb_offset + strlen(p2)+2;
  843. regs.realds:=tb_segment;
  844. regs.reales:=tb_segment;
  845. if LFNSupport then
  846. regs.realeax:=$7156
  847. else
  848. regs.realeax:=$5600;
  849. regs.realecx:=$ff; { attribute problem here ! }
  850. sysrealintr($21,regs);
  851. if (regs.realflags and carryflag) <> 0 then
  852. GetInOutRes(lo(regs.realeax));
  853. end;
  854. function do_write(h:longint;addr:pointer;len : longint) : longint;
  855. var
  856. regs : trealregs;
  857. size,
  858. writesize : longint;
  859. begin
  860. writesize:=0;
  861. while len > 0 do
  862. begin
  863. if len>tb_size then
  864. size:=tb_size
  865. else
  866. size:=len;
  867. syscopytodos(ptrint(addr)+writesize,size);
  868. regs.realecx:=size;
  869. regs.realedx:=tb_offset;
  870. regs.realds:=tb_segment;
  871. regs.realebx:=h;
  872. regs.realeax:=$4000;
  873. sysrealintr($21,regs);
  874. if (regs.realflags and carryflag) <> 0 then
  875. begin
  876. GetInOutRes(lo(regs.realeax));
  877. exit(writesize);
  878. end;
  879. inc(writesize,lo(regs.realeax));
  880. dec(len,lo(regs.realeax));
  881. { stop when not the specified size is written }
  882. if lo(regs.realeax)<size then
  883. break;
  884. end;
  885. Do_Write:=WriteSize;
  886. end;
  887. function do_read(h:longint;addr:pointer;len : longint) : longint;
  888. var
  889. regs : trealregs;
  890. size,
  891. readsize : longint;
  892. begin
  893. readsize:=0;
  894. while len > 0 do
  895. begin
  896. if len>tb_size then
  897. size:=tb_size
  898. else
  899. size:=len;
  900. regs.realecx:=size;
  901. regs.realedx:=tb_offset;
  902. regs.realds:=tb_segment;
  903. regs.realebx:=h;
  904. regs.realeax:=$3f00;
  905. sysrealintr($21,regs);
  906. if (regs.realflags and carryflag) <> 0 then
  907. begin
  908. GetInOutRes(lo(regs.realeax));
  909. do_read:=0;
  910. exit;
  911. end;
  912. syscopyfromdos(ptrint(addr)+readsize,lo(regs.realeax));
  913. inc(readsize,lo(regs.realeax));
  914. dec(len,lo(regs.realeax));
  915. { stop when not the specified size is read }
  916. if lo(regs.realeax)<size then
  917. break;
  918. end;
  919. do_read:=readsize;
  920. end;
  921. function do_filepos(handle : longint) : longint;
  922. var
  923. regs : trealregs;
  924. begin
  925. regs.realebx:=handle;
  926. regs.realecx:=0;
  927. regs.realedx:=0;
  928. regs.realeax:=$4201;
  929. sysrealintr($21,regs);
  930. if (regs.realflags and carryflag) <> 0 then
  931. Begin
  932. GetInOutRes(lo(regs.realeax));
  933. do_filepos:=0;
  934. end
  935. else
  936. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  937. end;
  938. procedure do_seek(handle,pos : longint);
  939. var
  940. regs : trealregs;
  941. begin
  942. regs.realebx:=handle;
  943. regs.realecx:=pos shr 16;
  944. regs.realedx:=pos and $ffff;
  945. regs.realeax:=$4200;
  946. sysrealintr($21,regs);
  947. if (regs.realflags and carryflag) <> 0 then
  948. GetInOutRes(lo(regs.realeax));
  949. end;
  950. function do_seekend(handle:longint):longint;
  951. var
  952. regs : trealregs;
  953. begin
  954. regs.realebx:=handle;
  955. regs.realecx:=0;
  956. regs.realedx:=0;
  957. regs.realeax:=$4202;
  958. sysrealintr($21,regs);
  959. if (regs.realflags and carryflag) <> 0 then
  960. Begin
  961. GetInOutRes(lo(regs.realeax));
  962. do_seekend:=0;
  963. end
  964. else
  965. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  966. end;
  967. function do_filesize(handle : longint) : longint;
  968. var
  969. aktfilepos : longint;
  970. begin
  971. aktfilepos:=do_filepos(handle);
  972. do_filesize:=do_seekend(handle);
  973. do_seek(handle,aktfilepos);
  974. end;
  975. { truncate at a given position }
  976. procedure do_truncate (handle,pos:longint);
  977. var
  978. regs : trealregs;
  979. begin
  980. do_seek(handle,pos);
  981. regs.realecx:=0;
  982. regs.realedx:=tb_offset;
  983. regs.realds:=tb_segment;
  984. regs.realebx:=handle;
  985. regs.realeax:=$4000;
  986. sysrealintr($21,regs);
  987. if (regs.realflags and carryflag) <> 0 then
  988. GetInOutRes(lo(regs.realeax));
  989. end;
  990. const
  991. FileHandleCount : longint = 20;
  992. function Increase_file_handle_count : boolean;
  993. var
  994. regs : trealregs;
  995. begin
  996. Inc(FileHandleCount,10);
  997. regs.realebx:=FileHandleCount;
  998. regs.realeax:=$6700;
  999. sysrealintr($21,regs);
  1000. if (regs.realflags and carryflag) <> 0 then
  1001. begin
  1002. Increase_file_handle_count:=false;
  1003. Dec (FileHandleCount, 10);
  1004. end
  1005. else
  1006. Increase_file_handle_count:=true;
  1007. end;
  1008. function dos_version : word;
  1009. var
  1010. regs : trealregs;
  1011. begin
  1012. regs.realeax := $3000;
  1013. sysrealintr($21,regs);
  1014. dos_version := regs.realeax
  1015. end;
  1016. procedure do_open(var f;p:pchar;flags:longint);
  1017. {
  1018. filerec and textrec have both handle and mode as the first items so
  1019. they could use the same routine for opening/creating.
  1020. when (flags and $100) the file will be append
  1021. when (flags and $1000) the file will be truncate/rewritten
  1022. when (flags and $10000) there is no check for close (needed for textfiles)
  1023. }
  1024. var
  1025. regs : trealregs;
  1026. action : longint;
  1027. Avoid6c00 : boolean;
  1028. begin
  1029. AllowSlash(p);
  1030. { check if Extended Open/Create API is safe to use }
  1031. Avoid6c00 := lo(dos_version) < 7;
  1032. { close first if opened }
  1033. if ((flags and $10000)=0) then
  1034. begin
  1035. case filerec(f).mode of
  1036. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  1037. fmclosed : ;
  1038. else
  1039. begin
  1040. inoutres:=102; {not assigned}
  1041. exit;
  1042. end;
  1043. end;
  1044. end;
  1045. { reset file handle }
  1046. filerec(f).handle:=UnusedHandle;
  1047. action:=$1;
  1048. { convert filemode to filerec modes }
  1049. case (flags and 3) of
  1050. 0 : filerec(f).mode:=fminput;
  1051. 1 : filerec(f).mode:=fmoutput;
  1052. 2 : filerec(f).mode:=fminout;
  1053. end;
  1054. if (flags and $1000)<>0 then
  1055. action:=$12; {create file function}
  1056. { empty name is special }
  1057. if p[0]=#0 then
  1058. begin
  1059. case FileRec(f).mode of
  1060. fminput :
  1061. FileRec(f).Handle:=StdInputHandle;
  1062. fminout, { this is set by rewrite }
  1063. fmoutput :
  1064. FileRec(f).Handle:=StdOutputHandle;
  1065. fmappend :
  1066. begin
  1067. FileRec(f).Handle:=StdOutputHandle;
  1068. FileRec(f).mode:=fmoutput; {fool fmappend}
  1069. end;
  1070. end;
  1071. exit;
  1072. end;
  1073. { real dos call }
  1074. syscopytodos(longint(p),strlen(p)+1);
  1075. {$ifndef RTLLITE}
  1076. if LFNSupport then
  1077. regs.realeax := $716c { Use LFN Open/Create API }
  1078. else
  1079. regs.realeax:=$6c00;
  1080. {$endif RTLLITE}
  1081. if Avoid6c00 then
  1082. regs.realeax := $3d00 + (flags and $ff) { For now, map to Open API }
  1083. else
  1084. regs.realeax := $6c00; { Use Extended Open/Create API }
  1085. if byte(regs.realeax shr 8) = $3d then
  1086. begin { Using the older Open or Create API's }
  1087. if (action and $00f0) <> 0 then
  1088. regs.realeax := $3c00; { Map to Create/Replace API }
  1089. regs.realds := tb_segment;
  1090. regs.realedx := tb_offset;
  1091. end
  1092. else
  1093. begin { Using LFN or Extended Open/Create API }
  1094. regs.realedx := action; { action if file does/doesn't exist }
  1095. regs.realds := tb_segment;
  1096. regs.realesi := tb_offset;
  1097. regs.realebx := $2000 + (flags and $ff); { file open mode }
  1098. end;
  1099. regs.realecx := $20; { file attributes }
  1100. sysrealintr($21,regs);
  1101. {$ifndef RTLLITE}
  1102. if (regs.realflags and carryflag) <> 0 then
  1103. if lo(regs.realeax)=4 then
  1104. if Increase_file_handle_count then
  1105. begin
  1106. { Try again }
  1107. if LFNSupport then
  1108. regs.realeax := $716c {Use LFN Open/Create API}
  1109. else
  1110. if Avoid6c00 then
  1111. regs.realeax := $3d00+(flags and $ff) {For now, map to Open API}
  1112. else
  1113. regs.realeax := $6c00; {Use Extended Open/Create API}
  1114. if byte(regs.realeax shr 8) = $3d then
  1115. begin { Using the older Open or Create API's }
  1116. if (action and $00f0) <> 0 then
  1117. regs.realeax := $3c00; {Map to Create/Replace API}
  1118. regs.realds := tb_segment;
  1119. regs.realedx := tb_offset;
  1120. end
  1121. else
  1122. begin { Using LFN or Extended Open/Create API }
  1123. regs.realedx := action; {action if file does/doesn't exist}
  1124. regs.realds := tb_segment;
  1125. regs.realesi := tb_offset;
  1126. regs.realebx := $2000+(flags and $ff); {file open mode}
  1127. end;
  1128. regs.realecx := $20; {file attributes}
  1129. sysrealintr($21,regs);
  1130. end;
  1131. {$endif RTLLITE}
  1132. if (regs.realflags and carryflag) <> 0 then
  1133. begin
  1134. GetInOutRes(lo(regs.realeax));
  1135. exit;
  1136. end
  1137. else
  1138. begin
  1139. filerec(f).handle:=lo(regs.realeax);
  1140. {$ifndef RTLLITE}
  1141. { for systems that have more then 20 by default ! }
  1142. if lo(regs.realeax)>FileHandleCount then
  1143. FileHandleCount:=lo(regs.realeax);
  1144. {$endif RTLLITE}
  1145. end;
  1146. if lo(regs.realeax)<max_files then
  1147. begin
  1148. {$ifdef SYSTEMDEBUG}
  1149. if openfiles[lo(regs.realeax)] and
  1150. assigned(opennames[lo(regs.realeax)]) then
  1151. begin
  1152. Writeln(stderr,'file ',opennames[lo(regs.realeax)],'(',lo(regs.realeax),') not closed but handle reused!');
  1153. sysfreememsize(opennames[lo(regs.realeax)],strlen(opennames[lo(regs.realeax)])+1);
  1154. end;
  1155. {$endif SYSTEMDEBUG}
  1156. openfiles[lo(regs.realeax)]:=true;
  1157. {$ifdef SYSTEMDEBUG}
  1158. opennames[lo(regs.realeax)] := sysgetmem(strlen(p)+1);
  1159. move(p^,opennames[lo(regs.realeax)]^,strlen(p)+1);
  1160. {$endif SYSTEMDEBUG}
  1161. end;
  1162. { append mode }
  1163. if ((flags and $100) <> 0) and
  1164. (FileRec (F).Handle <> UnusedHandle) then
  1165. begin
  1166. do_seekend(filerec(f).handle);
  1167. filerec(f).mode:=fmoutput; {fool fmappend}
  1168. end;
  1169. end;
  1170. function do_isdevice(handle:longint):boolean;
  1171. var
  1172. regs : trealregs;
  1173. begin
  1174. regs.realebx:=handle;
  1175. regs.realeax:=$4400;
  1176. sysrealintr($21,regs);
  1177. do_isdevice:=(regs.realedx and $80)<>0;
  1178. if (regs.realflags and carryflag) <> 0 then
  1179. GetInOutRes(lo(regs.realeax));
  1180. end;
  1181. {*****************************************************************************
  1182. UnTyped File Handling
  1183. *****************************************************************************}
  1184. {$i file.inc}
  1185. {*****************************************************************************
  1186. Typed File Handling
  1187. *****************************************************************************}
  1188. {$i typefile.inc}
  1189. {*****************************************************************************
  1190. Text File Handling
  1191. *****************************************************************************}
  1192. {$DEFINE EOF_CTRLZ}
  1193. {$i text.inc}
  1194. {*****************************************************************************
  1195. Generic Handling
  1196. *****************************************************************************}
  1197. {$ifdef TEST_GENERIC}
  1198. {$i generic.inc}
  1199. {$endif TEST_GENERIC}
  1200. {*****************************************************************************
  1201. Directory Handling
  1202. *****************************************************************************}
  1203. procedure DosDir(func:byte;const s:string);
  1204. var
  1205. buffer : array[0..255] of char;
  1206. regs : trealregs;
  1207. begin
  1208. move(s[1],buffer,length(s));
  1209. buffer[length(s)]:=#0;
  1210. AllowSlash(pchar(@buffer));
  1211. { True DOS does not like backslashes at end
  1212. Win95 DOS accepts this !!
  1213. but "\" and "c:\" should still be kept and accepted hopefully PM }
  1214. if (length(s)>0) and (buffer[length(s)-1]='\') and
  1215. Not ((length(s)=1) or ((length(s)=3) and (s[2]=':'))) then
  1216. buffer[length(s)-1]:=#0;
  1217. syscopytodos(longint(@buffer),length(s)+1);
  1218. regs.realedx:=tb_offset;
  1219. regs.realds:=tb_segment;
  1220. if LFNSupport then
  1221. regs.realeax:=$7100+func
  1222. else
  1223. regs.realeax:=func shl 8;
  1224. sysrealintr($21,regs);
  1225. if (regs.realflags and carryflag) <> 0 then
  1226. GetInOutRes(lo(regs.realeax));
  1227. end;
  1228. procedure mkdir(const s : string);[IOCheck];
  1229. begin
  1230. If (s='') or (InOutRes <> 0) then
  1231. exit;
  1232. DosDir($39,s);
  1233. end;
  1234. procedure rmdir(const s : string);[IOCheck];
  1235. begin
  1236. if (s = '.' ) then
  1237. InOutRes := 16;
  1238. If (s='') or (InOutRes <> 0) then
  1239. exit;
  1240. DosDir($3a,s);
  1241. end;
  1242. procedure chdir(const s : string);[IOCheck];
  1243. var
  1244. regs : trealregs;
  1245. begin
  1246. If (s='') or (InOutRes <> 0) then
  1247. exit;
  1248. { First handle Drive changes }
  1249. if (length(s)>=2) and (s[2]=':') then
  1250. begin
  1251. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  1252. regs.realeax:=$0e00;
  1253. sysrealintr($21,regs);
  1254. regs.realeax:=$1900;
  1255. sysrealintr($21,regs);
  1256. if byte(regs.realeax)<>byte(regs.realedx) then
  1257. begin
  1258. Inoutres:=15;
  1259. exit;
  1260. end;
  1261. { DosDir($3b,'c:') give Path not found error on
  1262. pure DOS PM }
  1263. if length(s)=2 then
  1264. exit;
  1265. end;
  1266. { do the normal dos chdir }
  1267. DosDir($3b,s);
  1268. end;
  1269. procedure getdir(drivenr : byte;var dir : shortstring);
  1270. var
  1271. temp : array[0..255] of char;
  1272. i : longint;
  1273. regs : trealregs;
  1274. begin
  1275. regs.realedx:=drivenr;
  1276. regs.realesi:=tb_offset;
  1277. regs.realds:=tb_segment;
  1278. if LFNSupport then
  1279. regs.realeax:=$7147
  1280. else
  1281. regs.realeax:=$4700;
  1282. sysrealintr($21,regs);
  1283. if (regs.realflags and carryflag) <> 0 then
  1284. Begin
  1285. GetInOutRes(lo(regs.realeax));
  1286. Dir := char (DriveNr + 64) + ':\';
  1287. exit;
  1288. end
  1289. else
  1290. syscopyfromdos(longint(@temp),251);
  1291. { conversion to Pascal string including slash conversion }
  1292. i:=0;
  1293. while (temp[i]<>#0) do
  1294. begin
  1295. if temp[i]='/' then
  1296. temp[i]:='\';
  1297. dir[i+4]:=temp[i];
  1298. inc(i);
  1299. end;
  1300. dir[2]:=':';
  1301. dir[3]:='\';
  1302. dir[0]:=char(i+3);
  1303. { upcase the string }
  1304. if not FileNameCaseSensitive then
  1305. dir:=upcase(dir);
  1306. if drivenr<>0 then { Drive was supplied. We know it }
  1307. dir[1]:=char(65+drivenr-1)
  1308. else
  1309. begin
  1310. { We need to get the current drive from DOS function 19H }
  1311. { because the drive was the default, which can be unknown }
  1312. regs.realeax:=$1900;
  1313. sysrealintr($21,regs);
  1314. i:= (regs.realeax and $ff) + ord('A');
  1315. dir[1]:=chr(i);
  1316. end;
  1317. end;
  1318. {*****************************************************************************
  1319. SystemUnit Initialization
  1320. *****************************************************************************}
  1321. function CheckLFN:boolean;
  1322. var
  1323. regs : TRealRegs;
  1324. RootName : pchar;
  1325. begin
  1326. { Check LFN API on drive c:\ }
  1327. RootName:='C:\';
  1328. syscopytodos(longint(RootName),strlen(RootName)+1);
  1329. { Call 'Get Volume Information' ($71A0) }
  1330. regs.realeax:=$71a0;
  1331. regs.reales:=tb_segment;
  1332. regs.realedi:=tb_offset;
  1333. regs.realecx:=32;
  1334. regs.realds:=tb_segment;
  1335. regs.realedx:=tb_offset;
  1336. regs.realflags:=carryflag;
  1337. sysrealintr($21,regs);
  1338. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1339. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1340. end;
  1341. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1342. {$define IN_SYSTEM}
  1343. {$i dpmiexcp.pp}
  1344. {$endif EXCEPTIONS_IN_SYSTEM}
  1345. procedure SysInitStdIO;
  1346. begin
  1347. OpenStdIO(Input,fmInput,StdInputHandle);
  1348. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1349. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1350. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1351. end;
  1352. var
  1353. temp_int : tseginfo;
  1354. Begin
  1355. alloc_tb;
  1356. StackLength := InitialStkLen;
  1357. StackBottom := __stkbottom;
  1358. { To be set if this is a GUI or console application }
  1359. IsConsole := TRUE;
  1360. { To be set if this is a library and not a program }
  1361. IsLibrary := FALSE;
  1362. { save old int 0 and 75 }
  1363. get_pm_interrupt($00,old_int00);
  1364. get_pm_interrupt($75,old_int75);
  1365. temp_int.segment:=get_cs;
  1366. temp_int.offset:=@new_int00;
  1367. set_pm_interrupt($00,temp_int);
  1368. {$ifndef EXCEPTIONS_IN_SYSTEM}
  1369. temp_int.offset:=@new_int75;
  1370. set_pm_interrupt($75,temp_int);
  1371. {$endif EXCEPTIONS_IN_SYSTEM}
  1372. { Setup heap }
  1373. InitHeap;
  1374. SysInitExceptions;
  1375. { Setup stdin, stdout and stderr }
  1376. SysInitStdIO;
  1377. { Setup environment and arguments }
  1378. Setup_Environment;
  1379. Setup_Arguments;
  1380. { Use LFNSupport LFN }
  1381. LFNSupport:=CheckLFN;
  1382. if LFNSupport then
  1383. FileNameCaseSensitive:=true;
  1384. { Reset IO Error }
  1385. InOutRes:=0;
  1386. ThreadID := 1;
  1387. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1388. InitDPMIExcp;
  1389. InstallDefaultHandlers;
  1390. {$endif EXCEPTIONS_IN_SYSTEM}
  1391. {$ifdef HASVARIANT}
  1392. initvariantmanager;
  1393. {$endif HASVARIANT}
  1394. End.
  1395. {
  1396. $Log$
  1397. Revision 1.13 2004-04-22 21:10:56 peter
  1398. * do_read/do_write addr argument changed to pointer
  1399. Revision 1.12 2004/01/20 23:12:49 hajny
  1400. * ExecuteProcess fixes, ProcessID and ThreadID added
  1401. Revision 1.11 2004/01/11 23:08:39 hajny
  1402. * merged Jonas fix from GO32v2
  1403. Revision 1.10 2004/01/11 22:54:44 hajny
  1404. * 'conservative' version of the do_open patch by Joe da Silva
  1405. Revision 1.9 2003/12/15 15:57:48 peter
  1406. * patches from wiktor
  1407. Revision 1.8 2003/11/17 19:55:13 hajny
  1408. * Wiktor Sywula: LFN detection uncommented in system, new units added
  1409. Revision 1.7 2003/10/18 09:31:59 hajny
  1410. * Wiktor Sywula: environment and arguments support added
  1411. Revision 1.6 2003/10/16 15:43:13 peter
  1412. * THandle is platform dependent
  1413. Revision 1.5 2003/10/03 21:59:28 peter
  1414. * stdcall fixes
  1415. Revision 1.4 2003/09/29 18:52:36 hajny
  1416. * append fix applied to Amiga, Atari, EMX, GO32v2, OS/2 and Watcom
  1417. Revision 1.3 2003/09/27 11:52:36 peter
  1418. * sbrk returns pointer
  1419. Revision 1.2 2003/09/07 22:29:26 hajny
  1420. * syswat renamed to system, CVS log added
  1421. }