sysutils.pp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for EMX
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. Dos;
  20. {$DEFINE HAS_SLEEP}
  21. { Include platform independent interface part }
  22. {$i sysutilh.inc}
  23. implementation
  24. uses
  25. sysconst;
  26. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  27. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  28. { Include platform independent implementation part }
  29. {$i sysutils.inc}
  30. {****************************************************************************
  31. System (imported) calls
  32. ****************************************************************************}
  33. (* "uses DosCalls" could not be used here due to type *)
  34. (* conflicts, so needed parts had to be redefined here). *)
  35. type
  36. TFileStatus = object
  37. end;
  38. PFileStatus = ^TFileStatus;
  39. TFileStatus3 = object (TFileStatus)
  40. DateCreation, {Date of file creation.}
  41. TimeCreation, {Time of file creation.}
  42. DateLastAccess, {Date of last access to file.}
  43. TimeLastAccess, {Time of last access to file.}
  44. DateLastWrite, {Date of last modification of file.}
  45. TimeLastWrite:word; {Time of last modification of file.}
  46. FileSize, {Size of file.}
  47. FileAlloc:cardinal; {Amount of space the file really
  48. occupies on disk.}
  49. AttrFile:cardinal; {Attributes of file.}
  50. end;
  51. PFileStatus3=^TFileStatus3;
  52. TFileStatus4=object(TFileStatus3)
  53. cbList:cardinal; {Length of entire EA set.}
  54. end;
  55. PFileStatus4=^TFileStatus4;
  56. TFileFindBuf3=object(TFileStatus)
  57. NextEntryOffset: cardinal; {Offset of next entry}
  58. DateCreation, {Date of file creation.}
  59. TimeCreation, {Time of file creation.}
  60. DateLastAccess, {Date of last access to file.}
  61. TimeLastAccess, {Time of last access to file.}
  62. DateLastWrite, {Date of last modification of file.}
  63. TimeLastWrite:word; {Time of last modification of file.}
  64. FileSize, {Size of file.}
  65. FileAlloc:cardinal; {Amount of space the file really
  66. occupies on disk.}
  67. AttrFile:cardinal; {Attributes of file.}
  68. Name:shortstring; {Also possible to use as ASCIIZ.
  69. The byte following the last string
  70. character is always zero.}
  71. end;
  72. PFileFindBuf3=^TFileFindBuf3;
  73. TFileFindBuf4=object(TFileStatus)
  74. NextEntryOffset: cardinal; {Offset of next entry}
  75. DateCreation, {Date of file creation.}
  76. TimeCreation, {Time of file creation.}
  77. DateLastAccess, {Date of last access to file.}
  78. TimeLastAccess, {Time of last access to file.}
  79. DateLastWrite, {Date of last modification of file.}
  80. TimeLastWrite:word; {Time of last modification of file.}
  81. FileSize, {Size of file.}
  82. FileAlloc:cardinal; {Amount of space the file really
  83. occupies on disk.}
  84. AttrFile:cardinal; {Attributes of file.}
  85. cbList:longint; {Size of the file's extended attributes.}
  86. Name:shortstring; {Also possible to use as ASCIIZ.
  87. The byte following the last string
  88. character is always zero.}
  89. end;
  90. PFileFindBuf4=^TFileFindBuf4;
  91. TFSInfo = record
  92. case word of
  93. 1:
  94. (File_Sys_ID,
  95. Sectors_Per_Cluster,
  96. Total_Clusters,
  97. Free_Clusters: cardinal;
  98. Bytes_Per_Sector: word);
  99. 2: {For date/time description,
  100. see file searching realted
  101. routines.}
  102. (Label_Date, {Date when volume label was created.}
  103. Label_Time: word; {Time when volume label was created.}
  104. VolumeLabel: ShortString); {Volume label. Can also be used
  105. as ASCIIZ, because the byte
  106. following the last character of
  107. the string is always zero.}
  108. end;
  109. PFSInfo = ^TFSInfo;
  110. TCountryCode=record
  111. Country, {Country to query info about (0=current).}
  112. CodePage: cardinal; {Code page to query info about (0=current).}
  113. end;
  114. PCountryCode=^TCountryCode;
  115. TTimeFmt = (Clock12, Clock24);
  116. TCountryInfo=record
  117. Country, CodePage: cardinal; {Country and codepage requested.}
  118. case byte of
  119. 0:
  120. (DateFormat: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  121. CurrencyUnit: array [0..4] of char;
  122. ThousandSeparator: char; {Thousands separator.}
  123. Zero1: byte; {Always zero.}
  124. DecimalSeparator: char; {Decimals separator,}
  125. Zero2: byte;
  126. DateSeparator: char; {Date separator.}
  127. Zero3: byte;
  128. TimeSeparator: char; {Time separator.}
  129. Zero4: byte;
  130. CurrencyFormat, {Bit field:
  131. Bit 0: 0=indicator before value
  132. 1=indicator after value
  133. Bit 1: 1=insert space after
  134. indicator.
  135. Bit 2: 1=Ignore bit 0&1, replace
  136. decimal separator with
  137. indicator.}
  138. DecimalPlace: byte; {Number of decimal places used in
  139. currency indication.}
  140. TimeFormat: TTimeFmt; {12/24 hour.}
  141. Reserve1: array [0..1] of word;
  142. DataSeparator: char; {Data list separator}
  143. Zero5: byte;
  144. Reserve2: array [0..4] of word);
  145. 1:
  146. (fsDateFmt: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  147. szCurrency: array [0..4] of char;
  148. {null terminated currency symbol}
  149. szThousandsSeparator: array [0..1] of char;
  150. {Thousands separator + #0}
  151. szDecimal: array [0..1] of char;
  152. {Decimals separator + #0}
  153. szDateSeparator: array [0..1] of char;
  154. {Date separator + #0}
  155. szTimeSeparator: array [0..1] of char;
  156. {Time separator + #0}
  157. fsCurrencyFmt, {Bit field:
  158. Bit 0: 0=indicator before value
  159. 1=indicator after value
  160. Bit 1: 1=insert space after
  161. indicator.
  162. Bit 2: 1=Ignore bit 0&1, replace
  163. decimal separator with
  164. indicator}
  165. cDecimalPlace: byte; {Number of decimal places used in
  166. currency indication}
  167. fsTimeFmt: byte; {0=12,1=24 hours}
  168. abReserved1: array [0..1] of word;
  169. szDataSeparator: array [0..1] of char;
  170. {Data list separator + #0}
  171. abReserved2: array [0..4] of word);
  172. end;
  173. PCountryInfo=^TCountryInfo;
  174. TRequestData=record
  175. PID, {ID of process that wrote element.}
  176. Data: cardinal; {Information from process writing the data.}
  177. end;
  178. PRequestData=^TRequestData;
  179. {Queue data structure for synchronously started sessions.}
  180. TChildInfo = record
  181. case boolean of
  182. false:
  183. (SessionID,
  184. Return: word); {Return code from the child process.}
  185. true:
  186. (usSessionID,
  187. usReturn: word); {Return code from the child process.}
  188. end;
  189. PChildInfo = ^TChildInfo;
  190. TStartData=record
  191. {Note: to omit some fields, use a length smaller than SizeOf(TStartData).}
  192. Length:word; {Length, in bytes, of datastructure
  193. (24/30/32/50/60).}
  194. Related:word; {Independent/child session (0/1).}
  195. FgBg:word; {Foreground/background (0/1).}
  196. TraceOpt:word; {No trace/trace this/trace all (0/1/2).}
  197. PgmTitle:PChar; {Program title.}
  198. PgmName:PChar; {Filename to program.}
  199. PgmInputs:PChar; {Command parameters (nil allowed).}
  200. TermQ:PChar; {System queue. (nil allowed).}
  201. Environment:PChar; {Environment to pass (nil allowed).}
  202. InheritOpt:word; {Inherit environment from shell/
  203. inherit environment from parent (0/1).}
  204. SessionType:word; {Auto/full screen/window/presentation
  205. manager/full screen Dos/windowed Dos
  206. (0/1/2/3/4/5/6/7).}
  207. Iconfile:PChar; {Icon file to use (nil allowed).}
  208. PgmHandle:cardinal; {0 or the program handle.}
  209. PgmControl:word; {Bitfield describing initial state
  210. of windowed sessions.}
  211. InitXPos,InitYPos:word; {Initial top coordinates.}
  212. InitXSize,InitYSize:word; {Initial size.}
  213. Reserved:word;
  214. ObjectBuffer:PChar; {If a module cannot be loaded, its
  215. name will be returned here.}
  216. ObjectBuffLen:cardinal; {Size of your buffer.}
  217. end;
  218. PStartData=^TStartData;
  219. const
  220. ilStandard = 1;
  221. ilQueryEAsize = 2;
  222. ilQueryEAs = 3;
  223. ilQueryFullName = 5;
  224. quFIFO = 0;
  225. quLIFO = 1;
  226. quPriority = 2;
  227. quNoConvert_Address = 0;
  228. quConvert_Address = 4;
  229. {Start the new session independent or as a child.}
  230. ssf_Related_Independent = 0; {Start new session independent
  231. of the calling session.}
  232. ssf_Related_Child = 1; {Start new session as a child
  233. session to the calling session.}
  234. {Start the new session in the foreground or in the background.}
  235. ssf_FgBg_Fore = 0; {Start new session in foreground.}
  236. ssf_FgBg_Back = 1; {Start new session in background.}
  237. {Should the program started in the new session
  238. be executed under conditions for tracing?}
  239. ssf_TraceOpt_None = 0; {No trace.}
  240. ssf_TraceOpt_Trace = 1; {Trace with no notification
  241. of descendants.}
  242. ssf_TraceOpt_TraceAll = 2; {Trace all descendant sessions.
  243. A termination queue must be
  244. supplied and Related must be
  245. ssf_Related_Child (=1).}
  246. {Will the new session inherit open file handles
  247. and environment from the calling process.}
  248. ssf_InhertOpt_Shell = 0; {Inherit from the shell.}
  249. ssf_InhertOpt_Parent = 1; {Inherit from the calling process.}
  250. {Specifies the type of session to start.}
  251. ssf_Type_Default = 0; {Use program's type.}
  252. ssf_Type_FullScreen = 1; {OS/2 full screen.}
  253. ssf_Type_WindowableVIO = 2; {OS/2 window.}
  254. ssf_Type_PM = 3; {Presentation Manager.}
  255. ssf_Type_VDM = 4; {DOS full screen.}
  256. ssf_Type_WindowedVDM = 7; {DOS window.}
  257. {Additional values for Windows programs}
  258. Prog_31_StdSeamlessVDM = 15; {Windows 3.1 program in its
  259. own windowed session.}
  260. Prog_31_StdSeamlessCommon = 16; {Windows 3.1 program in a
  261. common windowed session.}
  262. Prog_31_EnhSeamlessVDM = 17; {Windows 3.1 program in enhanced
  263. compatibility mode in its own
  264. windowed session.}
  265. Prog_31_EnhSeamlessCommon = 18; {Windows 3.1 program in enhanced
  266. compatibility mode in a common
  267. windowed session.}
  268. Prog_31_Enh = 19; {Windows 3.1 program in enhanced
  269. compatibility mode in a full
  270. screen session.}
  271. Prog_31_Std = 20; {Windows 3.1 program in a full
  272. screen session.}
  273. {Specifies the initial attributes for a OS/2 window or DOS window session.}
  274. ssf_Control_Visible = 0; {Window is visible.}
  275. ssf_Control_Invisible = 1; {Window is invisible.}
  276. ssf_Control_Maximize = 2; {Window is maximized.}
  277. ssf_Control_Minimize = 4; {Window is minimized.}
  278. ssf_Control_NoAutoClose = 8; {Window will not close after
  279. the program has ended.}
  280. ssf_Control_SetPos = 32768; {Use InitXPos, InitYPos,
  281. InitXSize, and InitYSize for
  282. the size and placement.}
  283. {This is the correct way to call external assembler procedures.}
  284. procedure syscall;external name '___SYSCALL';
  285. function DosSetFileInfo (Handle: THandle; InfoLevel: cardinal; AFileStatus: PFileStatus;
  286. FileStatusLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 218;
  287. function DosQueryFSInfo (DiskNum, InfoLevel: cardinal; var Buffer: TFSInfo;
  288. BufLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 278;
  289. function DosQueryFileInfo (Handle: THandle; InfoLevel: cardinal;
  290. AFileStatus: PFileStatus; FileStatusLen: cardinal): cardinal; cdecl;
  291. external 'DOSCALLS' index 279;
  292. function DosScanEnv (Name: PChar; var Value: PChar): cardinal; cdecl;
  293. external 'DOSCALLS' index 227;
  294. function DosFindFirst (FileMask: PChar; var Handle: THandle; Attrib: cardinal;
  295. AFileStatus: PFileStatus; FileStatusLen: cardinal;
  296. var Count: cardinal; InfoLevel: cardinal): cardinal; cdecl;
  297. external 'DOSCALLS' index 264;
  298. function DosFindNext (Handle: THandle; AFileStatus: PFileStatus;
  299. FileStatusLen: cardinal; var Count: cardinal): cardinal; cdecl;
  300. external 'DOSCALLS' index 265;
  301. function DosFindClose (Handle: THandle): cardinal; cdecl;
  302. external 'DOSCALLS' index 263;
  303. function DosQueryCtryInfo (Size: cardinal; var Country: TCountryCode;
  304. var Res: TCountryInfo; var ActualSize: cardinal): cardinal; cdecl;
  305. external 'NLS' index 5;
  306. function DosMapCase (Size: cardinal; var Country: TCountryCode;
  307. AString: PChar): cardinal; cdecl; external 'NLS' index 7;
  308. procedure DosSleep (MSec: cardinal); cdecl; external 'DOSCALLS' index 229;
  309. function DosCreateQueue (var Handle: THandle; Priority:longint;
  310. Name: PChar): cardinal; cdecl;
  311. external 'QUECALLS' index 16;
  312. function DosReadQueue (Handle: THandle; var ReqBuffer: TRequestData;
  313. var DataLen: cardinal; var DataPtr: pointer;
  314. Element, Wait: cardinal; var Priority: byte;
  315. ASem: THandle): cardinal; cdecl;
  316. external 'QUECALLS' index 9;
  317. function DosCloseQueue (Handle: THandle): cardinal; cdecl;
  318. external 'QUECALLS' index 11;
  319. function DosStartSession (var AStartData: TStartData;
  320. var SesID, PID: cardinal): cardinal; cdecl;
  321. external 'SESMGR' index 37;
  322. function DosFreeMem(P:pointer):cardinal; cdecl; external 'DOSCALLS' index 304;
  323. {****************************************************************************
  324. File Functions
  325. ****************************************************************************}
  326. const
  327. ofRead = $0000; {Open for reading}
  328. ofWrite = $0001; {Open for writing}
  329. ofReadWrite = $0002; {Open for reading/writing}
  330. doDenyRW = $0010; {DenyAll (no sharing)}
  331. faCreateNew = $00010000; {Create if file does not exist}
  332. faOpenReplace = $00040000; {Truncate if file exists}
  333. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  334. FindResvdMask = $00003737; {Allowed bits in attribute
  335. specification for DosFindFirst call.}
  336. {$ASMMODE INTEL}
  337. function FileOpen (const FileName: string; Mode: integer): longint; assembler;
  338. asm
  339. push ebx
  340. {$IFDEF REGCALL}
  341. mov ecx, edx
  342. mov edx, eax
  343. {$ELSE REGCALL}
  344. mov ecx, Mode
  345. mov edx, FileName
  346. {$ENDIF REGCALL}
  347. (* DenyNone if sharing not specified. *)
  348. mov eax, ecx
  349. xor eax, 112
  350. jz @FOpenDefSharing
  351. cmp eax, 64
  352. jbe FOpen1
  353. @FOpenDefSharing:
  354. or ecx, 64
  355. @FOpen1:
  356. mov eax, 7F2Bh
  357. call syscall
  358. (* syscall __open() returns -1 in case of error, i.e. exactly what we need *)
  359. pop ebx
  360. end {['eax', 'ebx', 'ecx', 'edx']};
  361. function FileCreate (const FileName: string): longint;
  362. begin
  363. FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW, 777);
  364. (* Sharing to DenyAll *)
  365. end;
  366. function FileCreate (const FileName: string; Rights: integer): longint;
  367. begin
  368. FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW,
  369. Rights); (* Sharing to DenyAll *)
  370. end;
  371. function FileCreate (const FileName: string; ShareMode: integer; Rights: integer): longint; assembler;
  372. asm
  373. push ebx
  374. {$IFDEF REGCALL}
  375. mov ecx, edx
  376. mov edx, eax
  377. {$ELSE REGCALL}
  378. mov ecx, ShareMode
  379. mov edx, FileName
  380. {$ENDIF REGCALL}
  381. and ecx, 112
  382. or ecx, ecx
  383. jz @FCDefSharing
  384. cmp ecx, 64
  385. jbe @FCSharingOK
  386. @FCDefSharing:
  387. mov ecx, doDenyRW (* Sharing to DenyAll *)
  388. @FCSharingOK:
  389. or ecx, ofReadWrite or faCreate
  390. mov eax, 7F2Bh
  391. call syscall
  392. pop ebx
  393. end {['eax', 'ebx', 'ecx', 'edx']};
  394. function FileRead (Handle: longint; Out Buffer; Count: longint): longint;
  395. assembler;
  396. asm
  397. push ebx
  398. {$IFDEF REGCALL}
  399. mov ebx, eax
  400. {$ELSE REGCALL}
  401. mov ebx, Handle
  402. mov ecx, Count
  403. mov edx, Buffer
  404. {$ENDIF REGCALL}
  405. mov eax, 3F00h
  406. call syscall
  407. jnc @FReadEnd
  408. mov eax, -1
  409. @FReadEnd:
  410. pop ebx
  411. end {['eax', 'ebx', 'ecx', 'edx']};
  412. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  413. assembler;
  414. asm
  415. push ebx
  416. {$IFDEF REGCALL}
  417. mov ebx, eax
  418. {$ELSE REGCALL}
  419. mov ebx, Handle
  420. mov ecx, Count
  421. mov edx, Buffer
  422. {$ENDIF REGCALL}
  423. mov eax, 4000h
  424. call syscall
  425. jnc @FWriteEnd
  426. mov eax, -1
  427. @FWriteEnd:
  428. pop ebx
  429. end {['eax', 'ebx', 'ecx', 'edx']};
  430. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  431. asm
  432. push ebx
  433. {$IFDEF REGCALL}
  434. mov ebx, eax
  435. mov eax, ecx
  436. {$ELSE REGCALL}
  437. mov ebx, Handle
  438. mov eax, Origin
  439. mov edx, FOffset
  440. {$ENDIF REGCALL}
  441. mov ah, 42h
  442. call syscall
  443. jnc @FSeekEnd
  444. mov eax, -1
  445. @FSeekEnd:
  446. pop ebx
  447. end {['eax', 'ebx', 'edx']};
  448. function FileSeek (Handle: longint; FOffset: Int64; Origin: longint): Int64;
  449. begin
  450. {$warning need to add 64bit call }
  451. Result:=FileSeek(Handle,Longint(Foffset),Longint(Origin));
  452. end;
  453. procedure FileClose (Handle: longint);
  454. begin
  455. if (Handle > 4) or ((os_mode = osOS2) and (Handle > 2)) then
  456. asm
  457. push ebx
  458. mov eax, 3E00h
  459. mov ebx, Handle
  460. call syscall
  461. pop ebx
  462. end ['eax'];
  463. end;
  464. function FileTruncate (Handle: THandle; Size: Int64): boolean; assembler;
  465. asm
  466. push ebx
  467. {$IFDEF REGCALL}
  468. mov ebx, eax
  469. {$ELSE REGCALL}
  470. mov ebx, Handle
  471. {$ENDIF REGCALL}
  472. mov edx, dword ptr Size
  473. mov eax, dword ptr Size+4
  474. or eax, eax
  475. mov eax, 0
  476. jz @FTruncEnd (* file sizes > 4 GB not supported with EMX *)
  477. mov eax, 7F25h
  478. push ebx
  479. call syscall
  480. pop ebx
  481. jc @FTruncEnd
  482. mov eax, 4202h
  483. mov edx, 0
  484. call syscall
  485. mov eax, 0
  486. jnc @FTruncEnd
  487. dec eax
  488. @FTruncEnd:
  489. pop ebx
  490. end {['eax', 'ebx', 'ecx', 'edx']};
  491. function FileAge (const FileName: string): longint;
  492. var Handle: longint;
  493. begin
  494. Handle := FileOpen (FileName, 0);
  495. if Handle <> -1 then
  496. begin
  497. Result := FileGetDate (Handle);
  498. FileClose (Handle);
  499. end
  500. else
  501. Result := -1;
  502. end;
  503. function FileExists (const FileName: string): boolean;
  504. begin
  505. if Directory = '' then
  506. Result := false
  507. else
  508. Result := FileGetAttr (ExpandFileName (Directory)) and
  509. faDirectory = faDirectory;
  510. end;
  511. type TRec = record
  512. T, D: word;
  513. end;
  514. PSearchRec = ^SearchRec;
  515. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  516. var SR: PSearchRec;
  517. FStat: PFileFindBuf3;
  518. Count: cardinal;
  519. Err: cardinal;
  520. begin
  521. if os_mode = osOS2 then
  522. begin
  523. New (FStat);
  524. Rslt.FindHandle := THandle ($FFFFFFFF);
  525. Count := 1;
  526. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  527. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count,
  528. ilStandard);
  529. if (Err = 0) and (Count = 0) then Err := 18;
  530. FindFirst := -Err;
  531. if Err = 0 then
  532. begin
  533. Rslt.Name := FStat^.Name;
  534. Rslt.Size := FStat^.FileSize;
  535. Rslt.Attr := FStat^.AttrFile;
  536. Rslt.ExcludeAttr := 0;
  537. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  538. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  539. end;
  540. Dispose (FStat);
  541. end
  542. else
  543. begin
  544. Err := DOS.DosError;
  545. GetMem (SR, SizeOf (SearchRec));
  546. Rslt.FindHandle := longint(SR);
  547. DOS.FindFirst (Path, Attr, SR^);
  548. FindFirst := -DOS.DosError;
  549. if DosError = 0 then
  550. begin
  551. Rslt.Time := SR^.Time;
  552. Rslt.Size := SR^.Size;
  553. Rslt.Attr := SR^.Attr;
  554. Rslt.ExcludeAttr := 0;
  555. Rslt.Name := SR^.Name;
  556. end;
  557. DOS.DosError := Err;
  558. end;
  559. end;
  560. function FindNext (var Rslt: TSearchRec): longint;
  561. var SR: PSearchRec;
  562. FStat: PFileFindBuf3;
  563. Count: cardinal;
  564. Err: cardinal;
  565. begin
  566. if os_mode = osOS2 then
  567. begin
  568. New (FStat);
  569. Count := 1;
  570. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^),
  571. Count);
  572. if (Err = 0) and (Count = 0) then Err := 18;
  573. FindNext := -Err;
  574. if Err = 0 then
  575. begin
  576. Rslt.Name := FStat^.Name;
  577. Rslt.Size := FStat^.FileSize;
  578. Rslt.Attr := FStat^.AttrFile;
  579. Rslt.ExcludeAttr := 0;
  580. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  581. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  582. end;
  583. Dispose (FStat);
  584. end
  585. else
  586. begin
  587. SR := PSearchRec (Rslt.FindHandle);
  588. if SR <> nil then
  589. begin
  590. DOS.FindNext (SR^);
  591. FindNext := -DosError;
  592. if DosError = 0 then
  593. begin
  594. Rslt.Time := SR^.Time;
  595. Rslt.Size := SR^.Size;
  596. Rslt.Attr := SR^.Attr;
  597. Rslt.ExcludeAttr := 0;
  598. Rslt.Name := SR^.Name;
  599. end;
  600. end;
  601. end;
  602. end;
  603. procedure FindClose (var F: TSearchrec);
  604. var SR: PSearchRec;
  605. begin
  606. if os_mode = osOS2 then
  607. begin
  608. DosFindClose (F.FindHandle);
  609. end
  610. else
  611. begin
  612. SR := PSearchRec (F.FindHandle);
  613. DOS.FindClose (SR^);
  614. FreeMem (SR, SizeOf (SearchRec));
  615. end;
  616. F.FindHandle := 0;
  617. end;
  618. function FileGetDate (Handle: longint): longint; assembler;
  619. asm
  620. push ebx
  621. {$IFDEF REGCALL}
  622. mov ebx, eax
  623. {$ELSE REGCALL}
  624. mov ebx, Handle
  625. {$ENDIF REGCALL}
  626. mov ax, 5700h
  627. call syscall
  628. mov eax, -1
  629. jc @FGetDateEnd
  630. mov ax, dx
  631. shld eax, ecx, 16
  632. @FGetDateEnd:
  633. pop ebx
  634. end {['eax', 'ebx', 'ecx', 'edx']};
  635. function FileSetDate (Handle, Age: longint): longint;
  636. var FStat: PFileStatus3;
  637. RC: cardinal;
  638. begin
  639. if os_mode = osOS2 then
  640. begin
  641. New (FStat);
  642. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  643. SizeOf (FStat^));
  644. if RC <> 0 then
  645. FileSetDate := -1
  646. else
  647. begin
  648. FStat^.DateLastAccess := Hi (Age);
  649. FStat^.DateLastWrite := Hi (Age);
  650. FStat^.TimeLastAccess := Lo (Age);
  651. FStat^.TimeLastWrite := Lo (Age);
  652. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  653. SizeOf (FStat^));
  654. if RC <> 0 then
  655. FileSetDate := -1
  656. else
  657. FileSetDate := 0;
  658. end;
  659. Dispose (FStat);
  660. end
  661. else
  662. asm
  663. push ebx
  664. mov ax, 5701h
  665. mov ebx, Handle
  666. mov cx, word ptr [Age]
  667. mov dx, word ptr [Age + 2]
  668. call syscall
  669. jnc @FSetDateEnd
  670. mov eax, -1
  671. @FSetDateEnd:
  672. mov Result, eax
  673. pop ebx
  674. end ['eax', 'ecx', 'edx'];
  675. end;
  676. function FileGetAttr (const FileName: string): longint; assembler;
  677. asm
  678. {$IFDEF REGCALL}
  679. mov edx, eax
  680. {$ELSE REGCALL}
  681. mov edx, FileName
  682. {$ENDIF REGCALL}
  683. mov ax, 4300h
  684. call syscall
  685. jnc @FGetAttrEnd
  686. mov eax, -1
  687. @FGetAttrEnd:
  688. end {['eax', 'edx']};
  689. function FileSetAttr (const Filename: string; Attr: longint): longint; assembler;
  690. asm
  691. {$IFDEF REGCALL}
  692. mov ecx, edx
  693. mov edx, eax
  694. {$ELSE REGCALL}
  695. mov ecx, Attr
  696. mov edx, FileName
  697. {$ENDIF REGCALL}
  698. mov ax, 4301h
  699. call syscall
  700. mov eax, 0
  701. jnc @FSetAttrEnd
  702. mov eax, -1
  703. @FSetAttrEnd:
  704. end {['eax', 'ecx', 'edx']};
  705. function DeleteFile (const FileName: string): boolean; assembler;
  706. asm
  707. {$IFDEF REGCALL}
  708. mov edx, eax
  709. {$ELSE REGCALL}
  710. mov edx, FileName
  711. {$ENDIF REGCALL}
  712. mov ax, 4100h
  713. call syscall
  714. mov eax, 0
  715. jc @FDeleteEnd
  716. inc eax
  717. @FDeleteEnd:
  718. end {['eax', 'edx']};
  719. function RenameFile (const OldName, NewName: string): boolean; assembler;
  720. asm
  721. push edi
  722. {$IFDEF REGCALL}
  723. mov edx, eax
  724. mov edi, edx
  725. {$ELSE REGCALL}
  726. mov edx, OldName
  727. mov edi, NewName
  728. {$ENDIF REGCALL}
  729. mov ax, 5600h
  730. call syscall
  731. mov eax, 0
  732. jc @FRenameEnd
  733. inc eax
  734. @FRenameEnd:
  735. pop edi
  736. end {['eax', 'edx', 'edi']};
  737. {****************************************************************************
  738. Disk Functions
  739. ****************************************************************************}
  740. {$ASMMODE ATT}
  741. function DiskFree (Drive: byte): int64;
  742. var FI: TFSinfo;
  743. RC: cardinal;
  744. begin
  745. if (os_mode = osDOS) or (os_mode = osDPMI) then
  746. {Function 36 is not supported in OS/2.}
  747. asm
  748. pushl %ebx
  749. movb Drive,%dl
  750. movb $0x36,%ah
  751. call syscall
  752. cmpw $-1,%ax
  753. je .LDISKFREE1
  754. mulw %cx
  755. mulw %bx
  756. shll $16,%edx
  757. movw %ax,%dx
  758. movl $0,%eax
  759. xchgl %edx,%eax
  760. jmp .LDISKFREE2
  761. .LDISKFREE1:
  762. cltd
  763. .LDISKFREE2:
  764. popl %ebx
  765. leave
  766. ret
  767. end
  768. else
  769. {In OS/2, we use the filesystem information.}
  770. begin
  771. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  772. if RC = 0 then
  773. DiskFree := int64 (FI.Free_Clusters) *
  774. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  775. else
  776. DiskFree := -1;
  777. end;
  778. end;
  779. function DiskSize (Drive: byte): int64;
  780. var FI: TFSinfo;
  781. RC: cardinal;
  782. begin
  783. if (os_mode = osDOS) or (os_mode = osDPMI) then
  784. {Function 36 is not supported in OS/2.}
  785. asm
  786. pushl %ebx
  787. movb Drive,%dl
  788. movb $0x36,%ah
  789. call syscall
  790. movw %dx,%bx
  791. cmpw $-1,%ax
  792. je .LDISKSIZE1
  793. mulw %cx
  794. mulw %bx
  795. shll $16,%edx
  796. movw %ax,%dx
  797. movl $0,%eax
  798. xchgl %edx,%eax
  799. jmp .LDISKSIZE2
  800. .LDISKSIZE1:
  801. cltd
  802. .LDISKSIZE2:
  803. popl %ebx
  804. leave
  805. ret
  806. end
  807. else
  808. {In OS/2, we use the filesystem information.}
  809. begin
  810. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  811. if RC = 0 then
  812. DiskSize := int64 (FI.Total_Clusters) *
  813. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  814. else
  815. DiskSize := -1;
  816. end;
  817. end;
  818. function GetCurrentDir: string;
  819. begin
  820. GetDir (0, Result);
  821. end;
  822. function SetCurrentDir (const NewDir: string): boolean;
  823. begin
  824. {$I-}
  825. ChDir (NewDir);
  826. Result := (IOResult = 0);
  827. {$I+}
  828. end;
  829. function CreateDir (const NewDir: string): boolean;
  830. begin
  831. {$I-}
  832. MkDir (NewDir);
  833. Result := (IOResult = 0);
  834. {$I+}
  835. end;
  836. function RemoveDir (const Dir: string): boolean;
  837. begin
  838. {$I-}
  839. RmDir (Dir);
  840. Result := (IOResult = 0);
  841. {$I+}
  842. end;
  843. function DirectoryExists (const Directory: string): boolean;
  844. var
  845. L: longint;
  846. begin
  847. if Directory = '' then
  848. Result := false
  849. else
  850. begin
  851. if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  852. (Length (Directory) > 1) and
  853. (* Do not remove '\' after ':' (root directory of a drive)
  854. or in '\\' (invalid path, possibly broken UNC path). *)
  855. not (Directory [Length (Directory) - 1] in AllowDriveSeparators + AllowDirectorySeparators) then
  856. L := FileGetAttr (ExpandFileName (Copy (Directory, 1, Length (Directory) - 1)))
  857. else
  858. L := FileGetAttr (ExpandFileName (Directory));
  859. Result := (L > 0) and (L and faDirectory = faDirectory);
  860. end;
  861. end;
  862. {****************************************************************************
  863. Time Functions
  864. ****************************************************************************}
  865. {$ASMMODE INTEL}
  866. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  867. asm
  868. (* Expects the default record alignment (word)!!! *)
  869. push edi
  870. {$IFDEF REGCALL}
  871. push eax
  872. {$ENDIF REGCALL}
  873. mov ah, 2Ah
  874. call syscall
  875. {$IFDEF REGCALL}
  876. pop eax
  877. {$ELSE REGCALL}
  878. mov edi, SystemTime
  879. {$ENDIF REGCALL}
  880. mov ax, cx
  881. stosw
  882. xor eax, eax
  883. mov al, 10
  884. mul dl
  885. shl eax, 16
  886. mov al, dh
  887. stosd
  888. push edi
  889. mov ah, 2Ch
  890. call syscall
  891. pop edi
  892. xor eax, eax
  893. mov al, cl
  894. shl eax, 16
  895. mov al, ch
  896. stosd
  897. mov al, dl
  898. shl eax, 16
  899. mov al, dh
  900. stosd
  901. pop edi
  902. end {['eax', 'ecx', 'edx', 'edi']};
  903. {$asmmode default}
  904. {****************************************************************************
  905. Misc Functions
  906. ****************************************************************************}
  907. procedure Beep;
  908. begin
  909. end;
  910. {****************************************************************************
  911. Locale Functions
  912. ****************************************************************************}
  913. procedure InitAnsi;
  914. var I: byte;
  915. Country: TCountryCode;
  916. begin
  917. for I := 0 to 255 do
  918. UpperCaseTable [I] := Chr (I);
  919. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  920. if os_mode = osOS2 then
  921. begin
  922. FillChar (Country, SizeOf (Country), 0);
  923. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  924. end
  925. else
  926. begin
  927. (* !!! TODO: DOS/DPMI mode support!!! *)
  928. end;
  929. for I := 0 to 255 do
  930. if UpperCaseTable [I] <> Chr (I) then
  931. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  932. end;
  933. procedure InitInternational;
  934. var Country: TCountryCode;
  935. CtryInfo: TCountryInfo;
  936. Size: cardinal;
  937. RC: cardinal;
  938. begin
  939. Size := 0;
  940. FillChar (Country, SizeOf (Country), 0);
  941. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  942. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  943. if RC = 0 then
  944. begin
  945. DateSeparator := CtryInfo.DateSeparator;
  946. case CtryInfo.DateFormat of
  947. 1: begin
  948. ShortDateFormat := 'd/m/y';
  949. LongDateFormat := 'dd" "mmmm" "yyyy';
  950. end;
  951. 2: begin
  952. ShortDateFormat := 'y/m/d';
  953. LongDateFormat := 'yyyy" "mmmm" "dd';
  954. end;
  955. 3: begin
  956. ShortDateFormat := 'm/d/y';
  957. LongDateFormat := 'mmmm" "dd" "yyyy';
  958. end;
  959. end;
  960. TimeSeparator := CtryInfo.TimeSeparator;
  961. DecimalSeparator := CtryInfo.DecimalSeparator;
  962. ThousandSeparator := CtryInfo.ThousandSeparator;
  963. CurrencyFormat := CtryInfo.CurrencyFormat;
  964. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  965. end;
  966. InitAnsi;
  967. InitInternationalGeneric;
  968. end;
  969. function SysErrorMessage(ErrorCode: Integer): String;
  970. begin
  971. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  972. end;
  973. {****************************************************************************
  974. OS Utils
  975. ****************************************************************************}
  976. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  977. begin
  978. GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
  979. end;
  980. Function GetEnvironmentVariableCount : Integer;
  981. begin
  982. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  983. GetEnvironmentVariableCount := EnvC;
  984. end;
  985. Function GetEnvironmentString(Index : Integer) : String;
  986. begin
  987. Result:=FPCGetEnvStrFromP (EnvP, Index);
  988. end;
  989. {$ASMMODE INTEL}
  990. procedure Sleep (Milliseconds: cardinal);
  991. begin
  992. if os_mode = osOS2 then DosSleep (Milliseconds) else
  993. asm
  994. mov edx, Milliseconds
  995. mov eax, 7F30h
  996. call syscall
  997. end ['eax', 'edx'];
  998. end;
  999. {$ASMMODE DEFAULT}
  1000. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  1001. integer;
  1002. var
  1003. HQ: THandle;
  1004. SPID, STID, QName: shortstring;
  1005. SD: TStartData;
  1006. SID, PID: cardinal;
  1007. RD: TRequestData;
  1008. PCI: PChildInfo;
  1009. CISize: cardinal;
  1010. Prio: byte;
  1011. E: EOSError;
  1012. CommandLine: ansistring;
  1013. begin
  1014. if os_Mode = osOS2 then
  1015. begin
  1016. FillChar (SD, SizeOf (SD), 0);
  1017. SD.Length := 24;
  1018. SD.Related := ssf_Related_Child;
  1019. SD.PgmName := PChar (Path);
  1020. SD.PgmInputs := PChar (ComLine);
  1021. Str (GetProcessID, SPID);
  1022. Str (ThreadID, STID);
  1023. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  1024. SD.TermQ := @QName [1];
  1025. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  1026. if Result = 0 then
  1027. begin
  1028. Result := DosStartSession (SD, SID, PID);
  1029. if (Result = 0) or (Result = 457) then
  1030. begin
  1031. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  1032. if Result = 0 then
  1033. begin
  1034. Result := PCI^.Return;
  1035. DosCloseQueue (HQ);
  1036. DosFreeMem (PCI);
  1037. Exit;
  1038. end;
  1039. end;
  1040. DosCloseQueue (HQ);
  1041. end;
  1042. if ComLine = '' then
  1043. CommandLine := Path
  1044. else
  1045. CommandLine := Path + ' ' + ComLine;
  1046. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result]);
  1047. E.ErrorCode := Result;
  1048. raise E;
  1049. end else
  1050. begin
  1051. Dos.Exec (Path, ComLine);
  1052. if DosError <> 0 then
  1053. begin
  1054. if ComLine = '' then
  1055. CommandLine := Path
  1056. else
  1057. CommandLine := Path + ' ' + ComLine;
  1058. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, DosError]);
  1059. E.ErrorCode := DosError;
  1060. raise E;
  1061. end;
  1062. ExecuteProcess := DosExitCode;
  1063. end;
  1064. end;
  1065. function ExecuteProcess (const Path: AnsiString;
  1066. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  1067. var
  1068. CommandLine: AnsiString;
  1069. I: integer;
  1070. begin
  1071. Commandline := '';
  1072. for I := 0 to High (ComLine) do
  1073. if Pos (' ', ComLine [I]) <> 0 then
  1074. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1075. else
  1076. CommandLine := CommandLine + ' ' + Comline [I];
  1077. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  1078. end;
  1079. {****************************************************************************
  1080. Initialization code
  1081. ****************************************************************************}
  1082. Initialization
  1083. InitExceptions; { Initialize exceptions. OS independent }
  1084. InitInternational; { Initialize internationalization settings }
  1085. Finalization
  1086. DoneExceptions;
  1087. end.