dos.pp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 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. interface
  14. Uses
  15. 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. { Needed for LFN Support }
  39. ComStr = String[255];
  40. PathStr = String[255];
  41. DirStr = String[255];
  42. NameStr = String[255];
  43. ExtStr = String[255];
  44. {
  45. filerec.inc contains the definition of the filerec.
  46. textrec.inc contains the definition of the textrec.
  47. It is in a separate file to make it available in other units without
  48. having to use the DOS unit for it.
  49. }
  50. {$i filerec.inc}
  51. {$i textrec.inc}
  52. DateTime = packed record
  53. Year,
  54. Month,
  55. Day,
  56. Hour,
  57. Min,
  58. Sec : word;
  59. End;
  60. searchrec = packed record
  61. fill : array[1..21] of byte;
  62. attr : byte;
  63. time : longint;
  64. { reserved : word; not in DJGPP V2 }
  65. size : longint;
  66. name : string[255]; { LFN Name, DJGPP uses only [12] but more can't hurt (PFV) }
  67. end;
  68. Registers = Go32.Registers;
  69. Var
  70. DosError : integer;
  71. {Interrupt}
  72. Procedure Intr(intno: byte; var regs: registers);
  73. Procedure MSDos(var regs: registers);
  74. {Info/Date/Time}
  75. Function DosVersion: Word;
  76. Procedure GetDate(var year, month, mday, wday: word);
  77. Procedure GetTime(var hour, minute, second, sec100: word);
  78. procedure SetDate(year,month,day: word);
  79. Procedure SetTime(hour,minute,second,sec100: word);
  80. Procedure UnpackTime(p: longint; var t: datetime);
  81. Procedure PackTime(var t: datetime; var p: longint);
  82. {Exec}
  83. Procedure Exec(const path: pathstr; const comline: comstr);
  84. Function DosExitCode: word;
  85. {Disk}
  86. Function DiskFree(drive: byte) : longint;
  87. Function DiskSize(drive: byte) : longint;
  88. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  89. Procedure FindNext(var f: searchRec);
  90. Procedure FindClose(Var f: SearchRec);
  91. {File}
  92. Procedure GetFAttr(var f; var attr: word);
  93. Procedure GetFTime(var f; var time: longint);
  94. Function FSearch(path: pathstr; dirlist: string): pathstr;
  95. Function FExpand(const path: pathstr): pathstr;
  96. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  97. function GetShortName(var p : String) : boolean;
  98. {Environment}
  99. Function EnvCount: longint;
  100. Function EnvStr(index: integer): string;
  101. Function GetEnv(envvar: string): string;
  102. {Misc}
  103. Procedure SetFAttr(var f; attr: word);
  104. Procedure SetFTime(var f; time: longint);
  105. Procedure GetCBreak(var breakvalue: boolean);
  106. Procedure SetCBreak(breakvalue: boolean);
  107. Procedure GetVerify(var verify: boolean);
  108. Procedure SetVerify(verify: boolean);
  109. {Do Nothing Functions}
  110. Procedure SwapVectors;
  111. Procedure GetIntVec(intno: byte; var vector: pointer);
  112. Procedure SetIntVec(intno: byte; vector: pointer);
  113. Procedure Keep(exitcode: word);
  114. implementation
  115. uses
  116. strings;
  117. {$ASMMODE ATT}
  118. {******************************************************************************
  119. --- Dos Interrupt ---
  120. ******************************************************************************}
  121. var
  122. dosregs : registers;
  123. procedure LoadDosError;
  124. var
  125. r : registers;
  126. SimpleDosError : word;
  127. begin
  128. if (dosregs.flags and carryflag) <> 0 then
  129. begin
  130. { I got a extended error = 0
  131. while CarryFlag was set from Exec function }
  132. SimpleDosError:=dosregs.ax;
  133. r.eax:=$5900;
  134. r.ebx:=$0;
  135. realintr($21,r);
  136. { conversion from word to integer !!
  137. gave a Bound check error if ax is $FFFF !! PM }
  138. doserror:=integer(r.ax);
  139. case doserror of
  140. 0 : DosError:=integer(SimpleDosError);
  141. 19 : DosError:=150;
  142. 21 : DosError:=152;
  143. end;
  144. end
  145. else
  146. doserror:=0;
  147. end;
  148. procedure intr(intno : byte;var regs : registers);
  149. begin
  150. realintr(intno,regs);
  151. end;
  152. procedure msdos(var regs : registers);
  153. begin
  154. intr($21,regs);
  155. end;
  156. {******************************************************************************
  157. --- Info / Date / Time ---
  158. ******************************************************************************}
  159. function dosversion : word;
  160. begin
  161. dosregs.ax:=$3000;
  162. msdos(dosregs);
  163. dosversion:=dosregs.ax;
  164. end;
  165. procedure getdate(var year,month,mday,wday : word);
  166. begin
  167. dosregs.ax:=$2a00;
  168. msdos(dosregs);
  169. wday:=dosregs.al;
  170. year:=dosregs.cx;
  171. month:=dosregs.dh;
  172. mday:=dosregs.dl;
  173. end;
  174. procedure setdate(year,month,day : word);
  175. begin
  176. dosregs.cx:=year;
  177. dosregs.dh:=month;
  178. dosregs.dl:=day;
  179. dosregs.ah:=$2b;
  180. msdos(dosregs);
  181. DosError:=0;
  182. end;
  183. procedure gettime(var hour,minute,second,sec100 : word);
  184. begin
  185. dosregs.ah:=$2c;
  186. msdos(dosregs);
  187. hour:=dosregs.ch;
  188. minute:=dosregs.cl;
  189. second:=dosregs.dh;
  190. sec100:=dosregs.dl;
  191. DosError:=0;
  192. end;
  193. procedure settime(hour,minute,second,sec100 : word);
  194. begin
  195. dosregs.ch:=hour;
  196. dosregs.cl:=minute;
  197. dosregs.dh:=second;
  198. dosregs.dl:=sec100;
  199. dosregs.ah:=$2d;
  200. msdos(dosregs);
  201. DosError:=0;
  202. end;
  203. Procedure packtime(var t : datetime;var p : longint);
  204. Begin
  205. 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);
  206. End;
  207. Procedure unpacktime(p : longint;var t : datetime);
  208. Begin
  209. with t do
  210. begin
  211. sec:=(p and 31) shl 1;
  212. min:=(p shr 5) and 63;
  213. hour:=(p shr 11) and 31;
  214. day:=(p shr 16) and 31;
  215. month:=(p shr 21) and 15;
  216. year:=(p shr 25)+1980;
  217. end;
  218. End;
  219. {******************************************************************************
  220. --- Exec ---
  221. ******************************************************************************}
  222. var
  223. lastdosexitcode : word;
  224. procedure exec(const path : pathstr;const comline : comstr);
  225. type
  226. realptr = packed record
  227. ofs,seg : word;
  228. end;
  229. texecblock = packed record
  230. envseg : word;
  231. comtail : realptr;
  232. firstFCB : realptr;
  233. secondFCB : realptr;
  234. iniStack : realptr;
  235. iniCSIP : realptr;
  236. end;
  237. var
  238. current_dos_buffer_pos,
  239. arg_ofs,
  240. i,la_env,
  241. la_p,la_c,la_e,
  242. fcb1_la,fcb2_la : longint;
  243. execblock : texecblock;
  244. c,p : string;
  245. function paste_to_dos(src : string) : boolean;
  246. var
  247. c : array[0..255] of char;
  248. begin
  249. paste_to_dos:=false;
  250. if current_dos_buffer_pos+length(src)+1>transfer_buffer+tb_size then
  251. RunError(217);
  252. move(src[1],c[0],length(src));
  253. c[length(src)]:=#0;
  254. seg_move(get_ds,longint(@c),dosmemselector,current_dos_buffer_pos,length(src)+1);
  255. current_dos_buffer_pos:=current_dos_buffer_pos+length(src)+1;
  256. paste_to_dos:=true;
  257. end;
  258. begin
  259. { create command line }
  260. move(comline[0],c[1],length(comline)+1);
  261. c[length(comline)+2]:=#13;
  262. c[0]:=char(length(comline)+2);
  263. { create path }
  264. p:=path;
  265. for i:=1 to length(p) do
  266. if p[i]='/' then
  267. p[i]:='\';
  268. if LFNSupport then
  269. GetShortName(p);
  270. { create buffer }
  271. la_env:=transfer_buffer;
  272. while (la_env and 15)<>0 do
  273. inc(la_env);
  274. current_dos_buffer_pos:=la_env;
  275. { copy environment }
  276. for i:=1 to envcount do
  277. paste_to_dos(envstr(i));
  278. paste_to_dos(''); { adds a double zero at the end }
  279. { allow slash as backslash }
  280. la_p:=current_dos_buffer_pos;
  281. paste_to_dos(p);
  282. la_c:=current_dos_buffer_pos;
  283. paste_to_dos(c);
  284. la_e:=current_dos_buffer_pos;
  285. fcb1_la:=la_e;
  286. la_e:=la_e+16;
  287. fcb2_la:=la_e;
  288. la_e:=la_e+16;
  289. { allocate FCB see dosexec code }
  290. arg_ofs:=1;
  291. while (c[arg_ofs] in [' ',#9]) do
  292. inc(arg_ofs);
  293. dosregs.ax:=$2901;
  294. dosregs.ds:=(la_c+arg_ofs) shr 4;
  295. dosregs.esi:=(la_c+arg_ofs) and 15;
  296. dosregs.es:=fcb1_la shr 4;
  297. dosregs.edi:=fcb1_la and 15;
  298. msdos(dosregs);
  299. { allocate second FCB see dosexec code }
  300. repeat
  301. inc(arg_ofs);
  302. until (c[arg_ofs] in [' ',#9,#13]);
  303. if c[arg_ofs]<>#13 then
  304. begin
  305. repeat
  306. inc(arg_ofs);
  307. until not (c[arg_ofs] in [' ',#9]);
  308. end;
  309. dosregs.ax:=$2901;
  310. dosregs.ds:=(la_c+arg_ofs) shr 4;
  311. dosregs.si:=(la_c+arg_ofs) and 15;
  312. dosregs.es:=fcb2_la shr 4;
  313. dosregs.di:=fcb2_la and 15;
  314. msdos(dosregs);
  315. with execblock do
  316. begin
  317. envseg:=la_env shr 4;
  318. comtail.seg:=la_c shr 4;
  319. comtail.ofs:=la_c and 15;
  320. firstFCB.seg:=fcb1_la shr 4;
  321. firstFCB.ofs:=fcb1_la and 15;
  322. secondFCB.seg:=fcb2_la shr 4;
  323. secondFCB.ofs:=fcb2_la and 15;
  324. end;
  325. seg_move(get_ds,longint(@execblock),dosmemselector,la_e,sizeof(texecblock));
  326. dosregs.edx:=la_p and 15;
  327. dosregs.ds:=la_p shr 4;
  328. dosregs.ebx:=la_e and 15;
  329. dosregs.es:=la_e shr 4;
  330. dosregs.ax:=$4b00;
  331. msdos(dosregs);
  332. LoadDosError;
  333. if DosError=0 then
  334. begin
  335. dosregs.ax:=$4d00;
  336. msdos(dosregs);
  337. LastDosExitCode:=DosRegs.al
  338. end
  339. else
  340. LastDosExitCode:=0;
  341. end;
  342. function dosexitcode : word;
  343. begin
  344. dosexitcode:=lastdosexitcode;
  345. end;
  346. procedure getcbreak(var breakvalue : boolean);
  347. begin
  348. DosError:=0;
  349. dosregs.ax:=$3300;
  350. msdos(dosregs);
  351. breakvalue:=dosregs.dl<>0;
  352. end;
  353. procedure setcbreak(breakvalue : boolean);
  354. begin
  355. DosError:=0;
  356. dosregs.ax:=$3301;
  357. dosregs.dl:=ord(breakvalue);
  358. msdos(dosregs);
  359. end;
  360. procedure getverify(var verify : boolean);
  361. begin
  362. DosError:=0;
  363. dosregs.ah:=$54;
  364. msdos(dosregs);
  365. verify:=dosregs.al<>0;
  366. end;
  367. procedure setverify(verify : boolean);
  368. begin
  369. DosError:=0;
  370. dosregs.ah:=$2e;
  371. dosregs.al:=ord(verify);
  372. msdos(dosregs);
  373. end;
  374. {******************************************************************************
  375. --- Disk ---
  376. ******************************************************************************}
  377. function diskfree(drive : byte) : longint;
  378. begin
  379. DosError:=0;
  380. dosregs.dl:=drive;
  381. dosregs.ah:=$36;
  382. msdos(dosregs);
  383. if dosregs.ax<>$FFFF then
  384. diskfree:=dosregs.ax*dosregs.bx*dosregs.cx
  385. else
  386. diskfree:=-1;
  387. end;
  388. function disksize(drive : byte) : longint;
  389. begin
  390. DosError:=0;
  391. dosregs.dl:=drive;
  392. dosregs.ah:=$36;
  393. msdos(dosregs);
  394. if dosregs.ax<>$FFFF then
  395. disksize:=dosregs.ax*dosregs.cx*dosregs.dx
  396. else
  397. disksize:=-1;
  398. end;
  399. {******************************************************************************
  400. --- LFNFindfirst LFNFindNext ---
  401. ******************************************************************************}
  402. type
  403. LFNSearchRec=packed record
  404. attr,
  405. crtime,
  406. crtimehi,
  407. actime,
  408. actimehi,
  409. lmtime,
  410. lmtimehi,
  411. sizehi,
  412. size : longint;
  413. reserved : array[0..7] of byte;
  414. name : array[0..259] of byte;
  415. shortname : array[0..13] of byte;
  416. end;
  417. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec);
  418. var
  419. Len : longint;
  420. begin
  421. With w do
  422. begin
  423. FillChar(d,sizeof(SearchRec),0);
  424. if DosError=0 then
  425. len:=StrLen(@Name)
  426. else
  427. len:=0;
  428. d.Name[0]:=chr(len);
  429. Move(Name[0],d.Name[1],Len);
  430. d.Time:=lmTime;
  431. d.Size:=Size;
  432. d.Attr:=Attr and $FF;
  433. Move(hdl,d.Fill,4);
  434. end;
  435. end;
  436. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  437. var
  438. i : longint;
  439. w : LFNSearchRec;
  440. begin
  441. { allow slash as backslash }
  442. for i:=0 to strlen(path) do
  443. if path[i]='/' then path[i]:='\';
  444. dosregs.si:=1; { use ms-dos time }
  445. { don't include the label if not asked for it, needed for network drives }
  446. if attr=$8 then
  447. dosregs.ecx:=8
  448. else
  449. dosregs.ecx:=attr and (not 8);
  450. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  451. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  452. dosregs.ds:=tb_segment;
  453. dosregs.edi:=tb_offset;
  454. dosregs.es:=tb_segment;
  455. dosregs.ax:=$714e;
  456. msdos(dosregs);
  457. LoadDosError;
  458. copyfromdos(w,sizeof(LFNSearchRec));
  459. LFNSearchRec2Dos(w,dosregs.ax,s);
  460. end;
  461. procedure LFNFindNext(var s:searchrec);
  462. var
  463. hdl : longint;
  464. w : LFNSearchRec;
  465. begin
  466. Move(s.Fill,hdl,4);
  467. dosregs.si:=1; { use ms-dos time }
  468. dosregs.edi:=tb_offset;
  469. dosregs.es:=tb_segment;
  470. dosregs.ebx:=hdl;
  471. dosregs.ax:=$714f;
  472. msdos(dosregs);
  473. LoadDosError;
  474. copyfromdos(w,sizeof(LFNSearchRec));
  475. LFNSearchRec2Dos(w,hdl,s);
  476. end;
  477. procedure LFNFindClose(var s:searchrec);
  478. var
  479. hdl : longint;
  480. begin
  481. Move(s.Fill,hdl,4);
  482. dosregs.ebx:=hdl;
  483. dosregs.ax:=$71a1;
  484. msdos(dosregs);
  485. LoadDosError;
  486. end;
  487. {******************************************************************************
  488. --- DosFindfirst DosFindNext ---
  489. ******************************************************************************}
  490. procedure dossearchrec2searchrec(var f : searchrec);
  491. var
  492. len : longint;
  493. begin
  494. len:=StrLen(@f.Name);
  495. Move(f.Name[0],f.Name[1],Len);
  496. f.Name[0]:=chr(len);
  497. end;
  498. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  499. var
  500. i : longint;
  501. begin
  502. { allow slash as backslash }
  503. for i:=0 to strlen(path) do
  504. if path[i]='/' then path[i]:='\';
  505. copytodos(f,sizeof(searchrec));
  506. dosregs.edx:=tb_offset;
  507. dosregs.ds:=tb_segment;
  508. dosregs.ah:=$1a;
  509. msdos(dosregs);
  510. dosregs.ecx:=attr;
  511. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  512. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  513. dosregs.ds:=tb_segment;
  514. dosregs.ah:=$4e;
  515. msdos(dosregs);
  516. copyfromdos(f,sizeof(searchrec));
  517. LoadDosError;
  518. dossearchrec2searchrec(f);
  519. end;
  520. procedure Dosfindnext(var f : searchrec);
  521. begin
  522. copytodos(f,sizeof(searchrec));
  523. dosregs.edx:=tb_offset;
  524. dosregs.ds:=tb_segment;
  525. dosregs.ah:=$1a;
  526. msdos(dosregs);
  527. dosregs.ah:=$4f;
  528. msdos(dosregs);
  529. copyfromdos(f,sizeof(searchrec));
  530. LoadDosError;
  531. dossearchrec2searchrec(f);
  532. end;
  533. {******************************************************************************
  534. --- Findfirst FindNext ---
  535. ******************************************************************************}
  536. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  537. var
  538. path0 : array[0..256] of char;
  539. begin
  540. doserror:=0;
  541. strpcopy(path0,path);
  542. if LFNSupport then
  543. LFNFindFirst(path0,attr,f)
  544. else
  545. Dosfindfirst(path0,attr,f);
  546. end;
  547. procedure findnext(var f : searchRec);
  548. begin
  549. doserror:=0;
  550. if LFNSupport then
  551. LFNFindnext(f)
  552. else
  553. Dosfindnext(f);
  554. end;
  555. Procedure FindClose(Var f: SearchRec);
  556. begin
  557. DosError:=0;
  558. if LFNSupport then
  559. LFNFindClose(f);
  560. end;
  561. type swap_proc = procedure;
  562. var
  563. _swap_in : swap_proc;external name '_swap_in';
  564. _swap_out : swap_proc;external name '_swap_out';
  565. _exception_exit : pointer;external name '_exception_exit';
  566. _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  567. procedure swapvectors;
  568. begin
  569. { DosError:=0; Who added this !!!!! }
  570. if _exception_exit<>nil then
  571. if _v2prt0_exceptions_on then
  572. _swap_in()
  573. else
  574. _swap_out();
  575. end;
  576. {******************************************************************************
  577. --- File ---
  578. ******************************************************************************}
  579. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  580. var
  581. dotpos,p1,i : longint;
  582. begin
  583. { allow slash as backslash }
  584. for i:=1 to length(path) do
  585. if path[i]='/' then path[i]:='\';
  586. { get drive name }
  587. p1:=pos(':',path);
  588. if p1>0 then
  589. begin
  590. dir:=path[1]+':';
  591. delete(path,1,p1);
  592. end
  593. else
  594. dir:='';
  595. { split the path and the name, there are no more path informtions }
  596. { if path contains no backslashes }
  597. while true do
  598. begin
  599. p1:=pos('\',path);
  600. if p1=0 then
  601. break;
  602. dir:=dir+copy(path,1,p1);
  603. delete(path,1,p1);
  604. end;
  605. { try to find out a extension }
  606. if LFNSupport then
  607. begin
  608. Ext:='';
  609. i:=Length(Path);
  610. DotPos:=256;
  611. While (i>0) Do
  612. Begin
  613. If (Path[i]='.') Then
  614. begin
  615. DotPos:=i;
  616. break;
  617. end;
  618. Dec(i);
  619. end;
  620. Ext:=Copy(Path,DotPos,255);
  621. Name:=Copy(Path,1,DotPos - 1);
  622. end
  623. else
  624. begin
  625. p1:=pos('.',path);
  626. if p1>0 then
  627. begin
  628. ext:=copy(path,p1,4);
  629. delete(path,p1,length(path)-p1+1);
  630. end
  631. else
  632. ext:='';
  633. name:=path;
  634. end;
  635. end;
  636. function fexpand(const path : pathstr) : pathstr;
  637. var
  638. s,pa : pathstr;
  639. i,j : longint;
  640. begin
  641. getdir(0,s);
  642. i:=ioresult;
  643. if LFNSupport then
  644. begin
  645. pa:=path;
  646. end
  647. else
  648. if FileNameCaseSensitive then
  649. pa:=path
  650. else
  651. pa:=upcase(path);
  652. { allow slash as backslash }
  653. for i:=1 to length(pa) do
  654. if pa[i]='/' then
  655. pa[i]:='\';
  656. if (length(pa)>1) and (pa[2]=':') and (pa[1] in ['A'..'Z','a'..'z']) then
  657. begin
  658. { Always uppercase driveletter }
  659. if (pa[1] in ['a'..'z']) then
  660. pa[1]:=Chr(Ord(Pa[1])-32);
  661. { we must get the right directory }
  662. getdir(ord(pa[1])-ord('A')+1,s);
  663. i:=ioresult;
  664. if (ord(pa[0])>2) and (pa[3]<>'\') then
  665. if pa[1]=s[1] then
  666. begin
  667. { remove ending slash if it already exists }
  668. if s[length(s)]='\' then
  669. dec(s[0]);
  670. pa:=s+'\'+copy (pa,3,length(pa));
  671. end
  672. else
  673. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  674. end
  675. else
  676. if pa[1]='\' then
  677. pa:=s[1]+':'+pa
  678. else if s[0]=#3 then
  679. pa:=s+pa
  680. else
  681. pa:=s+'\'+pa;
  682. { Turbo Pascal gives current dir on drive if only drive given as parameter! }
  683. if length(pa) = 2 then
  684. begin
  685. getdir(byte(pa[1])-64,s);
  686. pa := s;
  687. end;
  688. {First remove all references to '\.\'}
  689. while pos ('\.\',pa)<>0 do
  690. delete (pa,pos('\.\',pa),2);
  691. {Now remove also all references to '\..\' + of course previous dirs..}
  692. repeat
  693. i:=pos('\..\',pa);
  694. if i<>0 then
  695. begin
  696. j:=i-1;
  697. while (j>1) and (pa[j]<>'\') do
  698. dec (j);
  699. if pa[j+1] = ':' then j := 3;
  700. delete (pa,j,i-j+3);
  701. end;
  702. until i=0;
  703. { Turbo Pascal gets rid of a \.. at the end of the path }
  704. { Now remove also any reference to '\..' at end of line
  705. + of course previous dir.. }
  706. i:=pos('\..',pa);
  707. if i<>0 then
  708. begin
  709. if i = length(pa) - 2 then
  710. begin
  711. j:=i-1;
  712. while (j>1) and (pa[j]<>'\') do
  713. dec (j);
  714. delete (pa,j,i-j+3);
  715. end;
  716. pa := pa + '\';
  717. end;
  718. { Remove End . and \}
  719. if (length(pa)>0) and (pa[length(pa)]='.') then
  720. dec(byte(pa[0]));
  721. { if only the drive + a '\' is left then the '\' should be left to prevtn the program
  722. accessing the current directory on the drive rather than the root!}
  723. { if the last char of path = '\' then leave it in as this is what TP does! }
  724. if ((length(pa)>3) and (pa[length(pa)]='\')) and (path[length(path)] <> '\') then
  725. dec(byte(pa[0]));
  726. { if only a drive is given in path then there should be a '\' at the
  727. end of the string given back }
  728. if length(pa) = 2 then pa := pa + '\';
  729. fexpand:=pa;
  730. end;
  731. Function FSearch(path: pathstr; dirlist: string): pathstr;
  732. var
  733. i,p1 : longint;
  734. s : searchrec;
  735. newdir : pathstr;
  736. begin
  737. { check if the file specified exists }
  738. findfirst(path,anyfile,s);
  739. if doserror=0 then
  740. begin
  741. findclose(s);
  742. fsearch:=path;
  743. exit;
  744. end;
  745. { No wildcards allowed in these things }
  746. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  747. fsearch:=''
  748. else
  749. begin
  750. { allow slash as backslash }
  751. for i:=1 to length(dirlist) do
  752. if dirlist[i]='/' then dirlist[i]:='\';
  753. repeat
  754. p1:=pos(';',dirlist);
  755. if p1<>0 then
  756. begin
  757. newdir:=copy(dirlist,1,p1-1);
  758. delete(dirlist,1,p1);
  759. end
  760. else
  761. begin
  762. newdir:=dirlist;
  763. dirlist:='';
  764. end;
  765. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  766. newdir:=newdir+'\';
  767. findfirst(newdir+path,anyfile,s);
  768. if doserror=0 then
  769. newdir:=newdir+path
  770. else
  771. newdir:='';
  772. until (dirlist='') or (newdir<>'');
  773. fsearch:=newdir;
  774. end;
  775. findclose(s);
  776. end;
  777. { change to short filename if successful DOS call PM }
  778. function GetShortName(var p : String) : boolean;
  779. var
  780. c : array[0..255] of char;
  781. begin
  782. move(p[1],c[0],length(p));
  783. c[length(p)]:=#0;
  784. copytodos(@c,length(p)+1);
  785. dosregs.ax:=$7160;
  786. dosregs.cx:=1;
  787. dosregs.ds:=tb_segment;
  788. dosregs.si:=tb_offset;
  789. dosregs.es:=tb_segment;
  790. dosregs.di:=tb_offset;
  791. msdos(dosregs);
  792. LoadDosError;
  793. if DosError=0 then
  794. begin
  795. copyfromdos(@c,255);
  796. move(c[0],p[1],strlen(c));
  797. p[0]:=char(strlen(c));
  798. GetShortName:=true;
  799. end
  800. else
  801. GetShortName:=false;
  802. end;
  803. {******************************************************************************
  804. --- Get/Set File Time,Attr ---
  805. ******************************************************************************}
  806. procedure getftime(var f;var time : longint);
  807. begin
  808. dosregs.bx:=textrec(f).handle;
  809. dosregs.ax:=$5700;
  810. msdos(dosregs);
  811. loaddoserror;
  812. time:=(dosregs.dx shl 16)+dosregs.cx;
  813. end;
  814. procedure setftime(var f;time : longint);
  815. begin
  816. dosregs.bx:=textrec(f).handle;
  817. dosregs.cx:=time and $ffff;
  818. dosregs.dx:=time shr 16;
  819. dosregs.ax:=$5701;
  820. msdos(dosregs);
  821. loaddoserror;
  822. end;
  823. procedure getfattr(var f;var attr : word);
  824. begin
  825. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  826. dosregs.edx:=tb_offset;
  827. dosregs.ds:=tb_segment;
  828. if LFNSupport then
  829. begin
  830. dosregs.ax:=$7143;
  831. dosregs.bx:=0;
  832. end
  833. else
  834. dosregs.ax:=$4300;
  835. msdos(dosregs);
  836. LoadDosError;
  837. Attr:=dosregs.cx;
  838. end;
  839. procedure setfattr(var f;attr : word);
  840. begin
  841. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  842. dosregs.edx:=tb_offset;
  843. dosregs.ds:=tb_segment;
  844. if LFNSupport then
  845. begin
  846. dosregs.ax:=$7143;
  847. dosregs.bx:=1;
  848. end
  849. else
  850. dosregs.ax:=$4301;
  851. dosregs.cx:=attr;
  852. msdos(dosregs);
  853. LoadDosError;
  854. end;
  855. {******************************************************************************
  856. --- Environment ---
  857. ******************************************************************************}
  858. function envcount : longint;
  859. var
  860. hp : ppchar;
  861. begin
  862. hp:=envp;
  863. envcount:=0;
  864. while assigned(hp^) do
  865. begin
  866. inc(envcount);
  867. inc(hp);
  868. end;
  869. end;
  870. function envstr(index : integer) : string;
  871. begin
  872. if (index<=0) or (index>envcount) then
  873. begin
  874. envstr:='';
  875. exit;
  876. end;
  877. envstr:=strpas(ppchar(pointer(envp)+4*(index-1))^);
  878. end;
  879. Function GetEnv(envvar: string): string;
  880. var
  881. hp : ppchar;
  882. hs : string;
  883. eqpos : longint;
  884. begin
  885. envvar:=upcase(envvar);
  886. hp:=envp;
  887. getenv:='';
  888. while assigned(hp^) do
  889. begin
  890. hs:=strpas(hp^);
  891. eqpos:=pos('=',hs);
  892. if copy(hs,1,eqpos-1)=envvar then
  893. begin
  894. getenv:=copy(hs,eqpos+1,255);
  895. exit;
  896. end;
  897. inc(hp);
  898. end;
  899. end;
  900. {******************************************************************************
  901. --- Not Supported ---
  902. ******************************************************************************}
  903. Procedure keep(exitcode : word);
  904. Begin
  905. End;
  906. Procedure getintvec(intno : byte;var vector : pointer);
  907. Begin
  908. End;
  909. Procedure setintvec(intno : byte;vector : pointer);
  910. Begin
  911. End;
  912. end.
  913. {
  914. $Log$
  915. Revision 1.17 2000-01-07 16:41:30 daniel
  916. * copyright 2000
  917. Revision 1.16 2000/01/07 16:32:23 daniel
  918. * copyright 2000 added
  919. Revision 1.15 1999/12/06 18:26:49 peter
  920. * fpcmake updated for win32 commandline
  921. Revision 1.14 1999/11/09 11:07:50 pierre
  922. * SwapVectors does not reset DosError anymore
  923. + DosError is set to ax regsiter value if extended doserror function
  924. retruns zero.
  925. + Support for LFN in EXEC function using
  926. function 7160 to get short filename counterpart
  927. Revision 1.13 1999/11/06 14:38:23 peter
  928. * truncated log
  929. Revision 1.12 1999/09/10 17:14:09 peter
  930. * better errorcode returning using int21h,5900
  931. Revision 1.11 1999/09/08 18:55:49 peter
  932. * pointer fixes
  933. Revision 1.10 1999/08/13 21:23:15 peter
  934. * fsearch checks first if the specified file exists and returns that
  935. if it was found
  936. Revision 1.9 1999/05/16 17:08:58 peter
  937. * fixed driveletter checking
  938. Revision 1.8 1999/05/08 19:47:22 peter
  939. * check ioresult after getdir calls
  940. Revision 1.7 1999/05/04 23:55:50 pierre
  941. * unneeded assembler code converted to pascal
  942. Revision 1.6 1999/04/28 11:42:44 peter
  943. + FileNameCaseSensetive boolean
  944. Revision 1.5 1999/04/02 00:01:29 peter
  945. * fixed LFNFindfirst on network drives
  946. Revision 1.4 1999/03/01 15:40:48 peter
  947. * use external names
  948. * removed all direct assembler modes
  949. Revision 1.3 1999/01/22 15:44:59 pierre
  950. Daniel change removed : broke make cycle !!
  951. Revision 1.2 1999/01/22 10:07:03 daniel
  952. - Findclose removed: This is TP incompatible!!
  953. Revision 1.1 1998/12/21 13:07:02 peter
  954. * use -FE
  955. Revision 1.19 1998/11/23 13:53:59 peter
  956. * more fexpand fixes from marco van de voort
  957. Revision 1.18 1998/11/23 12:48:02 peter
  958. * fexpand('o:') fixed to return o:\ (from the mailinglist)
  959. Revision 1.17 1998/11/22 09:33:21 florian
  960. * fexpand bug (temp. strings were too shoort) fixed, was reported
  961. by Marco van de Voort
  962. Revision 1.16 1998/11/17 09:37:41 pierre
  963. * explicit conversion from word dosreg.ax to integer doserror
  964. Revision 1.15 1998/11/01 20:27:18 peter
  965. * fixed some doserror settings
  966. Revision 1.14 1998/10/22 15:05:28 pierre
  967. * fsplit adapted to long filenames
  968. Revision 1.13 1998/09/16 16:47:24 peter
  969. * merged fixes
  970. Revision 1.11.2.2 1998/09/16 16:16:04 peter
  971. * go32v1 compiles again
  972. }