system.pas 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457
  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. movb $0x3e,%ah
  409. movl h,%ebx
  410. call syscall
  411. jnc .Lnoerror { error code? }
  412. movw %ax, InOutRes { yes, then set InOutRes }
  413. .Lnoerror:
  414. end;
  415. end;
  416. end;
  417. procedure do_erase(p:Pchar);
  418. begin
  419. allowslash(p);
  420. asm
  421. movl P,%edx
  422. movb $0x41,%ah
  423. call syscall
  424. jnc .LERASE1
  425. movw %ax,inoutres;
  426. .LERASE1:
  427. end;
  428. end;
  429. procedure do_rename(p1,p2:Pchar);
  430. begin
  431. allowslash(p1);
  432. allowslash(p2);
  433. asm
  434. movl P1, %edx
  435. movl P2, %edi
  436. movb $0x56,%ah
  437. call syscall
  438. jnc .LRENAME1
  439. movw %ax,inoutres;
  440. .LRENAME1:
  441. end;
  442. end;
  443. function do_read(h,addr,len:longint):longint; assembler;
  444. asm
  445. movl len,%ecx
  446. movl addr,%edx
  447. movl h,%ebx
  448. movb $0x3f,%ah
  449. call syscall
  450. jnc .LDOSREAD1
  451. movw %ax,inoutres;
  452. xorl %eax,%eax
  453. .LDOSREAD1:
  454. end;
  455. function do_write(h,addr,len:longint) : longint; assembler;
  456. asm
  457. xorl %eax,%eax
  458. cmpl $0,len { 0 bytes to write is undefined behavior }
  459. jz .LDOSWRITE1
  460. movl len,%ecx
  461. movl addr,%edx
  462. movl h,%ebx
  463. movb $0x40,%ah
  464. call syscall
  465. jnc .LDOSWRITE1
  466. movw %ax,inoutres;
  467. .LDOSWRITE1:
  468. end;
  469. function do_filepos(handle:longint): longint; assembler;
  470. asm
  471. movw $0x4201,%ax
  472. movl handle,%ebx
  473. xorl %edx,%edx
  474. call syscall
  475. jnc .LDOSFILEPOS
  476. movw %ax,inoutres;
  477. xorl %eax,%eax
  478. .LDOSFILEPOS:
  479. end;
  480. procedure do_seek(handle,pos:longint); assembler;
  481. asm
  482. movw $0x4200,%ax
  483. movl handle,%ebx
  484. movl pos,%edx
  485. call syscall
  486. jnc .LDOSSEEK1
  487. movw %ax,inoutres;
  488. .LDOSSEEK1:
  489. end;
  490. function do_seekend(handle:longint):longint; assembler;
  491. asm
  492. movw $0x4202,%ax
  493. movl handle,%ebx
  494. xorl %edx,%edx
  495. call syscall
  496. jnc .Lset_at_end1
  497. movw %ax,inoutres;
  498. xorl %eax,%eax
  499. .Lset_at_end1:
  500. end;
  501. function do_filesize(handle:longint):longint;
  502. var aktfilepos:longint;
  503. begin
  504. aktfilepos:=do_filepos(handle);
  505. do_filesize:=do_seekend(handle);
  506. do_seek(handle,aktfilepos);
  507. end;
  508. procedure do_truncate(handle,pos:longint); assembler;
  509. asm
  510. (* DOS function 40h isn't safe for this according to EMX documentation *)
  511. movl $0x7F25,%eax
  512. movl Handle,%ebx
  513. movl Pos,%edx
  514. call syscall
  515. incl %eax
  516. movl %ecx, %eax
  517. jnz .LTruncate1 { compare the value of EAX to verify error }
  518. (* File position is undefined after truncation, move to the end. *)
  519. movl $0x4202,%eax
  520. movl Handle,%ebx
  521. movl $0,%edx
  522. call syscall
  523. jnc .LTruncate2
  524. .LTruncate1:
  525. movw %ax,inoutres;
  526. .LTruncate2:
  527. end;
  528. const
  529. FileHandleCount: longint = 20;
  530. function Increase_File_Handle_Count: boolean;
  531. var Err: word;
  532. L1, L2: longint;
  533. begin
  534. if os_mode = osOS2 then
  535. begin
  536. L1 := 10;
  537. if DosSetRelMaxFH (L1, L2) <> 0 then
  538. Increase_File_Handle_Count := false
  539. else
  540. if L2 > FileHandleCount then
  541. begin
  542. FileHandleCount := L2;
  543. Increase_File_Handle_Count := true;
  544. end
  545. else
  546. Increase_File_Handle_Count := false;
  547. end
  548. else
  549. begin
  550. Inc (FileHandleCount, 10);
  551. Err := 0;
  552. asm
  553. movl $0x6700, %eax
  554. movl FileHandleCount, %ebx
  555. call syscall
  556. jnc .LIncFHandles
  557. movw %ax, Err
  558. .LIncFHandles:
  559. end;
  560. if Err <> 0 then
  561. begin
  562. Increase_File_Handle_Count := false;
  563. Dec (FileHandleCount, 10);
  564. end
  565. else
  566. Increase_File_Handle_Count := true;
  567. end;
  568. end;
  569. procedure do_open(var f;p:pchar;flags:longint);
  570. {
  571. filerec and textrec have both handle and mode as the first items so
  572. they could use the same routine for opening/creating.
  573. when (flags and $100) the file will be append
  574. when (flags and $1000) the file will be truncate/rewritten
  575. when (flags and $10000) there is no check for close (needed for textfiles)
  576. }
  577. var Action: longint;
  578. begin
  579. allowslash(p);
  580. { close first if opened }
  581. if ((flags and $10000)=0) then
  582. begin
  583. case filerec(f).mode of
  584. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  585. fmclosed:;
  586. else
  587. begin
  588. inoutres:=102; {not assigned}
  589. exit;
  590. end;
  591. end;
  592. end;
  593. { reset file handle }
  594. filerec(f).handle := UnusedHandle;
  595. Action := 0;
  596. { convert filemode to filerec modes }
  597. case (flags and 3) of
  598. 0 : filerec(f).mode:=fminput;
  599. 1 : filerec(f).mode:=fmoutput;
  600. 2 : filerec(f).mode:=fminout;
  601. end;
  602. if (flags and $1000)<>0 then
  603. Action := $50000; (* Create / replace *)
  604. { empty name is special }
  605. if p[0]=#0 then
  606. begin
  607. case FileRec(f).mode of
  608. fminput :
  609. FileRec(f).Handle:=StdInputHandle;
  610. fminout, { this is set by rewrite }
  611. fmoutput :
  612. FileRec(f).Handle:=StdOutputHandle;
  613. fmappend :
  614. begin
  615. FileRec(f).Handle:=StdOutputHandle;
  616. FileRec(f).mode:=fmoutput; {fool fmappend}
  617. end;
  618. end;
  619. exit;
  620. end;
  621. Action := Action or (Flags and $FF);
  622. (* DenyNone if sharing not specified. *)
  623. if Flags and 112 = 0 then
  624. Action := Action or 64;
  625. asm
  626. movl $0x7f2b, %eax
  627. movl Action, %ecx
  628. movl p, %edx
  629. call syscall
  630. cmpl $0xffffffff, %eax
  631. jnz .LOPEN1
  632. movw %cx, InOutRes
  633. movw UnusedHandle, %ax
  634. .LOPEN1:
  635. movl f,%edx { Warning : This assumes Handle is first }
  636. movw %ax,(%edx) { field of FileRec }
  637. end;
  638. if (InOutRes = 4) and Increase_File_Handle_Count then
  639. (* Trying again after increasing amount of file handles *)
  640. asm
  641. movl $0x7f2b, %eax
  642. movl Action, %ecx
  643. movl p, %edx
  644. call syscall
  645. cmpl $0xffffffff, %eax
  646. jnz .LOPEN2
  647. movw %cx, InOutRes
  648. movw UnusedHandle, %ax
  649. .LOPEN2:
  650. movl f,%edx
  651. movw %ax,(%edx)
  652. end;
  653. { for systems that have more handles }
  654. if FileRec (F).Handle > FileHandleCount then
  655. FileHandleCount := FileRec (F).Handle;
  656. if ((Flags and $100) <> 0) and
  657. (FileRec (F).Handle <> UnusedHandle) then
  658. begin
  659. do_seekend (FileRec (F).Handle);
  660. FileRec (F).Mode := fmOutput; {fool fmappend}
  661. end;
  662. end;
  663. {$ASMMODE INTEL}
  664. function do_isdevice (Handle: longint): boolean; assembler;
  665. (*
  666. var HT, Attr: longint;
  667. begin
  668. if os_mode = osOS2 then
  669. begin
  670. if DosQueryHType (Handle, HT, Attr) <> 0 then HT := 1;
  671. end
  672. else
  673. *)
  674. asm
  675. mov ebx, Handle
  676. mov eax, 4400h
  677. call syscall
  678. mov eax, 1
  679. jc @IsDevEnd
  680. test edx, 80h { verify if it is a file }
  681. jnz @IsDevEnd
  682. dec eax { nope, so result is zero }
  683. @IsDevEnd:
  684. end;
  685. {$ASMMODE ATT}
  686. {*****************************************************************************
  687. UnTyped File Handling
  688. *****************************************************************************}
  689. {$i file.inc}
  690. {*****************************************************************************
  691. Typed File Handling
  692. *****************************************************************************}
  693. {$i typefile.inc}
  694. {*****************************************************************************
  695. Text File Handling
  696. *****************************************************************************}
  697. {$DEFINE EOF_CTRLZ}
  698. {$i text.inc}
  699. {****************************************************************************
  700. Directory related routines.
  701. ****************************************************************************}
  702. {*****************************************************************************
  703. Directory Handling
  704. *****************************************************************************}
  705. procedure dosdir(func:byte;const s:string);
  706. var buffer:array[0..255] of char;
  707. begin
  708. move(s[1],buffer,length(s));
  709. buffer[length(s)]:=#0;
  710. allowslash(Pchar(@buffer));
  711. asm
  712. leal buffer,%edx
  713. movb func,%ah
  714. call syscall
  715. jnc .LDOS_DIRS1
  716. movw %ax,inoutres
  717. .LDOS_DIRS1:
  718. end;
  719. end;
  720. procedure MkDir (const S: string);[IOCHECK];
  721. var buffer:array[0..255] of char;
  722. Rc : word;
  723. begin
  724. If (s='') or (InOutRes <> 0) then
  725. exit;
  726. if os_mode = osOs2 then
  727. begin
  728. move(s[1],buffer,length(s));
  729. buffer[length(s)]:=#0;
  730. allowslash(Pchar(@buffer));
  731. Rc := DosCreateDir(buffer,nil);
  732. if Rc <> 0 then
  733. begin
  734. InOutRes := Rc;
  735. Errno2Inoutres;
  736. end;
  737. end
  738. else
  739. begin
  740. { Under EMX 0.9d DOS this routine call may sometimes fail }
  741. { The syscall documentation indicates clearly that this }
  742. { routine was NOT tested. }
  743. DosDir ($39, S);
  744. end;
  745. end;
  746. procedure rmdir(const s : string);[IOCHECK];
  747. var buffer:array[0..255] of char;
  748. Rc : word;
  749. begin
  750. if (s = '.' ) then
  751. InOutRes := 16;
  752. If (s='') or (InOutRes <> 0) then
  753. exit;
  754. if os_mode = osOs2 then
  755. begin
  756. move(s[1],buffer,length(s));
  757. buffer[length(s)]:=#0;
  758. allowslash(Pchar(@buffer));
  759. Rc := DosDeleteDir(buffer);
  760. if Rc <> 0 then
  761. begin
  762. InOutRes := Rc;
  763. Errno2Inoutres;
  764. end;
  765. end
  766. else
  767. begin
  768. { Under EMX 0.9d DOS this routine call may sometimes fail }
  769. { The syscall documentation indicates clearly that this }
  770. { routine was NOT tested. }
  771. DosDir ($3A, S);
  772. end;
  773. end;
  774. {$ASMMODE INTEL}
  775. procedure ChDir (const S: string);[IOCheck];
  776. var RC: longint;
  777. Buffer: array [0..255] of char;
  778. begin
  779. If (s='') or (InOutRes <> 0) then
  780. exit;
  781. (* According to EMX documentation, EMX has only one current directory
  782. for all processes, so we'll use native calls under OS/2. *)
  783. if os_Mode = osOS2 then
  784. begin
  785. if (Length (S) >= 2) and (S [2] = ':') then
  786. begin
  787. RC := DosSetDefaultDisk ((Ord (S [1]) and
  788. not ($20)) - $40);
  789. if RC <> 0 then
  790. InOutRes := RC
  791. else
  792. if Length (S) > 2 then
  793. begin
  794. Move (S [1], Buffer, Length (S));
  795. Buffer [Length (S)] := #0;
  796. AllowSlash (PChar (@Buffer));
  797. RC := DosSetCurrentDir (@Buffer);
  798. if RC <> 0 then
  799. begin
  800. InOutRes := RC;
  801. Errno2InOutRes;
  802. end;
  803. end;
  804. end
  805. else
  806. begin
  807. Move (S [1], Buffer, Length (S));
  808. Buffer [Length (S)] := #0;
  809. AllowSlash (PChar (@Buffer));
  810. RC := DosSetCurrentDir (@Buffer);
  811. if RC <> 0 then
  812. begin
  813. InOutRes:= RC;
  814. Errno2InOutRes;
  815. end;
  816. end;
  817. end
  818. else
  819. if (Length (S) >= 2) and (S [2] = ':') then
  820. begin
  821. asm
  822. mov esi, S
  823. mov al, [esi + 1]
  824. and al, not (20h)
  825. sub al, 41h
  826. mov edx, eax
  827. mov ah, 0Eh
  828. call syscall
  829. mov ah, 19h
  830. call syscall
  831. cmp al, dl
  832. jz @LCHDIR
  833. mov InOutRes, 15
  834. @LCHDIR:
  835. end;
  836. if (Length (S) > 2) and (InOutRes <> 0) then
  837. { Under EMX 0.9d DOS this routine may sometime }
  838. { fail or crash the system. }
  839. DosDir ($3B, S);
  840. end
  841. else
  842. { Under EMX 0.9d DOS this routine may sometime }
  843. { fail or crash the system. }
  844. DosDir ($3B, S);
  845. end;
  846. {$ASMMODE ATT}
  847. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  848. {Written by Michael Van Canneyt.}
  849. var sof:Pchar;
  850. i:byte;
  851. begin
  852. Dir [4] := #0;
  853. { Used in case the specified drive isn't available }
  854. sof:=pchar(@dir[4]);
  855. { dir[1..3] will contain '[drivenr]:\', but is not }
  856. { supplied by DOS, so we let dos string start at }
  857. { dir[4] }
  858. { Get dir from drivenr : 0=default, 1=A etc... }
  859. asm
  860. movb drivenr,%dl
  861. movl sof,%esi
  862. mov $0x47,%ah
  863. call syscall
  864. jnc .LGetDir
  865. movw %ax, InOutRes
  866. .LGetDir:
  867. end;
  868. { Now Dir should be filled with directory in ASCIIZ, }
  869. { starting from dir[4] }
  870. dir[0]:=#3;
  871. dir[2]:=':';
  872. dir[3]:='\';
  873. i:=4;
  874. {Conversion to Pascal string }
  875. while (dir[i]<>#0) do
  876. begin
  877. { convert path name to DOS }
  878. if dir[i]='/' then
  879. dir[i]:='\';
  880. dir[0]:=char(i);
  881. inc(i);
  882. end;
  883. { upcase the string (FPC function) }
  884. if drivenr<>0 then { Drive was supplied. We know it }
  885. dir[1]:=chr(64+drivenr)
  886. else
  887. begin
  888. { We need to get the current drive from DOS function 19H }
  889. { because the drive was the default, which can be unknown }
  890. asm
  891. movb $0x19,%ah
  892. call syscall
  893. addb $65,%al
  894. movb %al,i
  895. end;
  896. dir[1]:=char(i);
  897. end;
  898. if not (FileNameCaseSensitive) then dir:=upcase(dir);
  899. end;
  900. {*****************************************************************************
  901. System unit initialization.
  902. ****************************************************************************}
  903. {****************************************************************************
  904. Error Message writing using messageboxes
  905. ****************************************************************************}
  906. type
  907. TWinMessageBox = function (Parent, Owner: cardinal;
  908. BoxText, BoxTitle: PChar; Identity, Style: cardinal): cardinal; cdecl;
  909. TWinInitialize = function (Options: cardinal): cardinal; cdecl;
  910. TWinCreateMsgQueue = function (Handle: cardinal; cmsg: longint): cardinal;
  911. cdecl;
  912. const
  913. ErrorBufferLength = 1024;
  914. mb_OK = $0000;
  915. mb_Error = $0040;
  916. mb_Moveable = $4000;
  917. MBStyle = mb_OK or mb_Error or mb_Moveable;
  918. WinInitialize: TWinInitialize = nil;
  919. WinCreateMsgQueue: TWinCreateMsgQueue = nil;
  920. WinMessageBox: TWinMessageBox = nil;
  921. EnvSize: cardinal = 0;
  922. var
  923. ErrorBuf: array [0..ErrorBufferLength] of char;
  924. ErrorLen: longint;
  925. PMWinHandle: cardinal;
  926. function ErrorWrite (var F: TextRec): integer;
  927. {
  928. An error message should always end with #13#10#13#10
  929. }
  930. var
  931. P: PChar;
  932. I: longint;
  933. begin
  934. if F.BufPos > 0 then
  935. begin
  936. if F.BufPos + ErrorLen > ErrorBufferLength then
  937. I := ErrorBufferLength - ErrorLen
  938. else
  939. I := F.BufPos;
  940. Move (F.BufPtr^, ErrorBuf [ErrorLen], I);
  941. Inc (ErrorLen, I);
  942. ErrorBuf [ErrorLen] := #0;
  943. end;
  944. if ErrorLen > 3 then
  945. begin
  946. P := @ErrorBuf [ErrorLen];
  947. for I := 1 to 4 do
  948. begin
  949. Dec (P);
  950. if not (P^ in [#10, #13]) then
  951. break;
  952. end;
  953. end;
  954. if ErrorLen = ErrorBufferLength then
  955. I := 4;
  956. if (I = 4) then
  957. begin
  958. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  959. ErrorLen := 0;
  960. end;
  961. F.BufPos := 0;
  962. ErrorWrite := 0;
  963. end;
  964. function ErrorClose (var F: TextRec): integer;
  965. begin
  966. if ErrorLen > 0 then
  967. begin
  968. WinMessageBox (0, 0, @ErrorBuf, PChar ('Error'), 0, MBStyle);
  969. ErrorLen := 0;
  970. end;
  971. ErrorLen := 0;
  972. ErrorClose := 0;
  973. end;
  974. function ErrorOpen (var F: TextRec): integer;
  975. begin
  976. TextRec(F).InOutFunc := @ErrorWrite;
  977. TextRec(F).FlushFunc := @ErrorWrite;
  978. TextRec(F).CloseFunc := @ErrorClose;
  979. ErrorOpen := 0;
  980. end;
  981. procedure AssignError (var T: Text);
  982. begin
  983. Assign (T, '');
  984. TextRec (T).OpenFunc := @ErrorOpen;
  985. Rewrite (T);
  986. end;
  987. procedure DosEnvInit;
  988. var
  989. Q: PPChar;
  990. I: cardinal;
  991. begin
  992. (* It's a hack, in fact - DOS stores the environment the same way as OS/2 does,
  993. but I don't know how to find Program Segment Prefix and thus the environment
  994. address under EMX, so I'm recreating this structure using EnvP pointer. *)
  995. {$ASMMODE INTEL}
  996. asm
  997. cld
  998. mov ecx, EnvC
  999. mov esi, EnvP
  1000. xor eax, eax
  1001. xor edx, edx
  1002. @L1:
  1003. xchg eax, edx
  1004. push ecx
  1005. mov ecx, -1
  1006. mov edi, [esi]
  1007. repne
  1008. scasb
  1009. neg ecx
  1010. dec ecx
  1011. xchg eax, edx
  1012. add eax, ecx
  1013. pop ecx
  1014. dec ecx
  1015. jecxz @Stop
  1016. inc esi
  1017. inc esi
  1018. inc esi
  1019. inc esi
  1020. jmp @L1
  1021. @Stop:
  1022. inc eax
  1023. mov EnvSize, eax
  1024. end;
  1025. Environment := GetMem (EnvSize);
  1026. asm
  1027. cld
  1028. mov ecx, EnvC
  1029. mov edx, EnvP
  1030. mov edi, Environment
  1031. @L2:
  1032. mov esi, [edx]
  1033. @Copying:
  1034. lodsb
  1035. stosb
  1036. or al, al
  1037. jnz @Copying
  1038. dec ecx
  1039. jecxz @Stop2
  1040. inc edx
  1041. inc edx
  1042. inc edx
  1043. inc edx
  1044. jmp @L2
  1045. @Stop2:
  1046. stosb
  1047. end;
  1048. end;
  1049. procedure SysInitStdIO;
  1050. begin
  1051. { Setup stdin, stdout and stderr, for GUI apps redirect stderr,stdout to be
  1052. displayed in a messagebox }
  1053. (*
  1054. StdInputHandle := longint(GetStdHandle(cardinal(STD_INPUT_HANDLE)));
  1055. StdOutputHandle := longint(GetStdHandle(cardinal(STD_OUTPUT_HANDLE)));
  1056. StdErrorHandle := longint(GetStdHandle(cardinal(STD_ERROR_HANDLE)));
  1057. if not IsConsole then
  1058. begin
  1059. if (DosLoadModule (nil, 0, 'PMWIN', PMWinHandle) = 0) and
  1060. (DosQueryProcAddr (PMWinHandle, 789, nil, pointer (WinMessageBox)) = 0)
  1061. and
  1062. (DosQueryProcAddr (PMWinHandle, 763, nil, pointer (WinInitialize)) = 0)
  1063. and
  1064. (DosQueryProcAddr (PMWinHandle, 716, nil, pointer (WinCreateMsgQueue))
  1065. = 0)
  1066. then
  1067. begin
  1068. WinInitialize (0);
  1069. WinCreateMsgQueue (0, 0);
  1070. end
  1071. else
  1072. HandleError (2);
  1073. AssignError (StdErr);
  1074. AssignError (StdOut);
  1075. Assign (Output, '');
  1076. Assign (Input, '');
  1077. end
  1078. else
  1079. begin
  1080. *)
  1081. OpenStdIO (Input, fmInput, StdInputHandle);
  1082. OpenStdIO (Output, fmOutput, StdOutputHandle);
  1083. OpenStdIO (StdOut, fmOutput, StdOutputHandle);
  1084. OpenStdIO (StdErr, fmOutput, StdErrorHandle);
  1085. (*
  1086. end;
  1087. *)
  1088. end;
  1089. function GetFileHandleCount: longint;
  1090. var L1, L2: longint;
  1091. begin
  1092. L1 := 0; (* Don't change the amount, just check. *)
  1093. if DosSetRelMaxFH (L1, L2) <> 0 then GetFileHandleCount := 50
  1094. else GetFileHandleCount := L2;
  1095. end;
  1096. var TIB: PThreadInfoBlock;
  1097. PIB: PProcessInfoBlock;
  1098. begin
  1099. IsLibrary := FALSE;
  1100. {Determine the operating system we are running on.}
  1101. {$ASMMODE INTEL}
  1102. asm
  1103. mov os_mode, 0
  1104. mov eax, 7F0Ah
  1105. call syscall
  1106. test bx, 512 {Bit 9 is OS/2 flag.}
  1107. setne byte ptr os_mode
  1108. test bx, 4096
  1109. jz @noRSX
  1110. mov os_mode, 2
  1111. @noRSX:
  1112. {Enable the brk area by initializing it with the initial heap size.}
  1113. mov eax, 7F01h
  1114. mov edx, heap_brk
  1115. add edx, heap_base
  1116. call syscall
  1117. cmp eax, -1
  1118. jnz @heapok
  1119. push dword 204
  1120. call HandleError
  1121. @heapok:
  1122. {$IFDEF CONTHEAP}
  1123. { Find out brk limit }
  1124. mov eax, 7F02h
  1125. mov ecx, 3
  1126. call syscall
  1127. jcxz @heaplimitknown
  1128. mov eax, 0
  1129. @heaplimitknown:
  1130. mov BrkLimit, eax
  1131. {$ELSE CONTHEAP}
  1132. { Change sbrk behaviour to allocate arbitrary (non-contiguous) memory blocks }
  1133. mov eax, 7F0Fh
  1134. mov ecx, 0Ch
  1135. mov edx, 8
  1136. call syscall
  1137. {$ENDIF CONTHEAP}
  1138. end;
  1139. { in OS/2 this will always be nil, but in DOS mode }
  1140. { this can be changed. }
  1141. first_meg := nil;
  1142. {Now request, if we are running under DOS,
  1143. read-access to the first meg. of memory.}
  1144. if os_mode in [osDOS,osDPMI] then
  1145. asm
  1146. mov eax, 7F13h
  1147. xor ebx, ebx
  1148. mov ecx, 0FFFh
  1149. xor edx, edx
  1150. call syscall
  1151. jc @endmem
  1152. mov first_meg, eax
  1153. @endmem:
  1154. end
  1155. else
  1156. begin
  1157. (* Initialize the amount of file handles *)
  1158. FileHandleCount := GetFileHandleCount;
  1159. end;
  1160. {At 0.9.2, case for enumeration does not work.}
  1161. case os_mode of
  1162. osDOS:
  1163. begin
  1164. stackbottom:=cardinal(heap_brk); {In DOS mode, heap_brk is
  1165. also the stack bottom.}
  1166. ApplicationType := 1; (* Running under DOS. *)
  1167. IsConsole := true;
  1168. DosEnvInit;
  1169. end;
  1170. osOS2:
  1171. begin
  1172. DosGetInfoBlocks (@TIB, @PIB);
  1173. StackBottom := cardinal (TIB^.Stack);
  1174. Environment := pointer (PIB^.Env);
  1175. ApplicationType := PIB^.ProcType;
  1176. IsConsole := ApplicationType <> 3;
  1177. end;
  1178. osDPMI:
  1179. begin
  1180. stackbottom:=0; {Not sure how to get it, but seems to be
  1181. always zero.}
  1182. ApplicationType := 1; (* Running under DOS. *)
  1183. IsConsole := true;
  1184. DosEnvInit;
  1185. end;
  1186. end;
  1187. exitproc:=nil;
  1188. {Initialize the heap.}
  1189. initheap;
  1190. { ... and exceptions }
  1191. SysInitExceptions;
  1192. { ... and I/O }
  1193. SysInitStdIO;
  1194. { no I/O-Error }
  1195. inoutres:=0;
  1196. {$ifdef HASVARIANT}
  1197. initvariantmanager;
  1198. {$endif HASVARIANT}
  1199. {$IFDEF DUMPGROW}
  1200. {$IFDEF CONTHEAP}
  1201. WriteLn ('Initial brk size is ', GetHeapSize);
  1202. WriteLn ('Brk limit is ', BrkLimit);
  1203. {$ENDIF CONTHEAP}
  1204. {$ENDIF DUMPGROW}
  1205. end.
  1206. {
  1207. $Log$
  1208. Revision 1.34 2003-09-29 18:39:59 hajny
  1209. * append fix applied to GO32v2, OS/2 and EMX
  1210. Revision 1.33 2003/09/27 11:52:36 peter
  1211. * sbrk returns pointer
  1212. Revision 1.32 2003/03/30 09:20:30 hajny
  1213. * platform extension unification
  1214. Revision 1.31 2003/01/15 22:16:12 hajny
  1215. * default sharing mode changed to DenyNone
  1216. Revision 1.30 2002/12/15 22:41:41 hajny
  1217. * First_Meg fixed + Environment initialization under Dos
  1218. Revision 1.29 2002/12/08 16:39:58 hajny
  1219. - WriteLn in GUI mode support commented out until fixed
  1220. Revision 1.28 2002/12/07 19:17:14 hajny
  1221. * GetEnv correction, better PM support, ...
  1222. Revision 1.27 2002/11/17 22:31:02 hajny
  1223. * type corrections (longint x cardinal)
  1224. Revision 1.26 2002/10/27 14:29:00 hajny
  1225. * heap management (hopefully) fixed
  1226. Revision 1.25 2002/10/14 19:39:17 peter
  1227. * threads unit added for thread support
  1228. Revision 1.24 2002/10/13 09:28:45 florian
  1229. + call to initvariantmanager inserted
  1230. Revision 1.23 2002/09/07 16:01:25 peter
  1231. * old logs removed and tabs fixed
  1232. Revision 1.22 2002/07/01 16:29:05 peter
  1233. * sLineBreak changed to normal constant like Kylix
  1234. Revision 1.21 2002/04/21 15:54:20 carl
  1235. + initialize some global variables
  1236. Revision 1.20 2002/04/12 17:42:16 carl
  1237. + generic stack checking
  1238. Revision 1.19 2002/03/11 19:10:33 peter
  1239. * Regenerated with updated fpcmake
  1240. Revision 1.18 2002/02/10 13:46:20 hajny
  1241. * heap management corrected (heap_brk)
  1242. }