system.pp 38 KB

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