system.pas 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. {
  2. $Id$
  3. ****************************************************************************
  4. This file is part of the Free Pascal run time library.
  5. Copyright (c) 1999-2002 by Free Pascal development team
  6. Free Pascal - EMX runtime library
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. ****************************************************************************}
  13. unit {$ifdef VER1_0}sysemx{$else}System{$endif};
  14. interface
  15. {Link the startup code.}
  16. {$ifdef VER1_0}
  17. {$l prt1.oo2}
  18. {$else}
  19. {$l prt1.o}
  20. {$endif}
  21. {$I systemh.inc}
  22. {$I heaph.inc}
  23. {Platform specific information}
  24. type
  25. THandle = Longint;
  26. const
  27. LineEnding = #13#10;
  28. { LFNSupport is defined separately below!!! }
  29. DirectorySeparator = '\';
  30. DriveSeparator = ':';
  31. PathSeparator = ';';
  32. { FileNameCaseSensitive is defined separately below!!! }
  33. maxExitCode = 255;
  34. type Tos=(osDOS,osOS2,osDPMI);
  35. var os_mode:Tos;
  36. first_meg:pointer;
  37. type TByteArray = array [0..$ffff] of byte;
  38. PByteArray = ^TByteArray;
  39. TSysThreadIB = record
  40. TID,
  41. Priority,
  42. Version: cardinal;
  43. MCCount,
  44. MCForceFlag: word;
  45. end;
  46. PSysThreadIB = ^TSysThreadIB;
  47. TThreadInfoBlock = record
  48. PExChain,
  49. Stack,
  50. StackLimit: pointer;
  51. TIB2: PSysThreadIB;
  52. Version,
  53. Ordinal: cardinal;
  54. end;
  55. PThreadInfoBlock = ^TThreadInfoBlock;
  56. PPThreadInfoBlock = ^PThreadInfoBlock;
  57. TProcessInfoBlock = record
  58. PID,
  59. ParentPid,
  60. Handle: cardinal;
  61. Cmd,
  62. Env: PByteArray;
  63. Status,
  64. ProcType: cardinal;
  65. end;
  66. PProcessInfoBlock = ^TProcessInfoBlock;
  67. PPProcessInfoBlock = ^PProcessInfoBlock;
  68. const UnusedHandle=-1;
  69. StdInputHandle=0;
  70. StdOutputHandle=1;
  71. StdErrorHandle=2;
  72. LFNSupport: boolean = true;
  73. FileNameCaseSensitive: boolean = false;
  74. sLineBreak = LineEnding;
  75. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  76. var
  77. { C-compatible arguments and environment }
  78. argc : longint;external name '_argc';
  79. argv : ppchar;external name '_argv';
  80. envp : ppchar;external name '_environ';
  81. EnvC: cardinal; external name '_envc';
  82. (* Pointer to the block of environment variables - used e.g. in unit Dos. *)
  83. Environment: PChar;
  84. var
  85. (* Type / run mode of the current process: *)
  86. (* 0 .. full screen OS/2 session *)
  87. (* 1 .. DOS session *)
  88. (* 2 .. VIO windowable OS/2 session *)
  89. (* 3 .. Presentation Manager OS/2 session *)
  90. (* 4 .. detached (background) OS/2 process *)
  91. ApplicationType: cardinal;
  92. procedure SetDefaultOS2FileType (FType: ShortString);
  93. procedure SetDefaultOS2Creator (Creator: ShortString);
  94. implementation
  95. {$I system.inc}
  96. var
  97. heap_base: pointer; external name '__heap_base';
  98. heap_brk: pointer; external name '__heap_brk';
  99. heap_end: pointer; external name '__heap_end';
  100. (* Maximum heap size - only used if heap is allocated as continuous block. *)
  101. {$IFDEF CONTHEAP}
  102. BrkLimit: cardinal;
  103. {$ENDIF CONTHEAP}
  104. var
  105. ProcessID: SizeUInt;
  106. function GetProcessID:SizeUInt;
  107. begin
  108. GetProcessID := ProcessID;
  109. end;
  110. procedure DosGetInfoBlocks (PATIB: PPThreadInfoBlock;
  111. PAPIB: PPProcessInfoBlock); cdecl;
  112. external 'DOSCALLS' index 312;
  113. function DosLoadModule (ObjName: PChar; ObjLen: cardinal; DLLName: PChar;
  114. var Handle: cardinal): cardinal; cdecl;
  115. external 'DOSCALLS' index 318;
  116. function DosQueryProcAddr (Handle, Ordinal: cardinal; ProcName: PChar;
  117. var Address: pointer): cardinal; cdecl;
  118. external 'DOSCALLS' index 321;
  119. function DosSetRelMaxFH (var ReqCount: longint; var CurMaxFH: cardinal):
  120. cardinal; cdecl;
  121. external 'DOSCALLS' index 382;
  122. function DosSetCurrentDir (Name:PChar): cardinal; cdecl;
  123. external 'DOSCALLS' index 255;
  124. function DosSetDefaultDisk (DiskNum:cardinal): cardinal; cdecl;
  125. external 'DOSCALLS' index 220;
  126. { This is not real prototype, but is close enough }
  127. { for us (the 2nd parameter is actually a pointer }
  128. { to a structure). }
  129. function DosCreateDir (Name: PChar; P: pointer): cardinal; cdecl;
  130. external 'DOSCALLS' index 270;
  131. function DosDeleteDir (Name: PChar): cardinal; cdecl;
  132. external 'DOSCALLS' index 226;
  133. {This is the correct way to call external assembler procedures.}
  134. procedure syscall; external name '___SYSCALL';
  135. {
  136. procedure syscall; external 'EMX' index 2;
  137. procedure emx_init; external 'EMX' index 1;
  138. }
  139. { converts an OS/2 error code to a TP compatible error }
  140. { code. Same thing exists under most other supported }
  141. { systems. }
  142. { Only call for OS/2 DLL imported routines }
  143. Procedure Errno2InOutRes;
  144. Begin
  145. { errors 1..18 are the same as in DOS }
  146. case InOutRes of
  147. { simple offset to convert these error codes }
  148. { exactly like the error codes in Win32 }
  149. 19..31 : InOutRes := InOutRes + 131;
  150. { gets a bit more complicated ... }
  151. 32..33 : InOutRes := 5;
  152. 38 : InOutRes := 100;
  153. 39 : InOutRes := 101;
  154. 112 : InOutRes := 101;
  155. 110 : InOutRes := 5;
  156. 114 : InOutRes := 6;
  157. 290 : InOutRes := 290;
  158. end;
  159. { all other cases ... we keep the same error code }
  160. end;
  161. {****************************************************************************
  162. Miscellaneous related routines.
  163. ****************************************************************************}
  164. {$asmmode intel}
  165. procedure system_exit; assembler;
  166. asm
  167. mov ah, 04ch
  168. mov al, byte ptr exitcode
  169. call syscall
  170. end {['EAX']};
  171. {$ASMMODE ATT}
  172. function paramcount:longint;assembler;
  173. asm
  174. movl argc,%eax
  175. decl %eax
  176. end {['EAX']};
  177. function args:pointer;assembler;
  178. asm
  179. movl argv,%eax
  180. end {['EAX']};
  181. function paramstr(l:longint):string;
  182. var p:^Pchar;
  183. begin
  184. { There seems to be a problem with EMX for DOS when trying to }
  185. { access paramstr(0), and to avoid problems between DOS and }
  186. { OS/2 they have been separated. }
  187. if os_Mode = OsOs2 then
  188. begin
  189. if L = 0 then
  190. begin
  191. GetMem (P, 260);
  192. p[0] := #0; { in case of error, initialize to empty string }
  193. {$ASMMODE INTEL}
  194. asm
  195. mov edx, P
  196. mov ecx, 260
  197. mov eax, 7F33h
  198. call syscall { error handle already with empty string }
  199. end ['eax', 'ecx', 'edx'];
  200. ParamStr := StrPas (PChar (P));
  201. FreeMem (P, 260);
  202. end
  203. else
  204. if (l>0) and (l<=paramcount) then
  205. begin
  206. p:=args;
  207. paramstr:=strpas(p[l]);
  208. end
  209. else paramstr:='';
  210. end
  211. else
  212. begin
  213. p:=args;
  214. paramstr:=strpas(p[l]);
  215. end;
  216. end;
  217. procedure randomize; assembler;
  218. asm
  219. mov ah, 2Ch
  220. call syscall
  221. mov word ptr [randseed], cx
  222. mov word ptr [randseed + 2], dx
  223. end {['eax', 'ecx', 'edx']};
  224. {$ASMMODE ATT}
  225. {****************************************************************************
  226. Heap management releated routines.
  227. ****************************************************************************}
  228. { this function allows to extend the heap by calling
  229. syscall $7f00 resizes the brk area}
  230. function sbrk(size:longint):pointer;
  231. xxx
  232. {$IFDEF DUMPGROW}
  233. var
  234. L: longword;
  235. begin
  236. WriteLn ('Trying to grow heap by ', Size);
  237. {$IFDEF CONTHEAP}
  238. WriteLn ('BrkLimit is ', BrkLimit);
  239. {$ENDIF CONTHEAP}
  240. asm
  241. movl size,%edx
  242. movw $0x7f00,%ax
  243. call syscall { result directly in EAX }
  244. inc %eax { Result in EAX, -1 = error (has to be transformed to 0) }
  245. jz .LSbrk_End
  246. dec %eax { No error - back to previous value }
  247. .LSbrk_End:
  248. mov %eax,L
  249. end ['eax', 'edx'];
  250. WriteLn ('New heap at ', L);
  251. Sbrk := pointer (L);
  252. end;
  253. {$ELSE DUMPGROW}
  254. assembler;
  255. asm
  256. {$IFDEF REGCALL}
  257. movl %eax,%edx
  258. {$ELSE REGCALL}
  259. movl size,%edx
  260. {$ENDIF REGCALL}
  261. movw $0x7f00,%ax
  262. call syscall
  263. inc %eax { Result in EAX, -1 = error (has to be transformed to 0) }
  264. jz .LSbrk_End
  265. dec %eax { No error - back to previous value }
  266. .LSbrk_End:
  267. end {['eax', 'edx']};
  268. {$ENDIF DUMPGROW}
  269. function SysOSAlloc (Size: ptrint): pointer;
  270. begin
  271. SysOSAlloc := Sbrk (Size);
  272. end;
  273. {.$define HAS_SYSOSFREE}
  274. procedure SysOSFree (P: pointer; Size: ptrint);
  275. begin
  276. end;
  277. {$i heap.inc}
  278. {****************************************************************************
  279. Low Level File Routines
  280. ****************************************************************************}
  281. procedure allowslash(p:Pchar);
  282. {Allow slash as backslash.}
  283. var i:longint;
  284. begin
  285. for i:=0 to strlen(p) do
  286. if p[i]='/' then p[i]:='\';
  287. end;
  288. procedure do_close (H: THandle);
  289. begin
  290. { Only three standard handles under real OS/2 }
  291. if (h > 4) or
  292. ((os_MODE = osOS2) and (h > 2)) then
  293. begin
  294. asm
  295. pushl %ebx
  296. movb $0x3e,%ah
  297. movl h,%ebx
  298. call syscall
  299. jnc .Lnoerror { error code? }
  300. movw %ax, InOutRes { yes, then set InOutRes }
  301. .Lnoerror:
  302. popl %ebx
  303. end ['eax'];
  304. end;
  305. end;
  306. procedure do_erase(p:Pchar);
  307. begin
  308. allowslash(p);
  309. asm
  310. movl P,%edx
  311. movb $0x41,%ah
  312. call syscall
  313. jnc .LERASE1
  314. movw %ax,inoutres
  315. .LERASE1:
  316. end ['eax', 'edx'];
  317. end;
  318. procedure do_rename(p1,p2:Pchar);
  319. begin
  320. allowslash(p1);
  321. allowslash(p2);
  322. asm
  323. movl P1, %edx
  324. movl P2, %edi
  325. movb $0x56,%ah
  326. call syscall
  327. jnc .LRENAME1
  328. movw %ax,inoutres
  329. .LRENAME1:
  330. end ['eax', 'edx', 'edi'];
  331. end;
  332. function do_read (H: THandle; Addr: pointer; Len: longint): longint; assembler;
  333. asm
  334. pushl %ebx
  335. {$IFNDEF REGCALL}
  336. movl len,%ecx
  337. movl addr,%edx
  338. movl %eax,%ebx
  339. {$ELSE REGCALL}
  340. movl h,%ebx
  341. {$ENDIF REGCALL}
  342. movb $0x3f,%ah
  343. call syscall
  344. jnc .LDOSREAD1
  345. movw %ax,inoutres
  346. xorl %eax,%eax
  347. .LDOSREAD1:
  348. popl %ebx
  349. end {['eax', 'ebx', 'ecx', 'edx']};
  350. function do_write (H: THandle; Addr: pointer; Len: longint): longint;
  351. assembler;
  352. asm
  353. pushl %ebx
  354. {$IFDEF REGCALL}
  355. movl %eax,%ebx
  356. {$ENDIF REGCALL}
  357. xorl %eax,%eax
  358. cmpl $0,len { 0 bytes to write is undefined behavior }
  359. jz .LDOSWRITE1
  360. {$IFNDEF REGCALL}
  361. movl len,%ecx
  362. movl addr,%edx
  363. movl h,%ebx
  364. {$ENDIF REGCALL}
  365. movb $0x40,%ah
  366. call syscall
  367. jnc .LDOSWRITE1
  368. movw %ax,inoutres
  369. .LDOSWRITE1:
  370. popl %ebx
  371. end {['eax', 'ebx', 'ecx', 'edx']};
  372. function do_filepos (Handle: THandle): longint; assembler;
  373. asm
  374. pushl %ebx
  375. {$IFDEF REGCALL}
  376. movl %eax,%ebx
  377. {$ELSE REGCALL}
  378. movl handle,%ebx
  379. {$ENDIF REGCALL}
  380. movw $0x4201,%ax
  381. xorl %edx,%edx
  382. call syscall
  383. jnc .LDOSFILEPOS
  384. movw %ax,inoutres
  385. xorl %eax,%eax
  386. .LDOSFILEPOS:
  387. popl %ebx
  388. end {['eax', 'ebx', 'ecx', 'edx']};
  389. procedure do_seek (Handle: THandle; Pos: longint); assembler;
  390. asm
  391. pushl %ebx
  392. {$IFDEF REGCALL}
  393. movl %eax,%ebx
  394. {$ELSE REGCALL}
  395. movl handle,%ebx
  396. movl pos,%edx
  397. {$ENDIF REGCALL}
  398. movw $0x4200,%ax
  399. call syscall
  400. jnc .LDOSSEEK1
  401. movw %ax,inoutres
  402. .LDOSSEEK1:
  403. popl %ebx
  404. end {['eax', 'ebx', 'ecx', 'edx']};
  405. function do_seekend (Handle: THandle): longint; assembler;
  406. asm
  407. pushl %ebx
  408. {$IFDEF REGCALL}
  409. movl %eax,%ebx
  410. {$ELSE REGCALL}
  411. movl handle,%ebx
  412. {$ENDIF REGCALL}
  413. movw $0x4202,%ax
  414. xorl %edx,%edx
  415. call syscall
  416. jnc .Lset_at_end1
  417. movw %ax,inoutres;
  418. xorl %eax,%eax
  419. .Lset_at_end1:
  420. popl %ebx
  421. end {['eax', 'ebx', 'ecx', 'edx']};
  422. function do_filesize (Handle: THandle): longint;
  423. var aktfilepos:longint;
  424. begin
  425. aktfilepos:=do_filepos(handle);
  426. do_filesize:=do_seekend(handle);
  427. do_seek(handle,aktfilepos);
  428. end;
  429. procedure do_truncate (Handle: THandle; Pos: longint); assembler;
  430. asm
  431. pushl %ebx
  432. (* DOS function 40h isn't safe for this according to EMX documentation *)
  433. {$IFDEF REGCALL}
  434. movl %eax,%ebx
  435. pushl %eax
  436. {$ELSE REGCALL}
  437. movl Handle,%ebx
  438. movl Pos,%edx
  439. {$ENDIF REGCALL}
  440. movl $0x7F25,%eax
  441. call syscall
  442. incl %eax
  443. movl %ecx, %eax
  444. {$IFDEF REGCALL}
  445. popl %ebx
  446. {$ENDIF REGCALL}
  447. jnz .LTruncate1 { compare the value of EAX to verify error }
  448. (* File position is undefined after truncation, move to the end. *)
  449. movl $0x4202,%eax
  450. {$IFNDEF REGCALL}
  451. movl Handle,%ebx
  452. {$ENDIF REGCALL}
  453. movl $0,%edx
  454. call syscall
  455. jnc .LTruncate2
  456. .LTruncate1:
  457. movw %ax,inoutres
  458. .LTruncate2:
  459. popl %ebx
  460. end {['eax', 'ebx', 'ecx', 'edx']};
  461. const
  462. FileHandleCount: cardinal = 20;
  463. function Increase_File_Handle_Count: boolean;
  464. var Err: word;
  465. L1: longint;
  466. L2: cardinal;
  467. begin
  468. if os_mode = osOS2 then
  469. begin
  470. L1 := 10;
  471. if DosSetRelMaxFH (L1, L2) <> 0 then
  472. Increase_File_Handle_Count := false
  473. else
  474. if L2 > FileHandleCount then
  475. begin
  476. FileHandleCount := L2;
  477. Increase_File_Handle_Count := true;
  478. end
  479. else
  480. Increase_File_Handle_Count := false;
  481. end
  482. else
  483. begin
  484. Inc (FileHandleCount, 10);
  485. Err := 0;
  486. asm
  487. pushl %ebx
  488. movl $0x6700, %eax
  489. movl FileHandleCount, %ebx
  490. call syscall
  491. jnc .LIncFHandles
  492. movw %ax, Err
  493. .LIncFHandles:
  494. popl %ebx
  495. end ['eax'];
  496. if Err <> 0 then
  497. begin
  498. Increase_File_Handle_Count := false;
  499. Dec (FileHandleCount, 10);
  500. end
  501. else
  502. Increase_File_Handle_Count := true;
  503. end;
  504. end;
  505. procedure do_open(var f;p:pchar;flags:longint);
  506. {
  507. filerec and textrec have both handle and mode as the first items so
  508. they could use the same routine for opening/creating.
  509. when (flags and $100) the file will be append
  510. when (flags and $1000) the file will be truncate/rewritten
  511. when (flags and $10000) there is no check for close (needed for textfiles)
  512. }
  513. var Action: cardinal;
  514. begin
  515. allowslash(p);
  516. { close first if opened }
  517. if ((flags and $10000)=0) then
  518. begin
  519. case filerec(f).mode of
  520. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  521. fmclosed:;
  522. else
  523. begin
  524. inoutres:=102; {not assigned}
  525. exit;
  526. end;
  527. end;
  528. end;
  529. { reset file handle }
  530. filerec(f).handle := UnusedHandle;
  531. Action := 0;
  532. { convert filemode to filerec modes }
  533. case (flags and 3) of
  534. 0 : filerec(f).mode:=fminput;
  535. 1 : filerec(f).mode:=fmoutput;
  536. 2 : filerec(f).mode:=fminout;
  537. end;
  538. if (flags and $1000)<>0 then
  539. Action := $50000; (* Create / replace *)
  540. { empty name is special }
  541. if p[0]=#0 then
  542. begin
  543. case FileRec(f).mode of
  544. fminput :
  545. FileRec(f).Handle:=StdInputHandle;
  546. fminout, { this is set by rewrite }
  547. fmoutput :
  548. FileRec(f).Handle:=StdOutputHandle;
  549. fmappend :
  550. begin
  551. FileRec(f).Handle:=StdOutputHandle;
  552. FileRec(f).mode:=fmoutput; {fool fmappend}
  553. end;
  554. end;
  555. exit;
  556. end;
  557. Action := Action or (Flags and $FF);
  558. (* DenyNone if sharing not specified. *)
  559. if Flags and 112 = 0 then
  560. Action := Action or 64;
  561. asm
  562. pushl %ebx
  563. movl $0x7f2b, %eax
  564. movl Action, %ecx
  565. movl p, %edx
  566. call syscall
  567. cmpl $0xffffffff, %eax
  568. jnz .LOPEN1
  569. movw %cx, InOutRes
  570. movl UnusedHandle, %eax
  571. .LOPEN1:
  572. movl f,%edx { Warning : This assumes Handle is first }
  573. movl %eax,(%edx) { field of FileRec }
  574. popl %ebx
  575. end ['eax', 'ecx', 'edx'];
  576. if (InOutRes = 4) and Increase_File_Handle_Count then
  577. (* Trying again after increasing amount of file handles *)
  578. asm
  579. pushl %ebx
  580. movl $0x7f2b, %eax
  581. movl Action, %ecx
  582. movl p, %edx
  583. call syscall
  584. cmpl $0xffffffff, %eax
  585. jnz .LOPEN2
  586. movw %cx, InOutRes
  587. movl UnusedHandle, %eax
  588. .LOPEN2:
  589. movl f,%edx
  590. movl %eax,(%edx)
  591. popl %ebx
  592. end ['eax', 'ecx', 'edx'];
  593. { for systems that have more handles }
  594. if (FileRec (F).Handle <> UnusedHandle) then
  595. begin
  596. if (FileRec (F).Handle > FileHandleCount) then
  597. FileHandleCount := FileRec (F).Handle;
  598. if ((Flags and $100) <> 0) then
  599. begin
  600. do_seekend (FileRec (F).Handle);
  601. FileRec (F).Mode := fmOutput; {fool fmappend}
  602. end;
  603. end;
  604. end;
  605. {$ASMMODE INTEL}
  606. function do_isdevice (Handle: THandle): boolean; assembler;
  607. (*
  608. var HT, Attr: longint;
  609. begin
  610. if os_mode = osOS2 then
  611. begin
  612. if DosQueryHType (Handle, HT, Attr) <> 0 then HT := 1;
  613. end
  614. else
  615. *)
  616. asm
  617. push ebx
  618. {$IFDEF REGCALL}
  619. mov ebx, eax
  620. {$ELSE REGCALL}
  621. mov ebx, Handle
  622. {$ENDIF REGCALL}
  623. mov eax, 4400h
  624. call syscall
  625. mov eax, 1
  626. jc @IsDevEnd
  627. test edx, 80h { verify if it is a file }
  628. jnz @IsDevEnd
  629. dec eax { nope, so result is zero }
  630. @IsDevEnd:
  631. pop ebx
  632. end {['eax', 'ebx', 'edx']};
  633. {$ASMMODE ATT}
  634. {*****************************************************************************
  635. UnTyped File Handling
  636. *****************************************************************************}
  637. {$i file.inc}
  638. {*****************************************************************************
  639. Typed File Handling
  640. *****************************************************************************}
  641. {$i typefile.inc}
  642. {*****************************************************************************
  643. Text File Handling
  644. *****************************************************************************}
  645. {$DEFINE EOF_CTRLZ}
  646. {$i text.inc}
  647. {****************************************************************************
  648. Directory related routines.
  649. ****************************************************************************}
  650. {*****************************************************************************
  651. Directory Handling
  652. *****************************************************************************}
  653. procedure dosdir(func:byte;const s:string);
  654. var buffer:array[0..255] of char;
  655. begin
  656. move(s[1],buffer,length(s));
  657. buffer[length(s)]:=#0;
  658. allowslash(Pchar(@buffer));
  659. asm
  660. leal buffer,%edx
  661. movb func,%ah
  662. call syscall
  663. jnc .LDOS_DIRS1
  664. movw %ax,inoutres
  665. .LDOS_DIRS1:
  666. end ['eax', 'edx'];
  667. end;
  668. procedure MkDir (const S: string);[IOCHECK];
  669. var buffer:array[0..255] of char;
  670. Rc : word;
  671. begin
  672. If (s='') or (InOutRes <> 0) then
  673. exit;
  674. if os_mode = osOs2 then
  675. begin
  676. move(s[1],buffer,length(s));
  677. buffer[length(s)]:=#0;
  678. allowslash(Pchar(@buffer));
  679. Rc := DosCreateDir(buffer,nil);
  680. if Rc <> 0 then
  681. begin
  682. InOutRes := Rc;
  683. Errno2Inoutres;
  684. end;
  685. end
  686. else
  687. begin
  688. { Under EMX 0.9d DOS this routine call may sometimes fail }
  689. { The syscall documentation indicates clearly that this }
  690. { routine was NOT tested. }
  691. DosDir ($39, S);
  692. end;
  693. end;
  694. procedure rmdir(const s : string);[IOCHECK];
  695. var buffer:array[0..255] of char;
  696. Rc : word;
  697. begin
  698. if (s = '.' ) then
  699. InOutRes := 16;
  700. If (s='') or (InOutRes <> 0) then
  701. exit;
  702. if os_mode = osOs2 then
  703. begin
  704. move(s[1],buffer,length(s));
  705. buffer[length(s)]:=#0;
  706. allowslash(Pchar(@buffer));
  707. Rc := DosDeleteDir(buffer);
  708. if Rc <> 0 then
  709. begin
  710. InOutRes := Rc;
  711. Errno2Inoutres;
  712. end;
  713. end
  714. else
  715. begin
  716. { Under EMX 0.9d DOS this routine call may sometimes fail }
  717. { The syscall documentation indicates clearly that this }
  718. { routine was NOT tested. }
  719. DosDir ($3A, S);
  720. end;
  721. end;
  722. {$ASMMODE INTEL}
  723. procedure ChDir (const S: string);[IOCheck];
  724. var RC: cardinal;
  725. Buffer: array [0..255] of char;
  726. begin
  727. If (s='') or (InOutRes <> 0) then
  728. exit;
  729. (* According to EMX documentation, EMX has only one current directory
  730. for all processes, so we'll use native calls under OS/2. *)
  731. if os_Mode = osOS2 then
  732. begin
  733. if (Length (S) >= 2) and (S [2] = ':') then
  734. begin
  735. RC := DosSetDefaultDisk ((Ord (S [1]) and
  736. not ($20)) - $40);
  737. if RC <> 0 then
  738. InOutRes := RC
  739. else
  740. if Length (S) > 2 then
  741. begin
  742. Move (S [1], Buffer, Length (S));
  743. Buffer [Length (S)] := #0;
  744. AllowSlash (PChar (@Buffer));
  745. RC := DosSetCurrentDir (@Buffer);
  746. if RC <> 0 then
  747. begin
  748. InOutRes := RC;
  749. Errno2InOutRes;
  750. end;
  751. end;
  752. end
  753. else
  754. begin
  755. Move (S [1], Buffer, Length (S));
  756. Buffer [Length (S)] := #0;
  757. AllowSlash (PChar (@Buffer));
  758. RC := DosSetCurrentDir (@Buffer);
  759. if RC <> 0 then
  760. begin
  761. InOutRes:= RC;
  762. Errno2InOutRes;
  763. end;
  764. end;
  765. end
  766. else
  767. if (Length (S) >= 2) and (S [2] = ':') then
  768. begin
  769. asm
  770. mov esi, S
  771. mov al, [esi + 1]
  772. and al, not (20h)
  773. sub al, 41h
  774. mov edx, eax
  775. mov ah, 0Eh
  776. call syscall
  777. mov ah, 19h
  778. call syscall
  779. cmp al, dl
  780. jz @LCHDIR
  781. mov InOutRes, 15
  782. @LCHDIR:
  783. end ['eax','edx','esi'];
  784. if (Length (S) > 2) and (InOutRes <> 0) then
  785. { Under EMX 0.9d DOS this routine may sometime }
  786. { fail or crash the system. }
  787. DosDir ($3B, S);
  788. end
  789. else
  790. { Under EMX 0.9d DOS this routine may sometime }
  791. { fail or crash the system. }
  792. DosDir ($3B, S);
  793. end;
  794. {$ASMMODE ATT}
  795. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  796. {Written by Michael Van Canneyt.}
  797. var sof:Pchar;
  798. i:byte;
  799. begin
  800. Dir [4] := #0;
  801. { Used in case the specified drive isn't available }
  802. sof:=pchar(@dir[4]);
  803. { dir[1..3] will contain '[drivenr]:\', but is not }
  804. { supplied by DOS, so we let dos string start at }
  805. { dir[4] }
  806. { Get dir from drivenr : 0=default, 1=A etc... }
  807. asm
  808. movb drivenr,%dl
  809. movl sof,%esi
  810. mov $0x47,%ah
  811. call syscall
  812. jnc .LGetDir
  813. movw %ax, InOutRes
  814. .LGetDir:
  815. end [ 'eax','edx','esi'];
  816. { Now Dir should be filled with directory in ASCIIZ, }
  817. { starting from dir[4] }
  818. dir[0]:=#3;
  819. dir[2]:=':';
  820. dir[3]:='\';
  821. i:=4;
  822. {Conversion to Pascal string }
  823. while (dir[i]<>#0) do
  824. begin
  825. { convert path name to DOS }
  826. if dir[i]='/' then
  827. dir[i]:='\';
  828. dir[0]:=char(i);
  829. inc(i);
  830. end;
  831. { upcase the string (FPC function) }
  832. if drivenr<>0 then { Drive was supplied. We know it }
  833. dir[1]:=chr(64+drivenr)
  834. else
  835. begin
  836. { We need to get the current drive from DOS function 19H }
  837. { because the drive was the default, which can be unknown }
  838. asm
  839. movb $0x19,%ah
  840. call syscall
  841. addb $65,%al
  842. movb %al,i
  843. end ['eax'];
  844. dir[1]:=char(i);
  845. end;
  846. if not (FileNameCaseSensitive) then dir:=upcase(dir);
  847. end;
  848. {*****************************************************************************
  849. System unit initialization.
  850. ****************************************************************************}
  851. {****************************************************************************
  852. Error Message writing using messageboxes
  853. ****************************************************************************}
  854. type
  855. TWinMessageBox = function (Parent, Owner: cardinal;
  856. BoxText, BoxTitle: PChar; Identity, Style: cardinal): cardinal; cdecl;
  857. TWinInitialize = function (Options: cardinal): cardinal; cdecl;
  858. TWinCreateMsgQueue = function (Handle: cardinal; cmsg: longint): cardinal;
  859. cdecl;
  860. const
  861. ErrorBufferLength = 1024;
  862. mb_OK = $0000;
  863. mb_Error = $0040;
  864. mb_Moveable = $4000;
  865. MBStyle = mb_OK or mb_Error or mb_Moveable;
  866. WinInitialize: TWinInitialize = nil;
  867. WinCreateMsgQueue: TWinCreateMsgQueue = nil;
  868. WinMessageBox: TWinMessageBox = nil;
  869. EnvSize: cardinal = 0;
  870. var
  871. ErrorBuf: array [0..ErrorBufferLength] of char;
  872. ErrorLen: longint;
  873. PMWinHandle: cardinal;
  874. function ErrorWrite (var F: TextRec): integer;
  875. {
  876. An error message should always end with #13#10#13#10
  877. }
  878. var
  879. P: PChar;
  880. I: longint;
  881. begin
  882. if F.BufPos > 0 then
  883. begin
  884. if F.BufPos + ErrorLen > ErrorBufferLength then
  885. I := ErrorBufferLength - ErrorLen
  886. else
  887. I := F.BufPos;
  888. Move (F.BufPtr^, ErrorBuf [ErrorLen], I);
  889. Inc (ErrorLen, I);
  890. ErrorBuf [ErrorLen] := #0;
  891. end;
  892. if ErrorLen > 3 then
  893. begin
  894. P := @ErrorBuf [ErrorLen];
  895. for I := 1 to 4 do
  896. begin
  897. Dec (P);
  898. if not (P^ in [#10, #13]) then
  899. break;
  900. end;
  901. end;
  902. if ErrorLen = ErrorBufferLength then
  903. I := 4;
  904. if (I = 4) then
  905. begin
  906. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  907. ErrorLen := 0;
  908. end;
  909. F.BufPos := 0;
  910. ErrorWrite := 0;
  911. end;
  912. function ErrorClose (var F: TextRec): integer;
  913. begin
  914. if ErrorLen > 0 then
  915. begin
  916. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  917. ErrorLen := 0;
  918. end;
  919. ErrorLen := 0;
  920. ErrorClose := 0;
  921. end;
  922. function ErrorOpen (var F: TextRec): integer;
  923. begin
  924. TextRec(F).InOutFunc := @ErrorWrite;
  925. TextRec(F).FlushFunc := @ErrorWrite;
  926. TextRec(F).CloseFunc := @ErrorClose;
  927. ErrorOpen := 0;
  928. end;
  929. procedure AssignError (var T: Text);
  930. begin
  931. Assign (T, '');
  932. TextRec (T).OpenFunc := @ErrorOpen;
  933. Rewrite (T);
  934. end;
  935. procedure DosEnvInit;
  936. var
  937. Q: PPChar;
  938. I: cardinal;
  939. begin
  940. (* It's a hack, in fact - DOS stores the environment the same way as OS/2 does,
  941. but I don't know how to find Program Segment Prefix and thus the environment
  942. address under EMX, so I'm recreating this structure using EnvP pointer. *)
  943. {$ASMMODE INTEL}
  944. asm
  945. cld
  946. mov ecx, EnvC
  947. mov esi, EnvP
  948. xor eax, eax
  949. xor edx, edx
  950. @L1:
  951. xchg eax, edx
  952. push ecx
  953. mov ecx, -1
  954. mov edi, [esi]
  955. repne
  956. scasb
  957. neg ecx
  958. dec ecx
  959. xchg eax, edx
  960. add eax, ecx
  961. pop ecx
  962. dec ecx
  963. jecxz @Stop
  964. inc esi
  965. inc esi
  966. inc esi
  967. inc esi
  968. jmp @L1
  969. @Stop:
  970. inc eax
  971. mov EnvSize, eax
  972. end ['eax','ecx','edx','esi','edi'];
  973. Environment := GetMem (EnvSize);
  974. asm
  975. cld
  976. mov ecx, EnvC
  977. mov edx, EnvP
  978. mov edi, Environment
  979. @L2:
  980. mov esi, [edx]
  981. @Copying:
  982. lodsb
  983. stosb
  984. or al, al
  985. jnz @Copying
  986. dec ecx
  987. jecxz @Stop2
  988. inc edx
  989. inc edx
  990. inc edx
  991. inc edx
  992. jmp @L2
  993. @Stop2:
  994. stosb
  995. end ['eax','ecx','edx','esi','edi'];
  996. end;
  997. procedure SysInitStdIO;
  998. begin
  999. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1000. displayed in a messagebox }
  1001. (*
  1002. StdInputHandle := longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  1003. StdOutputHandle := longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  1004. StdErrorHandle := longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  1005. if not IsConsole then
  1006. begin
  1007. if (DosLoadModule (nil, 0, 'PMWIN', PMWinHandle) = 0) and
  1008. (DosQueryProcAddr (PMWinHandle, 789, nil, pointer (WinMessageBox)) = 0)
  1009. and
  1010. (DosQueryProcAddr (PMWinHandle, 763, nil, pointer (WinInitialize)) = 0)
  1011. and
  1012. (DosQueryProcAddr (PMWinHandle, 716, nil, pointer (WinCreateMsgQueue))
  1013. = 0)
  1014. then
  1015. begin
  1016. WinInitialize (0);
  1017. WinCreateMsgQueue (0, 0);
  1018. end
  1019. else
  1020. HandleError (2);
  1021. AssignError (StdErr);
  1022. AssignError (StdOut);
  1023. Assign (Output, '');
  1024. Assign (Input, '');
  1025. end
  1026. else
  1027. begin
  1028. *)
  1029. OpenStdIO (Input, fmInput, StdInputHandle);
  1030. OpenStdIO (Output, fmOutput, StdOutputHandle);
  1031. OpenStdIO (ErrOutput, fmOutput, StdErrorHandle);
  1032. OpenStdIO (StdOut, fmOutput, StdOutputHandle);
  1033. OpenStdIO (StdErr, fmOutput, StdErrorHandle);
  1034. (*
  1035. end;
  1036. *)
  1037. end;
  1038. {$ifdef HASTHREADVAR}
  1039. threadvar
  1040. {$else HASTHREADVAR}
  1041. var
  1042. {$endif HASTHREADVAR}
  1043. DefaultCreator: ShortString = '';
  1044. DefaultFileType: ShortString = '';
  1045. procedure SetDefaultOS2FileType (FType: ShortString);
  1046. begin
  1047. {$WARNING Not implemented yet!}
  1048. DefaultFileType := FType;
  1049. end;
  1050. procedure SetDefaultOS2Creator (Creator: ShortString);
  1051. begin
  1052. {$WARNING Not implemented yet!}
  1053. DefaultCreator := Creator;
  1054. end;
  1055. function GetFileHandleCount: longint;
  1056. var L1: longint;
  1057. L2: cardinal;
  1058. begin
  1059. L1 := 0; (* Don't change the amount, just check. *)
  1060. if DosSetRelMaxFH (L1, L2) <> 0 then GetFileHandleCount := 50
  1061. else GetFileHandleCount := L2;
  1062. end;
  1063. var TIB: PThreadInfoBlock;
  1064. PIB: PProcessInfoBlock;
  1065. const
  1066. FatalHeap: array [0..33] of char = 'FATAL: Cannot initialize heap!!'#13#10'$';
  1067. begin
  1068. IsLibrary := FALSE;
  1069. {Determine the operating system we are running on.}
  1070. {$ASMMODE INTEL}
  1071. asm
  1072. push ebx
  1073. mov os_mode, 0
  1074. mov eax, 7F0Ah
  1075. call syscall
  1076. test bx, 512 {Bit 9 is OS/2 flag.}
  1077. setne byte ptr os_mode
  1078. test bx, 4096
  1079. jz @noRSX
  1080. mov os_mode, 2
  1081. @noRSX:
  1082. {Enable the brk area by initializing it with the initial heap size.}
  1083. mov eax, 7F01h
  1084. mov edx, heap_brk
  1085. add edx, heap_base
  1086. call syscall
  1087. cmp eax, -1
  1088. jnz @heapok
  1089. lea edx, FatalHeap
  1090. mov eax, 900h
  1091. call syscall
  1092. pop ebx
  1093. push dword 204
  1094. call HandleError
  1095. @heapok:
  1096. {$IFDEF CONTHEAP}
  1097. { Find out brk limit }
  1098. mov eax, 7F02h
  1099. mov ecx, 3
  1100. call syscall
  1101. jcxz @heaplimitknown
  1102. mov eax, 0
  1103. @heaplimitknown:
  1104. mov BrkLimit, eax
  1105. {$ELSE CONTHEAP}
  1106. { Change sbrk behaviour to allocate arbitrary (non-contiguous) memory blocks }
  1107. mov eax, 7F0Fh
  1108. mov ecx, 0Ch
  1109. mov edx, 8
  1110. call syscall
  1111. {$ENDIF CONTHEAP}
  1112. pop ebx
  1113. end ['eax', 'ecx', 'edx'];
  1114. { in OS/2 this will always be nil, but in DOS mode }
  1115. { this can be changed. }
  1116. first_meg := nil;
  1117. {Now request, if we are running under DOS,
  1118. read-access to the first meg. of memory.}
  1119. if os_mode in [osDOS,osDPMI] then
  1120. asm
  1121. push ebx
  1122. mov eax, 7F13h
  1123. xor ebx, ebx
  1124. mov ecx, 0FFFh
  1125. xor edx, edx
  1126. call syscall
  1127. jc @endmem
  1128. mov first_meg, eax
  1129. @endmem:
  1130. pop ebx
  1131. end ['eax', 'ecx', 'edx']
  1132. else
  1133. begin
  1134. (* Initialize the amount of file handles *)
  1135. FileHandleCount := GetFileHandleCount;
  1136. end;
  1137. {At 0.9.2, case for enumeration does not work.}
  1138. case os_mode of
  1139. osDOS:
  1140. begin
  1141. stackbottom:=pointer(heap_brk); {In DOS mode, heap_brk is
  1142. also the stack bottom.}
  1143. ApplicationType := 1; (* Running under DOS. *)
  1144. IsConsole := true;
  1145. ProcessID := 1;
  1146. ThreadID := 1;
  1147. end;
  1148. osOS2:
  1149. begin
  1150. DosGetInfoBlocks (@TIB, @PIB);
  1151. StackBottom := pointer (TIB^.Stack);
  1152. Environment := pointer (PIB^.Env);
  1153. ApplicationType := PIB^.ProcType;
  1154. ProcessID := PIB^.PID;
  1155. ThreadID := TIB^.TIB2^.TID;
  1156. IsConsole := ApplicationType <> 3;
  1157. end;
  1158. osDPMI:
  1159. begin
  1160. stackbottom:=nil; {Not sure how to get it, but seems to be
  1161. always zero.}
  1162. ApplicationType := 1; (* Running under DOS. *)
  1163. IsConsole := true;
  1164. ProcessID := 1;
  1165. ThreadID := 1;
  1166. end;
  1167. end;
  1168. exitproc:=nil;
  1169. {Initialize the heap.}
  1170. initheap;
  1171. { ... and exceptions }
  1172. SysInitExceptions;
  1173. { ... and I/O }
  1174. SysInitStdIO;
  1175. { no I/O-Error }
  1176. inoutres:=0;
  1177. {$ifdef HASVARIANT}
  1178. initvariantmanager;
  1179. {$endif HASVARIANT}
  1180. if os_Mode in [osDOS,osDPMI] then
  1181. DosEnvInit;
  1182. {$IFDEF DUMPGROW}
  1183. {$IFDEF CONTHEAP}
  1184. WriteLn ('Initial brk size is ', GetHeapSize);
  1185. WriteLn ('Brk limit is ', BrkLimit);
  1186. {$ENDIF CONTHEAP}
  1187. {$ENDIF DUMPGROW}
  1188. end.
  1189. {
  1190. $Log$
  1191. Revision 1.32 2004-12-12 21:08:29 hajny
  1192. * ThreadID is shared
  1193. Revision 1.31 2004/12/05 14:36:37 hajny
  1194. + GetProcessID added
  1195. Revision 1.30 2004/11/04 09:32:31 peter
  1196. ErrOutput added
  1197. Revision 1.29 2004/10/25 15:38:59 peter
  1198. * compiler defined HEAP and HEAPSIZE removed
  1199. Revision 1.28 2004/09/18 11:12:49 hajny
  1200. * handle type changed to thandle in do_isdevice
  1201. Revision 1.27 2004/09/03 19:25:41 olle
  1202. + added maxExitCode to all System.pp
  1203. * constrained error code to be below maxExitCode in RunError et. al.
  1204. Revision 1.26 2004/07/24 01:15:25 hajny
  1205. * simulated support for new heap manager
  1206. Revision 1.25 2004/05/16 20:39:59 hajny
  1207. * handle in do_* changed to THandle
  1208. Revision 1.24 2004/04/22 21:10:56 peter
  1209. * do_read/do_write addr argument changed to pointer
  1210. Revision 1.23 2004/01/20 23:05:31 hajny
  1211. * ExecuteProcess fixes, ProcessID and ThreadID added
  1212. Revision 1.22 2003/12/26 22:20:44 hajny
  1213. * regcall fixes
  1214. Revision 1.21 2003/12/17 22:52:39 hajny
  1215. * fix for stackbottom change to pointer
  1216. Revision 1.20 2003/11/06 23:21:51 hajny
  1217. * cardinal2pointer changes
  1218. Revision 1.19 2003/11/01 19:25:50 hajny
  1219. * fix of previous mistyping
  1220. Revision 1.18 2003/10/25 22:45:37 hajny
  1221. * file handling related fixes
  1222. Revision 1.17 2003/10/19 12:13:41 hajny
  1223. * UnusedHandle value made the same as with other targets
  1224. Revision 1.16 2003/10/19 09:35:28 hajny
  1225. * fixes from OS/2 merged to EMX
  1226. Revision 1.15 2003/10/16 15:43:13 peter
  1227. * THandle is platform dependent
  1228. Revision 1.14 2003/10/12 18:07:30 hajny
  1229. * wrong use of Intel syntax
  1230. Revision 1.13 2003/10/12 17:59:40 hajny
  1231. * wrong use of Intel syntax
  1232. Revision 1.12 2003/10/12 17:52:28 hajny
  1233. * wrong use of Intel syntax
  1234. Revision 1.11 2003/10/12 10:45:36 hajny
  1235. * sbrk error handling corrected
  1236. Revision 1.10 2003/10/07 21:33:24 hajny
  1237. * stdcall fixes and asm routines cleanup
  1238. Revision 1.9 2003/10/04 17:53:08 hajny
  1239. * stdcall changes merged to EMX
  1240. Revision 1.8 2003/09/29 18:39:59 hajny
  1241. * append fix applied to GO32v2, OS/2 and EMX
  1242. Revision 1.7 2003/09/27 11:52:35 peter
  1243. * sbrk returns pointer
  1244. Revision 1.6 2003/09/24 11:13:09 yuri
  1245. * Cosmetic changes
  1246. * Slightly improved emx.pas
  1247. Revision 1.5 2003/06/26 17:12:29 yuri
  1248. * pmbidi added
  1249. * some cosmetic changes
  1250. Revision 1.4 2003/03/23 23:11:17 hajny
  1251. + emx target added
  1252. Revision 1.3 2002/12/15 22:46:29 hajny
  1253. * First_Meg fixed + Environment initialization under Dos
  1254. Revision 1.2 2002/11/17 22:32:05 hajny
  1255. * type corrections (longing x cardinal)
  1256. Revision 1.1 2002/11/17 16:22:54 hajny
  1257. + RTL for emx target
  1258. }