dos.pas 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. {****************************************************************************
  2. FPKPascal Runtime-Library
  3. Copyright (c) 1994,97 by
  4. Florian Klaempfl and Michael Spiegel
  5. OS/2 port by Dani‰l Mantione
  6. ****************************************************************************}
  7. {
  8. History:
  9. 2.7.1994: Version 0.2
  10. Datenstrukturen sind deklariert sowie
  11. 50 % der Unterprogramme sind implementiert
  12. 12.8.1994: exec implemented
  13. 14.8.1994: findfirst and findnext implemented
  14. 24.8.1994: Version 0.3
  15. 28.2.1995: Version 0.31
  16. some parameter lists with const optimized
  17. 3.7.1996: bug in fsplit removed (dir and ext were not intializised)
  18. 7.7.1996: packtime and unpacktime implemented
  19. 20.9.1996: Version 0.5
  20. setftime and getftime implemented
  21. some optimizations done (integer -> longint)
  22. procedure fsearch from the LINUX version ported
  23. msdos call implemented
  24. 26th november 1996:
  25. better fexpand
  26. 29th january 1997:
  27. bug in getftime and setftime removed
  28. setfattr and getfattr added
  29. 2th february 1997: Version 0.9
  30. bug of searchrec corrected
  31. 2 june 1997:
  32. OS/2 support added.
  33. 12 june 1997:
  34. OS/2 port done.
  35. 12 November 1997:
  36. Adapted to new DLL stuff.
  37. }
  38. unit dos;
  39. {$I os.inc}
  40. {$I386_DIRECT}
  41. interface
  42. uses
  43. strings;
  44. const
  45. { bit masks for CPU flags}
  46. fcarry = $0001;
  47. fparity = $0004;
  48. fauxiliary = $0010;
  49. fzero = $0040;
  50. fsign = $0080;
  51. foverflow = $0800;
  52. { Bitmasken fuer Dateiattribute }
  53. readonly = $01;
  54. hidden = $02;
  55. sysfile = $04;
  56. volumeid = $08;
  57. directory = $10;
  58. archive = $20;
  59. anyfile = $3F;
  60. fmclosed = $D7B0;
  61. fminput = $D7B1;
  62. fmoutput = $D7B2;
  63. fminout = $D7B3;
  64. type
  65. { some string types }
  66. {$IFDEF OS2}
  67. comstr=string; {Filenames can be long in OS/2.}
  68. pathstr=string;
  69. {$ELSE}
  70. comstr = string[127]; { Kommandozeilenstring }
  71. pathstr = string[79]; { String fuer einen Pfadnamen }
  72. {$ENDIF}
  73. dirstr = string[67]; { String fuer kompletten Pfad }
  74. namestr = string[8]; { Dateinamenstring }
  75. extstr = string[4]; { String fuer Dateinamensuffix }
  76. { search record which is used by findfirst and findnext }
  77. {$PACKRECORDS 1}
  78. searchrec = record
  79. fill : array[1..21] of byte;
  80. attr : byte;
  81. time : longint;
  82. {$IFNDEF OS2} { A DJGPP strange thing.}
  83. reserved : word; { requires the DOS extender (DJ GNU-C) }
  84. {$ENDIF}
  85. size : longint;
  86. {$IFNDEF OS2}
  87. name : string[15]; { the same size as declared by (DJ GNU C) }
  88. {$ELSE}
  89. name:string; {Filenames can be very long in OS/2!}
  90. {$ENDIF}
  91. end;
  92. {$PACKRECORDS 2}
  93. { file record for untyped files }
  94. filerec = record
  95. handle : word;
  96. mode : word;
  97. recsize : word;
  98. _private : array[1..26] of byte;
  99. userdata: array[1..16] of byte;
  100. name: array[0..79] of char;
  101. end;
  102. { file record for text files }
  103. textbuf = array[0..127] of char;
  104. textrec = record
  105. handle : word;
  106. mode : word;
  107. bufSize : word;
  108. _private : word;
  109. bufpos : word;
  110. bufend : word;
  111. bufptr : ^textbuf;
  112. openfunc : pointer;
  113. inoutfunc : pointer;
  114. flushfunc : pointer;
  115. closefunc : pointer;
  116. userdata : array[1..16] of byte;
  117. name : array[0..79] of char;
  118. buffer : textbuf;
  119. end;
  120. { data structure for the registers needed by msdos and intr }
  121. registers = record
  122. case i : integer of
  123. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  124. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  125. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  126. end;
  127. { record for date and time }
  128. datetime = record
  129. year,month,day,hour,min,sec : word;
  130. end;
  131. {Flags for the exec procedure:
  132. Starting the program:
  133. efwait: Wait until program terminates, otherwise the program
  134. continues execution.
  135. efno_wait: ? Function unknown. Not implemented in EMX.
  136. efoverlay: Terminate this program, then execute the requested
  137. program. WARNING: Exit-procedures are not called!
  138. efdebug: Debug program. Details are unknown.
  139. efsession: Do not execute as child of this program. Use a seperate
  140. session instead.
  141. efdetach: Detached. Function unknown. Info wanted!
  142. efpm: Run as presentation manager program.
  143. Determining the window state of the program:
  144. efdefault: Run the pm program in it's default situation.
  145. efminimize: Run the pm program minimized.
  146. efmaximize: Run the pm program maximized.
  147. effullscreen: Run the non-pm program fullscreen.
  148. efwindowed: Run the non-pm program in a window.
  149. Other options are not implemented defined because lack of
  150. knowledge abou what they do.}
  151. type execrunflags=(efwait,efno_wait,efoverlay,efdebug,efsession,
  152. efdetach,efpm);
  153. execwinflags=(efdefault,efminimize,efmaximize,effullscreen,
  154. efwindowed);
  155. execset=set of execrunflags;
  156. var
  157. { error variable }
  158. doserror : integer;
  159. procedure getdate(var year,month,day,dayofweek : word);
  160. procedure gettime(var hour,minute,second,sec100 : word);
  161. function dosversion : word;
  162. procedure setdate(year,month,day : word);
  163. procedure settime(hour,minute,second,sec100 : word);
  164. procedure getcbreak(var breakvalue : boolean);
  165. procedure setcbreak(breakvalue : boolean);
  166. procedure getverify(var verify : boolean);
  167. procedure setverify(verify : boolean);
  168. function diskfree(drive : byte) : longint;
  169. function disksize(drive : byte) : longint;
  170. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  171. procedure findnext(var f : searchRec);
  172. { is a dummy }
  173. procedure swapvectors;
  174. { not supported:
  175. procedure getintvec(intno : byte;var vector : pointer);
  176. procedure setintvec(intno : byte;vector : pointer);
  177. procedure keep(exitcode : word);
  178. }
  179. procedure msdos(var regs : registers);
  180. procedure intr(intno : byte;var regs : registers);
  181. procedure getfattr(var f;var attr : word);
  182. procedure setfattr(var f;attr : word);
  183. function fsearch(const path : pathstr;dirlist : string) : pathstr;
  184. procedure getftime(var f;var time : longint);
  185. procedure setftime(var f;time : longint);
  186. procedure packtime (var d: datetime; var time: longint);
  187. procedure unpacktime (time: longint; var d: datetime);
  188. function fexpand(const path : pathstr) : pathstr;
  189. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;
  190. var ext : extstr);
  191. procedure exec(const path : pathstr;const comline : comstr);
  192. {$IFDEF OS2}
  193. function exec(path:pathstr;runflags:execset;winflags:execwinflags;
  194. const comline:comstr):longint;
  195. {$ENDIF}
  196. function dosexitcode : word;
  197. function envcount : longint;
  198. function envstr(index : longint) : string;
  199. function getenv(const envvar : string): string;
  200. implementation
  201. {$ifdef OS2}
  202. type OS2FSAllocate=record
  203. idfilesystem,
  204. csectorunit,
  205. cunit,
  206. cunitavail:longint;
  207. cbsector:word;
  208. end;
  209. function dosqueryFSinfo(driveno:word;infolevel:word;
  210. var info;infolen:word):word;
  211. external 'DOSCALLS' index 278;
  212. {$endif OS2}
  213. { this was first written for the LINUX version, }
  214. { by Michael Van Canneyt but it works also }
  215. { for the DOS version (I hope so) }
  216. function fsearch(const path : pathstr;dirlist : string) : pathstr;
  217. var
  218. newdir : pathstr;
  219. p1 : byte;
  220. s : searchrec;
  221. begin
  222. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  223. { No wildcards allowed in these things }
  224. fsearch:=''
  225. else
  226. begin
  227. repeat
  228. { get first path }
  229. p1:=pos(';',dirlist);
  230. if p1>0 then
  231. begin
  232. newdir:=copy(dirlist,1,p1-1);
  233. delete(dirlist,1,p1)
  234. end
  235. else
  236. begin
  237. newdir:=dirlist;
  238. dirlist:=''
  239. end;
  240. findfirst(newdir+'\'+path,anyfile,s);
  241. if doserror=0 then
  242. begin
  243. newdir:=newdir+'\'+s.name;
  244. { this was for LINUX:
  245. if pos('.\',newdir)=1 then
  246. delete(newdir, 1, 2)
  247. { DOS strips off an initial .\ }
  248. }
  249. end
  250. else newdir:='';
  251. until(dirlist='') or (length(newdir)>0);
  252. fsearch:=newdir;
  253. end;
  254. end;
  255. procedure getftime(var f;var time : longint);
  256. begin
  257. {$IFNDEF OS2}
  258. asm
  259. { load handle }
  260. movl f,%ebx
  261. movw (%ebx),%bx
  262. { get date }
  263. movw $0x5700,%ax
  264. int $0x21
  265. shll $16,%edx
  266. movw %cx,%dx
  267. movl time,%ebx
  268. movl %edx,(%ebx)
  269. xorb %ah,%ah
  270. movw %ax,U_DOS_DOSERROR
  271. end;
  272. {$ELSE}
  273. asm
  274. { load handle }
  275. movl f,%ebx
  276. movw (%ebx),%bx
  277. { get date }
  278. movw $0x5700,%ax
  279. call ___SYSCALL
  280. shll $16,%edx
  281. movw %cx,%dx
  282. movl time,%ebx
  283. movl %edx,(%ebx)
  284. xorb %ah,%ah
  285. movw %ax,U_DOS_DOSERROR
  286. end;
  287. {$ENDIF}
  288. end;
  289. procedure setftime(var f;time : longint);
  290. begin
  291. {$IFNDEF OS2}
  292. asm
  293. { load handle }
  294. movl f,%ebx
  295. movw (%ebx),%bx
  296. movl time,%ecx
  297. shldl $16,%ecx,%edx
  298. { set date }
  299. movw $0x5701,%ax
  300. int $0x21
  301. xorb %ah,%ah
  302. movw %ax,U_DOS_DOSERROR
  303. end;
  304. {$ELSE}
  305. asm
  306. { load handle }
  307. movl f,%ebx
  308. movw (%ebx),%bx
  309. movl time,%ecx
  310. shldl $16,%ecx,%edx
  311. { set date }
  312. movw $0x5701,%ax
  313. call ___SYSCALL
  314. xorb %ah,%ah
  315. movw %ax,U_DOS_DOSERROR
  316. end;
  317. {$ENDIF}
  318. end;
  319. procedure msdos(var regs : registers);
  320. { Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  321. begin
  322. intr($21,regs);
  323. end;
  324. procedure intr(intno : byte;var regs : registers);
  325. { Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  326. begin
  327. asm
  328. .data
  329. int86:
  330. .byte 0xcd
  331. int86_vec:
  332. .byte 0x03
  333. jmp int86_retjmp
  334. .text
  335. movl 8(%ebp),%eax
  336. movb %al,int86_vec
  337. movl 10(%ebp),%eax
  338. {do not use first int}
  339. addl $2,%eax
  340. movl 4(%eax),%ebx
  341. movl 8(%eax),%ecx
  342. movl 12(%eax),%edx
  343. movl 16(%eax),%ebp
  344. movl 20(%eax),%esi
  345. movl 24(%eax),%edi
  346. movl (%eax),%eax
  347. jmp int86
  348. int86_retjmp:
  349. pushf
  350. pushl %ebp
  351. pushl %eax
  352. movl %esp,%ebp
  353. {calc EBP new}
  354. addl $12,%ebp
  355. movl 10(%ebp),%eax
  356. {do not use first int}
  357. addl $2,%eax
  358. popl (%eax)
  359. movl %ebx,4(%eax)
  360. movl %ecx,8(%eax)
  361. movl %edx,12(%eax)
  362. {restore EBP}
  363. popl %edx
  364. movl %edx,16(%eax)
  365. movl %esi,20(%eax)
  366. movl %edi,24(%eax)
  367. {ignore ES and DS}
  368. popl %ebx /* flags */
  369. movl %ebx,32(%eax)
  370. {FS and GS too}
  371. end;
  372. end;
  373. var
  374. lastdosexitcode : word;
  375. {$IFNDEF OS2}
  376. procedure exec(const path : pathstr;const comline : comstr);
  377. procedure do_system(p : pchar);
  378. begin
  379. asm
  380. movl 12(%ebp),%ebx
  381. movw $0xff07,%ax
  382. int $0x21
  383. movw %ax,_LASTDOSEXITCODE
  384. end;
  385. end;
  386. var
  387. execute : string;
  388. b : array[0..255] of char;
  389. begin
  390. execute:=path+' '+comline;
  391. move(execute[1],b,length(execute));
  392. b[length(execute)]:=#0;
  393. do_system(b);
  394. end;
  395. {$ELSE}
  396. procedure exec(const path:pathstr;const comline:comstr);
  397. {Execute a program.}
  398. begin
  399. exec(path,[efwait],efdefault,comline);
  400. end;
  401. function exec(path:pathstr;runflags:execset;winflags:execwinflags;
  402. const comline:comstr):longint;
  403. {Execute a program. More suitable for OS/2 than the exec above.}
  404. {512 bytes should be enough to contain the command-line.}
  405. type bytearray=array[0..8191] of byte;
  406. Pbytearray=^bytearray;
  407. setarray=array[0..3] of byte;
  408. execstruc=record
  409. argofs,envofs,nameofs:pointer;
  410. argseg,envseg,nameseg:word;
  411. numarg,sizearg,
  412. numenv,sizeenv:word;
  413. mode1,mode2:byte;
  414. end;
  415. var args:Pbytearray;
  416. env:Pbytearray;
  417. i,j:word;
  418. es:execstruc;
  419. esadr:pointer;
  420. begin
  421. getmem(args,512);
  422. getmem(env,8192);
  423. i:=1;
  424. j:=0;
  425. es.numarg:=0;
  426. while i<=length(comline) do
  427. begin
  428. if comline[i]<>' ' then
  429. begin
  430. {Commandline argument found. Copy it.}
  431. inc(es.numarg);
  432. args^[j]:=$80;
  433. inc(j);
  434. while (i<=length(comline)) and (comline[i]<>' ') do
  435. begin
  436. args^[j]:=byte(comline[i]);
  437. inc(j);
  438. inc(i);
  439. end;
  440. args^[j]:=0;
  441. inc(j);
  442. end;
  443. inc(i);
  444. end;
  445. args^[j]:=0;
  446. inc(j);
  447. {Commandline ready, now build the environment.
  448. Oh boy, I always had the opinion that executing a program under Dos
  449. was a hard job!}
  450. asm
  451. movl env,%edi {Setup destination pointer.}
  452. movl _envc,%ecx {Load number of arguments in edx.}
  453. movl _environ,%esi {Load env. strings.}
  454. xorl %edx,%edx {Count environment size.}
  455. exa1:
  456. lodsl {Load a Pchar.}
  457. xchgl %eax,%ebx
  458. exa2:
  459. movb (%ebx),%al {Load a byte.}
  460. incl %ebx {Point to next byte.}
  461. stosb {Store it.}
  462. incl %edx {Increase counter.}
  463. cmpb $0,%al {Ready ?.}
  464. jne exa2
  465. loop exa1 {Next argument.}
  466. stosb {Store an extra 0 to finish. (AL is now 0).}
  467. incl %edx
  468. movl %edx,(24)es {Store environment size.}
  469. end;
  470. {Environtment ready, now set-up exec structure.}
  471. es.argofs:=args;
  472. es.envofs:=env;
  473. asm
  474. leal path,%esi
  475. lodsb
  476. movzbl %al,%eax
  477. incl %eax
  478. addl %eax,%esi
  479. movb $0,(%esi)
  480. end;
  481. es.nameofs:=pointer(longint(@path)+1);
  482. asm
  483. movw %ss,(12)es {Compiler doesn't like record elems in asm.}
  484. movw %ss,(14)es
  485. movw %ss,(16)es
  486. end;
  487. es.sizearg:=j;
  488. es.numenv:=0;
  489. {Typecasting of sets in FPK is a bit hard.}
  490. es.mode1:=setarray(runflags)[0];
  491. es.mode2:=byte(winflags);
  492. {Now exec the program.}
  493. esadr:=@es;
  494. asm
  495. movl esadr,%edx
  496. mov $0x7f06,%ax
  497. call ___SYSCALL
  498. jnc exprg1
  499. movl %eax,U_DOS_DOSERROR
  500. xorl %eax,%eax
  501. decl %eax
  502. exprg1:
  503. movl %eax,__RESULT
  504. end;
  505. freemem(args,512);
  506. freemem(env,8192);
  507. {Phew! That's it. This was the most sophisticated procedure to call
  508. a system function I ever wrote!}
  509. end;
  510. {$ENDIF}
  511. function dosexitcode : word;
  512. begin
  513. dosexitcode:=lastdosexitcode;
  514. end;
  515. function dosversion : word;
  516. begin
  517. {$IFNDEF OS2}
  518. asm
  519. movb $0x30,%ah
  520. pushl %ebp
  521. int $0x21
  522. popl %ebp
  523. leave
  524. ret
  525. end;
  526. {$ELSE}
  527. {Returns DOS version in DOS and OS/2 version in OS/2}
  528. asm
  529. movb $0x30,%ah
  530. call ___SYSCALL
  531. leave
  532. ret
  533. end;
  534. {$ENDIF}
  535. end;
  536. procedure getdate(var year,month,day,dayofweek : word);
  537. begin
  538. {$IFNDEF OS2}
  539. asm
  540. movb $0x2a,%ah
  541. pushl %ebp
  542. int $0x21
  543. popl %ebp
  544. xorb %ah,%ah
  545. movl 20(%ebp),%edi
  546. stosw
  547. movl 16(%ebp),%edi
  548. movb %dl,%al
  549. stosw
  550. movl 12(%ebp),%edi
  551. movb %dh,%al
  552. stosw
  553. movl 8(%ebp),%edi
  554. movw %cx,%ax
  555. stosw
  556. end;
  557. {$ELSE}
  558. asm
  559. movb $0x2a,%ah
  560. call ___SYSCALL
  561. xorb %ah,%ah
  562. movl 20(%ebp),%edi
  563. stosw
  564. movl 16(%ebp),%edi
  565. movb %dl,%al
  566. stosw
  567. movl 12(%ebp),%edi
  568. movb %dh,%al
  569. stosw
  570. movl 8(%ebp),%edi
  571. xchgw %ecx,%eax
  572. stosw
  573. end;
  574. {$ENDIF}
  575. end;
  576. procedure setdate(year,month,day : word);
  577. begin
  578. {$IFNDEF OS2}
  579. asm
  580. movw 8(%ebp),%cx
  581. movb 10(%ebp),%dh
  582. movb 12(%ebp),%dl
  583. movb $0x2b,%ah
  584. pushl %ebp
  585. int $0x21
  586. popl %ebp
  587. xorb %ah,%ah
  588. movw %ax,U_DOS_DOSERROR
  589. end;
  590. {$ELSE}
  591. {DOS only! You cannot change the system date in OS/2!}
  592. asm
  593. movw 8(%ebp),%cx
  594. movb 10(%ebp),%dh
  595. movb 12(%ebp),%dl
  596. movb $0x2b,%ah
  597. call ___SYSCALL
  598. xorb %ah,%ah
  599. movw %ax,U_DOS_DOSERROR
  600. end;
  601. {$ENDIF}
  602. end;
  603. procedure gettime(var hour,minute,second,sec100 : word);
  604. begin
  605. {$IFNDEF OS2}
  606. asm
  607. movb $0x2c,%ah
  608. pushl %ebp
  609. int $0x21
  610. popl %ebp
  611. xorb %ah,%ah
  612. movl 20(%ebp),%edi
  613. movb %dl,%al
  614. stosw
  615. movl 16(%ebp),%edi
  616. movb %dh,%al
  617. stosw
  618. movl 12(%ebp),%edi
  619. movb %cl,%al
  620. stosw
  621. movl 8(%ebp),%edi
  622. movb %ch,%al
  623. stosw
  624. end;
  625. {$ELSE}
  626. asm
  627. movb $0x2c,%ah
  628. call ___SYSCALL
  629. xorb %ah,%ah
  630. movl 20(%ebp),%edi
  631. movb %dl,%al
  632. stosw
  633. movl 16(%ebp),%edi
  634. movb %dh,%al
  635. stosw
  636. movl 12(%ebp),%edi
  637. movb %cl,%al
  638. stosw
  639. movl 8(%ebp),%edi
  640. movb %ch,%al
  641. stosw
  642. end;
  643. {$ENDIF}
  644. end;
  645. procedure settime(hour,minute,second,sec100 : word);
  646. begin
  647. {$IFNDEF OS2}
  648. asm
  649. movb 8(%ebp),%ch
  650. movb 10(%ebp),%cl
  651. movb 12(%ebp),%dh
  652. movb 14(%ebp),%dl
  653. movb $0x2d,%ah
  654. pushl %ebp
  655. int $0x21
  656. popl %ebp
  657. xorb %ah,%ah
  658. movw %ax,U_DOS_DOSERROR
  659. end;
  660. {$ELSE}
  661. asm
  662. movb 8(%ebp),%ch
  663. movb 10(%ebp),%cl
  664. movb 12(%ebp),%dh
  665. movb 14(%ebp),%dl
  666. movb $0x2d,%ah
  667. call ___SYSCALL
  668. xorb %ah,%ah
  669. movw %ax,U_DOS_DOSERROR
  670. end;
  671. {$ENDIF}
  672. end;
  673. procedure getcbreak(var breakvalue : boolean);
  674. begin
  675. {$IFNDEF OS2}
  676. asm
  677. movw $0x3300,%ax
  678. pushl %ebp
  679. int $0x21
  680. popl %ebp
  681. movl 8(%ebp),%eax
  682. movb %dl,(%eax)
  683. end;
  684. {$ELSE}
  685. {! Do not use in OS/2. Also not recommended in DOS. Use
  686. signal handling instead.}
  687. asm
  688. movw $0x3300,%ax
  689. call ___SYSCALL
  690. movl 8(%ebp),%eax
  691. movb %dl,(%eax)
  692. end;
  693. {$ENDIF}
  694. end;
  695. procedure setcbreak(breakvalue : boolean);
  696. begin
  697. {$IFNDEF OS2}
  698. asm
  699. movb 8(%ebp),%dl
  700. movl $0x3301,%ax
  701. pushl %ebp
  702. int $0x21
  703. popl %ebp
  704. end;
  705. {$ELSE}
  706. {! Do not use in OS/2. Also not recommended in DOS. Use
  707. signal handling instead.}
  708. asm
  709. movb 8(%ebp),%dl
  710. movl $0x3301,%ax
  711. call ___SYSCALL
  712. end;
  713. {$ENDIF}
  714. end;
  715. procedure getverify(var verify : boolean);
  716. begin
  717. {$IFNDEF OS2}
  718. asm
  719. movb $0x54,%ah
  720. pushl %ebp
  721. int $0x21
  722. popl %ebp
  723. movl 8(%ebp),%edi
  724. stosb
  725. end;
  726. {$ELSE}
  727. {! Do not use in OS/2.}
  728. asm
  729. movb $0x54,%ah
  730. call ___SYSCALL
  731. movl 8(%ebp),%edi
  732. stosb
  733. end;
  734. {$ENDIF}
  735. end;
  736. procedure setverify(verify : boolean);
  737. begin
  738. {$IFNDEF OS2}
  739. asm
  740. movb 8(%ebp),%al
  741. movb $0x2e,%ah
  742. pushl %ebp
  743. int $0x21
  744. popl %ebp
  745. end;
  746. {$ELSE}
  747. {! Do not use in OS/2.}
  748. asm
  749. movb 8(%ebp),%al
  750. movb $0x2e,%ah
  751. call ___SYSCALL
  752. end;
  753. {$ENDIF}
  754. end;
  755. function diskfree(drive : byte) : longint;
  756. var fi:OS2FSallocate;
  757. begin
  758. {$IFNDEF OS2}
  759. asm
  760. movb 8(%ebp),%dl
  761. movb $0x36,%ah
  762. pushl %ebp
  763. int $0x21
  764. popl %ebp
  765. cmpw $-1,%ax
  766. je LDISKFREE1
  767. mulw %cx
  768. mulw %bx
  769. shll $16,%edx
  770. movw %ax,%dx
  771. movl %edx,%eax
  772. leave
  773. ret
  774. LDISKFREE1:
  775. cwde
  776. leave
  777. ret
  778. end;
  779. {$ELSE}
  780. if os_mode=osDOS then
  781. {Function 36 is not supported in OS/2.}
  782. asm
  783. movb 8(%ebp),%dl
  784. movb $0x36,%ah
  785. call ___SYSCALL
  786. cmpw $-1,%ax
  787. je LDISKFREE1
  788. mulw %cx
  789. mulw %bx
  790. shll $16,%edx
  791. movw %ax,%dx
  792. xchgl %edx,%eax
  793. leave
  794. ret
  795. LDISKFREE1:
  796. cwde
  797. leave
  798. ret
  799. end
  800. else
  801. {In OS/2, we use the filesystem information.}
  802. begin
  803. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  804. if doserror=0 then
  805. diskfree:=FI.cunitavail*FI.csectorunit*FI.cbsector
  806. else
  807. diskfree:=-1;
  808. end;
  809. {$ENDIF}
  810. end;
  811. function disksize(drive : byte) : longint;
  812. var fi:OS2FSallocate;
  813. begin
  814. {$IFNDEF OS2}
  815. asm
  816. movb 8(%ebp),%dl
  817. movb $0x36,%ah
  818. pushl %ebp
  819. int $0x21
  820. popl %ebp
  821. movw %dx,%bx
  822. cmpw $-1,%ax
  823. je LDISKSIZE1
  824. mulw %cx
  825. mulw %bx
  826. shll $16,%edx
  827. movw %ax,%dx
  828. movl %edx,%eax
  829. leave
  830. ret
  831. LDISKSIZE1:
  832. movl $-1,%eax
  833. leave
  834. ret
  835. end;
  836. {$ELSE}
  837. if os_mode=osDOS then
  838. {Function 36 is not supported in OS/2.}
  839. asm
  840. movb 8(%ebp),%dl
  841. movb $0x36,%ah
  842. call ___SYSCALL
  843. movw %dx,%bx
  844. cmpw $-1,%ax
  845. je LDISKSIZE1
  846. mulw %cx
  847. mulw %bx
  848. shll $16,%edx
  849. movw %ax,%dx
  850. xchgl %edx,%eax
  851. leave
  852. ret
  853. LDISKSIZE1:
  854. cwde
  855. leave
  856. ret
  857. end
  858. else
  859. {In OS/2, we use the filesystem information.}
  860. begin
  861. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  862. if doserror=0 then
  863. disksize:=FI.cunit*FI.csectorunit*FI.cbsector
  864. else
  865. disksize:=-1;
  866. end;
  867. {$ENDIF}
  868. end;
  869. procedure searchrec2dossearchrec(var f : searchrec);
  870. var
  871. l,i : longint;
  872. {$IFDEF OS2}
  873. const namesize=255;
  874. {$ELSE}
  875. const namesize=12;
  876. {$ENDIF}
  877. begin
  878. l:=length(f.name);
  879. for i:=1 to namesize do
  880. f.name[i-1]:=f.name[i];
  881. f.name[l]:=#0;
  882. end;
  883. procedure dossearchrec2searchrec(var f : searchrec);
  884. var
  885. l,i : longint;
  886. {$IFDEF OS2}
  887. const namesize=255;
  888. {$ELSE}
  889. const namesize=12;
  890. {$ENDIF}
  891. begin
  892. for i:=0 to namesize do
  893. if f.name[i]=#0 then
  894. begin
  895. l:=i;
  896. break;
  897. end;
  898. for i:=namesize-1 downto 0 do
  899. f.name[i+1]:=f.name[i];
  900. f.name[0]:=chr(l);
  901. end;
  902. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  903. procedure _findfirst(path : pchar;attr : word;var f : searchrec);
  904. begin
  905. {$IFNDEF OS2}
  906. asm
  907. movl 18(%ebp),%edx
  908. movb $0x1a,%ah
  909. int $0x21
  910. movl 12(%esp),%edx
  911. movzwl 16(%esp),%ecx
  912. movb $0x4e,%ah
  913. int $0x21
  914. jnc LFF
  915. movw %ax,U_DOS_DOSERROR
  916. LFF:
  917. end;
  918. {$ELSE}
  919. asm
  920. movl 12(%esp),%edx
  921. movw 16(%esp),%cx
  922. {No need to set DTA in EMX. Just give a pointer in ESI.}
  923. movl 18(%ebp),%esi
  924. movb $0x4e,%ah
  925. call ___SYSCALL
  926. jnc LFF
  927. movw %ax,U_DOS_DOSERROR
  928. LFF:
  929. end;
  930. {$ENDIF}
  931. end;
  932. var
  933. path0 : array[0..80] of char;
  934. begin
  935. { no error }
  936. doserror:=0;
  937. strpcopy(path0,path);
  938. _findfirst(path0,attr,f);
  939. dossearchrec2searchrec(f);
  940. end;
  941. procedure findnext(var f : searchRec);
  942. procedure _findnext(var f : searchrec);
  943. begin
  944. {$IFNDEF OS2}
  945. asm
  946. movl 12(%ebp),%edx
  947. movb $0x1a,%ah
  948. int $0x21
  949. movb $0x4f,%ah
  950. int $0x21
  951. jnc LFN
  952. movw %ax,U_DOS_DOSERROR
  953. LFN:
  954. end;
  955. {$ELSE}
  956. asm
  957. movl 12(%ebp),%esi
  958. movb $0x4f,%ah
  959. call ___SYSCALL
  960. jnc LFN
  961. movw %ax,U_DOS_DOSERROR
  962. LFN:
  963. end;
  964. {$ENDIF}
  965. end;
  966. begin
  967. { no error }
  968. doserror:=0;
  969. searchrec2dossearchrec(f);
  970. _findnext(f);
  971. dossearchrec2searchrec(f);
  972. end;
  973. procedure swapvectors;
  974. begin
  975. { tut nichts, DOS-Extender �bernimmt das N”tige }
  976. { normalerweise selber }
  977. { nur aus Kompatibilit„tsgr�nden implementiert }
  978. end;
  979. type
  980. ppchar = ^pchar;
  981. function envs : ppchar;
  982. begin
  983. asm
  984. movl _environ,%eax
  985. leave
  986. ret
  987. end ['EAX'];
  988. end;
  989. function envcount : longint;
  990. var
  991. hp : ppchar;
  992. begin
  993. {$IFNDEF OS2}
  994. hp:=envs;
  995. envcount:=0;
  996. while assigned(hp^) do
  997. begin
  998. { not the best solution, but quite understandable }
  999. inc(envcount);
  1000. hp:=hp+4;
  1001. end;
  1002. {$ELSE}
  1003. asm
  1004. movl _envc,%eax
  1005. leave
  1006. ret
  1007. end ['EAX'];
  1008. {$ENDIF}
  1009. end;
  1010. function envstr(index : longint) : string;
  1011. var
  1012. hp : ppchar;
  1013. begin
  1014. if (index<=0) or (index>envcount) then
  1015. begin
  1016. envstr:='';
  1017. exit;
  1018. end;
  1019. hp:=envs+4*(index-1);
  1020. envstr:=strpas(hp^);
  1021. end;
  1022. function getenv(const envvar : string) : string;
  1023. var
  1024. hs,_envvar : string;
  1025. eqpos,i : longint;
  1026. begin
  1027. _envvar:=upcase(envvar);
  1028. getenv:='';
  1029. for i:=1 to envcount do
  1030. begin
  1031. hs:=envstr(i);
  1032. eqpos:=pos('=',hs);
  1033. if copy(hs,1,eqpos-1)=_envvar then
  1034. begin
  1035. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  1036. exit;
  1037. end;
  1038. end;
  1039. end;
  1040. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;
  1041. var ext : extstr);
  1042. var
  1043. p1 : byte;
  1044. begin
  1045. { try to find out a extension }
  1046. p1:=pos('.',path);
  1047. if p1>0 then
  1048. begin
  1049. ext:=copy(path,p1,4);
  1050. delete(path,p1,length(path)-p1+1);
  1051. end
  1052. else
  1053. ext:='';
  1054. { get drive name }
  1055. p1:=pos(':',path);
  1056. if p1>0 then
  1057. begin
  1058. dir:=path[1]+':';
  1059. delete(path,1,p1);
  1060. end
  1061. else
  1062. dir:='';
  1063. { split the path and the name, there are no more path informtions }
  1064. { if path contains no backslashes }
  1065. while true do
  1066. begin
  1067. p1:=pos('\',path);
  1068. if p1=0 then
  1069. break;
  1070. dir:=dir+copy(path,1,p1);
  1071. delete(path,1,p1);
  1072. end;
  1073. name:=path;
  1074. end;
  1075. function fexpand(const path : pathstr) : pathstr;
  1076. function get_current_drive : byte;
  1077. var
  1078. r : registers;
  1079. begin
  1080. r.ah:=$19;
  1081. msdos(r);
  1082. get_current_drive:=r.al;
  1083. end;
  1084. var
  1085. {$IFDEF DOS}
  1086. s,pa : string[79];
  1087. {$ELSE}
  1088. s,pa:string;
  1089. {$ENDIF}
  1090. begin
  1091. { There are differences between FPKPascal and Turbo Pascal
  1092. e.g. for the string 'D:\DEMO\..\HELLO' which isn't handled }
  1093. getdir(0,s);
  1094. pa:=upcase(path);
  1095. if (byte(pa[0])>1) and ((pa[1] in ['A'..'Z']) and (pa[2]=':')) then
  1096. begin
  1097. if (byte(pa[0])>2) and (pa[3]<>'\') then
  1098. if pa[1]=s[1] then
  1099. pa:=s+'\'+copy (pa,3,length(pa))
  1100. else
  1101. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  1102. end
  1103. else
  1104. if pa[1]='\' then
  1105. pa:=s[1]+':'+pa
  1106. else if s[0]=#3 then
  1107. pa:=s+pa
  1108. else
  1109. pa:=s+'\'+pa;
  1110. fexpand:=pa;
  1111. end;
  1112. procedure packtime(var d : datetime;var time : longint);
  1113. var
  1114. zs : longint;
  1115. begin
  1116. time:=-1980;
  1117. time:=time+d.year and 127;
  1118. time:=time shl 4;
  1119. time:=time+d.month;
  1120. time:=time shl 5;
  1121. time:=time+d.day;
  1122. time:=time shl 16;
  1123. zs:=d.hour;
  1124. zs:=zs shl 6;
  1125. zs:=zs+d.min;
  1126. zs:=zs shl 5;
  1127. zs:=zs+d.sec div 2;
  1128. time:=time+(zs and $ffff);
  1129. end;
  1130. procedure unpacktime (time: longint; var d: datetime);
  1131. begin
  1132. d.sec:=(time and 31) * 2;
  1133. time:=time shr 5;
  1134. d.min:=time and 63;
  1135. time:=time shr 6;
  1136. d.hour:=time and 31;
  1137. time:=time shr 5;
  1138. d.day:=time and 31;
  1139. time:=time shr 5;
  1140. d.month:=time and 15;
  1141. time:=time shr 4;
  1142. d.year:=time + 1980;
  1143. end;
  1144. procedure getfattr(var f;var attr : word);
  1145. var
  1146. { to avoid problems }
  1147. n : array[0..255] of char;
  1148. {$IFNDEF OS2}
  1149. r : registers;
  1150. {$ENDIF}
  1151. begin
  1152. strpcopy(n,filerec(f).name);
  1153. {$IFNDEF OS2}
  1154. r.ax:=$4300;
  1155. r.edx:=longint(@n);
  1156. msdos(r);
  1157. attr:=r.cx;
  1158. {$ELSE}
  1159. {Alas, msdos(r) doesn't work when we are running in OS/2.}
  1160. asm
  1161. movw $0x4300,%ax
  1162. leal n,%edx
  1163. call ___SYSCALL
  1164. movl attr,%ebx
  1165. movw %cx,(%ebx)
  1166. end;
  1167. {$ENDIF}
  1168. end;
  1169. procedure setfattr(var f;attr : word);
  1170. var
  1171. { to avoid problems }
  1172. n : array[0..255] of char;
  1173. {$IFNDEF OS2}
  1174. r : registers;
  1175. {$ENDIF}
  1176. begin
  1177. strpcopy(n,filerec(f).name);
  1178. {$IFNDEF OS2}
  1179. r.ax:=$4301;
  1180. r.edx:=longint(@n);
  1181. r.cx:=attr;
  1182. msdos(r);
  1183. {$ELSE}
  1184. {Alas, msdos(r) doesn't work when we are running in OS/2.}
  1185. asm
  1186. movw $0x4301,%ax
  1187. leal n,%edx
  1188. movw attr,%cx
  1189. call ___SYSCALL
  1190. end;
  1191. {$ENDIF}
  1192. end;
  1193. end.