dos.pp 27 KB

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