dos.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  1. {****************************************************************************
  2. $Id$
  3. Free Pascal Runtime-Library
  4. DOS unit for OS/2
  5. Copyright (c) 1997,1998 by Dani‰l Mantione,
  6. member of the Free Pascal development team
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. ****************************************************************************}
  13. unit dos;
  14. {$I os.inc}
  15. {$ASMMODE ATT}
  16. {***************************************************************************}
  17. interface
  18. {***************************************************************************}
  19. {$PACKRECORDS 1}
  20. uses strings;
  21. const {Bit masks for CPU flags.}
  22. fcarry = $0001;
  23. fparity = $0004;
  24. fauxiliary = $0010;
  25. fzero = $0040;
  26. fsign = $0080;
  27. foverflow = $0800;
  28. {Bit masks for file attributes.}
  29. readonly = $01;
  30. hidden = $02;
  31. sysfile = $04;
  32. volumeid = $08;
  33. directory = $10;
  34. archive = $20;
  35. anyfile = $3F;
  36. fmclosed = $D7B0;
  37. fminput = $D7B1;
  38. fmoutput = $D7B2;
  39. fminout = $D7B3;
  40. type {Some string types:}
  41. comstr=string; {Filenames can be long in OS/2.}
  42. pathstr=string; {String for pathnames.}
  43. dirstr=string; {String for a directory}
  44. namestr=string; {String for a filename.}
  45. extstr=string[40]; {String for an extension. Can be 253
  46. characters long, in theory, but let's
  47. say fourty will be enough.}
  48. {Search record which is used by findfirst and findnext:}
  49. searchrec=record
  50. fill:array[1..21] of byte;
  51. attr:byte;
  52. time:longint;
  53. size:longint;
  54. name:string; {Filenames can be long in OS/2!}
  55. end;
  56. {$i filerec.inc}
  57. {$i textrec.inc}
  58. {Data structure for the registers needed by msdos and intr:}
  59. registers=record
  60. case i:integer of
  61. 0:(ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,
  62. f8,flags,fs,gs:word);
  63. 1:(al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh:byte);
  64. 2:(eax,ebx,ecx,edx,ebp,esi,edi:longint);
  65. end;
  66. {Record for date and time:}
  67. datetime=record
  68. year,month,day,hour,min,sec:word;
  69. end;
  70. {Flags for the exec procedure:
  71. Starting the program:
  72. efwait: Wait until program terminates.
  73. efno_wait: Don't wait until the program terminates. Does not work
  74. in dos, as DOS cannot multitask.
  75. efoverlay: Terminate this program, then execute the requested
  76. program. WARNING: Exit-procedures are not called!
  77. efdebug: Debug program. Details are unknown.
  78. efsession: Do not execute as child of this program. Use a seperate
  79. session instead.
  80. efdetach: Detached. Function unknown. Info wanted!
  81. efpm: Run as presentation manager program.
  82. Determining the window state of the program:
  83. efdefault: Run the pm program in it's default situation.
  84. efminimize: Run the pm program minimized.
  85. efmaximize: Run the pm program maximized.
  86. effullscreen: Run the non-pm program fullscreen.
  87. efwindowed: Run the non-pm program in a window.
  88. Other options are not implemented defined because lack of
  89. knowledge abou what they do.}
  90. type execrunflags=(efwait,efno_wait,efoverlay,efdebug,efsession,
  91. efdetach,efpm);
  92. execwinflags=(efdefault,efminimize,efmaximize,effullscreen,
  93. efwindowed);
  94. var doserror:integer;
  95. dosexitcode:word;
  96. procedure getdate(var year,month,day,dayofweek:word);
  97. procedure gettime(var hour,minute,second,sec100:word);
  98. function dosversion:word;
  99. procedure setdate(year,month,day:word);
  100. procedure settime(hour,minute,second,sec100:word);
  101. procedure getcbreak(var breakvalue:boolean);
  102. procedure setcbreak(breakvalue:boolean);
  103. procedure getverify(var verify:boolean);
  104. procedure setverify(verify : boolean);
  105. function diskfree(drive:byte):longint;
  106. function disksize(drive:byte):longint;
  107. procedure findfirst(const path:pathstr;attr:word;var f:searchRec);
  108. procedure findnext(var f:searchRec);
  109. {Is a dummy:}
  110. procedure swapvectors;
  111. {Not supported:
  112. procedure getintvec(intno:byte;var vector:pointer);
  113. procedure setintvec(intno:byte;vector:pointer);
  114. procedure keep(exitcode:word);
  115. }
  116. procedure msdos(var regs:registers);
  117. procedure intr(intno : byte;var regs:registers);
  118. procedure getfattr(var f;var attr:word);
  119. procedure setfattr(var f;attr:word);
  120. function fsearch(path:pathstr;dirlist:string):pathstr;
  121. procedure getftime(var f;var time:longint);
  122. procedure setftime(var f;time:longint);
  123. procedure packtime (var d:datetime; var time:longint);
  124. procedure unpacktime (time:longint; var d:datetime);
  125. function fexpand(const path:pathstr):pathstr;
  126. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  127. var ext:extstr);
  128. procedure exec(const path:pathstr;const comline:comstr);
  129. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  130. const comline:comstr):longint;
  131. function envcount:longint;
  132. function envstr(index:longint) : string;
  133. function getenv(const envvar:string): string;
  134. implementation
  135. uses doscalls;
  136. {Import syscall to call it nicely from assembler procedures.}
  137. procedure syscall;external name '___SYSCALL';
  138. function fsearch(path:pathstr;dirlist:string):pathstr;
  139. var i,p1:longint;
  140. s:searchrec;
  141. newdir:pathstr;
  142. begin
  143. {No wildcards allowed in these things:}
  144. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  145. fsearch:=''
  146. else
  147. begin
  148. { allow slash as backslash }
  149. for i:=1 to length(dirlist) do
  150. if dirlist[i]='/' then dirlist[i]:='\';
  151. repeat
  152. p1:=pos(';',dirlist);
  153. if p1=0 then
  154. begin
  155. newdir:=copy(dirlist,1,p1-1);
  156. delete(dirlist,1,p1);
  157. end
  158. else
  159. begin
  160. newdir:=dirlist;
  161. dirlist:='';
  162. end;
  163. if (newdir<>'') and
  164. not (newdir[length(newdir)] in ['\',':']) then
  165. newdir:=newdir+'\';
  166. findfirst(newdir+path,anyfile,s);
  167. if doserror=0 then
  168. newdir:=newdir+path
  169. else
  170. newdir:='';
  171. until (dirlist='') or (newdir<>'');
  172. fsearch:=newdir;
  173. end;
  174. end;
  175. procedure getftime(var f;var time:longint);
  176. begin
  177. asm
  178. {Load handle}
  179. movl f,%ebx
  180. movw (%ebx),%bx
  181. {Get date}
  182. movw $0x5700,%ax
  183. call syscall
  184. shll $16,%edx
  185. movw %cx,%dx
  186. movl time,%ebx
  187. movl %edx,(%ebx)
  188. xorb %ah,%ah
  189. movw %ax,doserror
  190. end;
  191. end;
  192. procedure setftime(var f;time : longint);
  193. begin
  194. asm
  195. {Load handle}
  196. movl f,%ebx
  197. movw (%ebx),%bx
  198. movl time,%ecx
  199. shldl $16,%ecx,%edx
  200. {Set date}
  201. movw $0x5701,%ax
  202. call syscall
  203. xorb %ah,%ah
  204. movw %ax,doserror
  205. end;
  206. end;
  207. procedure msdos(var regs:registers);
  208. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  209. begin
  210. intr($21,regs);
  211. end;
  212. {$ASMMODE DIRECT}
  213. procedure intr(intno:byte;var regs:registers);
  214. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  215. begin
  216. asm
  217. .data
  218. int86:
  219. .byte 0xcd
  220. int86_vec:
  221. .byte 0x03
  222. jmp int86_retjmp
  223. .text
  224. movl 8(%ebp),%eax
  225. movb %al,int86_vec
  226. movl 10(%ebp),%eax
  227. {Do not use first int}
  228. incl %eax
  229. incl %eax
  230. movl 4(%eax),%ebx
  231. movl 8(%eax),%ecx
  232. movl 12(%eax),%edx
  233. movl 16(%eax),%ebp
  234. movl 20(%eax),%esi
  235. movl 24(%eax),%edi
  236. movl (%eax),%eax
  237. jmp int86
  238. int86_retjmp:
  239. pushf
  240. pushl %ebp
  241. pushl %eax
  242. movl %esp,%ebp
  243. {Calc EBP new}
  244. addl $12,%ebp
  245. movl 10(%ebp),%eax
  246. {Do not use first int}
  247. incl %eax
  248. incl %eax
  249. popl (%eax)
  250. movl %ebx,4(%eax)
  251. movl %ecx,8(%eax)
  252. movl %edx,12(%eax)
  253. {Restore EBP}
  254. popl %edx
  255. movl %edx,16(%eax)
  256. movl %esi,20(%eax)
  257. movl %edi,24(%eax)
  258. {Ignore ES and DS}
  259. popl %ebx {Flags.}
  260. movl %ebx,32(%eax)
  261. {FS and GS too}
  262. end;
  263. end;
  264. {$ASMMODE ATT}
  265. procedure exec(const path:pathstr;const comline:comstr);
  266. {Execute a program.}
  267. begin
  268. dosexitcode:=exec(path,efwait,efdefault,comline);
  269. end;
  270. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  271. const comline:comstr):longint;
  272. {Execute a program. More suitable for OS/2 than the exec above.}
  273. {512 bytes should be enough to contain the command-line.}
  274. type bytearray=array[0..8191] of byte;
  275. Pbytearray=^bytearray;
  276. execstruc=record
  277. argofs,envofs,nameofs:pointer;
  278. argseg,envseg,nameseg:word;
  279. numarg,sizearg,
  280. numenv,sizeenv:word;
  281. mode1,mode2:byte;
  282. end;
  283. var args:Pbytearray;
  284. env:Pbytearray;
  285. i,j:word;
  286. es:execstruc;
  287. esadr:pointer;
  288. d:dirstr;
  289. n:namestr;
  290. e:extstr;
  291. begin
  292. getmem(args,512);
  293. getmem(env,8192);
  294. j:=1;
  295. {Now setup the arguments. The first argument should be the program
  296. name without directory and extension.}
  297. fsplit(path,d,n,e);
  298. es.numarg:=1;
  299. args^[0]:=$80;
  300. for i:=1 to length(n) do
  301. begin
  302. args^[j]:=byte(n[i]);
  303. inc(j);
  304. end;
  305. args^[j]:=0;
  306. inc(j);
  307. {Now do the real arguments.}
  308. i:=1;
  309. while i<=length(comline) do
  310. begin
  311. if comline[i]<>' ' then
  312. begin
  313. {Commandline argument found. Copy it.}
  314. inc(es.numarg);
  315. args^[j]:=$80;
  316. inc(j);
  317. while (i<=length(comline)) and (comline[i]<>' ') do
  318. begin
  319. args^[j]:=byte(comline[i]);
  320. inc(j);
  321. inc(i);
  322. end;
  323. args^[j]:=0;
  324. inc(j);
  325. end;
  326. inc(i);
  327. end;
  328. args^[j]:=0;
  329. inc(j);
  330. {Commandline ready, now build the environment.
  331. Oh boy, I always had the opinion that executing a program under Dos
  332. was a hard job!}
  333. {$ASMMODE DIRECT}
  334. asm
  335. movl env,%edi {Setup destination pointer.}
  336. movl _envc,%ecx {Load number of arguments in edx.}
  337. movl _environ,%esi {Load env. strings.}
  338. xorl %edx,%edx {Count environment size.}
  339. exa1:
  340. lodsl {Load a Pchar.}
  341. xchgl %eax,%ebx
  342. exa2:
  343. movb (%ebx),%al {Load a byte.}
  344. incl %ebx {Point to next byte.}
  345. stosb {Store it.}
  346. incl %edx {Increase counter.}
  347. cmpb $0,%al {Ready ?.}
  348. jne exa2
  349. loop exa1 {Next argument.}
  350. stosb {Store an extra 0 to finish. (AL is now 0).}
  351. incl %edx
  352. movl %edx,(24)es {Store environment size.}
  353. end;
  354. {$ASMMODE ATT}
  355. {Environtment ready, now set-up exec structure.}
  356. es.argofs:=args;
  357. es.envofs:=env;
  358. asm
  359. leal path,%esi
  360. lodsb
  361. movzbl %al,%eax
  362. addl %eax,%esi
  363. movb $0,(%esi)
  364. end;
  365. es.nameofs:=pointer(longint(@path)+1);
  366. asm
  367. movw %ss,es.argseg
  368. movw %ss,es.envseg
  369. movw %ss,es.nameseg
  370. end;
  371. es.sizearg:=j;
  372. es.numenv:=0;
  373. {Typecasting of sets in FPK is a bit hard.}
  374. es.mode1:=byte(runflags);
  375. es.mode2:=byte(winflags);
  376. {Now exec the program.}
  377. asm
  378. leal es,%edx
  379. mov $0x7f06,%ax
  380. call syscall
  381. xorl %edi,%edi
  382. jnc .Lexprg1
  383. xchgl %eax,%edi
  384. xorl %eax,%eax
  385. decl %eax
  386. .Lexprg1:
  387. movw %di,doserror
  388. movl %eax,__RESULT
  389. end;
  390. freemem(args,512);
  391. freemem(env,8192);
  392. {Phew! That's it. This was the most sophisticated procedure to call
  393. a system function I ever wrote!}
  394. end;
  395. function dosversion:word;assembler;
  396. {Returns DOS version in DOS and OS/2 version in OS/2}
  397. asm
  398. movb $0x30,%ah
  399. call syscall
  400. end;
  401. procedure getdate(var year,month,day,dayofweek:word);
  402. begin
  403. asm
  404. movb $0x2a,%ah
  405. call syscall
  406. xorb %ah,%ah
  407. movl 20(%ebp),%edi
  408. stosw
  409. movl 16(%ebp),%edi
  410. movb %dl,%al
  411. stosw
  412. movl 12(%ebp),%edi
  413. movb %dh,%al
  414. stosw
  415. movl 8(%ebp),%edi
  416. xchgw %ecx,%eax
  417. stosw
  418. end;
  419. end;
  420. procedure setdate(year,month,day : word);
  421. begin
  422. {DOS only! You cannot change the system date in OS/2!}
  423. asm
  424. movw 8(%ebp),%cx
  425. movb 10(%ebp),%dh
  426. movb 12(%ebp),%dl
  427. movb $0x2b,%ah
  428. call syscall
  429. xorb %ah,%ah
  430. movw %ax,doserror
  431. end;
  432. end;
  433. procedure gettime(var hour,minute,second,sec100:word);
  434. begin
  435. asm
  436. movb $0x2c,%ah
  437. call syscall
  438. xorb %ah,%ah
  439. movl 20(%ebp),%edi
  440. movb %dl,%al
  441. stosw
  442. movl 16(%ebp),%edi
  443. movb %dh,%al
  444. stosw
  445. movl 12(%ebp),%edi
  446. movb %cl,%al
  447. stosw
  448. movl 8(%ebp),%edi
  449. movb %ch,%al
  450. stosw
  451. end;
  452. end;
  453. procedure settime(hour,minute,second,sec100:word);
  454. begin
  455. asm
  456. movb 8(%ebp),%ch
  457. movb 10(%ebp),%cl
  458. movb 12(%ebp),%dh
  459. movb 14(%ebp),%dl
  460. movb $0x2d,%ah
  461. call syscall
  462. xorb %ah,%ah
  463. movw %ax,doserror
  464. end;
  465. end;
  466. procedure getcbreak(var breakvalue:boolean);
  467. begin
  468. {! Do not use in OS/2. Also not recommended in DOS. Use
  469. signal handling instead.}
  470. asm
  471. movw $0x3300,%ax
  472. call syscall
  473. movl 8(%ebp),%eax
  474. movb %dl,(%eax)
  475. end;
  476. end;
  477. procedure setcbreak(breakvalue:boolean);
  478. begin
  479. {! Do not use in OS/2. Also not recommended in DOS. Use
  480. signal handling instead.}
  481. asm
  482. movb 8(%ebp),%dl
  483. movw $0x3301,%ax
  484. call syscall
  485. end;
  486. end;
  487. procedure getverify(var verify:boolean);
  488. begin
  489. {! Do not use in OS/2.}
  490. asm
  491. movb $0x54,%ah
  492. call syscall
  493. movl 8(%ebp),%edi
  494. stosb
  495. end;
  496. end;
  497. procedure setverify(verify:boolean);
  498. begin
  499. {! Do not use in OS/2.}
  500. asm
  501. movb 8(%ebp),%al
  502. movb $0x2e,%ah
  503. call syscall
  504. end;
  505. end;
  506. function diskfree(drive:byte):longint;
  507. var fi:TFSinfo;
  508. begin
  509. if os_mode=osDOS then
  510. {Function 36 is not supported in OS/2.}
  511. asm
  512. movb 8(%ebp),%dl
  513. movb $0x36,%ah
  514. call syscall
  515. cmpw $-1,%ax
  516. je .LDISKFREE1
  517. mulw %cx
  518. mulw %bx
  519. shll $16,%edx
  520. movw %ax,%dx
  521. xchgl %edx,%eax
  522. leave
  523. ret
  524. .LDISKFREE1:
  525. cwde
  526. leave
  527. ret
  528. end
  529. else
  530. {In OS/2, we use the filesystem information.}
  531. begin
  532. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  533. if doserror=0 then
  534. diskfree:=FI.free_clusters*FI.sectors_per_cluster*
  535. FI.bytes_per_sector
  536. else
  537. diskfree:=-1;
  538. end;
  539. end;
  540. function disksize(drive:byte):longint;
  541. var fi:TFSinfo;
  542. begin
  543. if os_mode=osDOS then
  544. {Function 36 is not supported in OS/2.}
  545. asm
  546. movb 8(%ebp),%dl
  547. movb $0x36,%ah
  548. call syscall
  549. movw %dx,%bx
  550. cmpw $-1,%ax
  551. je .LDISKSIZE1
  552. mulw %cx
  553. mulw %bx
  554. shll $16,%edx
  555. movw %ax,%dx
  556. xchgl %edx,%eax
  557. leave
  558. ret
  559. .LDISKSIZE1:
  560. cwde
  561. leave
  562. ret
  563. end
  564. else
  565. {In OS/2, we use the filesystem information.}
  566. begin
  567. doserror:=dosqueryFSinfo(drive,1,FI,sizeof(FI));
  568. if doserror=0 then
  569. disksize:=FI.total_clusters*FI.sectors_per_cluster*
  570. FI.bytes_per_sector
  571. else
  572. disksize:=-1;
  573. end;
  574. end;
  575. procedure searchrec2dossearchrec(var f:searchrec);
  576. const namesize=255;
  577. var l,i:longint;
  578. begin
  579. l:=length(f.name);
  580. for i:=1 to namesize do
  581. f.name[i-1]:=f.name[i];
  582. f.name[l]:=#0;
  583. end;
  584. procedure dossearchrec2searchrec(var f : searchrec);
  585. const namesize=255;
  586. var l,i : longint;
  587. begin
  588. for i:=0 to namesize do
  589. if f.name[i]=#0 then
  590. begin
  591. l:=i;
  592. break;
  593. end;
  594. for i:=namesize-1 downto 0 do
  595. f.name[i+1]:=f.name[i];
  596. f.name[0]:=char(l);
  597. end;
  598. procedure findfirst(const path:pathstr;attr:word;var f:searchRec);
  599. procedure _findfirst(path:pchar;attr:word;var f:searchrec);
  600. begin
  601. asm
  602. movl 12(%esp),%edx
  603. movw 16(%esp),%cx
  604. {No need to set DTA in EMX. Just give a pointer in ESI.}
  605. movl 18(%ebp),%esi
  606. movb $0x4e,%ah
  607. call syscall
  608. jnc .LFF
  609. movw %ax,doserror
  610. .LFF:
  611. end;
  612. end;
  613. var path0:array[0..255] of char;
  614. begin
  615. {No error.}
  616. doserror:=0;
  617. strPcopy(path0,path);
  618. _findfirst(path0,attr,f);
  619. dossearchrec2searchrec(f);
  620. end;
  621. procedure findnext(var f:searchRec);
  622. procedure _findnext(var f : searchrec);
  623. begin
  624. asm
  625. movl 12(%ebp),%esi
  626. movb $0x4f,%ah
  627. call syscall
  628. jnc .LFN
  629. movw %ax,doserror
  630. .LFN:
  631. end;
  632. end;
  633. begin
  634. {No error}
  635. doserror:=0;
  636. searchrec2dossearchrec(f);
  637. _findnext(f);
  638. dossearchrec2searchrec(f);
  639. end;
  640. procedure swapvectors;
  641. {For TP compatibility, this exists.}
  642. begin
  643. end;
  644. type PPchar=^Pchar;
  645. {$ASMMODE DIRECT}
  646. function envs:PPchar;assembler;
  647. asm
  648. movl _environ,%eax
  649. end ['EAX'];
  650. function envcount:longint;assembler;
  651. var hp : ppchar;
  652. asm
  653. movl _envc,%eax
  654. end ['EAX'];
  655. {$ASMMODE ATT}
  656. function envstr(index : longint) : string;
  657. var hp:PPchar;
  658. begin
  659. if (index<=0) or (index>envcount) then
  660. begin
  661. envstr:='';
  662. exit;
  663. end;
  664. hp:=envs+4*(index-1);
  665. envstr:=strpas(hp^);
  666. end;
  667. function getenv(const envvar : string) : string;
  668. var hs,_envvar : string;
  669. eqpos,i : longint;
  670. begin
  671. _envvar:=upcase(envvar);
  672. getenv:='';
  673. for i:=1 to envcount do
  674. begin
  675. hs:=envstr(i);
  676. eqpos:=pos('=',hs);
  677. if copy(hs,1,eqpos-1)=_envvar then
  678. begin
  679. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  680. exit;
  681. end;
  682. end;
  683. end;
  684. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  685. var ext:extstr);
  686. var p1,i : longint;
  687. begin
  688. {Get drive name}
  689. p1:=pos(':',path);
  690. if p1>0 then
  691. begin
  692. dir:=path[1]+':';
  693. delete(path,1,p1);
  694. end
  695. else
  696. dir:='';
  697. { split the path and the name, there are no more path informtions }
  698. { if path contains no backslashes }
  699. while true do
  700. begin
  701. p1:=pos('\',path);
  702. if p1=0 then
  703. p1:=pos('/',path);
  704. if p1=0 then
  705. break;
  706. dir:=dir+copy(path,1,p1);
  707. delete(path,1,p1);
  708. end;
  709. {Try to find an extension.}
  710. ext:='';
  711. for i:=length(path) downto 1 do
  712. if path[i]='.' then
  713. begin
  714. ext:=copy(path,i,high(extstr));
  715. delete(path,i,length(path)-i+1);
  716. break;
  717. end;
  718. name:=path;
  719. end;
  720. function fexpand(const path:pathstr):pathstr;
  721. function get_current_drive:byte;assembler;
  722. asm
  723. movb $0x19,%ah
  724. call syscall
  725. end;
  726. var s,pa:string;
  727. i,j:longint;
  728. begin
  729. getdir(0,s);
  730. pa:=upcase(path);
  731. {Allow slash as backslash}
  732. for i:=1 to length(pa) do
  733. if pa[i]='/' then
  734. pa[i]:='\';
  735. if (length(pa)>1) and (pa[1] in ['A'..'Z']) and (pa[2]=':') then
  736. begin
  737. {We must get the right directory}
  738. getdir(byte(pa[1])-byte('A')+1,s);
  739. if (byte(pa[0])>2) and (pa[3]<>'\') then
  740. if pa[1]=s[1] then
  741. pa:=s+'\'+copy (pa,3,length(pa))
  742. else
  743. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  744. end
  745. else
  746. if pa[1]='\' then
  747. pa:=s[1]+':'+pa
  748. else if s[0]=#3 then
  749. pa:=s+pa
  750. else
  751. pa:=s+'\'+pa;
  752. {First remove all references to '\.\'}
  753. i:=pos('\.\',pa);
  754. while i<>0 do
  755. begin
  756. delete(pa,i,2);
  757. i:=pos('\.\',pa);
  758. end;
  759. {Now remove also all references to '\..\' + of course previous dirs..}
  760. repeat
  761. i:=pos('\..\',pa);
  762. if i<>0 then
  763. begin
  764. j:=i-1;
  765. while (j>1) and (pa[j]<>'\') do
  766. dec(j);
  767. delete (pa,j,i-j+3);
  768. end;
  769. until i=0;
  770. {Remove End . and \}
  771. if (length(pa)>0) and (pa[length(pa)]='.') then
  772. dec(byte(pa[0]));
  773. if (length(pa)>0) and (pa[length(pa)]='\') then
  774. dec(byte(pa[0]));
  775. fexpand:=pa;
  776. end;
  777. procedure packtime(var d:datetime;var time:longint);
  778. var zs:longint;
  779. begin
  780. time:=-1980;
  781. time:=time+d.year and 127;
  782. time:=time shl 4;
  783. time:=time+d.month;
  784. time:=time shl 5;
  785. time:=time+d.day;
  786. time:=time shl 16;
  787. zs:=d.hour;
  788. zs:=zs shl 6;
  789. zs:=zs+d.min;
  790. zs:=zs shl 5;
  791. zs:=zs+d.sec div 2;
  792. time:=time+(zs and $ffff);
  793. end;
  794. procedure unpacktime (time:longint;var d:datetime);
  795. begin
  796. d.sec:=(time and 31) * 2;
  797. time:=time shr 5;
  798. d.min:=time and 63;
  799. time:=time shr 6;
  800. d.hour:=time and 31;
  801. time:=time shr 5;
  802. d.day:=time and 31;
  803. time:=time shr 5;
  804. d.month:=time and 15;
  805. time:=time shr 4;
  806. d.year:=time+1980;
  807. end;
  808. procedure getfattr(var f;var attr : word);assembler;
  809. asm
  810. movw $0x4300,%ax
  811. movl f,%edx
  812. {addl $filerec.name,%edx Doesn't work!!}
  813. addl $60,%edx
  814. call syscall
  815. movl attr,%ebx
  816. movw %cx,(%ebx)
  817. end;
  818. procedure setfattr(var f;attr : word);assembler;
  819. asm
  820. movw $0x4301,%ax
  821. movl f,%edx
  822. {addl $filerec.name,%edx Doesn't work!!}
  823. addl $60,%edx
  824. movw attr,%cx
  825. call syscall
  826. end;
  827. end.
  828. {
  829. $Log$
  830. Revision 1.8 1998-10-16 14:18:02 daniel
  831. * Updates
  832. Revision 1.7 1998/07/08 14:44:11 daniel
  833. + Added moucalls and viocalls written by Tomas Hajny.
  834. + Final routines in doscalls implemented.
  835. * Fixed bugs in dos.pas.
  836. * Changed some old $ifdef FPK into $ifdef FPC.
  837. - Removed go32 stuff from dos.pas.
  838. - Removed '/' to '\' translation from system unit - EMX does this
  839. automatically.
  840. }