system.pp 34 KB

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