dos.pas 27 KB

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