system.pp 34 KB

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