system.pp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 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. { no stack check in system }
  12. {$S-}
  13. unit system;
  14. {$I os.inc}
  15. interface
  16. { include system-independent routine headers }
  17. {$I systemh.inc}
  18. { include heap support headers }
  19. {$I heaph.inc}
  20. const
  21. { Default filehandles }
  22. UnusedHandle = -1;
  23. StdInputHandle = 0;
  24. StdOutputHandle = 1;
  25. StdErrorHandle = 2;
  26. { Default memory segments (Tp7 compatibility) }
  27. seg0040 = $0040;
  28. segA000 = $A000;
  29. segB000 = $B000;
  30. segB800 = $B800;
  31. var
  32. { Mem[] support }
  33. mem : array[0..$7fffffff] of byte absolute $0:$0;
  34. memw : array[0..$7fffffff] of word absolute $0:$0;
  35. meml : array[0..$7fffffff] of longint absolute $0:$0;
  36. { C-compatible arguments and environment }
  37. argc : longint;
  38. argv : ppchar;
  39. envp : ppchar;
  40. dos_argv0 : pchar;
  41. {$ifndef RTLLITE}
  42. { System info }
  43. LFNSupport : boolean;
  44. {$endif RTLLITE}
  45. type
  46. { Dos Extender info }
  47. p_stub_info = ^t_stub_info;
  48. t_stub_info = packed record
  49. magic : array[0..15] of char;
  50. size : longint;
  51. minstack : longint;
  52. memory_handle : longint;
  53. initial_size : longint;
  54. minkeep : word;
  55. ds_selector : word;
  56. ds_segment : word;
  57. psp_selector : word;
  58. cs_selector : word;
  59. env_size : word;
  60. basename : array[0..7] of char;
  61. argv0 : array [0..15] of char;
  62. dpmi_server : array [0..15] of char;
  63. end;
  64. p_go32_info_block = ^t_go32_info_block;
  65. t_go32_info_block = packed record
  66. size_of_this_structure_in_bytes : longint; {offset 0}
  67. linear_address_of_primary_screen : longint; {offset 4}
  68. linear_address_of_secondary_screen : longint; {offset 8}
  69. linear_address_of_transfer_buffer : longint; {offset 12}
  70. size_of_transfer_buffer : longint; {offset 16}
  71. pid : longint; {offset 20}
  72. master_interrupt_controller_base : byte; {offset 24}
  73. slave_interrupt_controller_base : byte; {offset 25}
  74. selector_for_linear_memory : word; {offset 26}
  75. linear_address_of_stub_info_structure : longint; {offset 28}
  76. linear_address_of_original_psp : longint; {offset 32}
  77. run_mode : word; {offset 36}
  78. run_mode_info : word; {offset 38}
  79. end;
  80. var
  81. stub_info : p_stub_info;
  82. go32_info_block : t_go32_info_block;
  83. {
  84. necessary for objects.pas, should be removed (at least from the interface
  85. to the implementation)
  86. }
  87. type
  88. trealregs=record
  89. realedi,realesi,realebp,realres,
  90. realebx,realedx,realecx,realeax : longint;
  91. realflags,
  92. reales,realds,realfs,realgs,
  93. realip,realcs,realsp,realss : word;
  94. end;
  95. function do_write(h,addr,len : longint) : longint;
  96. function do_read(h,addr,len : longint) : longint;
  97. procedure syscopyfromdos(addr : longint; len : longint);
  98. procedure syscopytodos(addr : longint; len : longint);
  99. procedure sysrealintr(intnr : word;var regs : trealregs);
  100. function tb : longint;
  101. implementation
  102. { include system independent routines }
  103. {$I system.inc}
  104. const
  105. carryflag = 1;
  106. type
  107. tseginfo=packed record
  108. offset : pointer;
  109. segment : word;
  110. end;
  111. var
  112. doscmd : string[128]; { Dos commandline copied from PSP, max is 128 chars }
  113. old_int00 : tseginfo;cvar;
  114. old_int75 : tseginfo;cvar;
  115. {$ASMMODE DIRECT}
  116. {*****************************************************************************
  117. Go32 Helpers
  118. *****************************************************************************}
  119. function far_strlen(selector : word;linear_address : longint) : longint;
  120. begin
  121. asm
  122. movl linear_address,%edx
  123. movl %edx,%ecx
  124. movw selector,%gs
  125. .Larg19:
  126. movb %gs:(%edx),%al
  127. testb %al,%al
  128. je .Larg20
  129. incl %edx
  130. jmp .Larg19
  131. .Larg20:
  132. movl %edx,%eax
  133. subl %ecx,%eax
  134. movl %eax,__RESULT
  135. end;
  136. end;
  137. {$ASMMODE ATT}
  138. function tb : longint;
  139. begin
  140. tb:=go32_info_block.linear_address_of_transfer_buffer;
  141. end;
  142. function tb_segment : longint;
  143. begin
  144. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  145. end;
  146. function tb_offset : longint;
  147. begin
  148. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  149. end;
  150. function tb_size : longint;
  151. begin
  152. tb_size:=go32_info_block.size_of_transfer_buffer;
  153. end;
  154. function dos_selector : word;
  155. begin
  156. dos_selector:=go32_info_block.selector_for_linear_memory;
  157. end;
  158. function get_ds : word;assembler;
  159. asm
  160. movw %ds,%ax
  161. end;
  162. function get_cs : word;assembler;
  163. asm
  164. movw %cs,%ax
  165. end;
  166. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  167. begin
  168. if count=0 then
  169. exit;
  170. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  171. asm
  172. pushw %es
  173. pushw %ds
  174. cld
  175. movl count,%ecx
  176. movl source,%esi
  177. movl dest,%edi
  178. movw dseg,%ax
  179. movw %ax,%es
  180. movw sseg,%ax
  181. movw %ax,%ds
  182. movl %ecx,%eax
  183. shrl $2,%ecx
  184. rep
  185. movsl
  186. movl %eax,%ecx
  187. andl $3,%ecx
  188. rep
  189. movsb
  190. popw %ds
  191. popw %es
  192. end ['ESI','EDI','ECX','EAX']
  193. else if (source<dest) then
  194. { copy backward for overlapping }
  195. asm
  196. pushw %es
  197. pushw %ds
  198. std
  199. movl count,%ecx
  200. movl source,%esi
  201. movl dest,%edi
  202. movw dseg,%ax
  203. movw %ax,%es
  204. movw sseg,%ax
  205. movw %ax,%ds
  206. addl %ecx,%esi
  207. addl %ecx,%edi
  208. movl %ecx,%eax
  209. andl $3,%ecx
  210. orl %ecx,%ecx
  211. jz .LSEG_MOVE1
  212. { calculate esi and edi}
  213. decl %esi
  214. decl %edi
  215. rep
  216. movsb
  217. incl %esi
  218. incl %edi
  219. .LSEG_MOVE1:
  220. subl $4,%esi
  221. subl $4,%edi
  222. movl %eax,%ecx
  223. shrl $2,%ecx
  224. rep
  225. movsl
  226. cld
  227. popw %ds
  228. popw %es
  229. end ['ESI','EDI','ECX'];
  230. end;
  231. function atohex(s : pchar) : longint;
  232. var
  233. rv : longint;
  234. v : byte;
  235. begin
  236. rv:=0;
  237. while (s^ <>#0) do
  238. begin
  239. v:=byte(s^)-byte('0');
  240. if (v > 9) then
  241. dec(v,7);
  242. v:=v and 15; { in case it's lower case }
  243. rv:=(rv shl 4) or v;
  244. inc(longint(s));
  245. end;
  246. atohex:=rv;
  247. end;
  248. procedure setup_arguments;
  249. type arrayword = array [0..0] of word;
  250. var psp : word;
  251. i,j : byte;
  252. quote : char;
  253. proxy_s : string[7];
  254. tempargv : ppchar;
  255. al,proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  256. largs : array[0..127] of pchar;
  257. rm_argv : ^arrayword;
  258. begin
  259. for i := 1 to 127 do
  260. largs[i] := nil;
  261. psp:=stub_info^.psp_selector;
  262. largs[0]:=dos_argv0;
  263. argc := 1;
  264. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  265. {$IfDef SYSTEMDEBUG}
  266. Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
  267. {$EndIf SYSTEMDEBUG}
  268. j := 1;
  269. quote := #0;
  270. for i:=1 to length(doscmd) do
  271. Begin
  272. if doscmd[i] = quote then
  273. begin
  274. quote := #0;
  275. doscmd[i] := #0;
  276. largs[argc]:=@doscmd[j];
  277. inc(argc);
  278. j := i+1;
  279. end else
  280. if (quote = #0) and ((doscmd[i] = '''') or (doscmd[i]='"')) then
  281. begin
  282. quote := doscmd[i];
  283. j := i + 1;
  284. end else
  285. if (quote = #0) and ((doscmd[i] = ' ')
  286. or (doscmd[i] = #9) or (doscmd[i] = #10) or
  287. (doscmd[i] = #12) or (doscmd[i] = #9)) then
  288. begin
  289. doscmd[i]:=#0;
  290. if j<i then
  291. begin
  292. largs[argc]:=@doscmd[j];
  293. inc(argc);
  294. j := i+1;
  295. end else inc(j);
  296. end else
  297. if (i = length(doscmd)) then
  298. begin
  299. doscmd[i+1]:=#0;
  300. largs[argc]:=@doscmd[j];
  301. inc(argc);
  302. end;
  303. end;
  304. if (argc > 1) and (far_strlen(get_ds,longint(largs[1])) = 6) then
  305. begin
  306. move(largs[1]^,proxy_s[1],6);
  307. proxy_s[0] := #6;
  308. if (proxy_s = '!proxy') then
  309. begin
  310. {$IfDef SYSTEMDEBUG}
  311. Writeln(stderr,'proxy command line ');
  312. {$EndIf SYSTEMDEBUG}
  313. proxy_argc := atohex(largs[2]);
  314. proxy_seg := atohex(largs[3]);
  315. proxy_ofs := atohex(largs[4]);
  316. getmem(rm_argv,proxy_argc*sizeof(word));
  317. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  318. for i:=0 to proxy_argc - 1 do
  319. begin
  320. lin := proxy_seg*16 + rm_argv^[i];
  321. al :=far_strlen(dos_selector, lin);
  322. getmem(largs[i],al+1);
  323. sysseg_move(dos_selector, lin, get_ds,longint(largs[i]), al+1);
  324. {$IfDef SYSTEMDEBUG}
  325. Writeln(stderr,'arg ',i,' #',largs[i],'#');
  326. {$EndIf SYSTEMDEBUG}
  327. end;
  328. argc := proxy_argc;
  329. end;
  330. end;
  331. getmem(argv,argc shl 2);
  332. for i := 0 to argc-1 do
  333. argv[i] := largs[i];
  334. tempargv:=argv;
  335. {$ASMMODE DIRECT}
  336. asm
  337. movl tempargv,%eax
  338. movl %eax,_args
  339. end;
  340. {$ASMMODE ATT}
  341. end;
  342. function strcopy(dest,source : pchar) : pchar;
  343. begin
  344. asm
  345. cld
  346. movl 12(%ebp),%edi
  347. movl $0xffffffff,%ecx
  348. xorb %al,%al
  349. repne
  350. scasb
  351. not %ecx
  352. movl 8(%ebp),%edi
  353. movl 12(%ebp),%esi
  354. movl %ecx,%eax
  355. shrl $2,%ecx
  356. rep
  357. movsl
  358. movl %eax,%ecx
  359. andl $3,%ecx
  360. rep
  361. movsb
  362. movl 8(%ebp),%eax
  363. leave
  364. ret $8
  365. end;
  366. end;
  367. procedure setup_environment;
  368. var env_selector : word;
  369. env_count : longint;
  370. dos_env,cp : pchar;
  371. stubaddr : p_stub_info;
  372. begin
  373. {$ASMMODE DIRECT}
  374. asm
  375. movl __stubinfo,%eax
  376. movl %eax,stubaddr
  377. end;
  378. {$ASMMODE ATT}
  379. stub_info:=stubaddr;
  380. getmem(dos_env,stub_info^.env_size);
  381. env_count:=0;
  382. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  383. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  384. cp:=dos_env;
  385. while cp ^ <> #0 do
  386. begin
  387. inc(env_count);
  388. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  389. inc(longint(cp)); { skip to next character }
  390. end;
  391. getmem(envp,(env_count+1) * sizeof(pchar));
  392. if (envp = nil) then exit;
  393. cp:=dos_env;
  394. env_count:=0;
  395. while cp^ <> #0 do
  396. begin
  397. getmem(envp[env_count],strlen(cp)+1);
  398. strcopy(envp[env_count], cp);
  399. {$IfDef SYSTEMDEBUG}
  400. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  401. {$EndIf SYSTEMDEBUG}
  402. inc(env_count);
  403. while (cp^ <> #0) do
  404. inc(longint(cp)); { skip to NUL }
  405. inc(longint(cp)); { skip to next character }
  406. end;
  407. envp[env_count]:=nil;
  408. longint(cp):=longint(cp)+3;
  409. getmem(dos_argv0,strlen(cp)+1);
  410. if (dos_argv0 = nil) then halt;
  411. strcopy(dos_argv0, cp);
  412. { update ___dos_argv0 also }
  413. {$ASMMODE DIRECT}
  414. asm
  415. movl U_SYSTEM_DOS_ARGV0,%eax
  416. movl %eax,___dos_argv0
  417. end;
  418. {$ASMMODE ATT}
  419. end;
  420. procedure syscopytodos(addr : longint; len : longint);
  421. begin
  422. if len > tb_size then
  423. HandleError(217);
  424. sysseg_move(get_ds,addr,dos_selector,tb,len);
  425. end;
  426. procedure syscopyfromdos(addr : longint; len : longint);
  427. begin
  428. if len > tb_size then
  429. HandleError(217);
  430. sysseg_move(dos_selector,tb,get_ds,addr,len);
  431. end;
  432. procedure sysrealintr(intnr : word;var regs : trealregs);
  433. begin
  434. regs.realsp:=0;
  435. regs.realss:=0;
  436. asm
  437. movw intnr,%bx
  438. xorl %ecx,%ecx
  439. movl regs,%edi
  440. movw $0x300,%ax
  441. int $0x31
  442. end;
  443. end;
  444. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  445. begin
  446. asm
  447. movl intaddr,%eax
  448. movl (%eax),%edx
  449. movw 4(%eax),%cx
  450. movl $0x205,%eax
  451. movb vector,%bl
  452. int $0x31
  453. end;
  454. end;
  455. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  456. begin
  457. asm
  458. movb vector,%bl
  459. movl $0x204,%eax
  460. int $0x31
  461. movl intaddr,%eax
  462. movl %edx,(%eax)
  463. movw %cx,4(%eax)
  464. end;
  465. end;
  466. {$ifdef SYSTEMDEBUG}
  467. { Keep Track of open files }
  468. const
  469. max_files = 50;
  470. free_closed_names : boolean = true;
  471. var
  472. opennames : array [0..max_files-1] of pchar;
  473. openfiles : array [0..max_files-1] of boolean;
  474. {$endif SYSTEMDEBUG}
  475. {*****************************************************************************
  476. System Dependent Exit code
  477. *****************************************************************************}
  478. Procedure system_exit;
  479. {$ASMMODE DIRECT}
  480. {$ifdef SYSTEMDEBUG}
  481. var h : byte;
  482. {$endif SYSTEMDEBUG}
  483. begin
  484. {$ifdef SYSTEMDEBUG}
  485. for h:=0 to max_files do
  486. if openfiles[h] then
  487. writeln(stderr,'file ',opennames[h],' not closed at exit');
  488. {$endif SYSTEMDEBUG}
  489. { halt is not allways called !! }
  490. { not on normal exit !! PM }
  491. set_pm_interrupt($00,old_int00);
  492. set_pm_interrupt($75,old_int75);
  493. asm
  494. movzbw exitcode,%ax
  495. pushw %ax
  496. call ___exit {frees all dpmi memory !!}
  497. end;
  498. end;
  499. procedure halt(errnum : byte);
  500. begin
  501. exitcode:=errnum;
  502. do_exit;
  503. { do_exit should call system_exit but this does not hurt }
  504. System_exit;
  505. end;
  506. procedure new_int00;
  507. begin
  508. HandleError(200);
  509. end;
  510. procedure new_int75;
  511. begin
  512. asm
  513. xorl %eax,%eax
  514. outb %al,$0x0f0
  515. movb $0x20,%al
  516. outb %al,$0x0a0
  517. outb %al,$0x020
  518. end;
  519. HandleError(200);
  520. end;
  521. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  522. {
  523. called when trying to get local stack if the compiler directive $S
  524. is set this function must preserve esi !!!! because esi is set by
  525. the calling proc for methods it must preserve all registers !!
  526. With a 2048 byte safe area used to write to StdIo without crossing
  527. the stack boundary
  528. }
  529. begin
  530. asm
  531. pushl %eax
  532. pushl %ebx
  533. movl stack_size,%ebx
  534. addl $2048,%ebx
  535. movl %esp,%eax
  536. subl %ebx,%eax
  537. {$ifdef SYSTEMDEBUG}
  538. movl U_SYSTEM_LOWESTSTACK,%ebx
  539. cmpl %eax,%ebx
  540. jb .L_is_not_lowest
  541. movl %eax,U_SYSTEM_LOWESTSTACK
  542. .L_is_not_lowest:
  543. {$endif SYSTEMDEBUG}
  544. movl __stkbottom,%ebx
  545. cmpl %eax,%ebx
  546. jae .L__short_on_stack
  547. popl %ebx
  548. popl %eax
  549. leave
  550. ret $4
  551. .L__short_on_stack:
  552. { can be usefull for error recovery !! }
  553. popl %ebx
  554. popl %eax
  555. end['EAX','EBX'];
  556. HandleError(202);
  557. end;
  558. {$ASMMODE ATT}
  559. {*****************************************************************************
  560. ParamStr/Randomize
  561. *****************************************************************************}
  562. function paramcount : longint;
  563. begin
  564. paramcount := argc - 1;
  565. end;
  566. function paramstr(l : longint) : string;
  567. begin
  568. if (l>=0) and (l+1<=argc) then
  569. paramstr:=strpas(argv[l])
  570. else
  571. paramstr:='';
  572. end;
  573. procedure randomize;
  574. var
  575. hl : longint;
  576. regs : trealregs;
  577. begin
  578. regs.realeax:=$2c00;
  579. sysrealintr($21,regs);
  580. hl:=regs.realedx and $ffff;
  581. randseed:=hl*$10000+ (regs.realecx and $ffff);
  582. end;
  583. {*****************************************************************************
  584. Heap Management
  585. *****************************************************************************}
  586. {$ASMMODE DIRECT}
  587. function getheapstart:pointer;assembler;
  588. asm
  589. leal HEAP,%eax
  590. end ['EAX'];
  591. function getheapsize:longint;assembler;
  592. asm
  593. movl HEAPSIZE,%eax
  594. end ['EAX'];
  595. function Sbrk(size : longint):longint;assembler;
  596. asm
  597. movl size,%eax
  598. pushl %eax
  599. call ___sbrk
  600. addl $4,%esp
  601. end;
  602. {$ASMMODE ATT}
  603. { include standard heap management }
  604. {$I heap.inc}
  605. {****************************************************************************
  606. Low level File Routines
  607. ****************************************************************************}
  608. procedure AllowSlash(p:pchar);
  609. var
  610. i : longint;
  611. begin
  612. { allow slash as backslash }
  613. for i:=0 to strlen(p) do
  614. if p[i]='/' then p[i]:='\';
  615. end;
  616. procedure do_close(handle : longint);
  617. var
  618. regs : trealregs;
  619. begin
  620. regs.realebx:=handle;
  621. {$ifdef SYSTEMDEBUG}
  622. if handle<max_files then
  623. begin
  624. openfiles[handle]:=false;
  625. if assigned(opennames[handle]) and free_closed_names then
  626. begin
  627. freemem(opennames[handle],strlen(opennames[handle])+1);
  628. opennames[handle]:=nil;
  629. end;
  630. end;
  631. {$endif SYSTEMDEBUG}
  632. regs.realeax:=$3e00;
  633. sysrealintr($21,regs);
  634. if (regs.realflags and carryflag) <> 0 then
  635. InOutRes:=lo(regs.realeax);
  636. end;
  637. procedure do_erase(p : pchar);
  638. var
  639. regs : trealregs;
  640. begin
  641. AllowSlash(p);
  642. syscopytodos(longint(p),strlen(p)+1);
  643. regs.realedx:=tb_offset;
  644. regs.realds:=tb_segment;
  645. {$ifndef RTLLITE}
  646. if LFNSupport then
  647. regs.realeax:=$7141
  648. else
  649. {$endif RTLLITE}
  650. regs.realeax:=$4100;
  651. regs.realesi:=0;
  652. regs.realecx:=0;
  653. sysrealintr($21,regs);
  654. if (regs.realflags and carryflag) <> 0 then
  655. InOutRes:=lo(regs.realeax);
  656. end;
  657. procedure do_rename(p1,p2 : pchar);
  658. var
  659. regs : trealregs;
  660. begin
  661. AllowSlash(p1);
  662. AllowSlash(p2);
  663. if strlen(p1)+strlen(p2)+3>tb_size then
  664. HandleError(217);
  665. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  666. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  667. regs.realedi:=tb_offset;
  668. regs.realedx:=tb_offset + strlen(p2)+2;
  669. regs.realds:=tb_segment;
  670. regs.reales:=tb_segment;
  671. {$ifndef RTLLITE}
  672. if LFNSupport then
  673. regs.realeax:=$7156
  674. else
  675. {$endif RTLLITE}
  676. regs.realeax:=$5600;
  677. regs.realecx:=$ff; { attribute problem here ! }
  678. sysrealintr($21,regs);
  679. if (regs.realflags and carryflag) <> 0 then
  680. InOutRes:=lo(regs.realeax);
  681. end;
  682. function do_write(h,addr,len : longint) : longint;
  683. var
  684. regs : trealregs;
  685. size,
  686. writesize : longint;
  687. begin
  688. writesize:=0;
  689. while len > 0 do
  690. begin
  691. if len>tb_size then
  692. size:=tb_size
  693. else
  694. size:=len;
  695. syscopytodos(addr+writesize,size);
  696. regs.realecx:=size;
  697. regs.realedx:=tb_offset;
  698. regs.realds:=tb_segment;
  699. regs.realebx:=h;
  700. regs.realeax:=$4000;
  701. sysrealintr($21,regs);
  702. if (regs.realflags and carryflag) <> 0 then
  703. begin
  704. InOutRes:=lo(regs.realeax);
  705. exit(writesize);
  706. end;
  707. len:=len-size;
  708. writesize:=writesize+size;
  709. end;
  710. Do_Write:=WriteSize
  711. end;
  712. function do_read(h,addr,len : longint) : longint;
  713. var
  714. regs : trealregs;
  715. size,
  716. readsize : longint;
  717. begin
  718. readsize:=0;
  719. while len > 0 do
  720. begin
  721. if len>tb_size then
  722. size:=tb_size
  723. else
  724. size:=len;
  725. regs.realecx:=size;
  726. regs.realedx:=tb_offset;
  727. regs.realds:=tb_segment;
  728. regs.realebx:=h;
  729. regs.realeax:=$3f00;
  730. sysrealintr($21,regs);
  731. if (regs.realflags and carryflag) <> 0 then
  732. begin
  733. InOutRes:=lo(regs.realeax);
  734. do_read:=0;
  735. exit;
  736. end
  737. else
  738. if regs.realeax<size then
  739. begin
  740. syscopyfromdos(addr+readsize,regs.realeax);
  741. do_read:=readsize+regs.realeax;
  742. exit;
  743. end;
  744. syscopyfromdos(addr+readsize,regs.realeax);
  745. readsize:=readsize+regs.realeax;
  746. len:=len-regs.realeax;
  747. end;
  748. do_read:=readsize;
  749. end;
  750. function do_filepos(handle : longint) : longint;
  751. var
  752. regs : trealregs;
  753. begin
  754. regs.realebx:=handle;
  755. regs.realecx:=0;
  756. regs.realedx:=0;
  757. regs.realeax:=$4201;
  758. sysrealintr($21,regs);
  759. if (regs.realflags and carryflag) <> 0 then
  760. Begin
  761. InOutRes:=lo(regs.realeax);
  762. do_filepos:=0;
  763. end
  764. else
  765. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  766. end;
  767. procedure do_seek(handle,pos : longint);
  768. var
  769. regs : trealregs;
  770. begin
  771. regs.realebx:=handle;
  772. regs.realecx:=pos shr 16;
  773. regs.realedx:=pos and $ffff;
  774. regs.realeax:=$4200;
  775. sysrealintr($21,regs);
  776. if (regs.realflags and carryflag) <> 0 then
  777. InOutRes:=lo(regs.realeax);
  778. end;
  779. function do_seekend(handle:longint):longint;
  780. var
  781. regs : trealregs;
  782. begin
  783. regs.realebx:=handle;
  784. regs.realecx:=0;
  785. regs.realedx:=0;
  786. regs.realeax:=$4202;
  787. sysrealintr($21,regs);
  788. if (regs.realflags and carryflag) <> 0 then
  789. Begin
  790. InOutRes:=lo(regs.realeax);
  791. do_seekend:=0;
  792. end
  793. else
  794. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  795. end;
  796. function do_filesize(handle : longint) : longint;
  797. var
  798. aktfilepos : longint;
  799. begin
  800. aktfilepos:=do_filepos(handle);
  801. do_filesize:=do_seekend(handle);
  802. do_seek(handle,aktfilepos);
  803. end;
  804. { truncate at a given position }
  805. procedure do_truncate (handle,pos:longint);
  806. var
  807. regs : trealregs;
  808. begin
  809. do_seek(handle,pos);
  810. regs.realecx:=0;
  811. regs.realedx:=tb_offset;
  812. regs.realds:=tb_segment;
  813. regs.realebx:=handle;
  814. regs.realeax:=$4000;
  815. sysrealintr($21,regs);
  816. if (regs.realflags and carryflag) <> 0 then
  817. InOutRes:=lo(regs.realeax);
  818. end;
  819. procedure do_open(var f;p:pchar;flags:longint);
  820. {
  821. filerec and textrec have both handle and mode as the first items so
  822. they could use the same routine for opening/creating.
  823. when (flags and $10) the file will be append
  824. when (flags and $100) the file will be truncate/rewritten
  825. when (flags and $1000) there is no check for close (needed for textfiles)
  826. }
  827. var
  828. regs : trealregs;
  829. action : longint;
  830. begin
  831. AllowSlash(p);
  832. { close first if opened }
  833. if ((flags and $1000)=0) then
  834. begin
  835. case filerec(f).mode of
  836. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  837. fmclosed : ;
  838. else
  839. begin
  840. inoutres:=102; {not assigned}
  841. exit;
  842. end;
  843. end;
  844. end;
  845. { reset file handle }
  846. filerec(f).handle:=UnusedHandle;
  847. action:=$1;
  848. { convert filemode to filerec modes }
  849. case (flags and 3) of
  850. 0 : filerec(f).mode:=fminput;
  851. 1 : filerec(f).mode:=fmoutput;
  852. 2 : filerec(f).mode:=fminout;
  853. end;
  854. if (flags and $100)<>0 then
  855. begin
  856. filerec(f).mode:=fmoutput;
  857. action:=$12; {create file function}
  858. end;
  859. { empty name is special }
  860. if p[0]=#0 then
  861. begin
  862. case filerec(f).mode of
  863. fminput : filerec(f).handle:=StdInputHandle;
  864. fmappend,
  865. fmoutput : begin
  866. filerec(f).handle:=StdOutputHandle;
  867. filerec(f).mode:=fmoutput; {fool fmappend}
  868. end;
  869. end;
  870. exit;
  871. end;
  872. { real dos call }
  873. syscopytodos(longint(p),strlen(p)+1);
  874. {$ifndef RTLLITE}
  875. if LFNSupport then
  876. regs.realeax:=$716c
  877. else
  878. {$endif RTLLITE}
  879. regs.realeax:=$6c00;
  880. regs.realedx:=action;
  881. regs.realds:=tb_segment;
  882. regs.realesi:=tb_offset;
  883. regs.realebx:=$2000+(flags and $ff);
  884. regs.realecx:=$20;
  885. sysrealintr($21,regs);
  886. if (regs.realflags and carryflag) <> 0 then
  887. begin
  888. InOutRes:=lo(regs.realeax);
  889. exit;
  890. end
  891. else
  892. filerec(f).handle:=regs.realeax;
  893. {$ifdef SYSTEMDEBUG}
  894. if regs.realeax<max_files then
  895. begin
  896. openfiles[regs.realeax]:=true;
  897. getmem(opennames[regs.realeax],strlen(p)+1);
  898. move(p^,opennames[regs.realeax]^,strlen(p)+1);
  899. end;
  900. {$endif SYSTEMDEBUG}
  901. { append mode }
  902. if (flags and $10)<>0 then
  903. begin
  904. do_seekend(filerec(f).handle);
  905. filerec(f).mode:=fmoutput; {fool fmappend}
  906. end;
  907. end;
  908. function do_isdevice(handle:longint):boolean;
  909. var
  910. regs : trealregs;
  911. begin
  912. regs.realebx:=handle;
  913. regs.realeax:=$4400;
  914. sysrealintr($21,regs);
  915. do_isdevice:=(regs.realedx and $80)<>0;
  916. if (regs.realflags and carryflag) <> 0 then
  917. InOutRes:=lo(regs.realeax);
  918. end;
  919. {*****************************************************************************
  920. UnTyped File Handling
  921. *****************************************************************************}
  922. {$i file.inc}
  923. {*****************************************************************************
  924. Typed File Handling
  925. *****************************************************************************}
  926. {$i typefile.inc}
  927. {*****************************************************************************
  928. Text File Handling
  929. *****************************************************************************}
  930. {$DEFINE EOF_CTRLZ}
  931. {$i text.inc}
  932. {*****************************************************************************
  933. Directory Handling
  934. *****************************************************************************}
  935. procedure DosDir(func:byte;const s:string);
  936. var
  937. buffer : array[0..255] of char;
  938. regs : trealregs;
  939. begin
  940. move(s[1],buffer,length(s));
  941. buffer[length(s)]:=#0;
  942. AllowSlash(pchar(@buffer));
  943. syscopytodos(longint(@buffer),length(s)+1);
  944. regs.realedx:=tb_offset;
  945. regs.realds:=tb_segment;
  946. {$ifndef RTLLITE}
  947. if LFNSupport then
  948. regs.realeax:=$7100+func
  949. else
  950. {$endif RTLLITE}
  951. regs.realeax:=func shl 8;
  952. sysrealintr($21,regs);
  953. if (regs.realflags and carryflag) <> 0 then
  954. InOutRes:=lo(regs.realeax);
  955. end;
  956. procedure mkdir(const s : string);[IOCheck];
  957. begin
  958. If InOutRes <> 0 then
  959. exit;
  960. DosDir($39,s);
  961. end;
  962. procedure rmdir(const s : string);[IOCheck];
  963. begin
  964. If InOutRes <> 0 then
  965. exit;
  966. DosDir($3a,s);
  967. end;
  968. procedure chdir(const s : string);[IOCheck];
  969. var
  970. regs : trealregs;
  971. begin
  972. If InOutRes <> 0 then
  973. exit;
  974. { First handle Drive changes }
  975. if (length(s)>=2) and (s[2]=':') then
  976. begin
  977. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  978. regs.realeax:=$0e00;
  979. sysrealintr($21,regs);
  980. regs.realeax:=$1900;
  981. sysrealintr($21,regs);
  982. if byte(regs.realeax)<>byte(regs.realedx) then
  983. begin
  984. Inoutres:=15;
  985. exit;
  986. end;
  987. end;
  988. { do the normal dos chdir }
  989. DosDir($3b,s);
  990. end;
  991. procedure getdir(drivenr : byte;var dir : shortstring);
  992. var
  993. temp : array[0..255] of char;
  994. i : longint;
  995. regs : trealregs;
  996. begin
  997. regs.realedx:=drivenr;
  998. regs.realesi:=tb_offset;
  999. regs.realds:=tb_segment;
  1000. {$ifndef RTLLITE}
  1001. if LFNSupport then
  1002. regs.realeax:=$7147
  1003. else
  1004. {$endif RTLLITE}
  1005. regs.realeax:=$4700;
  1006. sysrealintr($21,regs);
  1007. if (regs.realflags and carryflag) <> 0 then
  1008. Begin
  1009. InOutRes:=lo(regs.realeax);
  1010. exit;
  1011. end
  1012. else
  1013. syscopyfromdos(longint(@temp),251);
  1014. { conversion to Pascal string including slash conversion }
  1015. i:=0;
  1016. while (temp[i]<>#0) do
  1017. begin
  1018. if temp[i]='/' then
  1019. temp[i]:='\';
  1020. dir[i+4]:=temp[i];
  1021. inc(i);
  1022. end;
  1023. dir[2]:=':';
  1024. dir[3]:='\';
  1025. dir[0]:=char(i+3);
  1026. { upcase the string }
  1027. dir:=upcase(dir);
  1028. if drivenr<>0 then { Drive was supplied. We know it }
  1029. dir[1]:=char(65+drivenr-1)
  1030. else
  1031. begin
  1032. { We need to get the current drive from DOS function 19H }
  1033. { because the drive was the default, which can be unknown }
  1034. regs.realeax:=$1900;
  1035. sysrealintr($21,regs);
  1036. i:= (regs.realeax and $ff) + ord('A');
  1037. dir[1]:=chr(i);
  1038. end;
  1039. end;
  1040. {*****************************************************************************
  1041. SystemUnit Initialization
  1042. *****************************************************************************}
  1043. {$ifndef RTLLITE}
  1044. function CheckLFN:boolean;
  1045. var
  1046. regs : TRealRegs;
  1047. RootName : pchar;
  1048. begin
  1049. { Check LFN API on drive c:\ }
  1050. RootName:='C:\';
  1051. syscopytodos(longint(RootName),strlen(RootName)+1);
  1052. { Call 'Get Volume Information' ($71A0) }
  1053. regs.realeax:=$71a0;
  1054. regs.reales:=tb_segment;
  1055. regs.realedi:=tb_offset;
  1056. regs.realecx:=32;
  1057. regs.realds:=tb_segment;
  1058. regs.realedx:=tb_offset;
  1059. regs.realflags:=carryflag;
  1060. sysrealintr($21,regs);
  1061. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1062. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1063. end;
  1064. {$endif RTLLITE}
  1065. var
  1066. temp_int : tseginfo;
  1067. Begin
  1068. { save old int 0 and 75 }
  1069. get_pm_interrupt($00,old_int00);
  1070. get_pm_interrupt($75,old_int75);
  1071. temp_int.segment:=get_cs;
  1072. temp_int.offset:=@new_int00;
  1073. set_pm_interrupt($00,temp_int);
  1074. { temp_int.offset:=@new_int75;
  1075. set_pm_interrupt($75,temp_int); }
  1076. { to test stack depth }
  1077. loweststack:=maxlongint;
  1078. { Setup heap }
  1079. InitHeap;
  1080. { Setup stdin, stdout and stderr }
  1081. OpenStdIO(Input,fmInput,StdInputHandle);
  1082. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1083. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1084. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1085. { Setup environment and arguments }
  1086. Setup_Environment;
  1087. Setup_Arguments;
  1088. { Use LFNSupport LFN }
  1089. LFNSupport:=CheckLFN;
  1090. { Reset IO Error }
  1091. InOutRes:=0;
  1092. End.
  1093. {
  1094. $Log$
  1095. Revision 1.5 1999-01-18 10:05:50 pierre
  1096. + system_exit procedure added
  1097. Revision 1.4 1998/12/30 22:17:59 peter
  1098. * fixed mem decls to use $0:$0
  1099. Revision 1.3 1998/12/28 15:50:45 peter
  1100. + stdout, which is needed when you write something in the system unit
  1101. to the screen. Like the runtime error
  1102. Revision 1.2 1998/12/21 14:22:02 pierre
  1103. * old_int?? transformed to cvar to be readable by dpmiexcp
  1104. Revision 1.1 1998/12/21 13:07:03 peter
  1105. * use -FE
  1106. Revision 1.25 1998/12/15 22:42:52 peter
  1107. * removed temp symbols
  1108. Revision 1.24 1998/11/29 22:28:10 peter
  1109. + io-error 103 added
  1110. Revision 1.23 1998/11/16 14:15:02 pierre
  1111. * changed getdir(byte,string) to getdir(byte,shortstring)
  1112. Revision 1.22 1998/10/26 14:49:46 pierre
  1113. * system debug info output to stderr
  1114. Revision 1.21 1998/10/20 07:34:07 pierre
  1115. + systemdebug reports about unclosed files at exit
  1116. Revision 1.20 1998/10/13 21:41:06 peter
  1117. + int 0 for divide by zero
  1118. Revision 1.19 1998/09/14 10:48:05 peter
  1119. * FPC_ names
  1120. * Heap manager is now system independent
  1121. Revision 1.18 1998/08/28 10:48:04 peter
  1122. * fixed chdir with drive changing
  1123. * updated checklfn from mailinglist
  1124. Revision 1.17 1998/08/27 10:30:51 pierre
  1125. * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !)
  1126. I renamed tb_selector to tb_segment because
  1127. it is a real mode segment as opposed to
  1128. a protected mode selector
  1129. Fixed it for go32v1 (remove the $E0000000 offset !)
  1130. Revision 1.16 1998/08/26 10:04:03 peter
  1131. * new lfn check from mailinglist
  1132. * renamed win95 -> LFNSupport
  1133. + tb_selector, tb_offset for easier access to transferbuffer
  1134. Revision 1.15 1998/08/19 10:56:34 pierre
  1135. + added some special code for C interface
  1136. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  1137. Revision 1.14 1998/08/04 14:34:38 pierre
  1138. * small bug fix to get it compiled with bugfix version !!
  1139. (again the asmmode problem !!!
  1140. Peter it was really not the best idea you had !!)
  1141. Revision 1.13 1998/07/30 13:26:22 michael
  1142. + Added support for ErrorProc variable. All internal functions are required
  1143. to call HandleError instead of runerror from now on.
  1144. This is necessary for exception support.
  1145. Revision 1.12 1998/07/13 21:19:08 florian
  1146. * some problems with ansi string support fixed
  1147. Revision 1.11 1998/07/07 12:33:08 carl
  1148. * added 2k buffer for stack checking for correct io on error
  1149. Revision 1.10 1998/07/02 12:29:20 carl
  1150. * IOCheck for rmdir,chdir and mkdir as in TP
  1151. NOTE: I'm pretty SURE this will not compile and link correctly with FPC
  1152. 0.99.5
  1153. Revision 1.9 1998/07/01 15:29:57 peter
  1154. * better readln/writeln
  1155. Revision 1.8 1998/06/26 08:19:10 pierre
  1156. + all debug in ifdef SYSTEMDEBUG
  1157. + added local arrays :
  1158. opennames names of opened files
  1159. fileopen boolean array to know if still open
  1160. usefull with gdb if you get problems about too
  1161. many open files !!
  1162. Revision 1.7 1998/06/15 15:17:08 daniel
  1163. * RTLLITE conditional added to produce smaller RTL.
  1164. Revision 1.6 1998/05/31 14:18:29 peter
  1165. * force att or direct assembling
  1166. * cleanup of some files
  1167. Revision 1.5 1998/05/21 19:30:52 peter
  1168. * objects compiles for linux
  1169. + assign(pchar), assign(char), rename(pchar), rename(char)
  1170. * fixed read_text_as_array
  1171. + read_text_as_pchar which was not yet in the rtl
  1172. Revision 1.4 1998/05/04 17:58:41 peter
  1173. * fix for smartlinking with _ARGS
  1174. Revision 1.3 1998/05/04 16:21:54 florian
  1175. + LFNSupport flag to the interface moved
  1176. }