system.pp 32 KB

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