system.pp 41 KB

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