dos.pas 25 KB

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