dos.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  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 OS/2}
  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. movl $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. movl $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. begin
  813. {$IFNDEF OS/2}
  814. asm
  815. movb 8(%ebp),%dl
  816. movb $0x36,%ah
  817. pushl %ebp
  818. int $0x21
  819. popl %ebp
  820. movw %dx,%bx
  821. cmpw $-1,%ax
  822. je LDISKSIZE1
  823. mulw %cx
  824. mulw %bx
  825. shll $16,%edx
  826. movw %ax,%dx
  827. movl %edx,%eax
  828. leave
  829. ret
  830. LDISKSIZE1:
  831. movl $-1,%eax
  832. leave
  833. ret
  834. end;
  835. {$ELSE}
  836. if os_mode=osDOS then
  837. {Function 36 is not supported in OS/2.}
  838. asm
  839. movb 8(%ebp),%dl
  840. movb $0x36,%ah
  841. call ___SYSCALL
  842. movw %dx,%bx
  843. cmpw $-1,%ax
  844. je LDISKSIZE1
  845. mulw %cx
  846. mulw %bx
  847. shll $16,%edx
  848. movw %ax,%dx
  849. xchgl %edx,%eax
  850. leave
  851. ret
  852. LDISKSIZE1:
  853. cwde
  854. leave
  855. ret
  856. end;
  857. else
  858. {In OS/2, we use the filesystem information.}
  859. begin
  860. doserror:=dosQFSinfo(drive,1,FI,sizeof(FI));
  861. if doserror=0 then
  862. diskfree:=FI.cunit*FI.csectorunit*FI.cbsector
  863. else
  864. diskfree:=-1;
  865. end;
  866. {$ENDIF}
  867. end;
  868. procedure searchrec2dossearchrec(var f : searchrec);
  869. var
  870. l,i : longint;
  871. {$IFDEF OS2}
  872. const namesize=255;
  873. {$ELSE}
  874. const namesize=12;
  875. {$ENDIF}
  876. begin
  877. l:=length(f.name);
  878. for i:=1 to namesize do
  879. f.name[i-1]:=f.name[i];
  880. f.name[l]:=#0;
  881. end;
  882. procedure dossearchrec2searchrec(var f : searchrec);
  883. var
  884. l,i : longint;
  885. {$IFDEF OS2}
  886. const namesize=255;
  887. {$ELSE}
  888. const namesize=12;
  889. {$ENDIF}
  890. begin
  891. for i:=0 to namesize do
  892. if f.name[i]=#0 then
  893. begin
  894. l:=i;
  895. break;
  896. end;
  897. for i:=namesize-1 downto 0 do
  898. f.name[i+1]:=f.name[i];
  899. f.name[0]:=chr(l);
  900. end;
  901. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  902. procedure _findfirst(path : pchar;attr : word;var f : searchrec);
  903. begin
  904. {$IFNDEF OS2}
  905. asm
  906. movl 18(%ebp),%edx
  907. movb $0x1a,%ah
  908. int $0x21
  909. movl 12(%esp),%edx
  910. movzwl 16(%esp),%ecx
  911. movb $0x4e,%ah
  912. int $0x21
  913. jnc LFF
  914. movw %ax,U_DOS_DOSERROR
  915. LFF:
  916. end;
  917. {$ELSE}
  918. asm
  919. movl 12(%esp),%edx
  920. movw 16(%esp),%cx
  921. {No need to set DTA in EMX. Just give a pointer in ESI.}
  922. movl 18(%ebp),%esi
  923. movb $0x4e,%ah
  924. call ___SYSCALL
  925. jnc LFF
  926. movw %ax,U_DOS_DOSERROR
  927. LFF:
  928. end;
  929. {$ENDIF}
  930. end;
  931. var
  932. path0 : array[0..80] of char;
  933. begin
  934. { no error }
  935. doserror:=0;
  936. strpcopy(path0,path);
  937. _findfirst(path0,attr,f);
  938. dossearchrec2searchrec(f);
  939. end;
  940. procedure findnext(var f : searchRec);
  941. procedure _findnext(var f : searchrec);
  942. begin
  943. {$IFNDEF OS2}
  944. asm
  945. movl 12(%ebp),%edx
  946. movb $0x1a,%ah
  947. int $0x21
  948. movb $0x4f,%ah
  949. int $0x21
  950. jnc LFN
  951. movw %ax,U_DOS_DOSERROR
  952. LFN:
  953. end;
  954. {$ELSE}
  955. asm
  956. movl 12(%ebp),%esi
  957. movb $0x4f,%ah
  958. call ___SYSCALL
  959. jnc LFN
  960. movw %ax,U_DOS_DOSERROR
  961. LFN:
  962. end;
  963. {$ENDIF}
  964. end;
  965. begin
  966. { no error }
  967. doserror:=0;
  968. searchrec2dossearchrec(f);
  969. _findnext(f);
  970. dossearchrec2searchrec(f);
  971. end;
  972. procedure swapvectors;
  973. begin
  974. { tut nichts, DOS-Extender �bernimmt das N”tige }
  975. { normalerweise selber }
  976. { nur aus Kompatibilit„tsgr�nden implementiert }
  977. end;
  978. type
  979. ppchar = ^pchar;
  980. function envs : ppchar;
  981. begin
  982. asm
  983. movl _environ,%eax
  984. leave
  985. ret
  986. end ['EAX'];
  987. end;
  988. function envcount : longint;
  989. var
  990. hp : ppchar;
  991. begin
  992. {$IFNDEF OS2}
  993. hp:=envs;
  994. envcount:=0;
  995. while assigned(hp^) do
  996. begin
  997. { not the best solution, but quite understandable }
  998. inc(envcount);
  999. hp:=hp+4;
  1000. end;
  1001. {$ELSE}
  1002. asm
  1003. movl _envc,%eax
  1004. leave
  1005. ret
  1006. end ['EAX'];
  1007. {$ENDIF}
  1008. end;
  1009. function envstr(index : longint) : string;
  1010. var
  1011. hp : ppchar;
  1012. begin
  1013. if (index<=0) or (index>envcount) then
  1014. begin
  1015. envstr:='';
  1016. exit;
  1017. end;
  1018. hp:=envs+4*(index-1);
  1019. envstr:=strpas(hp^);
  1020. end;
  1021. function getenv(const envvar : string) : string;
  1022. var
  1023. hs,_envvar : string;
  1024. eqpos,i : longint;
  1025. begin
  1026. _envvar:=upcase(envvar);
  1027. getenv:='';
  1028. for i:=1 to envcount do
  1029. begin
  1030. hs:=envstr(i);
  1031. eqpos:=pos('=',hs);
  1032. if copy(hs,1,eqpos-1)=_envvar then
  1033. begin
  1034. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  1035. exit;
  1036. end;
  1037. end;
  1038. end;
  1039. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;
  1040. var ext : extstr);
  1041. var
  1042. p1 : byte;
  1043. begin
  1044. { try to find out a extension }
  1045. p1:=pos('.',path);
  1046. if p1>0 then
  1047. begin
  1048. ext:=copy(path,p1,4);
  1049. delete(path,p1,length(path)-p1+1);
  1050. end
  1051. else
  1052. ext:='';
  1053. { get drive name }
  1054. p1:=pos(':',path);
  1055. if p1>0 then
  1056. begin
  1057. dir:=path[1]+':';
  1058. delete(path,1,p1);
  1059. end
  1060. else
  1061. dir:='';
  1062. { split the path and the name, there are no more path informtions }
  1063. { if path contains no backslashes }
  1064. while true do
  1065. begin
  1066. p1:=pos('\',path);
  1067. if p1=0 then
  1068. break;
  1069. dir:=dir+copy(path,1,p1);
  1070. delete(path,1,p1);
  1071. end;
  1072. name:=path;
  1073. end;
  1074. function fexpand(const path : pathstr) : pathstr;
  1075. function get_current_drive : byte;
  1076. var
  1077. r : registers;
  1078. begin
  1079. r.ah:=$19;
  1080. msdos(r);
  1081. get_current_drive:=r.al;
  1082. end;
  1083. var
  1084. {$IFDEF DOS}
  1085. s,pa : string[79];
  1086. {$ELSE}
  1087. s,pa:string;
  1088. {$ENDIF}
  1089. begin
  1090. { There are differences between FPKPascal and Turbo Pascal
  1091. e.g. for the string 'D:\DEMO\..\HELLO' which isn't handled }
  1092. getdir(0,s);
  1093. pa:=upcase(path);
  1094. if (byte(pa[0])>1) and ((pa[1] in ['A'..'Z']) and (pa[2]=':')) then
  1095. begin
  1096. if (byte(pa[0])>2) and (pa[3]<>'\') then
  1097. if pa[1]=s[1] then
  1098. pa:=s+'\'+copy (pa,3,length(pa))
  1099. else
  1100. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  1101. end
  1102. else
  1103. if pa[1]='\' then
  1104. pa:=s[1]+':'+pa
  1105. else if s[0]=#3 then
  1106. pa:=s+pa
  1107. else
  1108. pa:=s+'\'+pa;
  1109. fexpand:=pa;
  1110. end;
  1111. procedure packtime(var d : datetime;var time : longint);
  1112. var
  1113. zs : longint;
  1114. begin
  1115. time:=-1980;
  1116. time:=time+d.year and 127;
  1117. time:=time shl 4;
  1118. time:=time+d.month;
  1119. time:=time shl 5;
  1120. time:=time+d.day;
  1121. time:=time shl 16;
  1122. zs:=d.hour;
  1123. zs:=zs shl 6;
  1124. zs:=zs+d.min;
  1125. zs:=zs shl 5;
  1126. zs:=zs+d.sec div 2;
  1127. time:=time+(zs and $ffff);
  1128. end;
  1129. procedure unpacktime (time: longint; var d: datetime);
  1130. begin
  1131. d.sec:=(time and 31) * 2;
  1132. time:=time shr 5;
  1133. d.min:=time and 63;
  1134. time:=time shr 6;
  1135. d.hour:=time and 31;
  1136. time:=time shr 5;
  1137. d.day:=time and 31;
  1138. time:=time shr 5;
  1139. d.month:=time and 15;
  1140. time:=time shr 4;
  1141. d.year:=time + 1980;
  1142. end;
  1143. procedure getfattr(var f;var attr : word);
  1144. var
  1145. { to avoid problems }
  1146. n : array[0..255] of char;
  1147. {$IFNDEF OS2}
  1148. r : registers;
  1149. {$ENDIF}
  1150. begin
  1151. strpcopy(n,filerec(f).name);
  1152. {$IFNDEF OS2}
  1153. r.ax:=$4300;
  1154. r.edx:=longint(@n);
  1155. msdos(r);
  1156. attr:=r.cx;
  1157. {$ELSE}
  1158. {Alas, msdos(r) doesn't work when we are running in OS/2.}
  1159. asm
  1160. movw $0x4300,%ax
  1161. leal n,%edx
  1162. call ___SYSCALL
  1163. movl attr,%ebx
  1164. movw %cx,(%ebx)
  1165. end;
  1166. {$ENDIF}
  1167. end;
  1168. procedure setfattr(var f;attr : word);
  1169. var
  1170. { to avoid problems }
  1171. n : array[0..255] of char;
  1172. {$IFNDEF OS2}
  1173. r : registers;
  1174. {$ENDIF}
  1175. begin
  1176. strpcopy(n,filerec(f).name);
  1177. {$IFNDEF OS2}
  1178. r.ax:=$4301;
  1179. r.edx:=longint(@n);
  1180. r.cx:=attr;
  1181. msdos(r);
  1182. {$ELSE}
  1183. {Alas, msdos(r) doesn't work when we are running in OS/2.}
  1184. asm
  1185. movw $0x4301,%ax
  1186. leal n,%edx
  1187. movw attr,%cx
  1188. call ___SYSCALL
  1189. end;
  1190. {$ENDIF}
  1191. end;
  1192. end.