system.pas 41 KB

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