system.pp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695
  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. {$ifndef NO_EXCEPTIONS_IN_SYSTEM}
  23. {$define EXCEPTIONS_IN_SYSTEM}
  24. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  25. { include system-independent routine headers }
  26. {$I systemh.inc}
  27. { include heap support headers }
  28. {$I heaph.inc}
  29. {Platform specific information}
  30. type
  31. THandle = Longint;
  32. const
  33. LineEnding = #13#10;
  34. { LFNSupport is a variable here, defined below!!! }
  35. DirectorySeparator = '\';
  36. DriveSeparator = ':';
  37. PathSeparator = ';';
  38. ExtensionSeparator = '.';
  39. { FileNameCaseSensitive is defined separately below!!! }
  40. maxExitCode = 255;
  41. const
  42. { Default filehandles }
  43. UnusedHandle = -1;
  44. StdInputHandle = 0;
  45. StdOutputHandle = 1;
  46. StdErrorHandle = 2;
  47. FileNameCaseSensitive : boolean = false;
  48. sLineBreak = LineEnding;
  49. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  50. { Default memory segments (Tp7 compatibility) }
  51. seg0040 = $0040;
  52. segA000 = $A000;
  53. segB000 = $B000;
  54. segB800 = $B800;
  55. var
  56. { Mem[] support }
  57. mem : array[0..$7fffffff-1] of byte absolute $0:$0;
  58. memw : array[0..($7fffffff div sizeof(word))-1] of word absolute $0:$0;
  59. meml : array[0..($7fffffff div sizeof(longint))-1] of longint absolute $0:$0;
  60. { C-compatible arguments and environment }
  61. argc : longint;
  62. argv : ppchar;
  63. envp : ppchar;
  64. dos_argv0 : pchar;
  65. {$ifndef RTLLITE}
  66. { System info }
  67. LFNSupport : boolean;
  68. {$ELSE RTLLITE}
  69. const
  70. LFNSupport = false;
  71. {$endif RTLLITE}
  72. type
  73. { Dos Extender info }
  74. p_stub_info = ^t_stub_info;
  75. t_stub_info = packed record
  76. magic : array[0..15] of char;
  77. size : longint;
  78. minstack : longint;
  79. memory_handle : longint;
  80. initial_size : longint;
  81. minkeep : word;
  82. ds_selector : word;
  83. ds_segment : word;
  84. psp_selector : word;
  85. cs_selector : word;
  86. env_size : word;
  87. basename : array[0..7] of char;
  88. argv0 : array [0..15] of char;
  89. dpmi_server : array [0..15] of char;
  90. end;
  91. p_go32_info_block = ^t_go32_info_block;
  92. t_go32_info_block = packed record
  93. size_of_this_structure_in_bytes : longint; {offset 0}
  94. linear_address_of_primary_screen : longint; {offset 4}
  95. linear_address_of_secondary_screen : longint; {offset 8}
  96. linear_address_of_transfer_buffer : longint; {offset 12}
  97. size_of_transfer_buffer : longint; {offset 16}
  98. pid : longint; {offset 20}
  99. master_interrupt_controller_base : byte; {offset 24}
  100. slave_interrupt_controller_base : byte; {offset 25}
  101. selector_for_linear_memory : word; {offset 26}
  102. linear_address_of_stub_info_structure : longint; {offset 28}
  103. linear_address_of_original_psp : longint; {offset 32}
  104. run_mode : word; {offset 36}
  105. run_mode_info : word; {offset 38}
  106. end;
  107. var
  108. stub_info : p_stub_info;
  109. go32_info_block : t_go32_info_block;
  110. {$ifdef SYSTEMDEBUG}
  111. const
  112. accept_sbrk : boolean = true;
  113. {$endif}
  114. {
  115. necessary for objects.pas, should be removed (at least from the interface
  116. to the implementation)
  117. }
  118. type
  119. trealregs=record
  120. realedi,realesi,realebp,realres,
  121. realebx,realedx,realecx,realeax : longint;
  122. realflags,
  123. reales,realds,realfs,realgs,
  124. realip,realcs,realsp,realss : word;
  125. end;
  126. function do_write(h:longint;addr:pointer;len : longint) : longint;
  127. function do_read(h:longint;addr:pointer;len : longint) : longint;
  128. procedure syscopyfromdos(addr : longint; len : longint);
  129. procedure syscopytodos(addr : longint; len : longint);
  130. procedure sysrealintr(intnr : word;var regs : trealregs);
  131. function tb : longint;
  132. implementation
  133. { include system independent routines }
  134. {$I system.inc}
  135. const
  136. carryflag = 1;
  137. type
  138. tseginfo=packed record
  139. offset : pointer;
  140. segment : word;
  141. end;
  142. var
  143. old_int00 : tseginfo;cvar;
  144. old_int75 : tseginfo;cvar;
  145. {$asmmode ATT}
  146. {*****************************************************************************
  147. Go32 Helpers
  148. *****************************************************************************}
  149. function far_strlen(selector : word;linear_address : longint) : longint;assembler;
  150. asm
  151. movl linear_address,%edx
  152. movl %edx,%ecx
  153. movw selector,%gs
  154. .Larg19:
  155. movb %gs:(%edx),%al
  156. testb %al,%al
  157. je .Larg20
  158. incl %edx
  159. jmp .Larg19
  160. .Larg20:
  161. movl %edx,%eax
  162. subl %ecx,%eax
  163. end;
  164. function tb : longint;
  165. begin
  166. tb:=go32_info_block.linear_address_of_transfer_buffer;
  167. end;
  168. function tb_segment : longint;
  169. begin
  170. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  171. end;
  172. function tb_offset : longint;
  173. begin
  174. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  175. end;
  176. function tb_size : longint;
  177. begin
  178. tb_size:=go32_info_block.size_of_transfer_buffer;
  179. end;
  180. function dos_selector : word;
  181. begin
  182. dos_selector:=go32_info_block.selector_for_linear_memory;
  183. end;
  184. function get_ds : word;assembler;
  185. asm
  186. movw %ds,%ax
  187. end;
  188. function get_cs : word;assembler;
  189. asm
  190. movw %cs,%ax
  191. end;
  192. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  193. begin
  194. if count=0 then
  195. exit;
  196. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  197. asm
  198. pushl %esi
  199. pushl %edi
  200. pushw %es
  201. pushw %ds
  202. cld
  203. movl count,%ecx
  204. movl source,%esi
  205. movl dest,%edi
  206. movw dseg,%ax
  207. movw %ax,%es
  208. movw sseg,%ax
  209. movw %ax,%ds
  210. movl %ecx,%eax
  211. shrl $2,%ecx
  212. rep
  213. movsl
  214. movl %eax,%ecx
  215. andl $3,%ecx
  216. rep
  217. movsb
  218. popw %ds
  219. popw %es
  220. popl %edi
  221. popl %esi
  222. end
  223. else if (source<dest) then
  224. { copy backward for overlapping }
  225. asm
  226. pushl %esi
  227. pushl %edi
  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. popl %edi
  262. popl %esi
  263. end;
  264. end;
  265. var
  266. _args : ppchar;external name '_args';
  267. procedure setup_arguments;
  268. type
  269. arrayword = array [0..255] of word;
  270. var
  271. psp : word;
  272. proxy_s : string[50];
  273. proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  274. rm_argv : ^arrayword;
  275. argv0len : longint;
  276. useproxy : boolean;
  277. hp : ppchar;
  278. doscmd : string[129]; { Dos commandline copied from PSP, max is 128 chars +1 for terminating zero }
  279. arglen,
  280. count : longint;
  281. argstart,
  282. pc,arg : pchar;
  283. quote : char;
  284. argvlen : longint;
  285. function atohex(s : pchar) : longint;
  286. var
  287. rv : longint;
  288. v : byte;
  289. begin
  290. rv:=0;
  291. while (s^<>#0) do
  292. begin
  293. v:=byte(s^)-byte('0');
  294. if (v > 9) then
  295. dec(v,7);
  296. v:=v and 15; { in case it's lower case }
  297. rv:=(rv shl 4) or v;
  298. inc(longint(s));
  299. end;
  300. atohex:=rv;
  301. end;
  302. procedure allocarg(idx,len:longint);
  303. begin
  304. if idx>=argvlen then
  305. begin
  306. argvlen:=(idx+8) and (not 7);
  307. sysreallocmem(argv,argvlen*sizeof(pointer));
  308. end;
  309. { use realloc to reuse already existing memory }
  310. if len<>0 then
  311. sysreallocmem(argv[idx],len+1);
  312. end;
  313. begin
  314. count:=0;
  315. argc:=1;
  316. argv:=nil;
  317. argvlen:=0;
  318. { load commandline from psp }
  319. psp:=stub_info^.psp_selector;
  320. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  321. doscmd[length(doscmd)+1]:=#0;
  322. {$IfDef SYSTEM_DEBUG_STARTUP}
  323. Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
  324. {$EndIf }
  325. { create argv[0] }
  326. argv0len:=strlen(dos_argv0);
  327. allocarg(count,argv0len);
  328. move(dos_argv0^,argv[count]^,argv0len);
  329. inc(count);
  330. { setup cmdline variable }
  331. cmdline:=Getmem(argv0len+length(doscmd)+2);
  332. move(dos_argv0^,cmdline^,argv0len);
  333. cmdline[argv0len]:=' ';
  334. inc(argv0len);
  335. move(doscmd[1],cmdline[argv0len],length(doscmd));
  336. cmdline[argv0len+length(doscmd)+1]:=#0;
  337. { parse dos commandline }
  338. pc:=@doscmd[1];
  339. while pc^<>#0 do
  340. begin
  341. { skip leading spaces }
  342. while pc^ in [#1..#32] do
  343. inc(pc);
  344. if pc^=#0 then
  345. break;
  346. { calc argument length }
  347. quote:=' ';
  348. argstart:=pc;
  349. arglen:=0;
  350. while (pc^<>#0) do
  351. begin
  352. case pc^ of
  353. #1..#32 :
  354. begin
  355. if quote<>' ' then
  356. inc(arglen)
  357. else
  358. break;
  359. end;
  360. '"' :
  361. begin
  362. if quote<>'''' then
  363. begin
  364. if pchar(pc+1)^<>'"' then
  365. begin
  366. if quote='"' then
  367. quote:=' '
  368. else
  369. quote:='"';
  370. end
  371. else
  372. inc(pc);
  373. end
  374. else
  375. inc(arglen);
  376. end;
  377. '''' :
  378. begin
  379. if quote<>'"' then
  380. begin
  381. if pchar(pc+1)^<>'''' then
  382. begin
  383. if quote='''' then
  384. quote:=' '
  385. else
  386. quote:='''';
  387. end
  388. else
  389. inc(pc);
  390. end
  391. else
  392. inc(arglen);
  393. end;
  394. else
  395. inc(arglen);
  396. end;
  397. inc(pc);
  398. end;
  399. { copy argument }
  400. allocarg(count,arglen);
  401. quote:=' ';
  402. pc:=argstart;
  403. arg:=argv[count];
  404. while (pc^<>#0) do
  405. begin
  406. case pc^ of
  407. #1..#32 :
  408. begin
  409. if quote<>' ' then
  410. begin
  411. arg^:=pc^;
  412. inc(arg);
  413. end
  414. else
  415. break;
  416. end;
  417. '"' :
  418. begin
  419. if quote<>'''' then
  420. begin
  421. if pchar(pc+1)^<>'"' then
  422. begin
  423. if quote='"' then
  424. quote:=' '
  425. else
  426. quote:='"';
  427. end
  428. else
  429. inc(pc);
  430. end
  431. else
  432. begin
  433. arg^:=pc^;
  434. inc(arg);
  435. end;
  436. end;
  437. '''' :
  438. begin
  439. if quote<>'"' then
  440. begin
  441. if pchar(pc+1)^<>'''' then
  442. begin
  443. if quote='''' then
  444. quote:=' '
  445. else
  446. quote:='''';
  447. end
  448. else
  449. inc(pc);
  450. end
  451. else
  452. begin
  453. arg^:=pc^;
  454. inc(arg);
  455. end;
  456. end;
  457. else
  458. begin
  459. arg^:=pc^;
  460. inc(arg);
  461. end;
  462. end;
  463. inc(pc);
  464. end;
  465. arg^:=#0;
  466. {$IfDef SYSTEM_DEBUG_STARTUP}
  467. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  468. {$EndIf SYSTEM_DEBUG_STARTUP}
  469. inc(count);
  470. end;
  471. argc:=count;
  472. { check for !proxy for long commandlines passed using environment }
  473. hp:=envp;
  474. useproxy:=false;
  475. while assigned(hp^) do
  476. begin
  477. if (hp^[0]=' ') then
  478. begin
  479. proxy_s:=strpas(hp^);
  480. if Copy(proxy_s,1,7)=' !proxy' then
  481. begin
  482. proxy_s[13]:=#0;
  483. proxy_s[18]:=#0;
  484. proxy_s[23]:=#0;
  485. argv[2]:=@proxy_s[9];
  486. argv[3]:=@proxy_s[14];
  487. argv[4]:=@proxy_s[19];
  488. useproxy:=true;
  489. break;
  490. end;
  491. end;
  492. inc(hp);
  493. end;
  494. { check for !proxy for long commandlines passed using commandline }
  495. if (not useproxy) and
  496. (argc > 1) and (far_strlen(get_ds,longint(argv[1])) = 6) then
  497. begin
  498. move(argv[1]^,proxy_s[1],6);
  499. proxy_s[0] := #6;
  500. if (proxy_s = '!proxy') then
  501. useproxy:=true;
  502. end;
  503. { use proxy when found }
  504. if useproxy then
  505. begin
  506. proxy_argc:=atohex(argv[2]);
  507. proxy_seg:=atohex(argv[3]);
  508. proxy_ofs:=atohex(argv[4]);
  509. {$IfDef SYSTEM_DEBUG_STARTUP}
  510. Writeln(stderr,'proxy command line found');
  511. writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs);
  512. {$EndIf SYSTEM_DEBUG_STARTUP}
  513. rm_argv:=SysGetmem(proxy_argc*sizeof(word));
  514. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  515. for count:=0 to proxy_argc - 1 do
  516. begin
  517. lin:=proxy_seg*16+rm_argv^[count];
  518. arglen:=far_strlen(dos_selector,lin);
  519. allocarg(count,arglen);
  520. sysseg_move(dos_selector,lin,get_ds,longint(argv[count]),arglen+1);
  521. {$IfDef SYSTEM_DEBUG_STARTUP}
  522. Writeln(stderr,'arg ',count,' #',rm_argv^[count],'#',arglen,'#',argv[count],'#');
  523. {$EndIf SYSTEM_DEBUG_STARTUP}
  524. end;
  525. SysFreemem(rm_argv);
  526. argc:=proxy_argc;
  527. end;
  528. { create an nil entry }
  529. allocarg(argc,0);
  530. { free unused memory }
  531. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  532. _args:=argv;
  533. end;
  534. function strcopy(dest,source : pchar) : pchar;assembler;
  535. var
  536. saveeax,saveesi,saveedi : longint;
  537. asm
  538. movl %edi,saveedi
  539. movl %esi,saveesi
  540. {$ifdef REGCALL}
  541. movl %eax,saveeax
  542. movl %edx,%edi
  543. {$else}
  544. movl source,%edi
  545. {$endif}
  546. testl %edi,%edi
  547. jz .LStrCopyDone
  548. leal 3(%edi),%ecx
  549. andl $-4,%ecx
  550. movl %edi,%esi
  551. subl %edi,%ecx
  552. {$ifdef REGCALL}
  553. movl %eax,%edi
  554. {$else}
  555. movl dest,%edi
  556. {$endif}
  557. jz .LStrCopyAligned
  558. .LStrCopyAlignLoop:
  559. movb (%esi),%al
  560. incl %edi
  561. incl %esi
  562. testb %al,%al
  563. movb %al,-1(%edi)
  564. jz .LStrCopyDone
  565. decl %ecx
  566. jnz .LStrCopyAlignLoop
  567. .balign 16
  568. .LStrCopyAligned:
  569. movl (%esi),%eax
  570. movl %eax,%edx
  571. leal 0x0fefefeff(%eax),%ecx
  572. notl %edx
  573. addl $4,%esi
  574. andl %edx,%ecx
  575. andl $0x080808080,%ecx
  576. jnz .LStrCopyEndFound
  577. movl %eax,(%edi)
  578. addl $4,%edi
  579. jmp .LStrCopyAligned
  580. .LStrCopyEndFound:
  581. testl $0x0ff,%eax
  582. jz .LStrCopyByte
  583. testl $0x0ff00,%eax
  584. jz .LStrCopyWord
  585. testl $0x0ff0000,%eax
  586. jz .LStrCopy3Bytes
  587. movl %eax,(%edi)
  588. jmp .LStrCopyDone
  589. .LStrCopy3Bytes:
  590. xorb %dl,%dl
  591. movw %ax,(%edi)
  592. movb %dl,2(%edi)
  593. jmp .LStrCopyDone
  594. .LStrCopyWord:
  595. movw %ax,(%edi)
  596. jmp .LStrCopyDone
  597. .LStrCopyByte:
  598. movb %al,(%edi)
  599. .LStrCopyDone:
  600. {$ifdef REGCALL}
  601. movl saveeax,%eax
  602. {$else}
  603. movl dest,%eax
  604. {$endif}
  605. movl saveedi,%edi
  606. movl saveesi,%esi
  607. end;
  608. var
  609. __stubinfo : p_stub_info;external name '__stubinfo';
  610. ___dos_argv0 : pchar;external name '___dos_argv0';
  611. procedure setup_environment;
  612. var env_selector : word;
  613. env_count : longint;
  614. dos_env,cp : pchar;
  615. begin
  616. stub_info:=__stubinfo;
  617. dos_env := sysgetmem(stub_info^.env_size);
  618. env_count:=0;
  619. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  620. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  621. cp:=dos_env;
  622. while cp ^ <> #0 do
  623. begin
  624. inc(env_count);
  625. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  626. inc(longint(cp)); { skip to next character }
  627. end;
  628. envp := sysgetmem((env_count+1) * sizeof(pchar));
  629. if (envp = nil) then exit;
  630. cp:=dos_env;
  631. env_count:=0;
  632. while cp^ <> #0 do
  633. begin
  634. envp[env_count] := sysgetmem(strlen(cp)+1);
  635. strcopy(envp[env_count], cp);
  636. {$IfDef SYSTEM_DEBUG_STARTUP}
  637. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  638. {$EndIf SYSTEM_DEBUG_STARTUP}
  639. inc(env_count);
  640. while (cp^ <> #0) do
  641. inc(longint(cp)); { skip to NUL }
  642. inc(longint(cp)); { skip to next character }
  643. end;
  644. envp[env_count]:=nil;
  645. longint(cp):=longint(cp)+3;
  646. dos_argv0 := sysgetmem(strlen(cp)+1);
  647. if (dos_argv0 = nil) then halt;
  648. strcopy(dos_argv0, cp);
  649. { update ___dos_argv0 also }
  650. ___dos_argv0:=dos_argv0
  651. end;
  652. procedure syscopytodos(addr : longint; len : longint);
  653. begin
  654. if len > tb_size then
  655. HandleError(217);
  656. sysseg_move(get_ds,addr,dos_selector,tb,len);
  657. end;
  658. procedure syscopyfromdos(addr : longint; len : longint);
  659. begin
  660. if len > tb_size then
  661. HandleError(217);
  662. sysseg_move(dos_selector,tb,get_ds,addr,len);
  663. end;
  664. procedure sysrealintr(intnr : word;var regs : trealregs);
  665. begin
  666. regs.realsp:=0;
  667. regs.realss:=0;
  668. asm
  669. pushl %ebx
  670. pushl %edi
  671. movw intnr,%bx
  672. xorl %ecx,%ecx
  673. movl regs,%edi
  674. movw $0x300,%ax
  675. int $0x31
  676. popl %edi
  677. popl %ebx
  678. end;
  679. end;
  680. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  681. begin
  682. asm
  683. pushl %ebx
  684. movl intaddr,%eax
  685. movl (%eax),%edx
  686. movw 4(%eax),%cx
  687. movl $0x205,%eax
  688. movb vector,%bl
  689. int $0x31
  690. popl %ebx
  691. end;
  692. end;
  693. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  694. begin
  695. asm
  696. pushl %ebx
  697. movb vector,%bl
  698. movl $0x204,%eax
  699. int $0x31
  700. movl intaddr,%eax
  701. movl %edx,(%eax)
  702. movw %cx,4(%eax)
  703. popl %ebx
  704. end;
  705. end;
  706. procedure getinoutres(def : word);
  707. var
  708. regs : trealregs;
  709. begin
  710. regs.realeax:=$5900;
  711. regs.realebx:=$0;
  712. sysrealintr($21,regs);
  713. InOutRes:=lo(regs.realeax);
  714. case InOutRes of
  715. 19 : InOutRes:=150;
  716. 21 : InOutRes:=152;
  717. 32 : InOutRes:=5;
  718. end;
  719. if InOutRes=0 then
  720. InOutRes:=Def;
  721. end;
  722. { Keep Track of open files }
  723. const
  724. max_files = 50;
  725. var
  726. openfiles : array [0..max_files-1] of boolean;
  727. {$ifdef SYSTEMDEBUG}
  728. opennames : array [0..max_files-1] of pchar;
  729. const
  730. free_closed_names : boolean = true;
  731. {$endif SYSTEMDEBUG}
  732. {*****************************************************************************
  733. System Dependent Exit code
  734. *****************************************************************************}
  735. procedure ___exit(exitcode:longint);cdecl;external name '___exit';
  736. procedure do_close(handle : longint);forward;
  737. Procedure system_exit;
  738. var
  739. h : byte;
  740. begin
  741. for h:=0 to max_files-1 do
  742. if openfiles[h] then
  743. begin
  744. {$ifdef SYSTEMDEBUG}
  745. writeln(stderr,'file ',opennames[h],' not closed at exit');
  746. {$endif SYSTEMDEBUG}
  747. if h>=5 then
  748. do_close(h);
  749. end;
  750. { halt is not allways called !! }
  751. { not on normal exit !! PM }
  752. set_pm_interrupt($00,old_int00);
  753. {$ifndef EXCEPTIONS_IN_SYSTEM}
  754. set_pm_interrupt($75,old_int75);
  755. {$endif EXCEPTIONS_IN_SYSTEM}
  756. ___exit(exitcode);
  757. end;
  758. procedure new_int00;
  759. begin
  760. HandleError(200);
  761. end;
  762. {$ifndef EXCEPTIONS_IN_SYSTEM}
  763. procedure new_int75;
  764. begin
  765. asm
  766. xorl %eax,%eax
  767. outb %al,$0x0f0
  768. movb $0x20,%al
  769. outb %al,$0x0a0
  770. outb %al,$0x020
  771. end;
  772. HandleError(200);
  773. end;
  774. {$endif EXCEPTIONS_IN_SYSTEM}
  775. var
  776. __stkbottom : pointer;external name '__stkbottom';
  777. {*****************************************************************************
  778. ParamStr/Randomize
  779. *****************************************************************************}
  780. function paramcount : longint;
  781. begin
  782. paramcount := argc - 1;
  783. end;
  784. function paramstr(l : longint) : string;
  785. begin
  786. if (l>=0) and (l+1<=argc) then
  787. paramstr:=strpas(argv[l])
  788. else
  789. paramstr:='';
  790. end;
  791. procedure randomize;
  792. var
  793. hl : longint;
  794. regs : trealregs;
  795. begin
  796. regs.realeax:=$2c00;
  797. sysrealintr($21,regs);
  798. hl:=lo(regs.realedx);
  799. randseed:=hl*$10000+ lo(regs.realecx);
  800. end;
  801. {*****************************************************************************
  802. Heap Management
  803. *****************************************************************************}
  804. function ___sbrk(size:longint):longint;cdecl;external name '___sbrk';
  805. function SysOSAlloc (size: PtrInt): pointer; assembler;
  806. asm
  807. {$ifdef SYSTEMDEBUG}
  808. cmpb $1,accept_sbrk
  809. je .Lsbrk
  810. movl $0,%eax
  811. jmp .Lsbrk_fail
  812. .Lsbrk:
  813. {$endif}
  814. movl size,%eax
  815. pushl %eax
  816. call ___sbrk
  817. addl $4,%esp
  818. {$ifdef SYSTEMDEBUG}
  819. .Lsbrk_fail:
  820. {$endif}
  821. end;
  822. {*****************************************************************************
  823. OS Memory allocation / deallocation
  824. ****************************************************************************}
  825. {function SysOSAlloc(size: ptrint): pointer;
  826. begin
  827. result := sbrk(size);
  828. end;
  829. }
  830. {.$define HAS_SYSOSFREE}
  831. procedure SysOSFree(p: pointer; size: ptrint);
  832. begin
  833. end;
  834. { include standard heap management }
  835. {$I heap.inc}
  836. {****************************************************************************
  837. Low level File Routines
  838. ****************************************************************************}
  839. procedure AllowSlash(p:pchar);
  840. var
  841. i : longint;
  842. begin
  843. { allow slash as backslash }
  844. for i:=0 to strlen(p) do
  845. if p[i]='/' then p[i]:='\';
  846. end;
  847. procedure do_close(handle : thandle);
  848. var
  849. regs : trealregs;
  850. begin
  851. if Handle<=4 then
  852. exit;
  853. regs.realebx:=handle;
  854. if handle<max_files then
  855. begin
  856. openfiles[handle]:=false;
  857. {$ifdef SYSTEMDEBUG}
  858. if assigned(opennames[handle]) and free_closed_names then
  859. begin
  860. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  861. opennames[handle]:=nil;
  862. end;
  863. {$endif SYSTEMDEBUG}
  864. end;
  865. regs.realeax:=$3e00;
  866. sysrealintr($21,regs);
  867. if (regs.realflags and carryflag) <> 0 then
  868. GetInOutRes(lo(regs.realeax));
  869. end;
  870. procedure do_erase(p : pchar);
  871. var
  872. regs : trealregs;
  873. begin
  874. AllowSlash(p);
  875. syscopytodos(longint(p),strlen(p)+1);
  876. regs.realedx:=tb_offset;
  877. regs.realds:=tb_segment;
  878. if LFNSupport then
  879. regs.realeax:=$7141
  880. else
  881. regs.realeax:=$4100;
  882. regs.realesi:=0;
  883. regs.realecx:=0;
  884. sysrealintr($21,regs);
  885. if (regs.realflags and carryflag) <> 0 then
  886. GetInOutRes(lo(regs.realeax));
  887. end;
  888. procedure do_rename(p1,p2 : pchar);
  889. var
  890. regs : trealregs;
  891. begin
  892. AllowSlash(p1);
  893. AllowSlash(p2);
  894. if strlen(p1)+strlen(p2)+3>tb_size then
  895. HandleError(217);
  896. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  897. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  898. regs.realedi:=tb_offset;
  899. regs.realedx:=tb_offset + strlen(p2)+2;
  900. regs.realds:=tb_segment;
  901. regs.reales:=tb_segment;
  902. if LFNSupport then
  903. regs.realeax:=$7156
  904. else
  905. regs.realeax:=$5600;
  906. regs.realecx:=$ff; { attribute problem here ! }
  907. sysrealintr($21,regs);
  908. if (regs.realflags and carryflag) <> 0 then
  909. GetInOutRes(lo(regs.realeax));
  910. end;
  911. function do_write(h:thandle;addr:pointer;len : longint) : longint;
  912. var
  913. regs : trealregs;
  914. size,
  915. writesize : longint;
  916. begin
  917. writesize:=0;
  918. while len > 0 do
  919. begin
  920. if len>tb_size then
  921. size:=tb_size
  922. else
  923. size:=len;
  924. syscopytodos(ptrint(addr)+writesize,size);
  925. regs.realecx:=size;
  926. regs.realedx:=tb_offset;
  927. regs.realds:=tb_segment;
  928. regs.realebx:=h;
  929. regs.realeax:=$4000;
  930. sysrealintr($21,regs);
  931. if (regs.realflags and carryflag) <> 0 then
  932. begin
  933. GetInOutRes(lo(regs.realeax));
  934. exit(writesize);
  935. end;
  936. inc(writesize,lo(regs.realeax));
  937. dec(len,lo(regs.realeax));
  938. { stop when not the specified size is written }
  939. if lo(regs.realeax)<size then
  940. break;
  941. end;
  942. Do_Write:=WriteSize;
  943. end;
  944. function do_read(h:thandle;addr:pointer;len : longint) : longint;
  945. var
  946. regs : trealregs;
  947. size,
  948. readsize : longint;
  949. begin
  950. readsize:=0;
  951. while len > 0 do
  952. begin
  953. if len>tb_size then
  954. size:=tb_size
  955. else
  956. size:=len;
  957. regs.realecx:=size;
  958. regs.realedx:=tb_offset;
  959. regs.realds:=tb_segment;
  960. regs.realebx:=h;
  961. regs.realeax:=$3f00;
  962. sysrealintr($21,regs);
  963. if (regs.realflags and carryflag) <> 0 then
  964. begin
  965. GetInOutRes(lo(regs.realeax));
  966. do_read:=0;
  967. exit;
  968. end;
  969. syscopyfromdos(ptrint(addr)+readsize,lo(regs.realeax));
  970. inc(readsize,lo(regs.realeax));
  971. dec(len,lo(regs.realeax));
  972. { stop when not the specified size is read }
  973. if lo(regs.realeax)<size then
  974. break;
  975. end;
  976. do_read:=readsize;
  977. end;
  978. function do_filepos(handle : thandle) : longint;
  979. var
  980. regs : trealregs;
  981. begin
  982. regs.realebx:=handle;
  983. regs.realecx:=0;
  984. regs.realedx:=0;
  985. regs.realeax:=$4201;
  986. sysrealintr($21,regs);
  987. if (regs.realflags and carryflag) <> 0 then
  988. Begin
  989. GetInOutRes(lo(regs.realeax));
  990. do_filepos:=0;
  991. end
  992. else
  993. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  994. end;
  995. procedure do_seek(handle:thandle;pos : longint);
  996. var
  997. regs : trealregs;
  998. begin
  999. regs.realebx:=handle;
  1000. regs.realecx:=pos shr 16;
  1001. regs.realedx:=pos and $ffff;
  1002. regs.realeax:=$4200;
  1003. sysrealintr($21,regs);
  1004. if (regs.realflags and carryflag) <> 0 then
  1005. GetInOutRes(lo(regs.realeax));
  1006. end;
  1007. function do_seekend(handle:thandle):longint;
  1008. var
  1009. regs : trealregs;
  1010. begin
  1011. regs.realebx:=handle;
  1012. regs.realecx:=0;
  1013. regs.realedx:=0;
  1014. regs.realeax:=$4202;
  1015. sysrealintr($21,regs);
  1016. if (regs.realflags and carryflag) <> 0 then
  1017. Begin
  1018. GetInOutRes(lo(regs.realeax));
  1019. do_seekend:=0;
  1020. end
  1021. else
  1022. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  1023. end;
  1024. function do_filesize(handle : thandle) : longint;
  1025. var
  1026. aktfilepos : longint;
  1027. begin
  1028. aktfilepos:=do_filepos(handle);
  1029. do_filesize:=do_seekend(handle);
  1030. do_seek(handle,aktfilepos);
  1031. end;
  1032. { truncate at a given position }
  1033. procedure do_truncate (handle:thandle;pos:longint);
  1034. var
  1035. regs : trealregs;
  1036. begin
  1037. do_seek(handle,pos);
  1038. regs.realecx:=0;
  1039. regs.realedx:=tb_offset;
  1040. regs.realds:=tb_segment;
  1041. regs.realebx:=handle;
  1042. regs.realeax:=$4000;
  1043. sysrealintr($21,regs);
  1044. if (regs.realflags and carryflag) <> 0 then
  1045. GetInOutRes(lo(regs.realeax));
  1046. end;
  1047. const
  1048. FileHandleCount : longint = 20;
  1049. function Increase_file_handle_count : boolean;
  1050. var
  1051. regs : trealregs;
  1052. begin
  1053. Inc(FileHandleCount,10);
  1054. regs.realebx:=FileHandleCount;
  1055. regs.realeax:=$6700;
  1056. sysrealintr($21,regs);
  1057. if (regs.realflags and carryflag) <> 0 then
  1058. begin
  1059. Increase_file_handle_count:=false;
  1060. Dec (FileHandleCount, 10);
  1061. end
  1062. else
  1063. Increase_file_handle_count:=true;
  1064. end;
  1065. function dos_version : word;
  1066. var
  1067. regs : trealregs;
  1068. begin
  1069. regs.realeax := $3000;
  1070. sysrealintr($21,regs);
  1071. dos_version := regs.realeax
  1072. end;
  1073. procedure do_open(var f;p:pchar;flags:longint);
  1074. {
  1075. filerec and textrec have both handle and mode as the first items so
  1076. they could use the same routine for opening/creating.
  1077. when (flags and $100) the file will be append
  1078. when (flags and $1000) the file will be truncate/rewritten
  1079. when (flags and $10000) there is no check for close (needed for textfiles)
  1080. }
  1081. var
  1082. regs : trealregs;
  1083. action : longint;
  1084. begin
  1085. AllowSlash(p);
  1086. { close first if opened }
  1087. if ((flags and $10000)=0) then
  1088. begin
  1089. case filerec(f).mode of
  1090. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  1091. fmclosed : ;
  1092. else
  1093. begin
  1094. inoutres:=102; {not assigned}
  1095. exit;
  1096. end;
  1097. end;
  1098. end;
  1099. { reset file handle }
  1100. filerec(f).handle:=UnusedHandle;
  1101. action:=$1;
  1102. { convert filemode to filerec modes }
  1103. case (flags and 3) of
  1104. 0 : filerec(f).mode:=fminput;
  1105. 1 : filerec(f).mode:=fmoutput;
  1106. 2 : filerec(f).mode:=fminout;
  1107. end;
  1108. if (flags and $1000)<>0 then
  1109. action:=$12; {create file function}
  1110. { empty name is special }
  1111. if p[0]=#0 then
  1112. begin
  1113. case FileRec(f).mode of
  1114. fminput :
  1115. FileRec(f).Handle:=StdInputHandle;
  1116. fminout, { this is set by rewrite }
  1117. fmoutput :
  1118. FileRec(f).Handle:=StdOutputHandle;
  1119. fmappend :
  1120. begin
  1121. FileRec(f).Handle:=StdOutputHandle;
  1122. FileRec(f).mode:=fmoutput; {fool fmappend}
  1123. end;
  1124. end;
  1125. exit;
  1126. end;
  1127. { real dos call }
  1128. syscopytodos(longint(p),strlen(p)+1);
  1129. {$ifndef RTLLITE}
  1130. if LFNSupport then
  1131. begin
  1132. regs.realeax := $716c; { Use LFN Open/Create API }
  1133. regs.realedx := action; { action if file does/doesn't exist }
  1134. regs.realesi := tb_offset;
  1135. regs.realebx := $2000 + (flags and $ff); { file open mode }
  1136. end
  1137. else
  1138. {$endif RTLLITE}
  1139. begin
  1140. if (action and $00f0) <> 0 then
  1141. regs.realeax := $3c00 { Map to Create/Replace API }
  1142. else
  1143. regs.realeax := $3d00 + (flags and $ff); { Map to Open_Existing API }
  1144. regs.realedx := tb_offset;
  1145. end;
  1146. regs.realds := tb_segment;
  1147. regs.realecx := $20; { file attributes }
  1148. sysrealintr($21,regs);
  1149. {$ifndef RTLLITE}
  1150. if (regs.realflags and carryflag) <> 0 then
  1151. if lo(regs.realeax)=4 then
  1152. if Increase_file_handle_count then
  1153. begin
  1154. { Try again }
  1155. if LFNSupport then
  1156. begin
  1157. regs.realeax := $716c; {Use LFN Open/Create API}
  1158. regs.realedx := action; {action if file does/doesn't exist}
  1159. regs.realesi := tb_offset;
  1160. regs.realebx := $2000 + (flags and $ff); {file open mode}
  1161. end
  1162. else
  1163. begin
  1164. if (action and $00f0) <> 0 then
  1165. regs.realeax := $3c00 {Map to Create/Replace API}
  1166. else
  1167. regs.realeax := $3d00 + (flags and $ff); {Map to Open API}
  1168. regs.realedx := tb_offset;
  1169. end;
  1170. regs.realds := tb_segment;
  1171. regs.realecx := $20; {file attributes}
  1172. sysrealintr($21,regs);
  1173. end;
  1174. {$endif RTLLITE}
  1175. if (regs.realflags and carryflag) <> 0 then
  1176. begin
  1177. GetInOutRes(lo(regs.realeax));
  1178. exit;
  1179. end
  1180. else
  1181. begin
  1182. filerec(f).handle:=lo(regs.realeax);
  1183. {$ifndef RTLLITE}
  1184. { for systems that have more then 20 by default ! }
  1185. if lo(regs.realeax)>FileHandleCount then
  1186. FileHandleCount:=lo(regs.realeax);
  1187. {$endif RTLLITE}
  1188. end;
  1189. if lo(regs.realeax)<max_files then
  1190. begin
  1191. {$ifdef SYSTEMDEBUG}
  1192. if openfiles[lo(regs.realeax)] and
  1193. assigned(opennames[lo(regs.realeax)]) then
  1194. begin
  1195. Writeln(stderr,'file ',opennames[lo(regs.realeax)],'(',lo(regs.realeax),') not closed but handle reused!');
  1196. sysfreememsize(opennames[lo(regs.realeax)],strlen(opennames[lo(regs.realeax)])+1);
  1197. end;
  1198. {$endif SYSTEMDEBUG}
  1199. openfiles[lo(regs.realeax)]:=true;
  1200. {$ifdef SYSTEMDEBUG}
  1201. opennames[lo(regs.realeax)] := sysgetmem(strlen(p)+1);
  1202. move(p^,opennames[lo(regs.realeax)]^,strlen(p)+1);
  1203. {$endif SYSTEMDEBUG}
  1204. end;
  1205. { append mode }
  1206. if ((flags and $100) <> 0) and
  1207. (FileRec (F).Handle <> UnusedHandle) then
  1208. begin
  1209. do_seekend(filerec(f).handle);
  1210. filerec(f).mode:=fmoutput; {fool fmappend}
  1211. end;
  1212. end;
  1213. function do_isdevice(handle:THandle):boolean;
  1214. var
  1215. regs : trealregs;
  1216. begin
  1217. regs.realebx:=handle;
  1218. regs.realeax:=$4400;
  1219. sysrealintr($21,regs);
  1220. do_isdevice:=(regs.realedx and $80)<>0;
  1221. if (regs.realflags and carryflag) <> 0 then
  1222. GetInOutRes(lo(regs.realeax));
  1223. end;
  1224. {*****************************************************************************
  1225. UnTyped File Handling
  1226. *****************************************************************************}
  1227. {$i file.inc}
  1228. {*****************************************************************************
  1229. Typed File Handling
  1230. *****************************************************************************}
  1231. {$i typefile.inc}
  1232. {*****************************************************************************
  1233. Text File Handling
  1234. *****************************************************************************}
  1235. {$DEFINE EOF_CTRLZ}
  1236. {$i text.inc}
  1237. {*****************************************************************************
  1238. Generic Handling
  1239. *****************************************************************************}
  1240. {$ifdef TEST_GENERIC}
  1241. {$i generic.inc}
  1242. {$endif TEST_GENERIC}
  1243. {*****************************************************************************
  1244. Directory Handling
  1245. *****************************************************************************}
  1246. procedure DosDir(func:byte;const s:string);
  1247. var
  1248. buffer : array[0..255] of char;
  1249. regs : trealregs;
  1250. begin
  1251. move(s[1],buffer,length(s));
  1252. buffer[length(s)]:=#0;
  1253. AllowSlash(pchar(@buffer));
  1254. { True DOS does not like backslashes at end
  1255. Win95 DOS accepts this !!
  1256. but "\" and "c:\" should still be kept and accepted hopefully PM }
  1257. if (length(s)>0) and (buffer[length(s)-1]='\') and
  1258. Not ((length(s)=1) or ((length(s)=3) and (s[2]=':'))) then
  1259. buffer[length(s)-1]:=#0;
  1260. syscopytodos(longint(@buffer),length(s)+1);
  1261. regs.realedx:=tb_offset;
  1262. regs.realds:=tb_segment;
  1263. if LFNSupport then
  1264. regs.realeax:=$7100+func
  1265. else
  1266. regs.realeax:=func shl 8;
  1267. sysrealintr($21,regs);
  1268. if (regs.realflags and carryflag) <> 0 then
  1269. GetInOutRes(lo(regs.realeax));
  1270. end;
  1271. procedure mkdir(const s : string);[IOCheck];
  1272. begin
  1273. If (s='') or (InOutRes <> 0) then
  1274. exit;
  1275. DosDir($39,s);
  1276. end;
  1277. procedure rmdir(const s : string);[IOCheck];
  1278. begin
  1279. if (s = '.' ) then
  1280. InOutRes := 16;
  1281. If (s='') or (InOutRes <> 0) then
  1282. exit;
  1283. DosDir($3a,s);
  1284. end;
  1285. procedure chdir(const s : string);[IOCheck];
  1286. var
  1287. regs : trealregs;
  1288. begin
  1289. If (s='') or (InOutRes <> 0) then
  1290. exit;
  1291. { First handle Drive changes }
  1292. if (length(s)>=2) and (s[2]=':') then
  1293. begin
  1294. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  1295. regs.realeax:=$0e00;
  1296. sysrealintr($21,regs);
  1297. regs.realeax:=$1900;
  1298. sysrealintr($21,regs);
  1299. if byte(regs.realeax)<>byte(regs.realedx) then
  1300. begin
  1301. Inoutres:=15;
  1302. exit;
  1303. end;
  1304. { DosDir($3b,'c:') give Path not found error on
  1305. pure DOS PM }
  1306. if length(s)=2 then
  1307. exit;
  1308. end;
  1309. { do the normal dos chdir }
  1310. DosDir($3b,s);
  1311. end;
  1312. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  1313. var
  1314. temp : array[0..255] of char;
  1315. i : longint;
  1316. regs : trealregs;
  1317. begin
  1318. regs.realedx:=drivenr;
  1319. regs.realesi:=tb_offset;
  1320. regs.realds:=tb_segment;
  1321. if LFNSupport then
  1322. regs.realeax:=$7147
  1323. else
  1324. regs.realeax:=$4700;
  1325. sysrealintr($21,regs);
  1326. if (regs.realflags and carryflag) <> 0 then
  1327. Begin
  1328. GetInOutRes (lo(regs.realeax));
  1329. Dir := char (DriveNr + 64) + ':\';
  1330. exit;
  1331. end
  1332. else
  1333. syscopyfromdos(longint(@temp),251);
  1334. { conversion to Pascal string including slash conversion }
  1335. i:=0;
  1336. while (temp[i]<>#0) do
  1337. begin
  1338. if temp[i]='/' then
  1339. temp[i]:='\';
  1340. dir[i+4]:=temp[i];
  1341. inc(i);
  1342. end;
  1343. dir[2]:=':';
  1344. dir[3]:='\';
  1345. dir[0]:=char(i+3);
  1346. { upcase the string }
  1347. if not FileNameCaseSensitive then
  1348. dir:=upcase(dir);
  1349. if drivenr<>0 then { Drive was supplied. We know it }
  1350. dir[1]:=char(65+drivenr-1)
  1351. else
  1352. begin
  1353. { We need to get the current drive from DOS function 19H }
  1354. { because the drive was the default, which can be unknown }
  1355. regs.realeax:=$1900;
  1356. sysrealintr($21,regs);
  1357. i:= (regs.realeax and $ff) + ord('A');
  1358. dir[1]:=chr(i);
  1359. end;
  1360. end;
  1361. {*****************************************************************************
  1362. SystemUnit Initialization
  1363. *****************************************************************************}
  1364. function CheckLFN:boolean;
  1365. var
  1366. regs : TRealRegs;
  1367. RootName : pchar;
  1368. begin
  1369. { Check LFN API on drive c:\ }
  1370. RootName:='C:\';
  1371. syscopytodos(longint(RootName),strlen(RootName)+1);
  1372. { Call 'Get Volume Information' ($71A0) }
  1373. regs.realeax:=$71a0;
  1374. regs.reales:=tb_segment;
  1375. regs.realedi:=tb_offset;
  1376. regs.realecx:=32;
  1377. regs.realds:=tb_segment;
  1378. regs.realedx:=tb_offset;
  1379. regs.realflags:=carryflag;
  1380. sysrealintr($21,regs);
  1381. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1382. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1383. end;
  1384. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1385. {$define IN_SYSTEM}
  1386. {$i dpmiexcp.pp}
  1387. {$endif EXCEPTIONS_IN_SYSTEM}
  1388. procedure SysInitStdIO;
  1389. begin
  1390. OpenStdIO(Input,fmInput,StdInputHandle);
  1391. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1392. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  1393. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1394. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1395. end;
  1396. function GetProcessID: SizeUInt;
  1397. begin
  1398. GetProcessID := SizeUInt (Go32_info_block.pid);
  1399. end;
  1400. var
  1401. temp_int : tseginfo;
  1402. Begin
  1403. StackLength := InitialStkLen;
  1404. StackBottom := __stkbottom;
  1405. { To be set if this is a GUI or console application }
  1406. IsConsole := TRUE;
  1407. { To be set if this is a library and not a program }
  1408. IsLibrary := FALSE;
  1409. { save old int 0 and 75 }
  1410. get_pm_interrupt($00,old_int00);
  1411. get_pm_interrupt($75,old_int75);
  1412. temp_int.segment:=get_cs;
  1413. temp_int.offset:=@new_int00;
  1414. set_pm_interrupt($00,temp_int);
  1415. {$ifndef EXCEPTIONS_IN_SYSTEM}
  1416. temp_int.offset:=@new_int75;
  1417. set_pm_interrupt($75,temp_int);
  1418. {$endif EXCEPTIONS_IN_SYSTEM}
  1419. { Setup heap }
  1420. InitHeap;
  1421. SysInitExceptions;
  1422. { Setup stdin, stdout and stderr }
  1423. SysInitStdIO;
  1424. { Setup environment and arguments }
  1425. Setup_Environment;
  1426. Setup_Arguments;
  1427. { Use LFNSupport LFN }
  1428. LFNSupport:=CheckLFN;
  1429. if LFNSupport then
  1430. FileNameCaseSensitive:=true;
  1431. { Reset IO Error }
  1432. InOutRes:=0;
  1433. ThreadID := 1;
  1434. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1435. InitDPMIExcp;
  1436. InstallDefaultHandlers;
  1437. {$endif EXCEPTIONS_IN_SYSTEM}
  1438. {$ifdef HASVARIANT}
  1439. initvariantmanager;
  1440. {$endif HASVARIANT}
  1441. End.
  1442. {
  1443. $Log$
  1444. Revision 1.43 2004-11-04 09:32:31 peter
  1445. ErrOutput added
  1446. Revision 1.42 2004/11/02 13:35:35 peter
  1447. * second try for data too large
  1448. Revision 1.41 2004/11/02 07:43:50 peter
  1449. * fix mem[] arrays
  1450. Revision 1.40 2004/10/27 18:52:05 hajny
  1451. * HEAP and HEAPSIZE removal reflected
  1452. Revision 1.39 2004/09/18 11:17:17 hajny
  1453. * handle type changed to thandle in do_isdevice
  1454. Revision 1.38 2004/09/03 19:25:49 olle
  1455. + added maxExitCode to all System.pp
  1456. * constrained error code to be below maxExitCode in RunError et. al.
  1457. Revision 1.37 2004/06/20 09:24:40 peter
  1458. fixed go32v2 compile
  1459. Revision 1.36 2004/06/17 16:16:13 peter
  1460. * New heapmanager that releases memory back to the OS, donated
  1461. by Micha Nelissen
  1462. Revision 1.35 2004/05/16 18:51:20 peter
  1463. * use thandle in do_*
  1464. Revision 1.34 2004/04/22 21:10:56 peter
  1465. * do_read/do_write addr argument changed to pointer
  1466. Revision 1.33 2004/01/25 13:05:08 jonas
  1467. * fixed compilation errors
  1468. Revision 1.32 2004/01/20 23:09:14 hajny
  1469. * ExecuteProcess fixes, ProcessID and ThreadID added
  1470. Revision 1.31 2004/01/10 10:49:24 jonas
  1471. * fixed compilation
  1472. Revision 1.30 2003/12/17 20:40:38 hajny
  1473. * 'conservative' version of the do_open patch by Joe da Silva
  1474. Revision 1.29 2003/12/04 21:42:07 peter
  1475. * register calling updates
  1476. Revision 1.28 2003/11/03 09:42:27 marco
  1477. * Peter's Cardinal<->Longint fixes patch
  1478. Revision 1.27 2003/10/16 15:43:13 peter
  1479. * THandle is platform dependent
  1480. Revision 1.26 2003/10/03 21:46:25 peter
  1481. * stdcall fixes
  1482. Revision 1.25 2003/09/29 18:39:59 hajny
  1483. * append fix applied to GO32v2, OS/2 and EMX
  1484. Revision 1.24 2003/09/27 11:52:35 peter
  1485. * sbrk returns pointer
  1486. Revision 1.23 2002/10/14 19:39:16 peter
  1487. * threads unit added for thread support
  1488. Revision 1.22 2002/10/13 09:28:44 florian
  1489. + call to initvariantmanager inserted
  1490. Revision 1.21 2002/09/07 21:32:08 carl
  1491. - removed unused defines
  1492. Revision 1.20 2002/09/07 16:01:19 peter
  1493. * old logs removed and tabs fixed
  1494. Revision 1.19 2002/07/01 16:29:05 peter
  1495. * sLineBreak changed to normal constant like Kylix
  1496. Revision 1.18 2002/05/05 10:23:54 peter
  1497. * fixed memw and meml array sizes
  1498. Revision 1.17 2002/04/21 15:52:58 carl
  1499. + initialize some global variables
  1500. Revision 1.16 2002/04/12 17:34:05 carl
  1501. + generic stack checking
  1502. Revision 1.15 2002/03/11 19:10:33 peter
  1503. * Regenerated with updated fpcmake
  1504. }