system.pp 30 KB

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