dos.pp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. {
  2. $Id$
  3. This unit mimics the DOS unit for Win32
  4. This file is part of the Free Pascal run time library.
  5. Copyright (c) 1998 by the Free Pascal development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$I os.inc}
  13. unit dos;
  14. interface
  15. uses
  16. strings;
  17. const
  18. { bit masks for CPU flags}
  19. fcarry = $0001;
  20. fparity = $0004;
  21. fauxiliary = $0010;
  22. fzero = $0040;
  23. fsign = $0080;
  24. foverflow = $0800;
  25. { bit masks for file attributes }
  26. readonly = $01;
  27. hidden = $02;
  28. sysfile = $04;
  29. volumeid = $08;
  30. directory = $10;
  31. archive = $20;
  32. anyfile = $3F;
  33. fmclosed = $D7B0;
  34. fminput = $D7B1;
  35. fmoutput = $D7B2;
  36. fminout = $D7B3;
  37. type
  38. { some string types }
  39. comstr = string[127]; { command line string }
  40. pathstr = string[79]; { string for a file path }
  41. dirstr = string[67]; { string for a directory }
  42. namestr = string[8]; { string for a file name }
  43. extstr = string[4]; { string for an extension }
  44. { search record which is used by findfirst and findnext }
  45. {$ifndef GO32V2}
  46. {$PACKRECORDS 1}
  47. searchrec = record
  48. fill : array[1..21] of byte;
  49. attr : byte;
  50. time : longint;
  51. reserved : word; { requires the DOS extender (DJ GNU-C) }
  52. size : longint;
  53. name : string[15]; { the same size as declared by (DJ GNU C) }
  54. end;
  55. {$else GO32V2}
  56. {$PACKRECORDS 1}
  57. searchrec = record
  58. fill : array[1..21] of byte;
  59. attr : byte;
  60. time : longint;
  61. { reserved : word; not in DJGPP V2 }
  62. size : longint;
  63. name : string[12]; { the same size as declared by (DJ GNU C) }
  64. end;
  65. {$endif GO32V2}
  66. {$PACKRECORDS 2}
  67. { file record for untyped files comes from filerec.inc}
  68. {$i filerec.inc}
  69. { file record for text files comes from textrec.inc}
  70. {$i textrec.inc}
  71. {$ifdef GO32V1}
  72. { data structure for the registers needed by msdos and intr }
  73. { Go32 V2 follows trealregs of go32 }
  74. registers = record
  75. case i : integer of
  76. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  77. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  78. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  79. end;
  80. {$endif GO32V1}
  81. {$ifdef GO32V2}
  82. { data structure for the registers needed by msdos and intr }
  83. { Go32 V2 follows trealregs of go32 }
  84. registers = go32.registers;
  85. {$endif GO32V2}
  86. {$PACKRECORDS 1}
  87. { record for date and time }
  88. datetime = record
  89. year,month,day,hour,min,sec : word;
  90. end;
  91. var
  92. { error variable }
  93. doserror : integer;
  94. procedure getdate(var year,month,day,dayofweek : word);
  95. procedure gettime(var hour,minute,second,sec100 : word);
  96. function dosversion : word;
  97. procedure setdate(year,month,day : word);
  98. procedure settime(hour,minute,second,sec100 : word);
  99. procedure getcbreak(var breakvalue : boolean);
  100. procedure setcbreak(breakvalue : boolean);
  101. procedure getverify(var verify : boolean);
  102. procedure setverify(verify : boolean);
  103. function diskfree(drive : byte) : longint;
  104. function disksize(drive : byte) : longint;
  105. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  106. procedure findnext(var f : searchRec);
  107. { is a dummy in win32 }
  108. procedure swapvectors;
  109. { not supported:
  110. procedure getintvec(intno : byte;var vector : pointer);
  111. procedure setintvec(intno : byte;vector : pointer);
  112. procedure keep(exitcode : word);
  113. procedure msdos(var regs : registers);
  114. procedure intr(intno : byte;var regs : registers);
  115. }
  116. procedure getfattr(var f;var attr : word);
  117. procedure setfattr(var f;attr : word);
  118. function fsearch(const path : pathstr;dirlist : string) : pathstr;
  119. procedure getftime(var f;var time : longint);
  120. procedure setftime(var f;time : longint);
  121. procedure packtime (var d: datetime; var time: longint);
  122. procedure unpacktime (time: longint; var d: datetime);
  123. function fexpand(const path : pathstr) : pathstr;
  124. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;
  125. var ext : extstr);
  126. procedure exec(const path : pathstr;const comline : comstr);
  127. function dosexitcode : word;
  128. function envcount : longint;
  129. function envstr(index : longint) : string;
  130. function getenv(const envvar : string): string;
  131. implementation
  132. { taken from the DOS version }
  133. function fsearch(const path : pathstr;dirlist : string) : pathstr;
  134. var
  135. newdir : pathstr;
  136. i,p1 : byte;
  137. s : searchrec;
  138. begin
  139. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  140. { No wildcards allowed in these things }
  141. fsearch:=''
  142. else
  143. begin
  144. { allow slash as backslash }
  145. for i:=1 to length(dirlist) do
  146. if dirlist[i]='/' then dirlist[i]:='\';
  147. repeat
  148. { get first path }
  149. p1:=pos(';',dirlist);
  150. if p1>0 then
  151. begin
  152. newdir:=copy(dirlist,1,p1-1);
  153. delete(dirlist,1,p1)
  154. end
  155. else
  156. begin
  157. newdir:=dirlist;
  158. dirlist:=''
  159. end;
  160. if (newdir[length(newdir)]<>'\') and
  161. (newdir[length(newdir)]<>':') then
  162. newdir:=newdir+'\';
  163. findfirst(newdir+path,anyfile,s);
  164. if doserror=0 then
  165. begin
  166. { this should be newdir:=newdir+path
  167. because path can contain a path part !! }
  168. {newdir:=newdir+s.name;}
  169. newdir:=newdir+path;
  170. { this was for LINUX:
  171. if pos('.\',newdir)=1 then
  172. delete(newdir, 1, 2)
  173. DOS strips off an initial .\
  174. }
  175. end
  176. else newdir:='';
  177. until(dirlist='') or (length(newdir)>0);
  178. fsearch:=newdir;
  179. end;
  180. end;
  181. procedure getftime(var f;var time : longint);
  182. begin
  183. dosregs.bx:=textrec(f).handle;
  184. dosregs.ax:=$5700;
  185. msdos(dosregs);
  186. time:=(dosregs.dx shl 16)+dosregs.cx;
  187. doserror:=dosregs.al;
  188. end;
  189. procedure setftime(var f;time : longint);
  190. begin
  191. dosregs.bx:=textrec(f).handle;
  192. dosregs.ecx:=time;
  193. dosregs.ax:=$5701;
  194. msdos(dosregs);
  195. doserror:=dosregs.al;
  196. end;
  197. procedure msdos(var regs : registers);
  198. begin
  199. intr($21,regs);
  200. end;
  201. {$ifdef GO32V2}
  202. procedure intr(intno : byte;var regs : registers);
  203. begin
  204. realintr(intno,regs);
  205. end;
  206. {$else GO32V2}
  207. procedure intr(intno : byte;var regs : registers);
  208. begin
  209. asm
  210. .data
  211. int86:
  212. .byte 0xcd
  213. int86_vec:
  214. .byte 0x03
  215. jmp int86_retjmp
  216. .text
  217. movl 8(%ebp),%eax
  218. movb %al,int86_vec
  219. movl 10(%ebp),%eax
  220. // do not use first int
  221. addl $2,%eax
  222. movl 4(%eax),%ebx
  223. movl 8(%eax),%ecx
  224. movl 12(%eax),%edx
  225. movl 16(%eax),%ebp
  226. movl 20(%eax),%esi
  227. movl 24(%eax),%edi
  228. movl (%eax),%eax
  229. jmp int86
  230. int86_retjmp:
  231. pushf
  232. pushl %ebp
  233. pushl %eax
  234. movl %esp,%ebp
  235. // calc EBP new
  236. addl $12,%ebp
  237. movl 10(%ebp),%eax
  238. // do not use first int
  239. addl $2,%eax
  240. popl (%eax)
  241. movl %ebx,4(%eax)
  242. movl %ecx,8(%eax)
  243. movl %edx,12(%eax)
  244. // restore EBP
  245. popl %edx
  246. movl %edx,16(%eax)
  247. movl %esi,20(%eax)
  248. movl %edi,24(%eax)
  249. // ignore ES and DS
  250. popl %ebx /* flags */
  251. movl %ebx,32(%eax)
  252. // FS and GS too
  253. end;
  254. end;
  255. {$endif GO32V2}
  256. var
  257. lastdosexitcode : word;
  258. {$ifdef GO32V2}
  259. { this code is just the most basic part of dosexec.c from
  260. the djgpp code }
  261. procedure exec(const path : pathstr;const comline : comstr);
  262. procedure do_system(p,c : string);
  263. {
  264. Table 0931
  265. Format of EXEC parameter block for AL=00h,01h,04h:
  266. Offset Size Description
  267. 00h WORD segment of environment to copy for child process (copy caller's
  268. environment if 0000h)
  269. this does not seem to work (PM)
  270. 02h DWORD pointer to command tail to be copied into child's PSP
  271. 06h DWORD pointer to first FCB to be copied into child's PSP
  272. 0Ah DWORD pointer to second FCB to be copied into child's PSP
  273. 0Eh DWORD (AL=01h) will hold subprogram's initial SS:SP on return
  274. 12h DWORD (AL=01h) will hold entry point (CS:IP) on return
  275. INT 21 4B--
  276. Copied from Ralf Brown's Interrupt List
  277. }
  278. type
  279. realptr = record
  280. ofs,seg : word;
  281. end;
  282. texecblock = record
  283. envseg : word;
  284. comtail : realptr;
  285. firstFCB : realptr;
  286. secondFCB : realptr;
  287. iniStack : realptr;
  288. iniCSIP : realptr;
  289. end;
  290. var current_dos_buffer_pos : longint;
  291. function paste_to_dos(src : string) : boolean;
  292. var c : array[0..255] of char;
  293. begin
  294. paste_to_dos:=false;
  295. if current_dos_buffer_pos+length(src)+1>transfer_buffer+tb_size then
  296. begin
  297. doserror:=200;{ what value should we use here ? }
  298. exit;
  299. end;
  300. move(src[1],c[0],length(src));
  301. c[length(src)]:=#0;
  302. seg_move(get_ds,longint(@c),dosmemselector,current_dos_buffer_pos,length(src)+1);
  303. current_dos_buffer_pos:=current_dos_buffer_pos+length(src)+1;
  304. paste_to_dos:=true;
  305. end;
  306. var
  307. i,la_env,la_p,la_c,la_e,fcb1_la,fcb2_la : longint;
  308. arg_ofs : longint;
  309. execblock : texecblock;
  310. begin
  311. la_env:=transfer_buffer;
  312. while (la_env mod 16)<>0 do inc(la_env);
  313. current_dos_buffer_pos:=la_env;
  314. for i:=1 to envcount do
  315. begin
  316. paste_to_dos(envstr(i));
  317. end;
  318. paste_to_dos(''); { adds a double zero at the end }
  319. { allow slash as backslash }
  320. for i:=1 to length(p) do
  321. if p[i]='/' then p[i]:='\';
  322. la_p:=current_dos_buffer_pos;
  323. paste_to_dos(p);
  324. la_c:=current_dos_buffer_pos;
  325. paste_to_dos(c);
  326. la_e:=current_dos_buffer_pos;
  327. fcb1_la:=la_e;
  328. la_e:=la_e+16;
  329. fcb2_la:=la_e;
  330. la_e:=la_e+16;
  331. { allocate FCB see dosexec code }
  332. dosregs.ax:=$2901;
  333. arg_ofs:=1;
  334. while (c[arg_ofs]=' ') or (c[arg_ofs]=#9) do inc(arg_ofs);
  335. dosregs.ds:=(la_c+arg_ofs) div 16;
  336. dosregs.si:=(la_c+arg_ofs) mod 16;
  337. dosregs.es:=fcb1_la div 16;
  338. dosregs.di:=fcb1_la mod 16;
  339. msdos(dosregs);
  340. repeat
  341. inc(arg_ofs);
  342. until (c[arg_ofs]=' ') or
  343. (c[arg_ofs]=#9) or
  344. (c[arg_ofs]=#13);
  345. if c[arg_ofs]<>#13 then
  346. begin
  347. inc(arg_ofs);
  348. while (c[arg_ofs]=' ') or (c[arg_ofs]=#9) do inc(arg_ofs);
  349. end;
  350. { allocate second FCB see dosexec code }
  351. dosregs.ax:=$2901;
  352. dosregs.ds:=(la_c+arg_ofs) div 16;
  353. dosregs.si:=(la_c+arg_ofs) mod 16;
  354. dosregs.es:=fcb2_la div 16;
  355. dosregs.di:=fcb2_la mod 16;
  356. msdos(dosregs);
  357. with execblock do
  358. begin
  359. envseg:=la_env div 16;
  360. comtail.seg:=la_c div 16;
  361. comtail.ofs:=la_c mod 16;
  362. firstFCB.seg:=fcb1_la div 16;
  363. firstFCB.ofs:=fcb1_la mod 16;
  364. secondFCB.seg:=fcb2_la div 16;
  365. secondFCB.ofs:=fcb2_la mod 16;
  366. end;
  367. seg_move(get_ds,longint(@execblock),dosmemselector,la_e,sizeof(texecblock));
  368. dosregs.edx:=la_p mod 16;
  369. dosregs.ds:=la_p div 16;
  370. dosregs.ebx:=la_e mod 16;
  371. dosregs.es:=la_e div 16;
  372. dosregs.ax:=$4b00;
  373. msdos(dosregs);
  374. if (dosregs.flags and 1) <> 0 then
  375. begin
  376. doserror:=dosregs.ax;
  377. lastdosexitcode:=0;
  378. exit;
  379. end
  380. else
  381. begin
  382. dosregs.ax:=$4d00;
  383. msdos(dosregs);
  384. lastdosexitcode:=dosregs.al;
  385. end;
  386. end;
  387. { var
  388. p,c : array[0..255] of char; }
  389. var c : string;
  390. begin
  391. doserror:=0;
  392. { move(path[1],p,length(path));
  393. p[length(path)]:=#0; }
  394. move(comline[0],c[1],length(comline)+1);
  395. c[length(comline)+2]:=#13;
  396. c[0]:=char(length(comline)+2);
  397. do_system(path,c);
  398. end;
  399. {$else GO32V2}
  400. procedure exec(const path : pathstr;const comline : comstr);
  401. procedure do_system(p : pchar);
  402. begin
  403. asm
  404. movl 12(%ebp),%ebx
  405. movw $0xff07,%ax
  406. int $0x21
  407. movw %ax,_LASTDOSEXITCODE
  408. end;
  409. end;
  410. var
  411. i : longint;
  412. execute : string;
  413. b : array[0..255] of char;
  414. begin
  415. doserror:=0;
  416. execute:=path+' '+comline;
  417. { allow slash as backslash for the program name only }
  418. for i:=1 to length(path) do
  419. if execute[i]='/' then execute[i]:='\';
  420. move(execute[1],b,length(execute));
  421. b[length(execute)]:=#0;
  422. do_system(b);
  423. end;
  424. {$endif GO32V2}
  425. function dosexitcode : word;
  426. begin
  427. dosexitcode:=lastdosexitcode;
  428. end;
  429. function dosversion : word;
  430. begin
  431. dosregs.ax:=$3000;
  432. msdos(dosregs);
  433. dosversion:=dosregs.ax;
  434. end;
  435. procedure getdate(var year,month,day,dayofweek : word);
  436. begin
  437. dosregs.ax:=$2a00;
  438. msdos(dosregs);
  439. dayofweek:=dosregs.al;
  440. year:=dosregs.cx;
  441. month:=dosregs.dh;
  442. day:=dosregs.dl;
  443. end;
  444. procedure setdate(year,month,day : word);
  445. begin
  446. dosregs.cx:=year;
  447. dosregs.dx:=month*$100+day;
  448. dosregs.ah:=$2b;
  449. msdos(dosregs);
  450. doserror:=dosregs.al;
  451. end;
  452. procedure gettime(var hour,minute,second,sec100 : word);
  453. begin
  454. dosregs.ah:=$2c;
  455. msdos(dosregs);
  456. hour:=dosregs.ch;
  457. minute:=dosregs.cl;
  458. second:=dosregs.dh;
  459. sec100:=dosregs.dl;
  460. end;
  461. procedure settime(hour,minute,second,sec100 : word);
  462. begin
  463. dosregs.cx:=hour*$100+minute;
  464. dosregs.dx:=second*$100+sec100;
  465. dosregs.ah:=$2d;
  466. msdos(dosregs);
  467. doserror:=dosregs.al;
  468. end;
  469. procedure getcbreak(var breakvalue : boolean);
  470. begin
  471. dosregs.ax:=$3300;
  472. msdos(dosregs);
  473. breakvalue:=dosregs.dl<>0;
  474. end;
  475. procedure setcbreak(breakvalue : boolean);
  476. begin
  477. dosregs.ax:=$3301;
  478. dosregs.dl:=ord(breakvalue);
  479. msdos(dosregs);
  480. end;
  481. procedure getverify(var verify : boolean);
  482. begin
  483. dosregs.ah:=$54;
  484. msdos(dosregs);
  485. verify:=dosregs.al<>0;
  486. end;
  487. procedure setverify(verify : boolean);
  488. begin
  489. dosregs.ah:=$2e;
  490. dosregs.al:=ord(verify);
  491. msdos(dosregs);
  492. end;
  493. function diskfree(drive : byte) : longint;
  494. begin
  495. dosregs.dl:=drive;
  496. dosregs.ah:=$36;
  497. msdos(dosregs);
  498. if dosregs.ax<>$FFFF then
  499. begin
  500. diskfree:=dosregs.ax;
  501. diskfree:=diskfree*dosregs.bx;
  502. diskfree:=diskfree*dosregs.cx;
  503. end
  504. else
  505. diskfree:=-1;
  506. end;
  507. function disksize(drive : byte) : longint;
  508. begin
  509. dosregs.dl:=drive;
  510. dosregs.ah:=$36;
  511. msdos(dosregs);
  512. if dosregs.ax<>$FFFF then
  513. begin
  514. disksize:=dosregs.ax;
  515. disksize:=disksize*dosregs.cx;
  516. disksize:=disksize*dosregs.dx;
  517. end
  518. else
  519. disksize:=-1;
  520. end;
  521. procedure searchrec2dossearchrec(var f : searchrec);
  522. var
  523. l,i : longint;
  524. begin
  525. l:=length(f.name);
  526. for i:=1 to 12 do
  527. f.name[i-1]:=f.name[i];
  528. f.name[l]:=#0;
  529. end;
  530. procedure dossearchrec2searchrec(var f : searchrec);
  531. var
  532. l,i : longint;
  533. begin
  534. l:=12;
  535. for i:=0 to 12 do
  536. if f.name[i]=#0 then
  537. begin
  538. l:=i;
  539. break;
  540. end;
  541. for i:=11 downto 0 do
  542. f.name[i+1]:=f.name[i];
  543. f.name[0]:=chr(l);
  544. end;
  545. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  546. {$ifdef GO32V2}
  547. procedure _findfirst(path : pchar;attr : word;var f : searchrec);
  548. var
  549. i : longint;
  550. begin
  551. { allow slash as backslash }
  552. for i:=0 to strlen(path) do
  553. if path[i]='/' then path[i]:='\';
  554. copytodos(f,sizeof(searchrec));
  555. dosregs.edx:=transfer_buffer mod 16;
  556. dosregs.ds:=transfer_buffer div 16;
  557. dosregs.ah:=$1a;
  558. msdos(dosregs);
  559. dosregs.ecx:=attr;
  560. dosregs.edx:=(transfer_buffer mod 16) + Sizeof(searchrec)+1;
  561. dosmemput(transfer_buffer div 16,
  562. (transfer_buffer mod 16) +Sizeof(searchrec)+1,path^,strlen(path)+1);
  563. dosregs.ds:=transfer_buffer div 16;
  564. dosregs.ah:=$4e;
  565. msdos(dosregs);
  566. copyfromdos(f,sizeof(searchrec));
  567. if dosregs.flags and carryflag<>0 then
  568. doserror:=dosregs.ax;
  569. end;
  570. {$else GO32V2}
  571. procedure _findfirst(path : pchar;attr : word;var f : searchrec);
  572. var
  573. i : longint;
  574. begin
  575. { allow slash as backslash }
  576. for i:=0 to strlen(path) do
  577. if path[i]='/' then path[i]:='\';
  578. asm
  579. movl 18(%ebp),%edx
  580. movb $0x1a,%ah
  581. int $0x21
  582. movl 12(%ebp),%edx
  583. movzwl 16(%ebp),%ecx
  584. movb $0x4e,%ah
  585. int $0x21
  586. jnc .LFF
  587. movw %ax,U_DOS_DOSERROR
  588. .LFF:
  589. end;
  590. end;
  591. {$endif GO32V2}
  592. var
  593. path0 : array[0..80] of char;
  594. begin
  595. { no error }
  596. doserror:=0;
  597. strpcopy(path0,path);
  598. _findfirst(path0,attr,f);
  599. dossearchrec2searchrec(f);
  600. end;
  601. procedure findnext(var f : searchRec);
  602. {$ifdef GO32V2}
  603. procedure _findnext(var f : searchrec);
  604. begin
  605. copytodos(f,sizeof(searchrec));
  606. dosregs.edx:=transfer_buffer mod 16;
  607. dosregs.ds:=transfer_buffer div 16;
  608. dosregs.ah:=$1a;
  609. msdos(dosregs);
  610. dosregs.ah:=$4f;
  611. msdos(dosregs);
  612. copyfromdos(f,sizeof(searchrec));
  613. if dosregs.flags and carryflag <> 0 then
  614. doserror:=dosregs.ax;
  615. end;
  616. {$else GO32V2}
  617. procedure _findnext(var f : searchrec);
  618. begin
  619. asm
  620. movl 12(%ebp),%edx
  621. movb $0x1a,%ah
  622. int $0x21
  623. movb $0x4f,%ah
  624. int $0x21
  625. jnc .LFN
  626. movw %ax,U_DOS_DOSERROR
  627. .LFN:
  628. end;
  629. end;
  630. {$endif GO32V2}
  631. begin
  632. { no error }
  633. doserror:=0;
  634. searchrec2dossearchrec(f);
  635. _findnext(f);
  636. dossearchrec2searchrec(f);
  637. end;
  638. procedure swapvectors;
  639. {$ifdef go32v2}
  640. { uses four global symbols from v2prt0.as
  641. to be able to know the current exception state
  642. without using dpmiexcp unit }
  643. begin
  644. asm
  645. movl _exception_exit,%eax
  646. orl %eax,%eax
  647. je .Lno_excep
  648. movl _v2prt0_exceptions_on,%eax
  649. orl %eax,%eax
  650. je .Lexceptions_off
  651. movl _swap_out,%eax
  652. call *%eax
  653. jmp .Lno_excep
  654. .Lexceptions_off:
  655. movl _swap_in,%eax
  656. call *%eax
  657. .Lno_excep:
  658. end;
  659. end;
  660. {$else not go32v2}
  661. begin
  662. { only a dummy }
  663. end;
  664. {$endif go32v2}
  665. type
  666. ppchar = ^pchar;
  667. {$ifdef GO32V1}
  668. function envs : ppchar;
  669. begin
  670. asm
  671. movl _environ,%eax
  672. leave
  673. ret
  674. end ['EAX'];
  675. end;
  676. {$endif}
  677. function envcount : longint;
  678. var
  679. hp : ppchar;
  680. begin
  681. {$ifdef GO32V2}
  682. hp:=environ;
  683. {$else GO32V2}
  684. hp:=envs;
  685. {$endif}
  686. envcount:=0;
  687. while assigned(hp^) do
  688. begin
  689. { not the best solution, but quite understandable }
  690. inc(envcount);
  691. hp:=hp+4;
  692. end;
  693. end;
  694. function envstr(index : longint) : string;
  695. var
  696. hp : ppchar;
  697. begin
  698. if (index<=0) or (index>envcount) then
  699. begin
  700. envstr:='';
  701. exit;
  702. end;
  703. {$ifdef GO32V2}
  704. hp:=environ+4*(index-1);
  705. {$else GO32V2}
  706. hp:=envs+4*(index-1);
  707. {$endif GO32V2}
  708. envstr:=strpas(hp^);
  709. end;
  710. function getenv(const envvar : string) : string;
  711. var
  712. hs,_envvar : string;
  713. eqpos,i : longint;
  714. begin
  715. _envvar:=upcase(envvar);
  716. getenv:='';
  717. for i:=1 to envcount do
  718. begin
  719. hs:=envstr(i);
  720. eqpos:=pos('=',hs);
  721. if copy(hs,1,eqpos-1)=_envvar then
  722. begin
  723. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  724. exit;
  725. end;
  726. end;
  727. end;
  728. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;
  729. var ext : extstr);
  730. var
  731. p1 : byte;
  732. i : longint;
  733. begin
  734. { allow slash as backslash }
  735. for i:=1 to length(path) do
  736. if path[i]='/' then path[i]:='\';
  737. { get drive name }
  738. p1:=pos(':',path);
  739. if p1>0 then
  740. begin
  741. dir:=path[1]+':';
  742. delete(path,1,p1);
  743. end
  744. else
  745. dir:='';
  746. { split the path and the name, there are no more path informtions }
  747. { if path contains no backslashes }
  748. while true do
  749. begin
  750. p1:=pos('\',path);
  751. if p1=0 then
  752. break;
  753. dir:=dir+copy(path,1,p1);
  754. delete(path,1,p1);
  755. end;
  756. { try to find out a extension }
  757. p1:=pos('.',path);
  758. if p1>0 then
  759. begin
  760. ext:=copy(path,p1,4);
  761. delete(path,p1,length(path)-p1+1);
  762. end
  763. else
  764. ext:='';
  765. name:=path;
  766. end;
  767. function fexpand(const path : pathstr) : pathstr;
  768. function get_current_drive : byte;
  769. var
  770. r : registers;
  771. begin
  772. r.ah:=$19;
  773. msdos(r);
  774. get_current_drive:=r.al;
  775. end;
  776. var
  777. s,pa : string[79];
  778. i,j : byte;
  779. begin
  780. { There are differences between FPKPascal and Turbo Pascal
  781. e.g. for the string 'D:\DEMO\..\HELLO' which isn't handled }
  782. getdir(0,s);
  783. pa:=upcase(path);
  784. { allow slash as backslash }
  785. for i:=1 to length(pa) do
  786. if pa[i]='/' then pa[i]:='\';
  787. if (ord(pa[0])>1) and (((pa[1]>='A') and (pa[1]<='Z')) and (pa[2]=':')) then
  788. begin
  789. { we must get the right directory }
  790. getdir(ord(pa[1])-ord('A')+1,s);
  791. if (ord(pa[0])>2) and (pa[3]<>'\') then
  792. if pa[1]=s[1] then
  793. pa:=s+'\'+copy (pa,3,length(pa))
  794. else
  795. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  796. end
  797. else
  798. if pa[1]='\' then
  799. pa:=s[1]+':'+pa
  800. else if s[0]=#3 then
  801. pa:=s+pa
  802. else
  803. pa:=s+'\'+pa;
  804. {First remove all references to '\.\'}
  805. while pos ('\.\',pa)<>0 do
  806. delete (pa,pos('\.\',pa),2);
  807. {Now remove also all references to '\..\' + of course previous dirs..}
  808. repeat
  809. i:=pos('\..\',pa);
  810. j:=i-1;
  811. while (j>1) and (pa[j]<>'\') do
  812. dec (j);
  813. delete (pa,j,i-j+3);
  814. until i=0;
  815. {Remove End . and \}
  816. if (length(pa)>0) and (pa[length(pa)]='.') then
  817. dec(byte(pa[0]));
  818. if (length(pa)>0) and (pa[length(pa)]='\') then
  819. dec(byte(pa[0]));
  820. fexpand:=pa;
  821. end;
  822. procedure packtime(var d : datetime;var time : longint);
  823. var
  824. zs : longint;
  825. begin
  826. time:=-1980;
  827. time:=time+d.year and 127;
  828. time:=time shl 4;
  829. time:=time+d.month;
  830. time:=time shl 5;
  831. time:=time+d.day;
  832. time:=time shl 16;
  833. zs:=d.hour;
  834. zs:=zs shl 6;
  835. zs:=zs+d.min;
  836. zs:=zs shl 5;
  837. zs:=zs+d.sec div 2;
  838. time:=time+(zs and $ffff);
  839. end;
  840. procedure unpacktime (time: longint; var d: datetime);
  841. begin
  842. d.sec:=(time and 31) * 2;
  843. time:=time shr 5;
  844. d.min:=time and 63;
  845. time:=time shr 6;
  846. d.hour:=time and 31;
  847. time:=time shr 5;
  848. d.day:=time and 31;
  849. time:=time shr 5;
  850. d.month:=time and 15;
  851. time:=time shr 4;
  852. d.year:=time + 1980;
  853. end;
  854. {$ifdef GO32V2}
  855. procedure getfattr(var f;var attr : word);
  856. var
  857. r : registers;
  858. begin
  859. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  860. r.ax:=$4300;
  861. r.edx:=transfer_buffer mod 16;
  862. r.ds:=transfer_buffer div 16;
  863. msdos(r);
  864. if (r.flags and carryflag) <> 0 then
  865. doserror:=r.ax;
  866. attr:=r.cx;
  867. end;
  868. procedure setfattr(var f;attr : word);
  869. var
  870. r : registers;
  871. begin
  872. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  873. r.ax:=$4301;
  874. r.edx:=transfer_buffer mod 16;
  875. r.ds:=transfer_buffer div 16;
  876. r.cx:=attr;
  877. msdos(r);
  878. if (r.flags and carryflag) <> 0 then
  879. doserror:=r.ax;
  880. end;
  881. {$else GO32V2}
  882. procedure getfattr(var f;var attr : word);
  883. var
  884. { to avoid problems }
  885. n : array[0..255] of char;
  886. r : registers;
  887. begin
  888. strpcopy(n,filerec(f).name);
  889. r.ax:=$4300;
  890. r.edx:=longint(@n);
  891. msdos(r);
  892. attr:=r.cx;
  893. end;
  894. procedure setfattr(var f;attr : word);
  895. var
  896. { to avoid problems }
  897. n : array[0..255] of char;
  898. r : registers;
  899. begin
  900. strpcopy(n,filerec(f).name);
  901. r.ax:=$4301;
  902. r.edx:=longint(@n);
  903. r.cx:=attr;
  904. msdos(r);
  905. end;
  906. {$endif GO32V2}
  907. end.
  908. {
  909. $Log$
  910. Revision 1.1 1998-03-25 11:18:47 root
  911. Initial revision
  912. Revision 1.2 1998/03/10 13:23:56 florian
  913. * just a few things adapted to win32
  914. Revision 1.1 1998/03/09 23:19:12 florian
  915. + Initial revision, just copied from the DOS version
  916. }