system.pp 28 KB

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