dos.pp 28 KB

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