dos.pp 31 KB

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