system.pp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422
  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. inc(writesize,regs.realeax);
  714. dec(len,regs.realeax);
  715. { stop when not the specified size is written }
  716. if regs.realeax<size then
  717. break;
  718. end;
  719. Do_Write:=WriteSize;
  720. end;
  721. function do_read(h,addr,len : longint) : longint;
  722. var
  723. regs : trealregs;
  724. size,
  725. readsize : longint;
  726. begin
  727. readsize:=0;
  728. while len > 0 do
  729. begin
  730. if len>tb_size then
  731. size:=tb_size
  732. else
  733. size:=len;
  734. regs.realecx:=size;
  735. regs.realedx:=tb_offset;
  736. regs.realds:=tb_segment;
  737. regs.realebx:=h;
  738. regs.realeax:=$3f00;
  739. sysrealintr($21,regs);
  740. if (regs.realflags and carryflag) <> 0 then
  741. begin
  742. InOutRes:=lo(regs.realeax);
  743. do_read:=0;
  744. exit;
  745. end;
  746. syscopyfromdos(addr+readsize,regs.realeax);
  747. inc(readsize,regs.realeax);
  748. dec(len,regs.realeax);
  749. { stop when not the specified size is read }
  750. if regs.realeax<size then
  751. break;
  752. end;
  753. do_read:=readsize;
  754. end;
  755. function do_filepos(handle : longint) : longint;
  756. var
  757. regs : trealregs;
  758. begin
  759. regs.realebx:=handle;
  760. regs.realecx:=0;
  761. regs.realedx:=0;
  762. regs.realeax:=$4201;
  763. sysrealintr($21,regs);
  764. if (regs.realflags and carryflag) <> 0 then
  765. Begin
  766. InOutRes:=lo(regs.realeax);
  767. do_filepos:=0;
  768. end
  769. else
  770. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  771. end;
  772. procedure do_seek(handle,pos : longint);
  773. var
  774. regs : trealregs;
  775. begin
  776. regs.realebx:=handle;
  777. regs.realecx:=pos shr 16;
  778. regs.realedx:=pos and $ffff;
  779. regs.realeax:=$4200;
  780. sysrealintr($21,regs);
  781. if (regs.realflags and carryflag) <> 0 then
  782. InOutRes:=lo(regs.realeax);
  783. end;
  784. function do_seekend(handle:longint):longint;
  785. var
  786. regs : trealregs;
  787. begin
  788. regs.realebx:=handle;
  789. regs.realecx:=0;
  790. regs.realedx:=0;
  791. regs.realeax:=$4202;
  792. sysrealintr($21,regs);
  793. if (regs.realflags and carryflag) <> 0 then
  794. Begin
  795. InOutRes:=lo(regs.realeax);
  796. do_seekend:=0;
  797. end
  798. else
  799. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  800. end;
  801. function do_filesize(handle : longint) : longint;
  802. var
  803. aktfilepos : longint;
  804. begin
  805. aktfilepos:=do_filepos(handle);
  806. do_filesize:=do_seekend(handle);
  807. do_seek(handle,aktfilepos);
  808. end;
  809. { truncate at a given position }
  810. procedure do_truncate (handle,pos:longint);
  811. var
  812. regs : trealregs;
  813. begin
  814. do_seek(handle,pos);
  815. regs.realecx:=0;
  816. regs.realedx:=tb_offset;
  817. regs.realds:=tb_segment;
  818. regs.realebx:=handle;
  819. regs.realeax:=$4000;
  820. sysrealintr($21,regs);
  821. if (regs.realflags and carryflag) <> 0 then
  822. InOutRes:=lo(regs.realeax);
  823. end;
  824. procedure do_open(var f;p:pchar;flags:longint);
  825. {
  826. filerec and textrec have both handle and mode as the first items so
  827. they could use the same routine for opening/creating.
  828. when (flags and $100) the file will be append
  829. when (flags and $1000) the file will be truncate/rewritten
  830. when (flags and $10000) there is no check for close (needed for textfiles)
  831. }
  832. var
  833. regs : trealregs;
  834. action : longint;
  835. begin
  836. AllowSlash(p);
  837. { close first if opened }
  838. if ((flags and $10000)=0) then
  839. begin
  840. case filerec(f).mode of
  841. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  842. fmclosed : ;
  843. else
  844. begin
  845. inoutres:=102; {not assigned}
  846. exit;
  847. end;
  848. end;
  849. end;
  850. { reset file handle }
  851. filerec(f).handle:=UnusedHandle;
  852. action:=$1;
  853. { convert filemode to filerec modes }
  854. case (flags and 3) of
  855. 0 : filerec(f).mode:=fminput;
  856. 1 : filerec(f).mode:=fmoutput;
  857. 2 : filerec(f).mode:=fminout;
  858. end;
  859. if (flags and $1000)<>0 then
  860. begin
  861. filerec(f).mode:=fmoutput;
  862. action:=$12; {create file function}
  863. end;
  864. { empty name is special }
  865. if p[0]=#0 then
  866. begin
  867. case filerec(f).mode of
  868. fminput : filerec(f).handle:=StdInputHandle;
  869. fmappend,
  870. fmoutput : begin
  871. filerec(f).handle:=StdOutputHandle;
  872. filerec(f).mode:=fmoutput; {fool fmappend}
  873. end;
  874. end;
  875. exit;
  876. end;
  877. { real dos call }
  878. syscopytodos(longint(p),strlen(p)+1);
  879. {$ifndef RTLLITE}
  880. if LFNSupport then
  881. regs.realeax:=$716c
  882. else
  883. {$endif RTLLITE}
  884. regs.realeax:=$6c00;
  885. regs.realedx:=action;
  886. regs.realds:=tb_segment;
  887. regs.realesi:=tb_offset;
  888. regs.realebx:=$2000+(flags and $ff);
  889. regs.realecx:=$20;
  890. sysrealintr($21,regs);
  891. if (regs.realflags and carryflag) <> 0 then
  892. begin
  893. InOutRes:=lo(regs.realeax);
  894. exit;
  895. end
  896. else
  897. filerec(f).handle:=regs.realeax;
  898. {$ifdef SYSTEMDEBUG}
  899. if regs.realeax<max_files then
  900. begin
  901. if openfiles[regs.realeax] and
  902. assigned(opennames[regs.realeax]) then
  903. begin
  904. Writeln(stderr,'file ',opennames[regs.realeax],'(',regs.realeax,') not closed but handle reused!');
  905. sysfreemem(opennames[regs.realeax],strlen(opennames[regs.realeax])+1);
  906. end;
  907. openfiles[regs.realeax]:=true;
  908. sysgetmem(opennames[regs.realeax],strlen(p)+1);
  909. move(p^,opennames[regs.realeax]^,strlen(p)+1);
  910. end;
  911. {$endif SYSTEMDEBUG}
  912. { append mode }
  913. if (flags and $100)<>0 then
  914. begin
  915. do_seekend(filerec(f).handle);
  916. filerec(f).mode:=fmoutput; {fool fmappend}
  917. end;
  918. end;
  919. function do_isdevice(handle:longint):boolean;
  920. var
  921. regs : trealregs;
  922. begin
  923. regs.realebx:=handle;
  924. regs.realeax:=$4400;
  925. sysrealintr($21,regs);
  926. do_isdevice:=(regs.realedx and $80)<>0;
  927. if (regs.realflags and carryflag) <> 0 then
  928. InOutRes:=lo(regs.realeax);
  929. end;
  930. {*****************************************************************************
  931. UnTyped File Handling
  932. *****************************************************************************}
  933. {$i file.inc}
  934. {*****************************************************************************
  935. Typed File Handling
  936. *****************************************************************************}
  937. {$i typefile.inc}
  938. {*****************************************************************************
  939. Text File Handling
  940. *****************************************************************************}
  941. {$DEFINE EOF_CTRLZ}
  942. {$i text.inc}
  943. {*****************************************************************************
  944. Generic Handling
  945. *****************************************************************************}
  946. {$ifdef TEST_GENERIC}
  947. {$i generic.inc}
  948. {$endif TEST_GENERIC}
  949. {*****************************************************************************
  950. Directory Handling
  951. *****************************************************************************}
  952. procedure DosDir(func:byte;const s:string);
  953. var
  954. buffer : array[0..255] of char;
  955. regs : trealregs;
  956. begin
  957. move(s[1],buffer,length(s));
  958. buffer[length(s)]:=#0;
  959. AllowSlash(pchar(@buffer));
  960. syscopytodos(longint(@buffer),length(s)+1);
  961. regs.realedx:=tb_offset;
  962. regs.realds:=tb_segment;
  963. {$ifndef RTLLITE}
  964. if LFNSupport then
  965. regs.realeax:=$7100+func
  966. else
  967. {$endif RTLLITE}
  968. regs.realeax:=func shl 8;
  969. sysrealintr($21,regs);
  970. if (regs.realflags and carryflag) <> 0 then
  971. InOutRes:=lo(regs.realeax);
  972. end;
  973. procedure mkdir(const s : string);[IOCheck];
  974. begin
  975. If InOutRes <> 0 then
  976. exit;
  977. DosDir($39,s);
  978. end;
  979. procedure rmdir(const s : string);[IOCheck];
  980. begin
  981. If InOutRes <> 0 then
  982. exit;
  983. DosDir($3a,s);
  984. end;
  985. procedure chdir(const s : string);[IOCheck];
  986. var
  987. regs : trealregs;
  988. begin
  989. If InOutRes <> 0 then
  990. exit;
  991. { First handle Drive changes }
  992. if (length(s)>=2) and (s[2]=':') then
  993. begin
  994. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  995. regs.realeax:=$0e00;
  996. sysrealintr($21,regs);
  997. regs.realeax:=$1900;
  998. sysrealintr($21,regs);
  999. if byte(regs.realeax)<>byte(regs.realedx) then
  1000. begin
  1001. Inoutres:=15;
  1002. exit;
  1003. end;
  1004. end;
  1005. { do the normal dos chdir }
  1006. DosDir($3b,s);
  1007. end;
  1008. procedure getdir(drivenr : byte;var dir : shortstring);
  1009. var
  1010. temp : array[0..255] of char;
  1011. i : longint;
  1012. regs : trealregs;
  1013. begin
  1014. regs.realedx:=drivenr;
  1015. regs.realesi:=tb_offset;
  1016. regs.realds:=tb_segment;
  1017. {$ifndef RTLLITE}
  1018. if LFNSupport then
  1019. regs.realeax:=$7147
  1020. else
  1021. {$endif RTLLITE}
  1022. regs.realeax:=$4700;
  1023. sysrealintr($21,regs);
  1024. if (regs.realflags and carryflag) <> 0 then
  1025. Begin
  1026. InOutRes:=lo(regs.realeax);
  1027. exit;
  1028. end
  1029. else
  1030. syscopyfromdos(longint(@temp),251);
  1031. { conversion to Pascal string including slash conversion }
  1032. i:=0;
  1033. while (temp[i]<>#0) do
  1034. begin
  1035. if temp[i]='/' then
  1036. temp[i]:='\';
  1037. dir[i+4]:=temp[i];
  1038. inc(i);
  1039. end;
  1040. dir[2]:=':';
  1041. dir[3]:='\';
  1042. dir[0]:=char(i+3);
  1043. { upcase the string }
  1044. if not FileNameCaseSensitive then
  1045. dir:=upcase(dir);
  1046. if drivenr<>0 then { Drive was supplied. We know it }
  1047. dir[1]:=char(65+drivenr-1)
  1048. else
  1049. begin
  1050. { We need to get the current drive from DOS function 19H }
  1051. { because the drive was the default, which can be unknown }
  1052. regs.realeax:=$1900;
  1053. sysrealintr($21,regs);
  1054. i:= (regs.realeax and $ff) + ord('A');
  1055. dir[1]:=chr(i);
  1056. end;
  1057. end;
  1058. {*****************************************************************************
  1059. SystemUnit Initialization
  1060. *****************************************************************************}
  1061. {$ifndef RTLLITE}
  1062. function CheckLFN:boolean;
  1063. var
  1064. regs : TRealRegs;
  1065. RootName : pchar;
  1066. begin
  1067. { Check LFN API on drive c:\ }
  1068. RootName:='C:\';
  1069. syscopytodos(longint(RootName),strlen(RootName)+1);
  1070. { Call 'Get Volume Information' ($71A0) }
  1071. regs.realeax:=$71a0;
  1072. regs.reales:=tb_segment;
  1073. regs.realedi:=tb_offset;
  1074. regs.realecx:=32;
  1075. regs.realds:=tb_segment;
  1076. regs.realedx:=tb_offset;
  1077. regs.realflags:=carryflag;
  1078. sysrealintr($21,regs);
  1079. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1080. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1081. end;
  1082. {$endif RTLLITE}
  1083. {$ifdef MT}
  1084. {$I thread.inc}
  1085. {$endif MT}
  1086. var
  1087. temp_int : tseginfo;
  1088. Begin
  1089. { save old int 0 and 75 }
  1090. get_pm_interrupt($00,old_int00);
  1091. get_pm_interrupt($75,old_int75);
  1092. temp_int.segment:=get_cs;
  1093. temp_int.offset:=@new_int00;
  1094. set_pm_interrupt($00,temp_int);
  1095. { temp_int.offset:=@new_int75;
  1096. set_pm_interrupt($75,temp_int); }
  1097. { to test stack depth }
  1098. loweststack:=maxlongint;
  1099. { Setup heap }
  1100. InitHeap;
  1101. {$ifdef MT}
  1102. { before this, you can't use thread vars !!!! }
  1103. { threadvarblocksize is calculate before the initialization }
  1104. { of the system unit }
  1105. sysgetmem(mainprogramthreadblock,threadvarblocksize);
  1106. {$endif MT}
  1107. InitExceptions;
  1108. { Setup stdin, stdout and stderr }
  1109. OpenStdIO(Input,fmInput,StdInputHandle);
  1110. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1111. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1112. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1113. { Setup environment and arguments }
  1114. Setup_Environment;
  1115. Setup_Arguments;
  1116. { Use LFNSupport LFN }
  1117. LFNSupport:=CheckLFN;
  1118. if LFNSupport then
  1119. FileNameCaseSensitive:=true;
  1120. { Reset IO Error }
  1121. InOutRes:=0;
  1122. End.
  1123. {
  1124. $Log$
  1125. Revision 1.17 1999-09-10 15:40:33 peter
  1126. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  1127. Revision 1.16 1999/09/08 16:09:18 peter
  1128. * do_isdevice not called if already error
  1129. Revision 1.15 1999/08/19 14:03:16 pierre
  1130. * use sysgetmem for startup and debug allocations
  1131. Revision 1.14 1999/07/19 07:57:49 michael
  1132. + Small fix from Michael Baikov in setup_params
  1133. Revision 1.13 1999/05/19 16:54:21 pierre
  1134. * closes all handles >+ 5
  1135. Revision 1.12 1999/05/17 21:52:33 florian
  1136. * most of the Object Pascal stuff moved to the system unit
  1137. Revision 1.11 1999/05/04 23:28:40 pierre
  1138. SYSTEM_DEBUG_STARTUP used to output args and env at start
  1139. Revision 1.10 1999/04/28 11:42:45 peter
  1140. + FileNameCaseSensetive boolean
  1141. Revision 1.9 1999/04/28 06:01:25 florian
  1142. * define MT for multithreading introduced
  1143. Revision 1.8 1999/04/08 12:23:02 peter
  1144. * removed os.inc
  1145. Revision 1.7 1999/03/10 22:15:28 florian
  1146. + system.cmdline variable for go32v2 and win32 added
  1147. Revision 1.6 1999/03/01 15:40:52 peter
  1148. * use external names
  1149. * removed all direct assembler modes
  1150. Revision 1.5 1999/01/18 10:05:50 pierre
  1151. + system_exit procedure added
  1152. Revision 1.4 1998/12/30 22:17:59 peter
  1153. * fixed mem decls to use $0:$0
  1154. Revision 1.3 1998/12/28 15:50:45 peter
  1155. + stdout, which is needed when you write something in the system unit
  1156. to the screen. Like the runtime error
  1157. Revision 1.2 1998/12/21 14:22:02 pierre
  1158. * old_int?? transformed to cvar to be readable by dpmiexcp
  1159. Revision 1.1 1998/12/21 13:07:03 peter
  1160. * use -FE
  1161. Revision 1.25 1998/12/15 22:42:52 peter
  1162. * removed temp symbols
  1163. Revision 1.24 1998/11/29 22:28:10 peter
  1164. + io-error 103 added
  1165. Revision 1.23 1998/11/16 14:15:02 pierre
  1166. * changed getdir(byte,string) to getdir(byte,shortstring)
  1167. Revision 1.22 1998/10/26 14:49:46 pierre
  1168. * system debug info output to stderr
  1169. Revision 1.21 1998/10/20 07:34:07 pierre
  1170. + systemdebug reports about unclosed files at exit
  1171. Revision 1.20 1998/10/13 21:41:06 peter
  1172. + int 0 for divide by zero
  1173. Revision 1.19 1998/09/14 10:48:05 peter
  1174. * FPC_ names
  1175. * Heap manager is now system independent
  1176. Revision 1.18 1998/08/28 10:48:04 peter
  1177. * fixed chdir with drive changing
  1178. * updated checklfn from mailinglist
  1179. Revision 1.17 1998/08/27 10:30:51 pierre
  1180. * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !)
  1181. I renamed tb_selector to tb_segment because
  1182. it is a real mode segment as opposed to
  1183. a protected mode selector
  1184. Fixed it for go32v1 (remove the $E0000000 offset !)
  1185. Revision 1.16 1998/08/26 10:04:03 peter
  1186. * new lfn check from mailinglist
  1187. * renamed win95 -> LFNSupport
  1188. + tb_selector, tb_offset for easier access to transferbuffer
  1189. Revision 1.15 1998/08/19 10:56:34 pierre
  1190. + added some special code for C interface
  1191. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  1192. Revision 1.14 1998/08/04 14:34:38 pierre
  1193. * small bug fix to get it compiled with bugfix version !!
  1194. (again the asmmode problem !!!
  1195. Peter it was really not the best idea you had !!)
  1196. Revision 1.13 1998/07/30 13:26:22 michael
  1197. + Added support for ErrorProc variable. All internal functions are required
  1198. to call HandleError instead of runerror from now on.
  1199. This is necessary for exception support.
  1200. Revision 1.12 1998/07/13 21:19:08 florian
  1201. * some problems with ansi string support fixed
  1202. Revision 1.11 1998/07/07 12:33:08 carl
  1203. * added 2k buffer for stack checking for correct io on error
  1204. Revision 1.10 1998/07/02 12:29:20 carl
  1205. * IOCheck for rmdir,chdir and mkdir as in TP
  1206. NOTE: I'm pretty SURE this will not compile and link correctly with FPC
  1207. 0.99.5
  1208. Revision 1.9 1998/07/01 15:29:57 peter
  1209. * better readln/writeln
  1210. Revision 1.8 1998/06/26 08:19:10 pierre
  1211. + all debug in ifdef SYSTEMDEBUG
  1212. + added local arrays :
  1213. opennames names of opened files
  1214. fileopen boolean array to know if still open
  1215. usefull with gdb if you get problems about too
  1216. many open files !!
  1217. Revision 1.7 1998/06/15 15:17:08 daniel
  1218. * RTLLITE conditional added to produce smaller RTL.
  1219. Revision 1.6 1998/05/31 14:18:29 peter
  1220. * force att or direct assembling
  1221. * cleanup of some files
  1222. Revision 1.5 1998/05/21 19:30:52 peter
  1223. * objects compiles for linux
  1224. + assign(pchar), assign(char), rename(pchar), rename(char)
  1225. * fixed read_text_as_array
  1226. + read_text_as_pchar which was not yet in the rtl
  1227. Revision 1.4 1998/05/04 17:58:41 peter
  1228. * fix for smartlinking with _ARGS
  1229. Revision 1.3 1998/05/04 16:21:54 florian
  1230. + LFNSupport flag to the interface moved
  1231. }