system.pp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 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;assembler;
  127. asm
  128. movl linear_address,%edx
  129. movl %edx,%ecx
  130. movw selector,%gs
  131. .Larg19:
  132. movb %gs:(%edx),%al
  133. testb %al,%al
  134. je .Larg20
  135. incl %edx
  136. jmp .Larg19
  137. .Larg20:
  138. movl %edx,%eax
  139. subl %ecx,%eax
  140. end;
  141. function tb : longint;
  142. begin
  143. tb:=go32_info_block.linear_address_of_transfer_buffer;
  144. end;
  145. function tb_segment : longint;
  146. begin
  147. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  148. end;
  149. function tb_offset : longint;
  150. begin
  151. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  152. end;
  153. function tb_size : longint;
  154. begin
  155. tb_size:=go32_info_block.size_of_transfer_buffer;
  156. end;
  157. function dos_selector : word;
  158. begin
  159. dos_selector:=go32_info_block.selector_for_linear_memory;
  160. end;
  161. function get_ds : word;assembler;
  162. asm
  163. movw %ds,%ax
  164. end;
  165. function get_cs : word;assembler;
  166. asm
  167. movw %cs,%ax
  168. end;
  169. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  170. begin
  171. if count=0 then
  172. exit;
  173. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  174. asm
  175. pushw %es
  176. pushw %ds
  177. cld
  178. movl count,%ecx
  179. movl source,%esi
  180. movl dest,%edi
  181. movw dseg,%ax
  182. movw %ax,%es
  183. movw sseg,%ax
  184. movw %ax,%ds
  185. movl %ecx,%eax
  186. shrl $2,%ecx
  187. rep
  188. movsl
  189. movl %eax,%ecx
  190. andl $3,%ecx
  191. rep
  192. movsb
  193. popw %ds
  194. popw %es
  195. end ['ESI','EDI','ECX','EAX']
  196. else if (source<dest) then
  197. { copy backward for overlapping }
  198. asm
  199. pushw %es
  200. pushw %ds
  201. std
  202. movl count,%ecx
  203. movl source,%esi
  204. movl dest,%edi
  205. movw dseg,%ax
  206. movw %ax,%es
  207. movw sseg,%ax
  208. movw %ax,%ds
  209. addl %ecx,%esi
  210. addl %ecx,%edi
  211. movl %ecx,%eax
  212. andl $3,%ecx
  213. orl %ecx,%ecx
  214. jz .LSEG_MOVE1
  215. { calculate esi and edi}
  216. decl %esi
  217. decl %edi
  218. rep
  219. movsb
  220. incl %esi
  221. incl %edi
  222. .LSEG_MOVE1:
  223. subl $4,%esi
  224. subl $4,%edi
  225. movl %eax,%ecx
  226. shrl $2,%ecx
  227. rep
  228. movsl
  229. cld
  230. popw %ds
  231. popw %es
  232. end ['ESI','EDI','ECX'];
  233. end;
  234. var
  235. _args : ppchar;external name '_args';
  236. procedure setup_arguments;
  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. type
  255. arrayword = array [0..255] of word;
  256. var
  257. psp : word;
  258. i,j : longint;
  259. quote : char;
  260. proxy_s : string[50];
  261. al,proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  262. largs : array[0..127] of pchar;
  263. rm_argv : ^arrayword;
  264. argv0len : longint;
  265. useproxy : boolean;
  266. hp : ppchar;
  267. begin
  268. fillchar(largs,sizeof(largs),0);
  269. psp:=stub_info^.psp_selector;
  270. largs[0]:=dos_argv0;
  271. argc := 1;
  272. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  273. {$IfDef SYSTEM_DEBUG_STARTUP}
  274. Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
  275. {$EndIf }
  276. { setup cmdline variable }
  277. argv0len:=strlen(dos_argv0);
  278. cmdline:=sysgetmem(argv0len+length(doscmd)+1);
  279. move(dos_argv0^,cmdline^,argv0len);
  280. move(doscmd[1],cmdline[argv0len],length(doscmd));
  281. cmdline[argv0len+length(doscmd)]:=#0;
  282. j := 1;
  283. quote := #0;
  284. for i:=1 to length(doscmd) do
  285. Begin
  286. if doscmd[i] = quote then
  287. begin
  288. quote := #0;
  289. if (i>1) and ((doscmd[i-1]='''') or (doscmd[i-1]='"')) then
  290. begin
  291. j := i+1;
  292. doscmd[i] := #0;
  293. continue;
  294. end;
  295. doscmd[i] := #0;
  296. largs[argc]:=@doscmd[j];
  297. inc(argc);
  298. j := i+1;
  299. end
  300. else
  301. if (quote = #0) and ((doscmd[i] = '''') or (doscmd[i]='"')) then
  302. begin
  303. quote := doscmd[i];
  304. j := i + 1;
  305. end else
  306. if (quote = #0) and ((doscmd[i] = ' ')
  307. or (doscmd[i] = #9) or (doscmd[i] = #10) or
  308. (doscmd[i] = #12) or (doscmd[i] = #9)) then
  309. begin
  310. doscmd[i]:=#0;
  311. if j<i then
  312. begin
  313. largs[argc]:=@doscmd[j];
  314. inc(argc);
  315. j := i+1;
  316. end else inc(j);
  317. end else
  318. if (i = length(doscmd)) then
  319. begin
  320. doscmd[i+1]:=#0;
  321. largs[argc]:=@doscmd[j];
  322. inc(argc);
  323. end;
  324. end;
  325. hp:=envp;
  326. useproxy:=false;
  327. while assigned(hp^) do
  328. begin
  329. if (hp^[0]=' ') then
  330. begin
  331. proxy_s:=strpas(hp^);
  332. if Copy(proxy_s,1,7)=' !proxy' then
  333. begin
  334. proxy_s[13]:=#0;
  335. proxy_s[18]:=#0;
  336. proxy_s[23]:=#0;
  337. largs[2]:=@proxy_s[9];
  338. largs[3]:=@proxy_s[14];
  339. largs[4]:=@proxy_s[19];
  340. useproxy:=true;
  341. break;
  342. end;
  343. end;
  344. inc(hp);
  345. end;
  346. if (not useproxy) and
  347. (argc > 1) and (far_strlen(get_ds,longint(largs[1])) = 6) then
  348. begin
  349. move(largs[1]^,proxy_s[1],6);
  350. proxy_s[0] := #6;
  351. if (proxy_s = '!proxy') then
  352. useproxy:=true;
  353. end;
  354. if useproxy then
  355. begin
  356. proxy_argc := atohex(largs[2]);
  357. proxy_seg := atohex(largs[3]);
  358. proxy_ofs := atohex(largs[4]);
  359. {$IfDef SYSTEM_DEBUG_STARTUP}
  360. Writeln(stderr,'proxy command line found');
  361. writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs);
  362. {$EndIf SYSTEM_DEBUG_STARTUP}
  363. if proxy_argc>128 then
  364. proxy_argc:=128;
  365. rm_argv := sysgetmem(proxy_argc*sizeof(word));
  366. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  367. for i:=0 to proxy_argc - 1 do
  368. begin
  369. lin := proxy_seg*16 + rm_argv^[i];
  370. al :=far_strlen(dos_selector, lin);
  371. largs[i] := sysgetmem(al+1);
  372. sysseg_move(dos_selector, lin, get_ds,longint(largs[i]), al+1);
  373. {$IfDef SYSTEM_DEBUG_STARTUP}
  374. Writeln(stderr,'arg ',i,' #',rm_argv^[i],'#',al,'#',largs[i],'#');
  375. {$EndIf SYSTEM_DEBUG_STARTUP}
  376. end;
  377. sysfreemem(rm_argv);
  378. argc := proxy_argc;
  379. end;
  380. argv := sysgetmem(argc shl 2);
  381. for i := 0 to argc-1 do
  382. argv[i]:=largs[i];
  383. _args:=argv;
  384. end;
  385. function strcopy(dest,source : pchar) : pchar;
  386. begin
  387. asm
  388. cld
  389. movl 12(%ebp),%edi
  390. movl $0xffffffff,%ecx
  391. xorb %al,%al
  392. repne
  393. scasb
  394. not %ecx
  395. movl 8(%ebp),%edi
  396. movl 12(%ebp),%esi
  397. movl %ecx,%eax
  398. shrl $2,%ecx
  399. rep
  400. movsl
  401. movl %eax,%ecx
  402. andl $3,%ecx
  403. rep
  404. movsb
  405. movl 8(%ebp),%eax
  406. leave
  407. ret $8
  408. end;
  409. end;
  410. var
  411. __stubinfo : p_stub_info;external name '__stubinfo';
  412. ___dos_argv0 : pchar;external name '___dos_argv0';
  413. procedure setup_environment;
  414. var env_selector : word;
  415. env_count : longint;
  416. dos_env,cp : pchar;
  417. begin
  418. stub_info:=__stubinfo;
  419. dos_env := sysgetmem(stub_info^.env_size);
  420. env_count:=0;
  421. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  422. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  423. cp:=dos_env;
  424. while cp ^ <> #0 do
  425. begin
  426. inc(env_count);
  427. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  428. inc(longint(cp)); { skip to next character }
  429. end;
  430. envp := sysgetmem((env_count+1) * sizeof(pchar));
  431. if (envp = nil) then exit;
  432. cp:=dos_env;
  433. env_count:=0;
  434. while cp^ <> #0 do
  435. begin
  436. envp[env_count] := sysgetmem(strlen(cp)+1);
  437. strcopy(envp[env_count], cp);
  438. {$IfDef SYSTEM_DEBUG_STARTUP}
  439. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  440. {$EndIf SYSTEM_DEBUG_STARTUP}
  441. inc(env_count);
  442. while (cp^ <> #0) do
  443. inc(longint(cp)); { skip to NUL }
  444. inc(longint(cp)); { skip to next character }
  445. end;
  446. envp[env_count]:=nil;
  447. longint(cp):=longint(cp)+3;
  448. dos_argv0 := sysgetmem(strlen(cp)+1);
  449. if (dos_argv0 = nil) then halt;
  450. strcopy(dos_argv0, cp);
  451. { update ___dos_argv0 also }
  452. ___dos_argv0:=dos_argv0
  453. end;
  454. procedure syscopytodos(addr : longint; len : longint);
  455. begin
  456. if len > tb_size then
  457. HandleError(217);
  458. sysseg_move(get_ds,addr,dos_selector,tb,len);
  459. end;
  460. procedure syscopyfromdos(addr : longint; len : longint);
  461. begin
  462. if len > tb_size then
  463. HandleError(217);
  464. sysseg_move(dos_selector,tb,get_ds,addr,len);
  465. end;
  466. procedure sysrealintr(intnr : word;var regs : trealregs);
  467. begin
  468. regs.realsp:=0;
  469. regs.realss:=0;
  470. asm
  471. movw intnr,%bx
  472. xorl %ecx,%ecx
  473. movl regs,%edi
  474. movw $0x300,%ax
  475. int $0x31
  476. end;
  477. end;
  478. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  479. begin
  480. asm
  481. movl intaddr,%eax
  482. movl (%eax),%edx
  483. movw 4(%eax),%cx
  484. movl $0x205,%eax
  485. movb vector,%bl
  486. int $0x31
  487. end;
  488. end;
  489. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  490. begin
  491. asm
  492. movb vector,%bl
  493. movl $0x204,%eax
  494. int $0x31
  495. movl intaddr,%eax
  496. movl %edx,(%eax)
  497. movw %cx,4(%eax)
  498. end;
  499. end;
  500. procedure getinoutres;
  501. var
  502. regs : trealregs;
  503. begin
  504. regs.realeax:=$5900;
  505. regs.realebx:=$0;
  506. sysrealintr($21,regs);
  507. InOutRes:=lo(regs.realeax);
  508. case InOutRes of
  509. 19 : InOutRes:=150;
  510. 21 : InOutRes:=152;
  511. end;
  512. end;
  513. { Keep Track of open files }
  514. const
  515. max_files = 50;
  516. var
  517. openfiles : array [0..max_files-1] of boolean;
  518. {$ifdef SYSTEMDEBUG}
  519. opennames : array [0..max_files-1] of pchar;
  520. const
  521. free_closed_names : boolean = true;
  522. {$endif SYSTEMDEBUG}
  523. {*****************************************************************************
  524. System Dependent Exit code
  525. *****************************************************************************}
  526. procedure ___exit(exitcode:byte);cdecl;external name '___exit';
  527. procedure do_close(handle : longint);forward;
  528. Procedure system_exit;
  529. var
  530. h : byte;
  531. begin
  532. for h:=0 to max_files-1 do
  533. if openfiles[h] then
  534. begin
  535. {$ifdef SYSTEMDEBUG}
  536. writeln(stderr,'file ',opennames[h],' not closed at exit');
  537. {$endif SYSTEMDEBUG}
  538. if h>=5 then
  539. do_close(h);
  540. end;
  541. { halt is not allways called !! }
  542. { not on normal exit !! PM }
  543. set_pm_interrupt($00,old_int00);
  544. set_pm_interrupt($75,old_int75);
  545. ___exit(exitcode);
  546. end;
  547. procedure new_int00;
  548. begin
  549. HandleError(200);
  550. end;
  551. procedure new_int75;
  552. begin
  553. asm
  554. xorl %eax,%eax
  555. outb %al,$0x0f0
  556. movb $0x20,%al
  557. outb %al,$0x0a0
  558. outb %al,$0x020
  559. end;
  560. HandleError(200);
  561. end;
  562. var
  563. __stkbottom : longint;external name '__stkbottom';
  564. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  565. {
  566. called when trying to get local stack if the compiler directive $S
  567. is set this function must preserve esi !!!! because esi is set by
  568. the calling proc for methods it must preserve all registers !!
  569. With a 2048 byte safe area used to write to StdIo without crossing
  570. the stack boundary
  571. }
  572. begin
  573. asm
  574. pushl %eax
  575. pushl %ebx
  576. movl stack_size,%ebx
  577. addl $2048,%ebx
  578. movl %esp,%eax
  579. subl %ebx,%eax
  580. {$ifdef SYSTEMDEBUG}
  581. movl loweststack,%ebx
  582. cmpl %eax,%ebx
  583. jb .L_is_not_lowest
  584. movl %eax,loweststack
  585. .L_is_not_lowest:
  586. {$endif SYSTEMDEBUG}
  587. movl __stkbottom,%ebx
  588. cmpl %eax,%ebx
  589. jae .L__short_on_stack
  590. popl %ebx
  591. popl %eax
  592. leave
  593. ret $4
  594. .L__short_on_stack:
  595. { can be usefull for error recovery !! }
  596. popl %ebx
  597. popl %eax
  598. end['EAX','EBX'];
  599. HandleError(202);
  600. end;
  601. {*****************************************************************************
  602. ParamStr/Randomize
  603. *****************************************************************************}
  604. function paramcount : longint;
  605. begin
  606. paramcount := argc - 1;
  607. end;
  608. function paramstr(l : longint) : string;
  609. begin
  610. if (l>=0) and (l+1<=argc) then
  611. paramstr:=strpas(argv[l])
  612. else
  613. paramstr:='';
  614. end;
  615. procedure randomize;
  616. var
  617. hl : longint;
  618. regs : trealregs;
  619. begin
  620. regs.realeax:=$2c00;
  621. sysrealintr($21,regs);
  622. hl:=regs.realedx and $ffff;
  623. randseed:=hl*$10000+ (regs.realecx and $ffff);
  624. end;
  625. {*****************************************************************************
  626. Heap Management
  627. *****************************************************************************}
  628. var
  629. int_heap : longint;external name 'HEAP';
  630. int_heapsize : longint;external name 'HEAPSIZE';
  631. function getheapstart:pointer;
  632. begin
  633. getheapstart:=@int_heap;
  634. end;
  635. function getheapsize:longint;
  636. begin
  637. getheapsize:=int_heapsize;
  638. end;
  639. function ___sbrk(size:longint):longint;cdecl;external name '___sbrk';
  640. function Sbrk(size : longint):longint;assembler;
  641. asm
  642. movl size,%eax
  643. pushl %eax
  644. call ___sbrk
  645. addl $4,%esp
  646. end;
  647. { include standard heap management }
  648. {$I heap.inc}
  649. {****************************************************************************
  650. Low level File Routines
  651. ****************************************************************************}
  652. procedure AllowSlash(p:pchar);
  653. var
  654. i : longint;
  655. begin
  656. { allow slash as backslash }
  657. for i:=0 to strlen(p) do
  658. if p[i]='/' then p[i]:='\';
  659. end;
  660. procedure do_close(handle : longint);
  661. var
  662. regs : trealregs;
  663. begin
  664. if Handle<=4 then
  665. exit;
  666. regs.realebx:=handle;
  667. if handle<max_files then
  668. begin
  669. openfiles[handle]:=false;
  670. {$ifdef SYSTEMDEBUG}
  671. if assigned(opennames[handle]) and free_closed_names then
  672. begin
  673. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  674. opennames[handle]:=nil;
  675. end;
  676. {$endif SYSTEMDEBUG}
  677. end;
  678. regs.realeax:=$3e00;
  679. sysrealintr($21,regs);
  680. if (regs.realflags and carryflag) <> 0 then
  681. GetInOutRes;
  682. end;
  683. procedure do_erase(p : pchar);
  684. var
  685. regs : trealregs;
  686. begin
  687. AllowSlash(p);
  688. syscopytodos(longint(p),strlen(p)+1);
  689. regs.realedx:=tb_offset;
  690. regs.realds:=tb_segment;
  691. {$ifndef RTLLITE}
  692. if LFNSupport then
  693. regs.realeax:=$7141
  694. else
  695. {$endif RTLLITE}
  696. regs.realeax:=$4100;
  697. regs.realesi:=0;
  698. regs.realecx:=0;
  699. sysrealintr($21,regs);
  700. if (regs.realflags and carryflag) <> 0 then
  701. GetInOutRes;
  702. end;
  703. procedure do_rename(p1,p2 : pchar);
  704. var
  705. regs : trealregs;
  706. begin
  707. AllowSlash(p1);
  708. AllowSlash(p2);
  709. if strlen(p1)+strlen(p2)+3>tb_size then
  710. HandleError(217);
  711. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  712. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  713. regs.realedi:=tb_offset;
  714. regs.realedx:=tb_offset + strlen(p2)+2;
  715. regs.realds:=tb_segment;
  716. regs.reales:=tb_segment;
  717. {$ifndef RTLLITE}
  718. if LFNSupport then
  719. regs.realeax:=$7156
  720. else
  721. {$endif RTLLITE}
  722. regs.realeax:=$5600;
  723. regs.realecx:=$ff; { attribute problem here ! }
  724. sysrealintr($21,regs);
  725. if (regs.realflags and carryflag) <> 0 then
  726. GetInOutRes;
  727. end;
  728. function do_write(h,addr,len : longint) : longint;
  729. var
  730. regs : trealregs;
  731. size,
  732. writesize : longint;
  733. begin
  734. writesize:=0;
  735. while len > 0 do
  736. begin
  737. if len>tb_size then
  738. size:=tb_size
  739. else
  740. size:=len;
  741. syscopytodos(addr+writesize,size);
  742. regs.realecx:=size;
  743. regs.realedx:=tb_offset;
  744. regs.realds:=tb_segment;
  745. regs.realebx:=h;
  746. regs.realeax:=$4000;
  747. sysrealintr($21,regs);
  748. if (regs.realflags and carryflag) <> 0 then
  749. begin
  750. GetInOutRes;
  751. exit(writesize);
  752. end;
  753. inc(writesize,regs.realeax);
  754. dec(len,regs.realeax);
  755. { stop when not the specified size is written }
  756. if regs.realeax<size then
  757. break;
  758. end;
  759. Do_Write:=WriteSize;
  760. end;
  761. function do_read(h,addr,len : longint) : longint;
  762. var
  763. regs : trealregs;
  764. size,
  765. readsize : longint;
  766. begin
  767. readsize:=0;
  768. while len > 0 do
  769. begin
  770. if len>tb_size then
  771. size:=tb_size
  772. else
  773. size:=len;
  774. regs.realecx:=size;
  775. regs.realedx:=tb_offset;
  776. regs.realds:=tb_segment;
  777. regs.realebx:=h;
  778. regs.realeax:=$3f00;
  779. sysrealintr($21,regs);
  780. if (regs.realflags and carryflag) <> 0 then
  781. begin
  782. GetInOutRes;
  783. do_read:=0;
  784. exit;
  785. end;
  786. syscopyfromdos(addr+readsize,regs.realeax);
  787. inc(readsize,regs.realeax);
  788. dec(len,regs.realeax);
  789. { stop when not the specified size is read }
  790. if regs.realeax<size then
  791. break;
  792. end;
  793. do_read:=readsize;
  794. end;
  795. function do_filepos(handle : longint) : longint;
  796. var
  797. regs : trealregs;
  798. begin
  799. regs.realebx:=handle;
  800. regs.realecx:=0;
  801. regs.realedx:=0;
  802. regs.realeax:=$4201;
  803. sysrealintr($21,regs);
  804. if (regs.realflags and carryflag) <> 0 then
  805. Begin
  806. GetInOutRes;
  807. do_filepos:=0;
  808. end
  809. else
  810. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  811. end;
  812. procedure do_seek(handle,pos : longint);
  813. var
  814. regs : trealregs;
  815. begin
  816. regs.realebx:=handle;
  817. regs.realecx:=pos shr 16;
  818. regs.realedx:=pos and $ffff;
  819. regs.realeax:=$4200;
  820. sysrealintr($21,regs);
  821. if (regs.realflags and carryflag) <> 0 then
  822. GetInOutRes;
  823. end;
  824. function do_seekend(handle:longint):longint;
  825. var
  826. regs : trealregs;
  827. begin
  828. regs.realebx:=handle;
  829. regs.realecx:=0;
  830. regs.realedx:=0;
  831. regs.realeax:=$4202;
  832. sysrealintr($21,regs);
  833. if (regs.realflags and carryflag) <> 0 then
  834. Begin
  835. GetInOutRes;
  836. do_seekend:=0;
  837. end
  838. else
  839. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  840. end;
  841. function do_filesize(handle : longint) : longint;
  842. var
  843. aktfilepos : longint;
  844. begin
  845. aktfilepos:=do_filepos(handle);
  846. do_filesize:=do_seekend(handle);
  847. do_seek(handle,aktfilepos);
  848. end;
  849. { truncate at a given position }
  850. procedure do_truncate (handle,pos:longint);
  851. var
  852. regs : trealregs;
  853. begin
  854. do_seek(handle,pos);
  855. regs.realecx:=0;
  856. regs.realedx:=tb_offset;
  857. regs.realds:=tb_segment;
  858. regs.realebx:=handle;
  859. regs.realeax:=$4000;
  860. sysrealintr($21,regs);
  861. if (regs.realflags and carryflag) <> 0 then
  862. GetInOutRes;
  863. end;
  864. {$ifndef RTLLITE}
  865. const
  866. FileHandleCount : longint = 20;
  867. function Increase_file_handle_count : boolean;
  868. var
  869. regs : trealregs;
  870. begin
  871. Inc(FileHandleCount,10);
  872. regs.realebx:=FileHandleCount;
  873. regs.realeax:=$6700;
  874. sysrealintr($21,regs);
  875. if (regs.realflags and carryflag) <> 0 then
  876. Increase_file_handle_count:=false
  877. else
  878. Increase_file_handle_count:=true;
  879. end;
  880. {$endif not RTLLITE}
  881. procedure do_open(var f;p:pchar;flags:longint);
  882. {
  883. filerec and textrec have both handle and mode as the first items so
  884. they could use the same routine for opening/creating.
  885. when (flags and $100) the file will be append
  886. when (flags and $1000) the file will be truncate/rewritten
  887. when (flags and $10000) there is no check for close (needed for textfiles)
  888. }
  889. var
  890. regs : trealregs;
  891. action : longint;
  892. begin
  893. AllowSlash(p);
  894. { close first if opened }
  895. if ((flags and $10000)=0) then
  896. begin
  897. case filerec(f).mode of
  898. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  899. fmclosed : ;
  900. else
  901. begin
  902. inoutres:=102; {not assigned}
  903. exit;
  904. end;
  905. end;
  906. end;
  907. { reset file handle }
  908. filerec(f).handle:=UnusedHandle;
  909. action:=$1;
  910. { convert filemode to filerec modes }
  911. case (flags and 3) of
  912. 0 : filerec(f).mode:=fminput;
  913. 1 : filerec(f).mode:=fmoutput;
  914. 2 : filerec(f).mode:=fminout;
  915. end;
  916. if (flags and $1000)<>0 then
  917. action:=$12; {create file function}
  918. { empty name is special }
  919. if p[0]=#0 then
  920. begin
  921. case FileRec(f).mode of
  922. fminput :
  923. FileRec(f).Handle:=StdInputHandle;
  924. fminout, { this is set by rewrite }
  925. fmoutput :
  926. FileRec(f).Handle:=StdOutputHandle;
  927. fmappend :
  928. begin
  929. FileRec(f).Handle:=StdOutputHandle;
  930. FileRec(f).mode:=fmoutput; {fool fmappend}
  931. end;
  932. end;
  933. exit;
  934. end;
  935. { real dos call }
  936. syscopytodos(longint(p),strlen(p)+1);
  937. {$ifndef RTLLITE}
  938. if LFNSupport then
  939. regs.realeax:=$716c
  940. else
  941. {$endif RTLLITE}
  942. regs.realeax:=$6c00;
  943. regs.realedx:=action;
  944. regs.realds:=tb_segment;
  945. regs.realesi:=tb_offset;
  946. regs.realebx:=$2000+(flags and $ff);
  947. regs.realecx:=$20;
  948. sysrealintr($21,regs);
  949. {$ifndef RTLLITE}
  950. if (regs.realflags and carryflag) <> 0 then
  951. if (regs.realeax and $ffff)=4 then
  952. if Increase_file_handle_count then
  953. begin
  954. { Try again }
  955. if LFNSupport then
  956. regs.realeax:=$716c
  957. else
  958. regs.realeax:=$6c00;
  959. regs.realedx:=action;
  960. regs.realds:=tb_segment;
  961. regs.realesi:=tb_offset;
  962. regs.realebx:=$2000+(flags and $ff);
  963. regs.realecx:=$20;
  964. sysrealintr($21,regs);
  965. end;
  966. {$endif RTLLITE}
  967. if (regs.realflags and carryflag) <> 0 then
  968. begin
  969. GetInOutRes;
  970. exit;
  971. end
  972. else
  973. begin
  974. filerec(f).handle:=regs.realeax;
  975. {$ifndef RTLLITE}
  976. { for systems that have more then 20 by default ! }
  977. if regs.realeax>FileHandleCount then
  978. FileHandleCount:=regs.realeax;
  979. {$endif RTLLITE}
  980. end;
  981. if regs.realeax<max_files then
  982. begin
  983. {$ifdef SYSTEMDEBUG}
  984. if openfiles[regs.realeax] and
  985. assigned(opennames[regs.realeax]) then
  986. begin
  987. Writeln(stderr,'file ',opennames[regs.realeax],'(',regs.realeax,') not closed but handle reused!');
  988. sysfreememsize(opennames[regs.realeax],strlen(opennames[regs.realeax])+1);
  989. end;
  990. {$endif SYSTEMDEBUG}
  991. openfiles[regs.realeax]:=true;
  992. {$ifdef SYSTEMDEBUG}
  993. opennames[regs.realeax] := sysgetmem(strlen(p)+1);
  994. move(p^,opennames[regs.realeax]^,strlen(p)+1);
  995. {$endif SYSTEMDEBUG}
  996. end;
  997. { append mode }
  998. if (flags and $100)<>0 then
  999. begin
  1000. do_seekend(filerec(f).handle);
  1001. filerec(f).mode:=fmoutput; {fool fmappend}
  1002. end;
  1003. end;
  1004. function do_isdevice(handle:longint):boolean;
  1005. var
  1006. regs : trealregs;
  1007. begin
  1008. regs.realebx:=handle;
  1009. regs.realeax:=$4400;
  1010. sysrealintr($21,regs);
  1011. do_isdevice:=(regs.realedx and $80)<>0;
  1012. if (regs.realflags and carryflag) <> 0 then
  1013. GetInOutRes;
  1014. end;
  1015. {*****************************************************************************
  1016. UnTyped File Handling
  1017. *****************************************************************************}
  1018. {$i file.inc}
  1019. {*****************************************************************************
  1020. Typed File Handling
  1021. *****************************************************************************}
  1022. {$i typefile.inc}
  1023. {*****************************************************************************
  1024. Text File Handling
  1025. *****************************************************************************}
  1026. {$DEFINE EOF_CTRLZ}
  1027. {$i text.inc}
  1028. {*****************************************************************************
  1029. Generic Handling
  1030. *****************************************************************************}
  1031. {$ifdef TEST_GENERIC}
  1032. {$i generic.inc}
  1033. {$endif TEST_GENERIC}
  1034. {*****************************************************************************
  1035. Directory Handling
  1036. *****************************************************************************}
  1037. procedure DosDir(func:byte;const s:string);
  1038. var
  1039. buffer : array[0..255] of char;
  1040. regs : trealregs;
  1041. begin
  1042. move(s[1],buffer,length(s));
  1043. buffer[length(s)]:=#0;
  1044. AllowSlash(pchar(@buffer));
  1045. syscopytodos(longint(@buffer),length(s)+1);
  1046. regs.realedx:=tb_offset;
  1047. regs.realds:=tb_segment;
  1048. {$ifndef RTLLITE}
  1049. if LFNSupport then
  1050. regs.realeax:=$7100+func
  1051. else
  1052. {$endif RTLLITE}
  1053. regs.realeax:=func shl 8;
  1054. sysrealintr($21,regs);
  1055. if (regs.realflags and carryflag) <> 0 then
  1056. GetInOutRes;
  1057. end;
  1058. procedure mkdir(const s : string);[IOCheck];
  1059. begin
  1060. If InOutRes <> 0 then
  1061. exit;
  1062. DosDir($39,s);
  1063. end;
  1064. procedure rmdir(const s : string);[IOCheck];
  1065. begin
  1066. If InOutRes <> 0 then
  1067. exit;
  1068. DosDir($3a,s);
  1069. end;
  1070. procedure chdir(const s : string);[IOCheck];
  1071. var
  1072. regs : trealregs;
  1073. begin
  1074. If InOutRes <> 0 then
  1075. exit;
  1076. { First handle Drive changes }
  1077. if (length(s)>=2) and (s[2]=':') then
  1078. begin
  1079. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  1080. regs.realeax:=$0e00;
  1081. sysrealintr($21,regs);
  1082. regs.realeax:=$1900;
  1083. sysrealintr($21,regs);
  1084. if byte(regs.realeax)<>byte(regs.realedx) then
  1085. begin
  1086. Inoutres:=15;
  1087. exit;
  1088. end;
  1089. { DosDir($3b,'c:') give Path not found error on
  1090. pure DOS PM }
  1091. if length(s)=2 then
  1092. exit;
  1093. end;
  1094. { do the normal dos chdir }
  1095. DosDir($3b,s);
  1096. end;
  1097. procedure getdir(drivenr : byte;var dir : shortstring);
  1098. var
  1099. temp : array[0..255] of char;
  1100. i : longint;
  1101. regs : trealregs;
  1102. begin
  1103. regs.realedx:=drivenr;
  1104. regs.realesi:=tb_offset;
  1105. regs.realds:=tb_segment;
  1106. {$ifndef RTLLITE}
  1107. if LFNSupport then
  1108. regs.realeax:=$7147
  1109. else
  1110. {$endif RTLLITE}
  1111. regs.realeax:=$4700;
  1112. sysrealintr($21,regs);
  1113. if (regs.realflags and carryflag) <> 0 then
  1114. Begin
  1115. GetInOutRes;
  1116. exit;
  1117. end
  1118. else
  1119. syscopyfromdos(longint(@temp),251);
  1120. { conversion to Pascal string including slash conversion }
  1121. i:=0;
  1122. while (temp[i]<>#0) do
  1123. begin
  1124. if temp[i]='/' then
  1125. temp[i]:='\';
  1126. dir[i+4]:=temp[i];
  1127. inc(i);
  1128. end;
  1129. dir[2]:=':';
  1130. dir[3]:='\';
  1131. dir[0]:=char(i+3);
  1132. { upcase the string }
  1133. if not FileNameCaseSensitive then
  1134. dir:=upcase(dir);
  1135. if drivenr<>0 then { Drive was supplied. We know it }
  1136. dir[1]:=char(65+drivenr-1)
  1137. else
  1138. begin
  1139. { We need to get the current drive from DOS function 19H }
  1140. { because the drive was the default, which can be unknown }
  1141. regs.realeax:=$1900;
  1142. sysrealintr($21,regs);
  1143. i:= (regs.realeax and $ff) + ord('A');
  1144. dir[1]:=chr(i);
  1145. end;
  1146. end;
  1147. {*****************************************************************************
  1148. SystemUnit Initialization
  1149. *****************************************************************************}
  1150. {$ifndef RTLLITE}
  1151. function CheckLFN:boolean;
  1152. var
  1153. regs : TRealRegs;
  1154. RootName : pchar;
  1155. begin
  1156. { Check LFN API on drive c:\ }
  1157. RootName:='C:\';
  1158. syscopytodos(longint(RootName),strlen(RootName)+1);
  1159. { Call 'Get Volume Information' ($71A0) }
  1160. regs.realeax:=$71a0;
  1161. regs.reales:=tb_segment;
  1162. regs.realedi:=tb_offset;
  1163. regs.realecx:=32;
  1164. regs.realds:=tb_segment;
  1165. regs.realedx:=tb_offset;
  1166. regs.realflags:=carryflag;
  1167. sysrealintr($21,regs);
  1168. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1169. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1170. end;
  1171. {$endif RTLLITE}
  1172. {$ifdef MT}
  1173. {$I thread.inc}
  1174. {$endif MT}
  1175. var
  1176. temp_int : tseginfo;
  1177. Begin
  1178. { save old int 0 and 75 }
  1179. get_pm_interrupt($00,old_int00);
  1180. get_pm_interrupt($75,old_int75);
  1181. temp_int.segment:=get_cs;
  1182. temp_int.offset:=@new_int00;
  1183. set_pm_interrupt($00,temp_int);
  1184. { temp_int.offset:=@new_int75;
  1185. set_pm_interrupt($75,temp_int); }
  1186. { to test stack depth }
  1187. loweststack:=maxlongint;
  1188. { Setup heap }
  1189. InitHeap;
  1190. {$ifdef MT}
  1191. { before this, you can't use thread vars !!!! }
  1192. { threadvarblocksize is calculate before the initialization }
  1193. { of the system unit }
  1194. mainprogramthreadblock := sysgetmem(threadvarblocksize);
  1195. {$endif MT}
  1196. InitExceptions;
  1197. { Setup stdin, stdout and stderr }
  1198. OpenStdIO(Input,fmInput,StdInputHandle);
  1199. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1200. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1201. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1202. { Setup environment and arguments }
  1203. Setup_Environment;
  1204. Setup_Arguments;
  1205. { Use LFNSupport LFN }
  1206. LFNSupport:=CheckLFN;
  1207. if LFNSupport then
  1208. FileNameCaseSensitive:=true;
  1209. { Reset IO Error }
  1210. InOutRes:=0;
  1211. End.
  1212. {
  1213. $Log$
  1214. Revision 1.33 2000-02-09 16:59:29 peter
  1215. * truncated log
  1216. Revision 1.32 2000/02/09 12:41:14 peter
  1217. * halt moved to system.inc
  1218. Revision 1.31 2000/01/24 11:57:18 daniel
  1219. * !proxy support in environment added (Peter)
  1220. Revision 1.30 2000/01/20 23:38:02 peter
  1221. * support fm_inout as stdoutput for assign(f,'');rewrite(f,1); becuase
  1222. rewrite opens always with filemode 2
  1223. Revision 1.29 2000/01/16 22:25:38 peter
  1224. * check handle for file closing
  1225. Revision 1.28 2000/01/07 16:41:32 daniel
  1226. * copyright 2000
  1227. Revision 1.27 2000/01/07 16:32:23 daniel
  1228. * copyright 2000 added
  1229. Revision 1.26 1999/12/20 22:22:41 pierre
  1230. * better closing of left open files
  1231. Revision 1.25 1999/12/17 23:11:48 pierre
  1232. * fix for bug754 : increase now dynamically max open handles
  1233. Revision 1.24 1999/12/01 22:57:30 peter
  1234. * cmdline support
  1235. Revision 1.23 1999/11/25 16:24:56 pierre
  1236. * avoid a problem with ChDir('c:') on pure DOS
  1237. Revision 1.22 1999/11/06 14:38:24 peter
  1238. * truncated log
  1239. Revision 1.21 1999/10/31 09:34:48 jonas
  1240. * updated for new syntax of sysgetmem
  1241. Revision 1.20 1999/10/28 09:53:19 peter
  1242. * create can also open file in fminout
  1243. Revision 1.19 1999/09/20 12:40:20 pierre
  1244. * adapted to new heaph
  1245. Revision 1.18 1999/09/10 17:14:09 peter
  1246. * better errorcode returning using int21h,5900
  1247. Revision 1.17 1999/09/10 15:40:33 peter
  1248. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  1249. Revision 1.16 1999/09/08 16:09:18 peter
  1250. * do_isdevice not called if already error
  1251. Revision 1.15 1999/08/19 14:03:16 pierre
  1252. * use sysgetmem for startup and debug allocations
  1253. }