dos.pp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  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. Dos unit for BP7 compatible RTL
  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. unit dos;
  13. {$I os.inc}
  14. interface
  15. Uses Go32;
  16. Const
  17. {Bitmasks for CPU Flags}
  18. fcarry = $0001;
  19. fparity = $0004;
  20. fauxiliary = $0010;
  21. fzero = $0040;
  22. fsign = $0080;
  23. foverflow = $0800;
  24. {Bitmasks for file attribute}
  25. readonly = $01;
  26. hidden = $02;
  27. sysfile = $04;
  28. volumeid = $08;
  29. directory = $10;
  30. archive = $20;
  31. anyfile = $3F;
  32. {File Status}
  33. fmclosed = $D7B0;
  34. fminput = $D7B1;
  35. fmoutput = $D7B2;
  36. fminout = $D7B3;
  37. Type
  38. {$IFDEF GO32V2}
  39. { Needed for LFN Support }
  40. ComStr = String[255];
  41. PathStr = String[255];
  42. DirStr = String[255];
  43. NameStr = String[255];
  44. ExtStr = String[255];
  45. {$ELSE}
  46. comstr = string[127]; { command line string }
  47. pathstr = string[79]; { string for a file path }
  48. dirstr = string[67]; { string for a directory }
  49. namestr = string[8]; { string for a file name }
  50. extstr = string[4]; { string for an extension }
  51. {$ENDIF}
  52. {
  53. filerec.inc contains the definition of the filerec.
  54. textrec.inc contains the definition of the textrec.
  55. It is in a separate file to make it available in other units without
  56. having to use the DOS unit for it.
  57. }
  58. {$i filerec.inc}
  59. {$i textrec.inc}
  60. DateTime = packed record
  61. Year,
  62. Month,
  63. Day,
  64. Hour,
  65. Min,
  66. Sec : word;
  67. End;
  68. {$ifdef GO32V2}
  69. searchrec = packed record
  70. fill : array[1..21] of byte;
  71. attr : byte;
  72. time : longint;
  73. { reserved : word; not in DJGPP V2 }
  74. size : longint;
  75. name : string[255]; { LFN Name, DJGPP uses only [12] but more can't hurt (PFV) }
  76. end;
  77. Registers = Go32.Registers;
  78. {$ELSE}
  79. searchrec = packed record
  80. fill : array[1..21] of byte;
  81. attr : byte;
  82. time : longint;
  83. reserved : word; { requires the DOS extender (DJ GNU-C) }
  84. size : longint;
  85. name : string[15]; { the same size as declared by (DJ GNU C) }
  86. end;
  87. registers = packed record
  88. case i : integer of
  89. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  90. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  91. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  92. end;
  93. {$endif GO32V1}
  94. Var
  95. DosError : integer;
  96. {Interrupt}
  97. Procedure Intr(intno: byte; var regs: registers);
  98. Procedure MSDos(var regs: registers);
  99. {Info/Date/Time}
  100. Function DosVersion: Word;
  101. Procedure GetDate(var year, month, mday, wday: word);
  102. Procedure GetTime(var hour, minute, second, sec100: word);
  103. procedure SetDate(year,month,day: word);
  104. Procedure SetTime(hour,minute,second,sec100: word);
  105. Procedure UnpackTime(p: longint; var t: datetime);
  106. Procedure PackTime(var t: datetime; var p: longint);
  107. {Exec}
  108. Procedure Exec(const path: pathstr; const comline: comstr);
  109. Function DosExitCode: word;
  110. {Disk}
  111. Function DiskFree(drive: byte) : longint;
  112. Function DiskSize(drive: byte) : longint;
  113. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  114. Procedure FindNext(var f: searchRec);
  115. Procedure FindClose(Var f: SearchRec);
  116. {File}
  117. Procedure GetFAttr(var f; var attr: word);
  118. Procedure GetFTime(var f; var time: longint);
  119. Function FSearch(path: pathstr; dirlist: string): pathstr;
  120. Function FExpand(const path: pathstr): pathstr;
  121. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  122. {Environment}
  123. Function EnvCount: longint;
  124. Function EnvStr(index: integer): string;
  125. Function GetEnv(envvar: string): string;
  126. {Misc}
  127. Procedure SetFAttr(var f; attr: word);
  128. Procedure SetFTime(var f; time: longint);
  129. Procedure GetCBreak(var breakvalue: boolean);
  130. Procedure SetCBreak(breakvalue: boolean);
  131. Procedure GetVerify(var verify: boolean);
  132. Procedure SetVerify(verify: boolean);
  133. {Do Nothing Functions}
  134. Procedure SwapVectors;
  135. Procedure GetIntVec(intno: byte; var vector: pointer);
  136. Procedure SetIntVec(intno: byte; vector: pointer);
  137. Procedure Keep(exitcode: word);
  138. implementation
  139. uses
  140. strings;
  141. {$ASMMODE ATT}
  142. {******************************************************************************
  143. --- Dos Interrupt ---
  144. ******************************************************************************}
  145. var
  146. dosregs : registers;
  147. procedure LoadDosError;
  148. begin
  149. if (dosregs.flags and carryflag) <> 0 then
  150. doserror:=dosregs.ax
  151. else
  152. doserror:=0;
  153. end;
  154. {$ifdef GO32V2}
  155. procedure intr(intno : byte;var regs : registers);
  156. begin
  157. realintr(intno,regs);
  158. end;
  159. {$else GO32V2}
  160. {$ASMMODE DIRECT}
  161. procedure intr(intno : byte;var regs : registers);
  162. begin
  163. asm
  164. .data
  165. int86:
  166. .byte 0xcd
  167. int86_vec:
  168. .byte 0x03
  169. jmp int86_retjmp
  170. .text
  171. movl 8(%ebp),%eax
  172. movb %al,int86_vec
  173. movl 10(%ebp),%eax
  174. // do not use first int
  175. addl $2,%eax
  176. movl 4(%eax),%ebx
  177. movl 8(%eax),%ecx
  178. movl 12(%eax),%edx
  179. movl 16(%eax),%ebp
  180. movl 20(%eax),%esi
  181. movl 24(%eax),%edi
  182. movl (%eax),%eax
  183. jmp int86
  184. int86_retjmp:
  185. pushf
  186. pushl %ebp
  187. pushl %eax
  188. movl %esp,%ebp
  189. // calc EBP new
  190. addl $12,%ebp
  191. movl 10(%ebp),%eax
  192. // do not use first int
  193. addl $2,%eax
  194. popl (%eax)
  195. movl %ebx,4(%eax)
  196. movl %ecx,8(%eax)
  197. movl %edx,12(%eax)
  198. // restore EBP
  199. popl %edx
  200. movl %edx,16(%eax)
  201. movl %esi,20(%eax)
  202. movl %edi,24(%eax)
  203. // ignore ES and DS
  204. popl %ebx /* flags */
  205. movl %ebx,32(%eax)
  206. // FS and GS too
  207. end;
  208. end;
  209. {$ASMMODE ATT}
  210. {$endif GO32V2}
  211. procedure msdos(var regs : registers);
  212. begin
  213. intr($21,regs);
  214. end;
  215. {******************************************************************************
  216. --- Info / Date / Time ---
  217. ******************************************************************************}
  218. function dosversion : word;
  219. begin
  220. dosregs.ax:=$3000;
  221. msdos(dosregs);
  222. dosversion:=dosregs.ax;
  223. end;
  224. procedure getdate(var year,month,mday,wday : word);
  225. begin
  226. dosregs.ax:=$2a00;
  227. msdos(dosregs);
  228. wday:=dosregs.al;
  229. year:=dosregs.cx;
  230. month:=dosregs.dh;
  231. mday:=dosregs.dl;
  232. end;
  233. procedure setdate(year,month,day : word);
  234. begin
  235. dosregs.cx:=year;
  236. dosregs.dh:=month;
  237. dosregs.dl:=day;
  238. dosregs.ah:=$2b;
  239. msdos(dosregs);
  240. DosError:=0;
  241. end;
  242. procedure gettime(var hour,minute,second,sec100 : word);
  243. begin
  244. dosregs.ah:=$2c;
  245. msdos(dosregs);
  246. hour:=dosregs.ch;
  247. minute:=dosregs.cl;
  248. second:=dosregs.dh;
  249. sec100:=dosregs.dl;
  250. DosError:=0;
  251. end;
  252. procedure settime(hour,minute,second,sec100 : word);
  253. begin
  254. dosregs.ch:=hour;
  255. dosregs.cl:=minute;
  256. dosregs.dh:=second;
  257. dosregs.dl:=sec100;
  258. dosregs.ah:=$2d;
  259. msdos(dosregs);
  260. DosError:=0;
  261. end;
  262. Procedure packtime(var t : datetime;var p : longint);
  263. Begin
  264. p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25);
  265. End;
  266. Procedure unpacktime(p : longint;var t : datetime);
  267. Begin
  268. with t do
  269. begin
  270. sec:=(p and 31) shl 1;
  271. min:=(p shr 5) and 63;
  272. hour:=(p shr 11) and 31;
  273. day:=(p shr 16) and 31;
  274. month:=(p shr 21) and 15;
  275. year:=(p shr 25)+1980;
  276. end;
  277. End;
  278. {******************************************************************************
  279. --- Exec ---
  280. ******************************************************************************}
  281. var
  282. lastdosexitcode : word;
  283. {$ifdef GO32V2}
  284. procedure exec(const path : pathstr;const comline : comstr);
  285. type
  286. realptr = packed record
  287. ofs,seg : word;
  288. end;
  289. texecblock = packed record
  290. envseg : word;
  291. comtail : realptr;
  292. firstFCB : realptr;
  293. secondFCB : realptr;
  294. iniStack : realptr;
  295. iniCSIP : realptr;
  296. end;
  297. var
  298. current_dos_buffer_pos,
  299. arg_ofs,
  300. i,la_env,
  301. la_p,la_c,la_e,
  302. fcb1_la,fcb2_la : longint;
  303. execblock : texecblock;
  304. c,p : string;
  305. function paste_to_dos(src : string) : boolean;
  306. var
  307. c : array[0..255] of char;
  308. begin
  309. paste_to_dos:=false;
  310. if current_dos_buffer_pos+length(src)+1>transfer_buffer+tb_size then
  311. RunError(217);
  312. move(src[1],c[0],length(src));
  313. c[length(src)]:=#0;
  314. seg_move(get_ds,longint(@c),dosmemselector,current_dos_buffer_pos,length(src)+1);
  315. current_dos_buffer_pos:=current_dos_buffer_pos+length(src)+1;
  316. paste_to_dos:=true;
  317. end;
  318. begin
  319. { create command line }
  320. move(comline[0],c[1],length(comline)+1);
  321. c[length(comline)+2]:=#13;
  322. c[0]:=char(length(comline)+2);
  323. { create path }
  324. p:=path;
  325. for i:=1 to length(p) do
  326. if p[i]='/' then
  327. p[i]:='\';
  328. { create buffer }
  329. la_env:=transfer_buffer;
  330. while (la_env and 15)<>0 do
  331. inc(la_env);
  332. current_dos_buffer_pos:=la_env;
  333. { copy environment }
  334. for i:=1 to envcount do
  335. paste_to_dos(envstr(i));
  336. paste_to_dos(''); { adds a double zero at the end }
  337. { allow slash as backslash }
  338. la_p:=current_dos_buffer_pos;
  339. paste_to_dos(p);
  340. la_c:=current_dos_buffer_pos;
  341. paste_to_dos(c);
  342. la_e:=current_dos_buffer_pos;
  343. fcb1_la:=la_e;
  344. la_e:=la_e+16;
  345. fcb2_la:=la_e;
  346. la_e:=la_e+16;
  347. { allocate FCB see dosexec code }
  348. arg_ofs:=1;
  349. while (c[arg_ofs] in [' ',#9]) do
  350. inc(arg_ofs);
  351. dosregs.ax:=$2901;
  352. dosregs.ds:=(la_c+arg_ofs) shr 4;
  353. dosregs.esi:=(la_c+arg_ofs) and 15;
  354. dosregs.es:=fcb1_la shr 4;
  355. dosregs.edi:=fcb1_la and 15;
  356. msdos(dosregs);
  357. { allocate second FCB see dosexec code }
  358. repeat
  359. inc(arg_ofs);
  360. until (c[arg_ofs] in [' ',#9,#13]);
  361. if c[arg_ofs]<>#13 then
  362. begin
  363. repeat
  364. inc(arg_ofs);
  365. until not (c[arg_ofs] in [' ',#9]);
  366. end;
  367. dosregs.ax:=$2901;
  368. dosregs.ds:=(la_c+arg_ofs) shr 4;
  369. dosregs.si:=(la_c+arg_ofs) and 15;
  370. dosregs.es:=fcb2_la shr 4;
  371. dosregs.di:=fcb2_la and 15;
  372. msdos(dosregs);
  373. with execblock do
  374. begin
  375. envseg:=la_env shr 4;
  376. comtail.seg:=la_c shr 4;
  377. comtail.ofs:=la_c and 15;
  378. firstFCB.seg:=fcb1_la shr 4;
  379. firstFCB.ofs:=fcb1_la and 15;
  380. secondFCB.seg:=fcb2_la shr 4;
  381. secondFCB.ofs:=fcb2_la and 15;
  382. end;
  383. seg_move(get_ds,longint(@execblock),dosmemselector,la_e,sizeof(texecblock));
  384. dosregs.edx:=la_p and 15;
  385. dosregs.ds:=la_p shr 4;
  386. dosregs.ebx:=la_e and 15;
  387. dosregs.es:=la_e shr 4;
  388. dosregs.ax:=$4b00;
  389. msdos(dosregs);
  390. LoadDosError;
  391. if DosError=0 then
  392. begin
  393. dosregs.ax:=$4d00;
  394. msdos(dosregs);
  395. LastDosExitCode:=DosRegs.al
  396. end
  397. else
  398. LastDosExitCode:=0;
  399. end;
  400. {$else GO32V2}
  401. procedure exec(const path : pathstr;const comline : comstr);
  402. var
  403. i : longint;
  404. b : array[0..255] of char;
  405. begin
  406. doserror:=0;
  407. for i:=1to length(path) do
  408. if path[i]='/' then
  409. b[i-1]:='\'
  410. else
  411. b[i-1]:=path[i];
  412. b[i]:=' ';
  413. inc(i);
  414. move(comline[1],b[i],length(comline));
  415. inc(i,length(comline));
  416. b[i]:=#0;
  417. asm
  418. leal b,%ebx
  419. movw $0xff07,%ax
  420. int $0x21
  421. movw %ax,LastDosExitCode
  422. end;
  423. end;
  424. {$endif}
  425. function dosexitcode : word;
  426. begin
  427. dosexitcode:=lastdosexitcode;
  428. end;
  429. procedure getcbreak(var breakvalue : boolean);
  430. begin
  431. DosError:=0;
  432. dosregs.ax:=$3300;
  433. msdos(dosregs);
  434. breakvalue:=dosregs.dl<>0;
  435. end;
  436. procedure setcbreak(breakvalue : boolean);
  437. begin
  438. DosError:=0;
  439. dosregs.ax:=$3301;
  440. dosregs.dl:=ord(breakvalue);
  441. msdos(dosregs);
  442. end;
  443. procedure getverify(var verify : boolean);
  444. begin
  445. DosError:=0;
  446. dosregs.ah:=$54;
  447. msdos(dosregs);
  448. verify:=dosregs.al<>0;
  449. end;
  450. procedure setverify(verify : boolean);
  451. begin
  452. DosError:=0;
  453. dosregs.ah:=$2e;
  454. dosregs.al:=ord(verify);
  455. msdos(dosregs);
  456. end;
  457. {******************************************************************************
  458. --- Disk ---
  459. ******************************************************************************}
  460. function diskfree(drive : byte) : longint;
  461. begin
  462. DosError:=0;
  463. dosregs.dl:=drive;
  464. dosregs.ah:=$36;
  465. msdos(dosregs);
  466. if dosregs.ax<>$FFFF then
  467. diskfree:=dosregs.ax*dosregs.bx*dosregs.cx
  468. else
  469. diskfree:=-1;
  470. end;
  471. function disksize(drive : byte) : longint;
  472. begin
  473. DosError:=0;
  474. dosregs.dl:=drive;
  475. dosregs.ah:=$36;
  476. msdos(dosregs);
  477. if dosregs.ax<>$FFFF then
  478. disksize:=dosregs.ax*dosregs.cx*dosregs.dx
  479. else
  480. disksize:=-1;
  481. end;
  482. {******************************************************************************
  483. --- LFNFindfirst LFNFindNext ---
  484. ******************************************************************************}
  485. {$ifdef GO32V2}
  486. type
  487. LFNSearchRec=packed record
  488. attr,
  489. crtime,
  490. crtimehi,
  491. actime,
  492. actimehi,
  493. lmtime,
  494. lmtimehi,
  495. sizehi,
  496. size : longint;
  497. reserved : array[0..7] of byte;
  498. name : array[0..259] of byte;
  499. shortname : array[0..13] of byte;
  500. end;
  501. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec);
  502. var
  503. Len : longint;
  504. begin
  505. With w do
  506. begin
  507. FillChar(d,sizeof(SearchRec),0);
  508. if DosError=0 then
  509. len:=StrLen(@Name)
  510. else
  511. len:=0;
  512. d.Name[0]:=chr(len);
  513. Move(Name[0],d.Name[1],Len);
  514. d.Time:=lmTime;
  515. d.Size:=Size;
  516. d.Attr:=Attr and $FF;
  517. Move(hdl,d.Fill,4);
  518. end;
  519. end;
  520. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  521. var
  522. i : longint;
  523. w : LFNSearchRec;
  524. begin
  525. { allow slash as backslash }
  526. for i:=0 to strlen(path) do
  527. if path[i]='/' then path[i]:='\';
  528. dosregs.si:=1; { use ms-dos time }
  529. dosregs.ecx:=attr;
  530. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  531. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  532. dosregs.ds:=tb_segment;
  533. dosregs.edi:=tb_offset;
  534. dosregs.es:=tb_segment;
  535. dosregs.ax:=$714e;
  536. msdos(dosregs);
  537. LoadDosError;
  538. copyfromdos(w,sizeof(LFNSearchRec));
  539. LFNSearchRec2Dos(w,dosregs.ax,s);
  540. end;
  541. procedure LFNFindNext(var s:searchrec);
  542. var
  543. hdl : longint;
  544. w : LFNSearchRec;
  545. begin
  546. Move(s.Fill,hdl,4);
  547. dosregs.si:=1; { use ms-dos time }
  548. dosregs.edi:=tb_offset;
  549. dosregs.es:=tb_segment;
  550. dosregs.ebx:=hdl;
  551. dosregs.ax:=$714f;
  552. msdos(dosregs);
  553. LoadDosError;
  554. copyfromdos(w,sizeof(LFNSearchRec));
  555. LFNSearchRec2Dos(w,hdl,s);
  556. end;
  557. procedure LFNFindClose(var s:searchrec);
  558. var
  559. hdl : longint;
  560. begin
  561. Move(s.Fill,hdl,4);
  562. dosregs.ebx:=hdl;
  563. dosregs.ax:=$71a1;
  564. msdos(dosregs);
  565. LoadDosError;
  566. end;
  567. {$endif GO32V2}
  568. {******************************************************************************
  569. --- DosFindfirst DosFindNext ---
  570. ******************************************************************************}
  571. procedure dossearchrec2searchrec(var f : searchrec);
  572. var
  573. len : longint;
  574. begin
  575. len:=StrLen(@f.Name);
  576. Move(f.Name[0],f.Name[1],Len);
  577. f.Name[0]:=chr(len);
  578. end;
  579. {$ifdef GO32V2}
  580. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  581. var
  582. i : longint;
  583. begin
  584. { allow slash as backslash }
  585. for i:=0 to strlen(path) do
  586. if path[i]='/' then path[i]:='\';
  587. copytodos(f,sizeof(searchrec));
  588. dosregs.edx:=tb_offset;
  589. dosregs.ds:=tb_segment;
  590. dosregs.ah:=$1a;
  591. msdos(dosregs);
  592. dosregs.ecx:=attr;
  593. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  594. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  595. dosregs.ds:=tb_segment;
  596. dosregs.ah:=$4e;
  597. msdos(dosregs);
  598. copyfromdos(f,sizeof(searchrec));
  599. LoadDosError;
  600. dossearchrec2searchrec(f);
  601. end;
  602. procedure Dosfindnext(var f : searchrec);
  603. begin
  604. copytodos(f,sizeof(searchrec));
  605. dosregs.edx:=tb_offset;
  606. dosregs.ds:=tb_segment;
  607. dosregs.ah:=$1a;
  608. msdos(dosregs);
  609. dosregs.ah:=$4f;
  610. msdos(dosregs);
  611. copyfromdos(f,sizeof(searchrec));
  612. LoadDosError;
  613. dossearchrec2searchrec(f);
  614. end;
  615. {$else GO32V2}
  616. procedure Dosfindfirst(path : pchar;attr : word;var f : searchrec);
  617. var
  618. i : longint;
  619. begin
  620. { allow slash as backslash }
  621. for i:=0 to strlen(path) do
  622. if path[i]='/' then path[i]:='\';
  623. asm
  624. movl f,%edx
  625. movb $0x1a,%ah
  626. int $0x21
  627. movl path,%edx
  628. movzwl attr,%ecx
  629. movb $0x4e,%ah
  630. int $0x21
  631. jnc .LFF
  632. movw %ax,DosError
  633. .LFF:
  634. end;
  635. dossearchrec2searchrec(f);
  636. end;
  637. procedure Dosfindnext(var f : searchrec);
  638. begin
  639. asm
  640. movl 12(%ebp),%edx
  641. movb $0x1a,%ah
  642. int $0x21
  643. movb $0x4f,%ah
  644. int $0x21
  645. jnc .LFN
  646. movw %ax,DosError
  647. .LFN:
  648. end;
  649. dossearchrec2searchrec(f);
  650. end;
  651. {$endif GO32V2}
  652. {******************************************************************************
  653. --- Findfirst FindNext ---
  654. ******************************************************************************}
  655. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  656. var
  657. path0 : array[0..256] of char;
  658. begin
  659. doserror:=0;
  660. strpcopy(path0,path);
  661. {$ifdef Go32V2}
  662. if LFNSupport then
  663. LFNFindFirst(path0,attr,f)
  664. else
  665. Dosfindfirst(path0,attr,f);
  666. {$else}
  667. Dosfindfirst(path0,attr,f);
  668. {$endif}
  669. end;
  670. procedure findnext(var f : searchRec);
  671. begin
  672. doserror:=0;
  673. {$ifdef Go32V2}
  674. if LFNSupport then
  675. LFNFindnext(f)
  676. else
  677. Dosfindnext(f);
  678. {$else}
  679. Dosfindnext(f);
  680. {$endif}
  681. end;
  682. Procedure FindClose(Var f: SearchRec);
  683. begin
  684. DosError:=0;
  685. {$ifdef Go32V2}
  686. if LFNSupport then
  687. LFNFindClose(f);
  688. {$endif}
  689. end;
  690. {$ASMMODE DIRECT}
  691. procedure swapvectors;
  692. begin
  693. DosError:=0;
  694. {$ifdef go32v2}
  695. asm
  696. { uses four global symbols from v2prt0.as to be able to know the current
  697. exception state without using dpmiexcp unit }
  698. movl _exception_exit,%eax
  699. orl %eax,%eax
  700. je .Lno_excep
  701. movl _v2prt0_exceptions_on,%eax
  702. orl %eax,%eax
  703. je .Lexceptions_off
  704. movl _swap_out,%eax
  705. call *%eax
  706. jmp .Lno_excep
  707. .Lexceptions_off:
  708. movl _swap_in,%eax
  709. call *%eax
  710. .Lno_excep:
  711. end;
  712. {$endif go32v2}
  713. end;
  714. {$ASMMODE ATT}
  715. {******************************************************************************
  716. --- File ---
  717. ******************************************************************************}
  718. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  719. var
  720. dotpos,p1,i : longint;
  721. begin
  722. { allow slash as backslash }
  723. for i:=1 to length(path) do
  724. if path[i]='/' then path[i]:='\';
  725. { get drive name }
  726. p1:=pos(':',path);
  727. if p1>0 then
  728. begin
  729. dir:=path[1]+':';
  730. delete(path,1,p1);
  731. end
  732. else
  733. dir:='';
  734. { split the path and the name, there are no more path informtions }
  735. { if path contains no backslashes }
  736. while true do
  737. begin
  738. p1:=pos('\',path);
  739. if p1=0 then
  740. break;
  741. dir:=dir+copy(path,1,p1);
  742. delete(path,1,p1);
  743. end;
  744. { try to find out a extension }
  745. {$ifdef Go32V2}
  746. if LFNSupport then
  747. begin
  748. Ext:='';
  749. i:=Length(Path);
  750. DotPos:=256;
  751. While (i>0) Do
  752. Begin
  753. If (Path[i]='.') Then
  754. begin
  755. DotPos:=i;
  756. break;
  757. end;
  758. Dec(i);
  759. end;
  760. Ext:=Copy(Path,DotPos,255);
  761. Name:=Copy(Path,1,DotPos - 1);
  762. end
  763. else
  764. {$endif Go32V2}
  765. begin
  766. p1:=pos('.',path);
  767. if p1>0 then
  768. begin
  769. ext:=copy(path,p1,4);
  770. delete(path,p1,length(path)-p1+1);
  771. end
  772. else
  773. ext:='';
  774. name:=path;
  775. end;
  776. end;
  777. function fexpand(const path : pathstr) : pathstr;
  778. var
  779. s,pa : string[79];
  780. i,j : longint;
  781. begin
  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
  787. pa[i]:='\';
  788. if (length(pa)>1) and (pa[1] in ['A'..'Z']) and (pa[2]=':') then
  789. begin
  790. { we must get the right directory }
  791. getdir(ord(pa[1])-ord('A')+1,s);
  792. if (ord(pa[0])>2) and (pa[3]<>'\') then
  793. if pa[1]=s[1] then
  794. pa:=s+'\'+copy (pa,3,length(pa))
  795. else
  796. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  797. end
  798. else
  799. if pa[1]='\' then
  800. pa:=s[1]+':'+pa
  801. else if s[0]=#3 then
  802. pa:=s+pa
  803. else
  804. pa:=s+'\'+pa;
  805. { Turbo Pascal gives current dir on drive if only drive given as parameter! }
  806. if length(pa) = 2 then
  807. begin
  808. getdir(byte(pa[1])-64,s);
  809. pa := s;
  810. end;
  811. {First remove all references to '\.\'}
  812. while pos ('\.\',pa)<>0 do
  813. delete (pa,pos('\.\',pa),2);
  814. {Now remove also all references to '\..\' + of course previous dirs..}
  815. repeat
  816. i:=pos('\..\',pa);
  817. if i<>0 then
  818. begin
  819. j:=i-1;
  820. while (j>1) and (pa[j]<>'\') do
  821. dec (j);
  822. if pa[j+1] = ':' then j := 3;
  823. delete (pa,j,i-j+3);
  824. end;
  825. until i=0;
  826. { Turbo Pascal gets rid of a \.. at the end of the path }
  827. { Now remove also any reference to '\..' at end of line
  828. + of course previous dir.. }
  829. i:=pos('\..',pa);
  830. if i<>0 then
  831. begin
  832. if i = length(pa) - 2 then
  833. begin
  834. j:=i-1;
  835. while (j>1) and (pa[j]<>'\') do
  836. dec (j);
  837. delete (pa,j,i-j+3);
  838. end;
  839. pa := pa + '\';
  840. end;
  841. { Remove End . and \}
  842. if (length(pa)>0) and (pa[length(pa)]='.') then
  843. dec(byte(pa[0]));
  844. { if only the drive + a '\' is left then the '\' should be left to prevtn the program
  845. accessing the current directory on the drive rather than the root!}
  846. { if the last char of path = '\' then leave it in as this is what TP does! }
  847. if ((length(pa)>3) and (pa[length(pa)]='\')) and (path[length(path)] <> '\') then
  848. dec(byte(pa[0]));
  849. { if only a drive is given in path then there should be a '\' at the
  850. end of the string given back }
  851. if length(path) = 2 then pa := pa + '\';
  852. fexpand:=pa;
  853. end;
  854. Function FSearch(path: pathstr; dirlist: string): pathstr;
  855. var
  856. i,p1 : longint;
  857. s : searchrec;
  858. newdir : pathstr;
  859. begin
  860. { No wildcards allowed in these things }
  861. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  862. fsearch:=''
  863. else
  864. begin
  865. { allow slash as backslash }
  866. for i:=1 to length(dirlist) do
  867. if dirlist[i]='/' then dirlist[i]:='\';
  868. repeat
  869. p1:=pos(';',dirlist);
  870. if p1<>0 then
  871. begin
  872. newdir:=copy(dirlist,1,p1-1);
  873. delete(dirlist,1,p1);
  874. end
  875. else
  876. begin
  877. newdir:=dirlist;
  878. dirlist:='';
  879. end;
  880. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  881. newdir:=newdir+'\';
  882. findfirst(newdir+path,anyfile,s);
  883. if doserror=0 then
  884. newdir:=newdir+path
  885. else
  886. newdir:='';
  887. until (dirlist='') or (newdir<>'');
  888. fsearch:=newdir;
  889. end;
  890. end;
  891. {******************************************************************************
  892. --- Get/Set File Time,Attr ---
  893. ******************************************************************************}
  894. procedure getftime(var f;var time : longint);
  895. begin
  896. dosregs.bx:=textrec(f).handle;
  897. dosregs.ax:=$5700;
  898. msdos(dosregs);
  899. loaddoserror;
  900. time:=(dosregs.dx shl 16)+dosregs.cx;
  901. end;
  902. procedure setftime(var f;time : longint);
  903. begin
  904. dosregs.bx:=textrec(f).handle;
  905. dosregs.cx:=time and $ffff;
  906. dosregs.dx:=time shr 16;
  907. dosregs.ax:=$5701;
  908. msdos(dosregs);
  909. loaddoserror;
  910. end;
  911. procedure getfattr(var f;var attr : word);
  912. begin
  913. {$ifdef GO32V2}
  914. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  915. dosregs.edx:=tb_offset;
  916. dosregs.ds:=tb_segment;
  917. if LFNSupport then
  918. begin
  919. dosregs.ax:=$7143;
  920. dosregs.bx:=0;
  921. end
  922. else
  923. {$else}
  924. dosregs.edx:=longint(@filerec(f).name);
  925. {$endif GO32V2}
  926. dosregs.ax:=$4300;
  927. msdos(dosregs);
  928. LoadDosError;
  929. Attr:=dosregs.cx;
  930. end;
  931. procedure setfattr(var f;attr : word);
  932. begin
  933. {$ifdef GO32V2}
  934. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  935. dosregs.edx:=tb_offset;
  936. dosregs.ds:=tb_segment;
  937. if LFNSupport then
  938. begin
  939. dosregs.ax:=$7143;
  940. dosregs.bx:=1;
  941. end
  942. else
  943. {$else}
  944. dosregs.edx:=longint(@filerec(f).name);
  945. {$endif}
  946. dosregs.ax:=$4301;
  947. dosregs.cx:=attr;
  948. msdos(dosregs);
  949. LoadDosError;
  950. end;
  951. {******************************************************************************
  952. --- Environment ---
  953. ******************************************************************************}
  954. function envcount : longint;
  955. var
  956. hp : ppchar;
  957. begin
  958. hp:=envp;
  959. envcount:=0;
  960. while assigned(hp^) do
  961. begin
  962. inc(envcount);
  963. hp:=hp+4;
  964. end;
  965. end;
  966. function envstr(index : integer) : string;
  967. begin
  968. if (index<=0) or (index>envcount) then
  969. begin
  970. envstr:='';
  971. exit;
  972. end;
  973. envstr:=strpas(ppchar(envp+4*(index-1))^);
  974. end;
  975. Function GetEnv(envvar: string): string;
  976. var
  977. hp : ppchar;
  978. hs : string;
  979. eqpos : longint;
  980. begin
  981. envvar:=upcase(envvar);
  982. hp:=envp;
  983. getenv:='';
  984. while assigned(hp^) do
  985. begin
  986. hs:=strpas(hp^);
  987. eqpos:=pos('=',hs);
  988. if copy(hs,1,eqpos-1)=envvar then
  989. begin
  990. getenv:=copy(hs,eqpos+1,255);
  991. exit;
  992. end;
  993. hp:=hp+4;
  994. end;
  995. end;
  996. {******************************************************************************
  997. --- Not Supported ---
  998. ******************************************************************************}
  999. Procedure keep(exitcode : word);
  1000. Begin
  1001. End;
  1002. Procedure getintvec(intno : byte;var vector : pointer);
  1003. Begin
  1004. End;
  1005. Procedure setintvec(intno : byte;vector : pointer);
  1006. Begin
  1007. End;
  1008. end.
  1009. {
  1010. $Log$
  1011. Revision 1.15 1998-11-01 20:27:18 peter
  1012. * fixed some doserror settings
  1013. Revision 1.14 1998/10/22 15:05:28 pierre
  1014. * fsplit adapted to long filenames
  1015. Revision 1.13 1998/09/16 16:47:24 peter
  1016. * merged fixes
  1017. Revision 1.11.2.2 1998/09/16 16:16:04 peter
  1018. * go32v1 compiles again
  1019. Revision 1.12 1998/09/11 12:46:44 pierre
  1020. * range check problem with LFN attr removed
  1021. Revision 1.11.2.1 1998/09/11 12:38:41 pierre
  1022. * conversion from LFN attr to Dos attr did not respect range checking
  1023. Revision 1.11 1998/08/28 10:45:58 peter
  1024. * fixed path buffer in findfirst
  1025. Revision 1.10 1998/08/27 10:30:48 pierre
  1026. * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !)
  1027. I renamed tb_selector to tb_segment because
  1028. it is a real mode segment as opposed to
  1029. a protected mode selector
  1030. Fixed it for go32v1 (remove the $E0000000 offset !)
  1031. Revision 1.9 1998/08/26 10:04:01 peter
  1032. * new lfn check from mailinglist
  1033. * renamed win95 -> LFNSupport
  1034. + tb_selector, tb_offset for easier access to transferbuffer
  1035. Revision 1.8 1998/08/16 20:39:49 peter
  1036. + LFN Support
  1037. Revision 1.7 1998/08/16 09:12:13 michael
  1038. Corrected fexpand behaviour.
  1039. Revision 1.6 1998/08/05 21:01:50 michael
  1040. applied bugfix from maillist to fsearch
  1041. Revision 1.5 1998/05/31 14:18:13 peter
  1042. * force att or direct assembling
  1043. * cleanup of some files
  1044. Revision 1.4 1998/05/22 00:39:22 peter
  1045. * go32v1, go32v2 recompiles with the new objects
  1046. * remake3 works again with go32v2
  1047. - removed some "optimizes" from daniel which were wrong
  1048. Revision 1.3 1998/05/21 19:30:47 peter
  1049. * objects compiles for linux
  1050. + assign(pchar), assign(char), rename(pchar), rename(char)
  1051. * fixed read_text_as_array
  1052. + read_text_as_pchar which was not yet in the rtl
  1053. }