system.pp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  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. { two debug conditionnals can be used
  14. - SYSTEMDEBUG
  15. -for STACK checks
  16. -for non closed files at exit (or at any time with GDB)
  17. - SYSTEM_DEBUG_STARTUP
  18. specifically for
  19. - proxy command line (DJGPP feature)
  20. - list of args
  21. - list of env variables (PM) }
  22. { include system-independent routine headers }
  23. {$I systemh.inc}
  24. { include heap support headers }
  25. {$I heaph.inc}
  26. const
  27. { Default filehandles }
  28. UnusedHandle = -1;
  29. StdInputHandle = 0;
  30. StdOutputHandle = 1;
  31. StdErrorHandle = 2;
  32. FileNameCaseSensitive : boolean = false;
  33. { Default memory segments (Tp7 compatibility) }
  34. seg0040 = $0040;
  35. segA000 = $A000;
  36. segB000 = $B000;
  37. segB800 = $B800;
  38. var
  39. { Mem[] support }
  40. mem : array[0..$7fffffff] of byte absolute $0:$0;
  41. memw : array[0..$7fffffff] of word absolute $0:$0;
  42. meml : array[0..$7fffffff] of longint absolute $0:$0;
  43. { C-compatible arguments and environment }
  44. argc : longint;
  45. argv : ppchar;
  46. envp : ppchar;
  47. dos_argv0 : pchar;
  48. {$ifndef RTLLITE}
  49. { System info }
  50. LFNSupport : boolean;
  51. {$endif RTLLITE}
  52. type
  53. { Dos Extender info }
  54. p_stub_info = ^t_stub_info;
  55. t_stub_info = packed record
  56. magic : array[0..15] of char;
  57. size : longint;
  58. minstack : longint;
  59. memory_handle : longint;
  60. initial_size : longint;
  61. minkeep : word;
  62. ds_selector : word;
  63. ds_segment : word;
  64. psp_selector : word;
  65. cs_selector : word;
  66. env_size : word;
  67. basename : array[0..7] of char;
  68. argv0 : array [0..15] of char;
  69. dpmi_server : array [0..15] of char;
  70. end;
  71. p_go32_info_block = ^t_go32_info_block;
  72. t_go32_info_block = packed record
  73. size_of_this_structure_in_bytes : longint; {offset 0}
  74. linear_address_of_primary_screen : longint; {offset 4}
  75. linear_address_of_secondary_screen : longint; {offset 8}
  76. linear_address_of_transfer_buffer : longint; {offset 12}
  77. size_of_transfer_buffer : longint; {offset 16}
  78. pid : longint; {offset 20}
  79. master_interrupt_controller_base : byte; {offset 24}
  80. slave_interrupt_controller_base : byte; {offset 25}
  81. selector_for_linear_memory : word; {offset 26}
  82. linear_address_of_stub_info_structure : longint; {offset 28}
  83. linear_address_of_original_psp : longint; {offset 32}
  84. run_mode : word; {offset 36}
  85. run_mode_info : word; {offset 38}
  86. end;
  87. var
  88. stub_info : p_stub_info;
  89. go32_info_block : t_go32_info_block;
  90. {
  91. necessary for objects.pas, should be removed (at least from the interface
  92. to the implementation)
  93. }
  94. type
  95. trealregs=record
  96. realedi,realesi,realebp,realres,
  97. realebx,realedx,realecx,realeax : longint;
  98. realflags,
  99. reales,realds,realfs,realgs,
  100. realip,realcs,realsp,realss : word;
  101. end;
  102. function do_write(h,addr,len : longint) : longint;
  103. function do_read(h,addr,len : longint) : longint;
  104. procedure syscopyfromdos(addr : longint; len : longint);
  105. procedure syscopytodos(addr : longint; len : longint);
  106. procedure sysrealintr(intnr : word;var regs : trealregs);
  107. function tb : longint;
  108. implementation
  109. { include system independent routines }
  110. {$I system.inc}
  111. const
  112. carryflag = 1;
  113. type
  114. tseginfo=packed record
  115. offset : pointer;
  116. segment : word;
  117. end;
  118. var
  119. doscmd : string[128]; { Dos commandline copied from PSP, max is 128 chars }
  120. old_int00 : tseginfo;cvar;
  121. old_int75 : tseginfo;cvar;
  122. {$asmmode ATT}
  123. {*****************************************************************************
  124. Go32 Helpers
  125. *****************************************************************************}
  126. function far_strlen(selector : word;linear_address : longint) : longint;
  127. begin
  128. asm
  129. movl linear_address,%edx
  130. movl %edx,%ecx
  131. movw selector,%gs
  132. .Larg19:
  133. movb %gs:(%edx),%al
  134. testb %al,%al
  135. je .Larg20
  136. incl %edx
  137. jmp .Larg19
  138. .Larg20:
  139. movl %edx,%eax
  140. subl %ecx,%eax
  141. movl %eax,__RESULT
  142. end;
  143. end;
  144. function tb : longint;
  145. begin
  146. tb:=go32_info_block.linear_address_of_transfer_buffer;
  147. end;
  148. function tb_segment : longint;
  149. begin
  150. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  151. end;
  152. function tb_offset : longint;
  153. begin
  154. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  155. end;
  156. function tb_size : longint;
  157. begin
  158. tb_size:=go32_info_block.size_of_transfer_buffer;
  159. end;
  160. function dos_selector : word;
  161. begin
  162. dos_selector:=go32_info_block.selector_for_linear_memory;
  163. end;
  164. function get_ds : word;assembler;
  165. asm
  166. movw %ds,%ax
  167. end;
  168. function get_cs : word;assembler;
  169. asm
  170. movw %cs,%ax
  171. end;
  172. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  173. begin
  174. if count=0 then
  175. exit;
  176. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  177. asm
  178. pushw %es
  179. pushw %ds
  180. cld
  181. movl count,%ecx
  182. movl source,%esi
  183. movl dest,%edi
  184. movw dseg,%ax
  185. movw %ax,%es
  186. movw sseg,%ax
  187. movw %ax,%ds
  188. movl %ecx,%eax
  189. shrl $2,%ecx
  190. rep
  191. movsl
  192. movl %eax,%ecx
  193. andl $3,%ecx
  194. rep
  195. movsb
  196. popw %ds
  197. popw %es
  198. end ['ESI','EDI','ECX','EAX']
  199. else if (source<dest) then
  200. { copy backward for overlapping }
  201. asm
  202. pushw %es
  203. pushw %ds
  204. std
  205. movl count,%ecx
  206. movl source,%esi
  207. movl dest,%edi
  208. movw dseg,%ax
  209. movw %ax,%es
  210. movw sseg,%ax
  211. movw %ax,%ds
  212. addl %ecx,%esi
  213. addl %ecx,%edi
  214. movl %ecx,%eax
  215. andl $3,%ecx
  216. orl %ecx,%ecx
  217. jz .LSEG_MOVE1
  218. { calculate esi and edi}
  219. decl %esi
  220. decl %edi
  221. rep
  222. movsb
  223. incl %esi
  224. incl %edi
  225. .LSEG_MOVE1:
  226. subl $4,%esi
  227. subl $4,%edi
  228. movl %eax,%ecx
  229. shrl $2,%ecx
  230. rep
  231. movsl
  232. cld
  233. popw %ds
  234. popw %es
  235. end ['ESI','EDI','ECX'];
  236. end;
  237. function atohex(s : pchar) : longint;
  238. var
  239. rv : longint;
  240. v : byte;
  241. begin
  242. rv:=0;
  243. while (s^ <>#0) do
  244. begin
  245. v:=byte(s^)-byte('0');
  246. if (v > 9) then
  247. dec(v,7);
  248. v:=v and 15; { in case it's lower case }
  249. rv:=(rv shl 4) or v;
  250. inc(longint(s));
  251. end;
  252. atohex:=rv;
  253. end;
  254. var
  255. _args : ppchar;external name '_args';
  256. procedure setup_arguments;
  257. type arrayword = array [0..0] of word;
  258. var psp : word;
  259. i,j : byte;
  260. quote : char;
  261. proxy_s : string[7];
  262. al,proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  263. largs : array[0..127] of pchar;
  264. rm_argv : ^arrayword;
  265. begin
  266. for i := 1 to 127 do
  267. largs[i] := nil;
  268. psp:=stub_info^.psp_selector;
  269. largs[0]:=dos_argv0;
  270. argc := 1;
  271. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  272. {$IfDef SYSTEM_DEBUG_STARTUP}
  273. Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
  274. {$EndIf }
  275. // setup cmdline variable
  276. getmem(cmdline,length(doscmd)+1);
  277. move(doscmd[1],cmdline^,length(doscmd));
  278. cmdline[length(doscmd)]:=#0;
  279. j := 1;
  280. quote := #0;
  281. for i:=1 to length(doscmd) do
  282. Begin
  283. if doscmd[i] = quote then
  284. begin
  285. quote := #0;
  286. doscmd[i] := #0;
  287. largs[argc]:=@doscmd[j];
  288. inc(argc);
  289. j := i+1;
  290. end else
  291. if (quote = #0) and ((doscmd[i] = '''') or (doscmd[i]='"')) then
  292. begin
  293. quote := doscmd[i];
  294. j := i + 1;
  295. end else
  296. if (quote = #0) and ((doscmd[i] = ' ')
  297. or (doscmd[i] = #9) or (doscmd[i] = #10) or
  298. (doscmd[i] = #12) or (doscmd[i] = #9)) then
  299. begin
  300. doscmd[i]:=#0;
  301. if j<i then
  302. begin
  303. largs[argc]:=@doscmd[j];
  304. inc(argc);
  305. j := i+1;
  306. end else inc(j);
  307. end else
  308. if (i = length(doscmd)) then
  309. begin
  310. doscmd[i+1]:=#0;
  311. largs[argc]:=@doscmd[j];
  312. inc(argc);
  313. end;
  314. end;
  315. if (argc > 1) and (far_strlen(get_ds,longint(largs[1])) = 6) then
  316. begin
  317. move(largs[1]^,proxy_s[1],6);
  318. proxy_s[0] := #6;
  319. if (proxy_s = '!proxy') then
  320. begin
  321. {$IfDef SYSTEM_DEBUG_STARTUP}
  322. Writeln(stderr,'proxy command line ');
  323. {$EndIf SYSTEM_DEBUG_STARTUP}
  324. proxy_argc := atohex(largs[2]);
  325. proxy_seg := atohex(largs[3]);
  326. proxy_ofs := atohex(largs[4]);
  327. getmem(rm_argv,proxy_argc*sizeof(word));
  328. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  329. for i:=0 to proxy_argc - 1 do
  330. begin
  331. lin := proxy_seg*16 + rm_argv^[i];
  332. al :=far_strlen(dos_selector, lin);
  333. getmem(largs[i],al+1);
  334. sysseg_move(dos_selector, lin, get_ds,longint(largs[i]), al+1);
  335. {$IfDef SYSTEM_DEBUG_STARTUP}
  336. Writeln(stderr,'arg ',i,' #',largs[i],'#');
  337. {$EndIf SYSTEM_DEBUG_STARTUP}
  338. end;
  339. argc := proxy_argc;
  340. end;
  341. end;
  342. getmem(argv,argc shl 2);
  343. for i := 0 to argc-1 do
  344. argv[i] := largs[i];
  345. _args:=argv;
  346. end;
  347. function strcopy(dest,source : pchar) : pchar;
  348. begin
  349. asm
  350. cld
  351. movl 12(%ebp),%edi
  352. movl $0xffffffff,%ecx
  353. xorb %al,%al
  354. repne
  355. scasb
  356. not %ecx
  357. movl 8(%ebp),%edi
  358. movl 12(%ebp),%esi
  359. movl %ecx,%eax
  360. shrl $2,%ecx
  361. rep
  362. movsl
  363. movl %eax,%ecx
  364. andl $3,%ecx
  365. rep
  366. movsb
  367. movl 8(%ebp),%eax
  368. leave
  369. ret $8
  370. end;
  371. end;
  372. var
  373. __stubinfo : p_stub_info;external name '__stubinfo';
  374. ___dos_argv0 : pchar;external name '___dos_argv0';
  375. procedure setup_environment;
  376. var env_selector : word;
  377. env_count : longint;
  378. dos_env,cp : pchar;
  379. begin
  380. stub_info:=__stubinfo;
  381. getmem(dos_env,stub_info^.env_size);
  382. env_count:=0;
  383. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  384. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  385. cp:=dos_env;
  386. while cp ^ <> #0 do
  387. begin
  388. inc(env_count);
  389. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  390. inc(longint(cp)); { skip to next character }
  391. end;
  392. getmem(envp,(env_count+1) * sizeof(pchar));
  393. if (envp = nil) then exit;
  394. cp:=dos_env;
  395. env_count:=0;
  396. while cp^ <> #0 do
  397. begin
  398. getmem(envp[env_count],strlen(cp)+1);
  399. strcopy(envp[env_count], cp);
  400. {$IfDef SYSTEM_DEBUG_STARTUP}
  401. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  402. {$EndIf SYSTEM_DEBUG_STARTUP}
  403. inc(env_count);
  404. while (cp^ <> #0) do
  405. inc(longint(cp)); { skip to NUL }
  406. inc(longint(cp)); { skip to next character }
  407. end;
  408. envp[env_count]:=nil;
  409. longint(cp):=longint(cp)+3;
  410. getmem(dos_argv0,strlen(cp)+1);
  411. if (dos_argv0 = nil) then halt;
  412. strcopy(dos_argv0, cp);
  413. { update ___dos_argv0 also }
  414. ___dos_argv0:=dos_argv0
  415. end;
  416. procedure syscopytodos(addr : longint; len : longint);
  417. begin
  418. if len > tb_size then
  419. HandleError(217);
  420. sysseg_move(get_ds,addr,dos_selector,tb,len);
  421. end;
  422. procedure syscopyfromdos(addr : longint; len : longint);
  423. begin
  424. if len > tb_size then
  425. HandleError(217);
  426. sysseg_move(dos_selector,tb,get_ds,addr,len);
  427. end;
  428. procedure sysrealintr(intnr : word;var regs : trealregs);
  429. begin
  430. regs.realsp:=0;
  431. regs.realss:=0;
  432. asm
  433. movw intnr,%bx
  434. xorl %ecx,%ecx
  435. movl regs,%edi
  436. movw $0x300,%ax
  437. int $0x31
  438. end;
  439. end;
  440. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  441. begin
  442. asm
  443. movl intaddr,%eax
  444. movl (%eax),%edx
  445. movw 4(%eax),%cx
  446. movl $0x205,%eax
  447. movb vector,%bl
  448. int $0x31
  449. end;
  450. end;
  451. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  452. begin
  453. asm
  454. movb vector,%bl
  455. movl $0x204,%eax
  456. int $0x31
  457. movl intaddr,%eax
  458. movl %edx,(%eax)
  459. movw %cx,4(%eax)
  460. end;
  461. end;
  462. { Keep Track of open files }
  463. const
  464. max_files = 50;
  465. var
  466. openfiles : array [0..max_files-1] of boolean;
  467. {$ifdef SYSTEMDEBUG}
  468. opennames : array [0..max_files-1] of pchar;
  469. const
  470. free_closed_names : boolean = true;
  471. {$endif SYSTEMDEBUG}
  472. {*****************************************************************************
  473. System Dependent Exit code
  474. *****************************************************************************}
  475. procedure ___exit(exitcode:byte);cdecl;external name '___exit';
  476. procedure do_close(handle : longint);forward;
  477. Procedure system_exit;
  478. var
  479. h : byte;
  480. begin
  481. for h:=0 to max_files-1 do
  482. if openfiles[h] then
  483. begin
  484. {$ifdef SYSTEMDEBUG}
  485. writeln(stderr,'file ',opennames[h],' not closed at exit');
  486. {$endif SYSTEMDEBUG}
  487. if h>=5 then
  488. do_close(h);
  489. end;
  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. ___exit(exitcode);
  495. end;
  496. procedure halt(errnum : byte);
  497. begin
  498. exitcode:=errnum;
  499. do_exit;
  500. { do_exit should call system_exit but this does not hurt }
  501. System_exit;
  502. end;
  503. procedure new_int00;
  504. begin
  505. HandleError(200);
  506. end;
  507. procedure new_int75;
  508. begin
  509. asm
  510. xorl %eax,%eax
  511. outb %al,$0x0f0
  512. movb $0x20,%al
  513. outb %al,$0x0a0
  514. outb %al,$0x020
  515. end;
  516. HandleError(200);
  517. end;
  518. var
  519. __stkbottom : longint;external name '__stkbottom';
  520. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  521. {
  522. called when trying to get local stack if the compiler directive $S
  523. is set this function must preserve esi !!!! because esi is set by
  524. the calling proc for methods it must preserve all registers !!
  525. With a 2048 byte safe area used to write to StdIo without crossing
  526. the stack boundary
  527. }
  528. begin
  529. asm
  530. pushl %eax
  531. pushl %ebx
  532. movl stack_size,%ebx
  533. addl $2048,%ebx
  534. movl %esp,%eax
  535. subl %ebx,%eax
  536. {$ifdef SYSTEMDEBUG}
  537. movl loweststack,%ebx
  538. cmpl %eax,%ebx
  539. jb .L_is_not_lowest
  540. movl %eax,loweststack
  541. .L_is_not_lowest:
  542. {$endif SYSTEMDEBUG}
  543. movl __stkbottom,%ebx
  544. cmpl %eax,%ebx
  545. jae .L__short_on_stack
  546. popl %ebx
  547. popl %eax
  548. leave
  549. ret $4
  550. .L__short_on_stack:
  551. { can be usefull for error recovery !! }
  552. popl %ebx
  553. popl %eax
  554. end['EAX','EBX'];
  555. HandleError(202);
  556. end;
  557. {*****************************************************************************
  558. ParamStr/Randomize
  559. *****************************************************************************}
  560. function paramcount : longint;
  561. begin
  562. paramcount := argc - 1;
  563. end;
  564. function paramstr(l : longint) : string;
  565. begin
  566. if (l>=0) and (l+1<=argc) then
  567. paramstr:=strpas(argv[l])
  568. else
  569. paramstr:='';
  570. end;
  571. procedure randomize;
  572. var
  573. hl : longint;
  574. regs : trealregs;
  575. begin
  576. regs.realeax:=$2c00;
  577. sysrealintr($21,regs);
  578. hl:=regs.realedx and $ffff;
  579. randseed:=hl*$10000+ (regs.realecx and $ffff);
  580. end;
  581. {*****************************************************************************
  582. Heap Management
  583. *****************************************************************************}
  584. var
  585. int_heap : longint;external name 'HEAP';
  586. int_heapsize : longint;external name 'HEAPSIZE';
  587. function getheapstart:pointer;
  588. begin
  589. getheapstart:=@int_heap;
  590. end;
  591. function getheapsize:longint;
  592. begin
  593. getheapsize:=int_heapsize;
  594. end;
  595. function ___sbrk(size:longint):longint;cdecl;external name '___sbrk';
  596. function Sbrk(size : longint):longint;assembler;
  597. asm
  598. movl size,%eax
  599. pushl %eax
  600. call ___sbrk
  601. addl $4,%esp
  602. end;
  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. if not FileNameCaseSensitive then
  1028. dir:=upcase(dir);
  1029. if drivenr<>0 then { Drive was supplied. We know it }
  1030. dir[1]:=char(65+drivenr-1)
  1031. else
  1032. begin
  1033. { We need to get the current drive from DOS function 19H }
  1034. { because the drive was the default, which can be unknown }
  1035. regs.realeax:=$1900;
  1036. sysrealintr($21,regs);
  1037. i:= (regs.realeax and $ff) + ord('A');
  1038. dir[1]:=chr(i);
  1039. end;
  1040. end;
  1041. {*****************************************************************************
  1042. SystemUnit Initialization
  1043. *****************************************************************************}
  1044. {$ifndef RTLLITE}
  1045. function CheckLFN:boolean;
  1046. var
  1047. regs : TRealRegs;
  1048. RootName : pchar;
  1049. begin
  1050. { Check LFN API on drive c:\ }
  1051. RootName:='C:\';
  1052. syscopytodos(longint(RootName),strlen(RootName)+1);
  1053. { Call 'Get Volume Information' ($71A0) }
  1054. regs.realeax:=$71a0;
  1055. regs.reales:=tb_segment;
  1056. regs.realedi:=tb_offset;
  1057. regs.realecx:=32;
  1058. regs.realds:=tb_segment;
  1059. regs.realedx:=tb_offset;
  1060. regs.realflags:=carryflag;
  1061. sysrealintr($21,regs);
  1062. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1063. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1064. end;
  1065. {$endif RTLLITE}
  1066. {$ifdef MT}
  1067. {$I thread.inc}
  1068. {$endif MT}
  1069. var
  1070. temp_int : tseginfo;
  1071. Begin
  1072. { save old int 0 and 75 }
  1073. get_pm_interrupt($00,old_int00);
  1074. get_pm_interrupt($75,old_int75);
  1075. temp_int.segment:=get_cs;
  1076. temp_int.offset:=@new_int00;
  1077. set_pm_interrupt($00,temp_int);
  1078. { temp_int.offset:=@new_int75;
  1079. set_pm_interrupt($75,temp_int); }
  1080. { to test stack depth }
  1081. loweststack:=maxlongint;
  1082. { Setup heap }
  1083. InitHeap;
  1084. {$ifdef MT}
  1085. { before this, you can't use thread vars !!!! }
  1086. { threadvarblocksize is calculate before the initialization }
  1087. { of the system unit }
  1088. getmem(mainprogramthreadblock,threadvarblocksize);
  1089. {$endif MT}
  1090. InitExceptions;
  1091. { Setup stdin, stdout and stderr }
  1092. OpenStdIO(Input,fmInput,StdInputHandle);
  1093. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1094. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1095. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1096. { Setup environment and arguments }
  1097. Setup_Environment;
  1098. Setup_Arguments;
  1099. { Use LFNSupport LFN }
  1100. LFNSupport:=CheckLFN;
  1101. if LFNSupport then
  1102. FileNameCaseSensitive:=true;
  1103. { Reset IO Error }
  1104. InOutRes:=0;
  1105. End.
  1106. {
  1107. $Log$
  1108. Revision 1.13 1999-05-19 16:54:21 pierre
  1109. * closes all handles >+ 5
  1110. Revision 1.12 1999/05/17 21:52:33 florian
  1111. * most of the Object Pascal stuff moved to the system unit
  1112. Revision 1.11 1999/05/04 23:28:40 pierre
  1113. SYSTEM_DEBUG_STARTUP used to output args and env at start
  1114. Revision 1.10 1999/04/28 11:42:45 peter
  1115. + FileNameCaseSensetive boolean
  1116. Revision 1.9 1999/04/28 06:01:25 florian
  1117. * define MT for multithreading introduced
  1118. Revision 1.8 1999/04/08 12:23:02 peter
  1119. * removed os.inc
  1120. Revision 1.7 1999/03/10 22:15:28 florian
  1121. + system.cmdline variable for go32v2 and win32 added
  1122. Revision 1.6 1999/03/01 15:40:52 peter
  1123. * use external names
  1124. * removed all direct assembler modes
  1125. Revision 1.5 1999/01/18 10:05:50 pierre
  1126. + system_exit procedure added
  1127. Revision 1.4 1998/12/30 22:17:59 peter
  1128. * fixed mem decls to use $0:$0
  1129. Revision 1.3 1998/12/28 15:50:45 peter
  1130. + stdout, which is needed when you write something in the system unit
  1131. to the screen. Like the runtime error
  1132. Revision 1.2 1998/12/21 14:22:02 pierre
  1133. * old_int?? transformed to cvar to be readable by dpmiexcp
  1134. Revision 1.1 1998/12/21 13:07:03 peter
  1135. * use -FE
  1136. Revision 1.25 1998/12/15 22:42:52 peter
  1137. * removed temp symbols
  1138. Revision 1.24 1998/11/29 22:28:10 peter
  1139. + io-error 103 added
  1140. Revision 1.23 1998/11/16 14:15:02 pierre
  1141. * changed getdir(byte,string) to getdir(byte,shortstring)
  1142. Revision 1.22 1998/10/26 14:49:46 pierre
  1143. * system debug info output to stderr
  1144. Revision 1.21 1998/10/20 07:34:07 pierre
  1145. + systemdebug reports about unclosed files at exit
  1146. Revision 1.20 1998/10/13 21:41:06 peter
  1147. + int 0 for divide by zero
  1148. Revision 1.19 1998/09/14 10:48:05 peter
  1149. * FPC_ names
  1150. * Heap manager is now system independent
  1151. Revision 1.18 1998/08/28 10:48:04 peter
  1152. * fixed chdir with drive changing
  1153. * updated checklfn from mailinglist
  1154. Revision 1.17 1998/08/27 10:30:51 pierre
  1155. * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !)
  1156. I renamed tb_selector to tb_segment because
  1157. it is a real mode segment as opposed to
  1158. a protected mode selector
  1159. Fixed it for go32v1 (remove the $E0000000 offset !)
  1160. Revision 1.16 1998/08/26 10:04:03 peter
  1161. * new lfn check from mailinglist
  1162. * renamed win95 -> LFNSupport
  1163. + tb_selector, tb_offset for easier access to transferbuffer
  1164. Revision 1.15 1998/08/19 10:56:34 pierre
  1165. + added some special code for C interface
  1166. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  1167. Revision 1.14 1998/08/04 14:34:38 pierre
  1168. * small bug fix to get it compiled with bugfix version !!
  1169. (again the asmmode problem !!!
  1170. Peter it was really not the best idea you had !!)
  1171. Revision 1.13 1998/07/30 13:26:22 michael
  1172. + Added support for ErrorProc variable. All internal functions are required
  1173. to call HandleError instead of runerror from now on.
  1174. This is necessary for exception support.
  1175. Revision 1.12 1998/07/13 21:19:08 florian
  1176. * some problems with ansi string support fixed
  1177. Revision 1.11 1998/07/07 12:33:08 carl
  1178. * added 2k buffer for stack checking for correct io on error
  1179. Revision 1.10 1998/07/02 12:29:20 carl
  1180. * IOCheck for rmdir,chdir and mkdir as in TP
  1181. NOTE: I'm pretty SURE this will not compile and link correctly with FPC
  1182. 0.99.5
  1183. Revision 1.9 1998/07/01 15:29:57 peter
  1184. * better readln/writeln
  1185. Revision 1.8 1998/06/26 08:19:10 pierre
  1186. + all debug in ifdef SYSTEMDEBUG
  1187. + added local arrays :
  1188. opennames names of opened files
  1189. fileopen boolean array to know if still open
  1190. usefull with gdb if you get problems about too
  1191. many open files !!
  1192. Revision 1.7 1998/06/15 15:17:08 daniel
  1193. * RTLLITE conditional added to produce smaller RTL.
  1194. Revision 1.6 1998/05/31 14:18:29 peter
  1195. * force att or direct assembling
  1196. * cleanup of some files
  1197. Revision 1.5 1998/05/21 19:30:52 peter
  1198. * objects compiles for linux
  1199. + assign(pchar), assign(char), rename(pchar), rename(char)
  1200. * fixed read_text_as_array
  1201. + read_text_as_pchar which was not yet in the rtl
  1202. Revision 1.4 1998/05/04 17:58:41 peter
  1203. * fix for smartlinking with _ARGS
  1204. Revision 1.3 1998/05/04 16:21:54 florian
  1205. + LFNSupport flag to the interface moved
  1206. }