2
0

system.pp 38 KB

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