system.pp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  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;
  34. memw : array[0..$7fffffff] of word absolute $0;
  35. meml : array[0..$7fffffff] of longint absolute $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. ParamStr/Randomize
  477. *****************************************************************************}
  478. {$ASMMODE DIRECT}
  479. procedure halt(errnum : byte);
  480. {$ifdef SYSTEMDEBUG}
  481. var h : byte;
  482. {$endif SYSTEMDEBUG}
  483. begin
  484. do_exit;
  485. {$ifdef SYSTEMDEBUG}
  486. for h:=0 to max_files do
  487. if openfiles[h] then
  488. writeln(stderr,'file ',opennames[h],' not closed at exit');
  489. {$endif SYSTEMDEBUG}
  490. { halt is not allways called !! }
  491. { not on normal exit !! PM }
  492. set_pm_interrupt($00,old_int00);
  493. set_pm_interrupt($75,old_int75);
  494. asm
  495. movzbw errnum,%ax
  496. pushw %ax
  497. call ___exit {frees all dpmi memory !!}
  498. end;
  499. end;
  500. procedure new_int00;
  501. begin
  502. HandleError(200);
  503. end;
  504. procedure new_int75;
  505. begin
  506. asm
  507. xorl %eax,%eax
  508. outb %al,$0x0f0
  509. movb $0x20,%al
  510. outb %al,$0x0a0
  511. outb %al,$0x020
  512. end;
  513. HandleError(200);
  514. end;
  515. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  516. {
  517. called when trying to get local stack if the compiler directive $S
  518. is set this function must preserve esi !!!! because esi is set by
  519. the calling proc for methods it must preserve all registers !!
  520. With a 2048 byte safe area used to write to StdIo without crossing
  521. the stack boundary
  522. }
  523. begin
  524. asm
  525. pushl %eax
  526. pushl %ebx
  527. movl stack_size,%ebx
  528. addl $2048,%ebx
  529. movl %esp,%eax
  530. subl %ebx,%eax
  531. {$ifdef SYSTEMDEBUG}
  532. movl U_SYSTEM_LOWESTSTACK,%ebx
  533. cmpl %eax,%ebx
  534. jb .L_is_not_lowest
  535. movl %eax,U_SYSTEM_LOWESTSTACK
  536. .L_is_not_lowest:
  537. {$endif SYSTEMDEBUG}
  538. movl __stkbottom,%ebx
  539. cmpl %eax,%ebx
  540. jae .L__short_on_stack
  541. popl %ebx
  542. popl %eax
  543. leave
  544. ret $4
  545. .L__short_on_stack:
  546. { can be usefull for error recovery !! }
  547. popl %ebx
  548. popl %eax
  549. end['EAX','EBX'];
  550. HandleError(202);
  551. end;
  552. {$ASMMODE ATT}
  553. function paramcount : longint;
  554. begin
  555. paramcount := argc - 1;
  556. end;
  557. function paramstr(l : longint) : string;
  558. begin
  559. if (l>=0) and (l+1<=argc) then
  560. paramstr:=strpas(argv[l])
  561. else
  562. paramstr:='';
  563. end;
  564. procedure randomize;
  565. var
  566. hl : longint;
  567. regs : trealregs;
  568. begin
  569. regs.realeax:=$2c00;
  570. sysrealintr($21,regs);
  571. hl:=regs.realedx and $ffff;
  572. randseed:=hl*$10000+ (regs.realecx and $ffff);
  573. end;
  574. {*****************************************************************************
  575. Heap Management
  576. *****************************************************************************}
  577. {$ASMMODE DIRECT}
  578. function getheapstart:pointer;assembler;
  579. asm
  580. leal HEAP,%eax
  581. end ['EAX'];
  582. function getheapsize:longint;assembler;
  583. asm
  584. movl HEAPSIZE,%eax
  585. end ['EAX'];
  586. function Sbrk(size : longint):longint;assembler;
  587. asm
  588. movl size,%eax
  589. pushl %eax
  590. call ___sbrk
  591. addl $4,%esp
  592. end;
  593. {$ASMMODE ATT}
  594. { include standard heap management }
  595. {$I heap.inc}
  596. {****************************************************************************
  597. Low level File Routines
  598. ****************************************************************************}
  599. procedure AllowSlash(p:pchar);
  600. var
  601. i : longint;
  602. begin
  603. { allow slash as backslash }
  604. for i:=0 to strlen(p) do
  605. if p[i]='/' then p[i]:='\';
  606. end;
  607. procedure do_close(handle : longint);
  608. var
  609. regs : trealregs;
  610. begin
  611. regs.realebx:=handle;
  612. {$ifdef SYSTEMDEBUG}
  613. if handle<max_files then
  614. begin
  615. openfiles[handle]:=false;
  616. if assigned(opennames[handle]) and free_closed_names then
  617. begin
  618. freemem(opennames[handle],strlen(opennames[handle])+1);
  619. opennames[handle]:=nil;
  620. end;
  621. end;
  622. {$endif SYSTEMDEBUG}
  623. regs.realeax:=$3e00;
  624. sysrealintr($21,regs);
  625. if (regs.realflags and carryflag) <> 0 then
  626. InOutRes:=lo(regs.realeax);
  627. end;
  628. procedure do_erase(p : pchar);
  629. var
  630. regs : trealregs;
  631. begin
  632. AllowSlash(p);
  633. syscopytodos(longint(p),strlen(p)+1);
  634. regs.realedx:=tb_offset;
  635. regs.realds:=tb_segment;
  636. {$ifndef RTLLITE}
  637. if LFNSupport then
  638. regs.realeax:=$7141
  639. else
  640. {$endif RTLLITE}
  641. regs.realeax:=$4100;
  642. regs.realesi:=0;
  643. regs.realecx:=0;
  644. sysrealintr($21,regs);
  645. if (regs.realflags and carryflag) <> 0 then
  646. InOutRes:=lo(regs.realeax);
  647. end;
  648. procedure do_rename(p1,p2 : pchar);
  649. var
  650. regs : trealregs;
  651. begin
  652. AllowSlash(p1);
  653. AllowSlash(p2);
  654. if strlen(p1)+strlen(p2)+3>tb_size then
  655. HandleError(217);
  656. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  657. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  658. regs.realedi:=tb_offset;
  659. regs.realedx:=tb_offset + strlen(p2)+2;
  660. regs.realds:=tb_segment;
  661. regs.reales:=tb_segment;
  662. {$ifndef RTLLITE}
  663. if LFNSupport then
  664. regs.realeax:=$7156
  665. else
  666. {$endif RTLLITE}
  667. regs.realeax:=$5600;
  668. regs.realecx:=$ff; { attribute problem here ! }
  669. sysrealintr($21,regs);
  670. if (regs.realflags and carryflag) <> 0 then
  671. InOutRes:=lo(regs.realeax);
  672. end;
  673. function do_write(h,addr,len : longint) : longint;
  674. var
  675. regs : trealregs;
  676. size,
  677. writesize : longint;
  678. begin
  679. writesize:=0;
  680. while len > 0 do
  681. begin
  682. if len>tb_size then
  683. size:=tb_size
  684. else
  685. size:=len;
  686. syscopytodos(addr+writesize,size);
  687. regs.realecx:=size;
  688. regs.realedx:=tb_offset;
  689. regs.realds:=tb_segment;
  690. regs.realebx:=h;
  691. regs.realeax:=$4000;
  692. sysrealintr($21,regs);
  693. if (regs.realflags and carryflag) <> 0 then
  694. begin
  695. InOutRes:=lo(regs.realeax);
  696. exit(writesize);
  697. end;
  698. len:=len-size;
  699. writesize:=writesize+size;
  700. end;
  701. Do_Write:=WriteSize
  702. end;
  703. function do_read(h,addr,len : longint) : longint;
  704. var
  705. regs : trealregs;
  706. size,
  707. readsize : longint;
  708. begin
  709. readsize:=0;
  710. while len > 0 do
  711. begin
  712. if len>tb_size then
  713. size:=tb_size
  714. else
  715. size:=len;
  716. regs.realecx:=size;
  717. regs.realedx:=tb_offset;
  718. regs.realds:=tb_segment;
  719. regs.realebx:=h;
  720. regs.realeax:=$3f00;
  721. sysrealintr($21,regs);
  722. if (regs.realflags and carryflag) <> 0 then
  723. begin
  724. InOutRes:=lo(regs.realeax);
  725. do_read:=0;
  726. exit;
  727. end
  728. else
  729. if regs.realeax<size then
  730. begin
  731. syscopyfromdos(addr+readsize,regs.realeax);
  732. do_read:=readsize+regs.realeax;
  733. exit;
  734. end;
  735. syscopyfromdos(addr+readsize,regs.realeax);
  736. readsize:=readsize+regs.realeax;
  737. len:=len-regs.realeax;
  738. end;
  739. do_read:=readsize;
  740. end;
  741. function do_filepos(handle : longint) : longint;
  742. var
  743. regs : trealregs;
  744. begin
  745. regs.realebx:=handle;
  746. regs.realecx:=0;
  747. regs.realedx:=0;
  748. regs.realeax:=$4201;
  749. sysrealintr($21,regs);
  750. if (regs.realflags and carryflag) <> 0 then
  751. Begin
  752. InOutRes:=lo(regs.realeax);
  753. do_filepos:=0;
  754. end
  755. else
  756. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  757. end;
  758. procedure do_seek(handle,pos : longint);
  759. var
  760. regs : trealregs;
  761. begin
  762. regs.realebx:=handle;
  763. regs.realecx:=pos shr 16;
  764. regs.realedx:=pos and $ffff;
  765. regs.realeax:=$4200;
  766. sysrealintr($21,regs);
  767. if (regs.realflags and carryflag) <> 0 then
  768. InOutRes:=lo(regs.realeax);
  769. end;
  770. function do_seekend(handle:longint):longint;
  771. var
  772. regs : trealregs;
  773. begin
  774. regs.realebx:=handle;
  775. regs.realecx:=0;
  776. regs.realedx:=0;
  777. regs.realeax:=$4202;
  778. sysrealintr($21,regs);
  779. if (regs.realflags and carryflag) <> 0 then
  780. Begin
  781. InOutRes:=lo(regs.realeax);
  782. do_seekend:=0;
  783. end
  784. else
  785. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  786. end;
  787. function do_filesize(handle : longint) : longint;
  788. var
  789. aktfilepos : longint;
  790. begin
  791. aktfilepos:=do_filepos(handle);
  792. do_filesize:=do_seekend(handle);
  793. do_seek(handle,aktfilepos);
  794. end;
  795. { truncate at a given position }
  796. procedure do_truncate (handle,pos:longint);
  797. var
  798. regs : trealregs;
  799. begin
  800. do_seek(handle,pos);
  801. regs.realecx:=0;
  802. regs.realedx:=tb_offset;
  803. regs.realds:=tb_segment;
  804. regs.realebx:=handle;
  805. regs.realeax:=$4000;
  806. sysrealintr($21,regs);
  807. if (regs.realflags and carryflag) <> 0 then
  808. InOutRes:=lo(regs.realeax);
  809. end;
  810. procedure do_open(var f;p:pchar;flags:longint);
  811. {
  812. filerec and textrec have both handle and mode as the first items so
  813. they could use the same routine for opening/creating.
  814. when (flags and $10) the file will be append
  815. when (flags and $100) the file will be truncate/rewritten
  816. when (flags and $1000) there is no check for close (needed for textfiles)
  817. }
  818. var
  819. regs : trealregs;
  820. action : longint;
  821. begin
  822. AllowSlash(p);
  823. { close first if opened }
  824. if ((flags and $1000)=0) then
  825. begin
  826. case filerec(f).mode of
  827. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  828. fmclosed : ;
  829. else
  830. begin
  831. inoutres:=102; {not assigned}
  832. exit;
  833. end;
  834. end;
  835. end;
  836. { reset file handle }
  837. filerec(f).handle:=UnusedHandle;
  838. action:=$1;
  839. { convert filemode to filerec modes }
  840. case (flags and 3) of
  841. 0 : filerec(f).mode:=fminput;
  842. 1 : filerec(f).mode:=fmoutput;
  843. 2 : filerec(f).mode:=fminout;
  844. end;
  845. if (flags and $100)<>0 then
  846. begin
  847. filerec(f).mode:=fmoutput;
  848. action:=$12; {create file function}
  849. end;
  850. { empty name is special }
  851. if p[0]=#0 then
  852. begin
  853. case filerec(f).mode of
  854. fminput : filerec(f).handle:=StdInputHandle;
  855. fmappend,
  856. fmoutput : begin
  857. filerec(f).handle:=StdOutputHandle;
  858. filerec(f).mode:=fmoutput; {fool fmappend}
  859. end;
  860. end;
  861. exit;
  862. end;
  863. { real dos call }
  864. syscopytodos(longint(p),strlen(p)+1);
  865. {$ifndef RTLLITE}
  866. if LFNSupport then
  867. regs.realeax:=$716c
  868. else
  869. {$endif RTLLITE}
  870. regs.realeax:=$6c00;
  871. regs.realedx:=action;
  872. regs.realds:=tb_segment;
  873. regs.realesi:=tb_offset;
  874. regs.realebx:=$2000+(flags and $ff);
  875. regs.realecx:=$20;
  876. sysrealintr($21,regs);
  877. if (regs.realflags and carryflag) <> 0 then
  878. begin
  879. InOutRes:=lo(regs.realeax);
  880. exit;
  881. end
  882. else
  883. filerec(f).handle:=regs.realeax;
  884. {$ifdef SYSTEMDEBUG}
  885. if regs.realeax<max_files then
  886. begin
  887. openfiles[regs.realeax]:=true;
  888. getmem(opennames[regs.realeax],strlen(p)+1);
  889. move(p^,opennames[regs.realeax]^,strlen(p)+1);
  890. end;
  891. {$endif SYSTEMDEBUG}
  892. { append mode }
  893. if (flags and $10)<>0 then
  894. begin
  895. do_seekend(filerec(f).handle);
  896. filerec(f).mode:=fmoutput; {fool fmappend}
  897. end;
  898. end;
  899. function do_isdevice(handle:longint):boolean;
  900. var
  901. regs : trealregs;
  902. begin
  903. regs.realebx:=handle;
  904. regs.realeax:=$4400;
  905. sysrealintr($21,regs);
  906. do_isdevice:=(regs.realedx and $80)<>0;
  907. if (regs.realflags and carryflag) <> 0 then
  908. InOutRes:=lo(regs.realeax);
  909. end;
  910. {*****************************************************************************
  911. UnTyped File Handling
  912. *****************************************************************************}
  913. {$i file.inc}
  914. {*****************************************************************************
  915. Typed File Handling
  916. *****************************************************************************}
  917. {$i typefile.inc}
  918. {*****************************************************************************
  919. Text File Handling
  920. *****************************************************************************}
  921. {$DEFINE EOF_CTRLZ}
  922. {$i text.inc}
  923. {*****************************************************************************
  924. Directory Handling
  925. *****************************************************************************}
  926. procedure DosDir(func:byte;const s:string);
  927. var
  928. buffer : array[0..255] of char;
  929. regs : trealregs;
  930. begin
  931. move(s[1],buffer,length(s));
  932. buffer[length(s)]:=#0;
  933. AllowSlash(pchar(@buffer));
  934. syscopytodos(longint(@buffer),length(s)+1);
  935. regs.realedx:=tb_offset;
  936. regs.realds:=tb_segment;
  937. {$ifndef RTLLITE}
  938. if LFNSupport then
  939. regs.realeax:=$7100+func
  940. else
  941. {$endif RTLLITE}
  942. regs.realeax:=func shl 8;
  943. sysrealintr($21,regs);
  944. if (regs.realflags and carryflag) <> 0 then
  945. InOutRes:=lo(regs.realeax);
  946. end;
  947. procedure mkdir(const s : string);[IOCheck];
  948. begin
  949. If InOutRes <> 0 then
  950. exit;
  951. DosDir($39,s);
  952. end;
  953. procedure rmdir(const s : string);[IOCheck];
  954. begin
  955. If InOutRes <> 0 then
  956. exit;
  957. DosDir($3a,s);
  958. end;
  959. procedure chdir(const s : string);[IOCheck];
  960. var
  961. regs : trealregs;
  962. begin
  963. If InOutRes <> 0 then
  964. exit;
  965. { First handle Drive changes }
  966. if (length(s)>=2) and (s[2]=':') then
  967. begin
  968. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  969. regs.realeax:=$0e00;
  970. sysrealintr($21,regs);
  971. regs.realeax:=$1900;
  972. sysrealintr($21,regs);
  973. if byte(regs.realeax)<>byte(regs.realedx) then
  974. begin
  975. Inoutres:=15;
  976. exit;
  977. end;
  978. end;
  979. { do the normal dos chdir }
  980. DosDir($3b,s);
  981. end;
  982. procedure getdir(drivenr : byte;var dir : shortstring);
  983. var
  984. temp : array[0..255] of char;
  985. i : longint;
  986. regs : trealregs;
  987. begin
  988. regs.realedx:=drivenr;
  989. regs.realesi:=tb_offset;
  990. regs.realds:=tb_segment;
  991. {$ifndef RTLLITE}
  992. if LFNSupport then
  993. regs.realeax:=$7147
  994. else
  995. {$endif RTLLITE}
  996. regs.realeax:=$4700;
  997. sysrealintr($21,regs);
  998. if (regs.realflags and carryflag) <> 0 then
  999. Begin
  1000. InOutRes:=lo(regs.realeax);
  1001. exit;
  1002. end
  1003. else
  1004. syscopyfromdos(longint(@temp),251);
  1005. { conversation to Pascal string including slash conversion }
  1006. i:=0;
  1007. while (temp[i]<>#0) do
  1008. begin
  1009. if temp[i]='/' then
  1010. temp[i]:='\';
  1011. dir[i+4]:=temp[i];
  1012. inc(i);
  1013. end;
  1014. dir[2]:=':';
  1015. dir[3]:='\';
  1016. dir[0]:=char(i+3);
  1017. { upcase the string }
  1018. dir:=upcase(dir);
  1019. if drivenr<>0 then { Drive was supplied. We know it }
  1020. dir[1]:=char(65+drivenr-1)
  1021. else
  1022. begin
  1023. { We need to get the current drive from DOS function 19H }
  1024. { because the drive was the default, which can be unknown }
  1025. regs.realeax:=$1900;
  1026. sysrealintr($21,regs);
  1027. i:= (regs.realeax and $ff) + ord('A');
  1028. dir[1]:=chr(i);
  1029. end;
  1030. end;
  1031. {*****************************************************************************
  1032. SystemUnit Initialization
  1033. *****************************************************************************}
  1034. {$ifndef RTLLITE}
  1035. function CheckLFN:boolean;
  1036. var
  1037. regs : TRealRegs;
  1038. RootName : pchar;
  1039. begin
  1040. { Check LFN API on drive c:\ }
  1041. RootName:='C:\';
  1042. syscopytodos(longint(RootName),strlen(RootName)+1);
  1043. { Call 'Get Volume Information' ($71A0) }
  1044. regs.realeax:=$71a0;
  1045. regs.reales:=tb_segment;
  1046. regs.realedi:=tb_offset;
  1047. regs.realecx:=32;
  1048. regs.realds:=tb_segment;
  1049. regs.realedx:=tb_offset;
  1050. regs.realflags:=carryflag;
  1051. sysrealintr($21,regs);
  1052. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1053. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1054. end;
  1055. {$endif RTLLITE}
  1056. var
  1057. temp_int : tseginfo;
  1058. Begin
  1059. { save old int 0 and 75 }
  1060. get_pm_interrupt($00,old_int00);
  1061. get_pm_interrupt($75,old_int75);
  1062. temp_int.segment:=get_cs;
  1063. temp_int.offset:=@new_int00;
  1064. set_pm_interrupt($00,temp_int);
  1065. { temp_int.offset:=@new_int75;
  1066. set_pm_interrupt($75,temp_int); }
  1067. { to test stack depth }
  1068. loweststack:=maxlongint;
  1069. { Setup heap }
  1070. InitHeap;
  1071. { Setup stdin, stdout and stderr }
  1072. OpenStdIO(Input,fmInput,StdInputHandle);
  1073. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1074. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1075. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1076. { Setup environment and arguments }
  1077. Setup_Environment;
  1078. Setup_Arguments;
  1079. { Use LFNSupport LFN }
  1080. LFNSupport:=CheckLFN;
  1081. { Reset IO Error }
  1082. InOutRes:=0;
  1083. End.
  1084. {
  1085. $Log$
  1086. Revision 1.3 1998-12-28 15:50:45 peter
  1087. + stdout, which is needed when you write something in the system unit
  1088. to the screen. Like the runtime error
  1089. Revision 1.2 1998/12/21 14:22:02 pierre
  1090. * old_int?? transformed to cvar to be readable by dpmiexcp
  1091. Revision 1.1 1998/12/21 13:07:03 peter
  1092. * use -FE
  1093. Revision 1.25 1998/12/15 22:42:52 peter
  1094. * removed temp symbols
  1095. Revision 1.24 1998/11/29 22:28:10 peter
  1096. + io-error 103 added
  1097. Revision 1.23 1998/11/16 14:15:02 pierre
  1098. * changed getdir(byte,string) to getdir(byte,shortstring)
  1099. Revision 1.22 1998/10/26 14:49:46 pierre
  1100. * system debug info output to stderr
  1101. Revision 1.21 1998/10/20 07:34:07 pierre
  1102. + systemdebug reports about unclosed files at exit
  1103. Revision 1.20 1998/10/13 21:41:06 peter
  1104. + int 0 for divide by zero
  1105. Revision 1.19 1998/09/14 10:48:05 peter
  1106. * FPC_ names
  1107. * Heap manager is now system independent
  1108. Revision 1.18 1998/08/28 10:48:04 peter
  1109. * fixed chdir with drive changing
  1110. * updated checklfn from mailinglist
  1111. Revision 1.17 1998/08/27 10:30:51 pierre
  1112. * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !)
  1113. I renamed tb_selector to tb_segment because
  1114. it is a real mode segment as opposed to
  1115. a protected mode selector
  1116. Fixed it for go32v1 (remove the $E0000000 offset !)
  1117. Revision 1.16 1998/08/26 10:04:03 peter
  1118. * new lfn check from mailinglist
  1119. * renamed win95 -> LFNSupport
  1120. + tb_selector, tb_offset for easier access to transferbuffer
  1121. Revision 1.15 1998/08/19 10:56:34 pierre
  1122. + added some special code for C interface
  1123. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  1124. Revision 1.14 1998/08/04 14:34:38 pierre
  1125. * small bug fix to get it compiled with bugfix version !!
  1126. (again the asmmode problem !!!
  1127. Peter it was really not the best idea you had !!)
  1128. Revision 1.13 1998/07/30 13:26:22 michael
  1129. + Added support for ErrorProc variable. All internal functions are required
  1130. to call HandleError instead of runerror from now on.
  1131. This is necessary for exception support.
  1132. Revision 1.12 1998/07/13 21:19:08 florian
  1133. * some problems with ansi string support fixed
  1134. Revision 1.11 1998/07/07 12:33:08 carl
  1135. * added 2k buffer for stack checking for correct io on error
  1136. Revision 1.10 1998/07/02 12:29:20 carl
  1137. * IOCheck for rmdir,chdir and mkdir as in TP
  1138. NOTE: I'm pretty SURE this will not compile and link correctly with FPC
  1139. 0.99.5
  1140. Revision 1.9 1998/07/01 15:29:57 peter
  1141. * better readln/writeln
  1142. Revision 1.8 1998/06/26 08:19:10 pierre
  1143. + all debug in ifdef SYSTEMDEBUG
  1144. + added local arrays :
  1145. opennames names of opened files
  1146. fileopen boolean array to know if still open
  1147. usefull with gdb if you get problems about too
  1148. many open files !!
  1149. Revision 1.7 1998/06/15 15:17:08 daniel
  1150. * RTLLITE conditional added to produce smaller RTL.
  1151. Revision 1.6 1998/05/31 14:18:29 peter
  1152. * force att or direct assembling
  1153. * cleanup of some files
  1154. Revision 1.5 1998/05/21 19:30:52 peter
  1155. * objects compiles for linux
  1156. + assign(pchar), assign(char), rename(pchar), rename(char)
  1157. * fixed read_text_as_array
  1158. + read_text_as_pchar which was not yet in the rtl
  1159. Revision 1.4 1998/05/04 17:58:41 peter
  1160. * fix for smartlinking with _ARGS
  1161. Revision 1.3 1998/05/04 16:21:54 florian
  1162. + LFNSupport flag to the interface moved
  1163. }