fio.mod 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. (* Copyright (C) 1987 Jensen & Partners International *)
  2. (*$S-,R-,I-*)
  3. IMPLEMENTATION MODULE FIO;
  4. FROM Str IMPORT CHARSET,Length,Compare,IntToStr,CardToStr,RealToStr,
  5. StrToInt,StrToCard,StrToReal,Copy;
  6. FROM SYSTEM IMPORT Seg,Ofs,Registers,CarryFlag;
  7. IMPORT AsmLib;
  8. CONST
  9. TrueStr = 'TRUE';
  10. MaxHandle = MaxOpenFiles+3;
  11. (*$V-*)
  12. TYPE
  13. FileInf = POINTER TO BufRec;
  14. VAR
  15. IOR : CARDINAL; (* MSDOS result value *)
  16. BufInf : ARRAY[0..MaxHandle] OF FileInf;
  17. CONST
  18. ErrMsg2 = 'file not found';
  19. ErrMsg3 = 'path not found';
  20. ErrMsg4 = 'too many open files';
  21. ErrMsg5 = 'access denied';
  22. ErrMsg6 = 'invalid handle';
  23. ErrMsg15 = 'invalid drive';
  24. ErrMsg16 = 'current directory';
  25. ErrMsg17 = 'different device';
  26. ErrMsgDiskFull = 'disk full';
  27. PROCEDURE ErrorCheckNamed ( VAR r : Registers;
  28. str : ARRAY OF CHAR;
  29. name : ARRAY OF CHAR);
  30. VAR
  31. s : ARRAY[0..100] OF CHAR;
  32. ns : ARRAY[0..3] OF CHAR;
  33. sp : POINTER TO ARRAY[0..79] OF CHAR;
  34. PROCEDURE AddErr(es: ARRAY OF CHAR);
  35. BEGIN
  36. Str.Append(s,es);
  37. END AddErr;
  38. BEGIN
  39. WITH r DO
  40. IF (BITSET{CarryFlag} * Flags) # BITSET{} THEN
  41. IOR := AX;
  42. IF IOcheck THEN
  43. s := CHR(0);
  44. Copy(s,str);
  45. AddErr(' : ');
  46. CASE IOR OF
  47. 2 : sp := ADR(ErrMsg2) |
  48. 3 : sp := ADR(ErrMsg3) |
  49. 4 : sp := ADR(ErrMsg4) |
  50. 5 : sp := ADR(ErrMsg5) |
  51. 6 : sp := ADR(ErrMsg6) |
  52. 15: sp := ADR(ErrMsg15) |
  53. 16: sp := ADR(ErrMsg16) |
  54. 17: sp := ADR(ErrMsg17) |
  55. DiskFull: sp := ADR(ErrMsgDiskFull) |
  56. ELSE AddErr('MSDOS error # ') ;
  57. ns[0] := CHR(IOR DIV 10+48);
  58. ns[1] := CHR(IOR MOD 10+48);
  59. ns[2] := CHR(0);
  60. sp := ADR(ns);
  61. END;
  62. AddErr(sp^);
  63. IF name[0] # CHR(0) THEN
  64. AddErr(' (');
  65. AddErr(name);
  66. AddErr(')');
  67. END;
  68. Lib.FatalError(s);
  69. END;
  70. ELSE
  71. IOR := 0;
  72. END;
  73. END;
  74. END ErrorCheckNamed;
  75. PROCEDURE ErrorCheck(VAR r: Registers; str: ARRAY OF CHAR);
  76. BEGIN
  77. IF (BITSET{CarryFlag} * r.Flags) # BITSET{} THEN
  78. ErrorCheckNamed(r,str,CHR(0));
  79. ELSE
  80. IOR := 0;
  81. END;
  82. END ErrorCheck;
  83. PROCEDURE IOresult () : CARDINAL;
  84. BEGIN
  85. RETURN IOR;
  86. END IOresult;
  87. PROCEDURE Write(F: File; Buf: ARRAY OF BYTE; Count: CARDINAL);
  88. VAR r : Registers;
  89. BEGIN
  90. IF Count = 0 THEN RETURN END;
  91. WITH r DO
  92. DS := Seg(Buf);
  93. DX := Ofs(Buf);
  94. AH := 40H; (* file write *)
  95. BX := F;
  96. CX := Count;
  97. Lib.Dos(r);
  98. IF (AX # CX) AND ((BITSET{CarryFlag} * Flags) = BITSET{}) THEN
  99. AX := DiskFull;
  100. Flags := BITSET{CarryFlag};
  101. END;
  102. ErrorCheck(r,'Write');
  103. END;
  104. END Write;
  105. PROCEDURE Flush(F: File);
  106. VAR x : FileInf;
  107. r : Registers;
  108. conv : RECORD
  109. CASE : BOOLEAN OF
  110. | TRUE : lo,hi: CARDINAL;
  111. | FALSE : long : LONGINT;
  112. END;
  113. END;
  114. BEGIN
  115. IF (F <= MaxHandle) THEN
  116. x := BufInf[F];
  117. IF (x # NIL) THEN
  118. WITH x^ DO
  119. IF RWPos > EOB THEN
  120. Write( F,Buffer,RWPos );
  121. ELSIF RWPos < EOB THEN (* last was read, move DOS pointer back *)
  122. conv.long := LONGINT(RWPos) - LONGINT(EOB);
  123. WITH r DO
  124. CX := conv.hi;
  125. DX := conv.lo;
  126. AX := 4201H; (* seek relative *)
  127. BX := F;
  128. Lib.Dos(r);
  129. ErrorCheck(r,'Flush');
  130. END;
  131. END;
  132. RWPos := 0;
  133. EOB := 0;
  134. END;
  135. END;
  136. END;
  137. END Flush;
  138. PROCEDURE Truncate(F: File);
  139. VAR r : Registers;
  140. BEGIN
  141. Flush( F );
  142. WITH r DO
  143. AH := 40H; (* file write *)
  144. BX := F;
  145. CX := 0;
  146. Lib.Dos(r);
  147. ErrorCheck(r,'Truncate');
  148. END;
  149. END Truncate;
  150. PROCEDURE Read(F: File; VAR Buf: ARRAY OF BYTE; Count: CARDINAL) : CARDINAL;
  151. VAR r : Registers;
  152. BEGIN
  153. WITH r DO
  154. DS := Seg(Buf);
  155. DX := Ofs(Buf);
  156. AH := 3FH; (* file read *)
  157. BX := F;
  158. CX := Count;
  159. Lib.Dos(r);
  160. ErrorCheck(r,'Read');
  161. IF IOR = 0 THEN
  162. RETURN AX;
  163. ELSE
  164. RETURN 0;
  165. END;
  166. END;
  167. END Read;
  168. PROCEDURE WrStr(F: File; Buf: ARRAY OF CHAR);
  169. VAR Count : CARDINAL;
  170. BEGIN
  171. OK := TRUE;
  172. Count := Str.Length( Buf );
  173. WrBin( F,Buf,Count );
  174. END WrStr;
  175. PROCEDURE WrLn(F: File);
  176. TYPE a = ARRAY [ 0..1 ] OF CHAR;
  177. BEGIN
  178. WrStr( F, a( CHR( 13 ),CHR( 10 ) ) );
  179. END WrLn;
  180. PROCEDURE RdChar(F: File ) : CHAR;
  181. VAR c : CHAR;
  182. BEGIN
  183. OK := TRUE;
  184. IF (F <= MaxHandle) AND (BufInf[F] # NIL) THEN
  185. WITH BufInf[F]^ DO
  186. IF RWPos < EOB THEN
  187. c := CHAR(Buffer[ RWPos ]);
  188. INC(RWPos);
  189. EOF := (c = CHR(26));
  190. RETURN c;
  191. END;
  192. END;
  193. END;
  194. IF RdBin( F,c,1 ) = 0 THEN
  195. OK := FALSE;
  196. c := CHR(26);
  197. END;
  198. EOF := (c = CHR(26));
  199. RETURN c;
  200. END RdChar;
  201. PROCEDURE RdStr(F: File; VAR Buf: ARRAY OF CHAR);
  202. VAR
  203. i,h : CARDINAL;
  204. c : CHAR;
  205. BEGIN
  206. i := 0;
  207. h := HIGH( Buf );
  208. OK := TRUE;
  209. LOOP
  210. IF i > h THEN RETURN END;
  211. c := RdChar( F );
  212. IF c = CHR( 26 ) THEN
  213. Buf[ i ] := CHR(0);
  214. EOF := (i = 0);
  215. RETURN;
  216. ELSIF c = CHR( 13 ) THEN
  217. Buf[ i ] := CHR(0);
  218. RETURN;
  219. ELSIF c # CHR( 10 ) THEN
  220. Buf[ i ] := c;
  221. INC( i );
  222. END;
  223. END;
  224. END RdStr;
  225. PROCEDURE RdItem( F : File; VAR S : ARRAY OF CHAR );
  226. VAR c : CHAR; i,L : CARDINAL;
  227. BEGIN
  228. i := 0;
  229. LOOP
  230. c := RdChar( F );
  231. IF NOT OK OR NOT (c IN Separators) THEN EXIT; END;
  232. END;
  233. L := HIGH( S );
  234. LOOP
  235. IF NOT OK OR ( c IN Separators ) THEN EXIT; END;
  236. S[i] := c;
  237. INC( i );
  238. IF i > L THEN
  239. EXIT;
  240. ELSE
  241. c := RdChar( F );
  242. IF c = CHR(26) THEN OK := TRUE; EXIT; END;
  243. END;
  244. END;
  245. IF i <= L THEN S[i] := 0C; END;
  246. END RdItem;
  247. (*$V+*)
  248. PROCEDURE WrStrAdj(F: File; S: ARRAY OF CHAR; Length: INTEGER);
  249. VAR
  250. L : CARDINAL;
  251. a : INTEGER;
  252. BEGIN
  253. OK := TRUE;
  254. L := Str.Length( S );
  255. a := ABS( Length ) - INTEGER( L );
  256. IF (a < 0) AND ChopOff THEN
  257. L := CARDINAL(ABS(Length));
  258. IF L>HIGH(S) THEN
  259. L := HIGH(S)+1;
  260. ELSE
  261. S[L] := CHR(0);
  262. END;
  263. WHILE (L>0) DO DEC(L) ; S[L] := '?'; END;
  264. OK := FALSE;
  265. a := 0;
  266. END;
  267. IF (Length > 0) AND (a > 0) THEN WrCharRep( F,' ',a ); END;
  268. WrStr( F,S );
  269. IF (Length < 0) AND (a > 0) THEN WrCharRep( F,' ',a ); END;
  270. END WrStrAdj;
  271. (*$V-*)
  272. PROCEDURE WrChar(F: File; V: CHAR);
  273. BEGIN
  274. OK := TRUE;
  275. WrBin( F,V,1 );
  276. END WrChar;
  277. PROCEDURE WrCharRep(F: File; V: CHAR ; Count: CARDINAL);
  278. VAR
  279. S : ARRAY[0..80] OF CHAR;
  280. i,j : CARDINAL;
  281. BEGIN
  282. WHILE Count>0 DO
  283. i := SIZE(S)-2;
  284. IF i > Count THEN i := Count END;
  285. DEC(Count,i);
  286. j := 0;
  287. WHILE (j < i) DO S[j] := V; INC(j) END;
  288. OK := TRUE;
  289. WrBin( F,S,j );
  290. IF NOT OK THEN RETURN END ;
  291. END;
  292. END WrCharRep;
  293. PROCEDURE WrBool(F: File; V: BOOLEAN; Length: INTEGER);
  294. BEGIN
  295. IF V THEN
  296. WrStrAdj( F,TrueStr,Length );
  297. ELSE
  298. WrStrAdj( F,'FALSE',Length );
  299. END;
  300. END WrBool;
  301. PROCEDURE WrShtInt(F: File; V: SHORTINT; Length: INTEGER);
  302. VAR S : ARRAY[0..80] OF CHAR;
  303. BEGIN
  304. IntToStr( VAL( LONGINT,V ),S,10,OK );
  305. IF OK THEN WrStrAdj( F,S,Length ); END;
  306. END WrShtInt;
  307. PROCEDURE WrInt(F: File; V: INTEGER; Length: INTEGER);
  308. VAR S : ARRAY[0..80] OF CHAR;
  309. BEGIN
  310. IntToStr( VAL( LONGINT,V ),S,10,OK );
  311. IF OK THEN WrStrAdj( F,S,Length ); END;
  312. END WrInt;
  313. PROCEDURE WrLngInt(F: File; V: LONGINT; Length: INTEGER);
  314. VAR S : ARRAY[0..80] OF CHAR;
  315. BEGIN
  316. IntToStr( V,S,10,OK );
  317. IF OK THEN WrStrAdj( F,S,Length ); END;
  318. END WrLngInt;
  319. PROCEDURE WrShtCard(F: File; V: SHORTCARD; Length: INTEGER);
  320. VAR S : ARRAY[0..80] OF CHAR;
  321. BEGIN
  322. CardToStr( VAL( LONGCARD,V ),S,10,OK );
  323. IF OK THEN WrStrAdj( F,S,Length ); END;
  324. END WrShtCard;
  325. PROCEDURE WrCard(F: File; V: CARDINAL; Length: INTEGER);
  326. VAR S : ARRAY[0..80] OF CHAR;
  327. BEGIN
  328. CardToStr( VAL( LONGCARD,V ),S,10,OK );
  329. IF OK THEN WrStrAdj( F,S,Length ); END;
  330. END WrCard;
  331. PROCEDURE WrLngCard(F: File; V: LONGCARD; Length: INTEGER);
  332. VAR S : ARRAY[0..80] OF CHAR;
  333. BEGIN
  334. CardToStr( V,S,10,OK );
  335. IF OK THEN WrStrAdj( F,S,Length ); END;
  336. END WrLngCard;
  337. PROCEDURE WrShtHex(F: File; V: SHORTCARD; Length: INTEGER);
  338. VAR S : ARRAY[0..80] OF CHAR;
  339. BEGIN
  340. CardToStr( VAL( LONGCARD,V ),S,16,OK );
  341. IF OK THEN WrStrAdj( F,S,Length ); END;
  342. END WrShtHex;
  343. PROCEDURE WrHex(F: File; V: CARDINAL; Length: INTEGER);
  344. VAR S : ARRAY[0..80] OF CHAR;
  345. BEGIN
  346. CardToStr( VAL( LONGCARD,V ),S,16,OK );
  347. IF OK THEN WrStrAdj( F,S,Length ); END;
  348. END WrHex;
  349. PROCEDURE WrLngHex(F: File; V: LONGCARD; Length: INTEGER);
  350. VAR S : ARRAY[0..80] OF CHAR;
  351. BEGIN
  352. CardToStr( V,S,16,OK );
  353. IF OK THEN WrStrAdj( F,S,Length ); END;
  354. END WrLngHex;
  355. PROCEDURE WrReal(F: File; V: REAL; Precision: CARDINAL; Length: INTEGER);
  356. VAR S : ARRAY[0..80] OF CHAR;
  357. BEGIN
  358. RealToStr( VAL( LONGREAL,V ),Precision,Eng,S,OK );
  359. IF OK THEN WrStrAdj( F,S,Length ); END;
  360. END WrReal;
  361. PROCEDURE WrLngReal(F: File; V: LONGREAL; Precision: CARDINAL; Length: INTEGER);
  362. VAR S : ARRAY[0..80] OF CHAR;
  363. BEGIN
  364. RealToStr( V,Precision,Eng,S,OK );
  365. IF OK THEN WrStrAdj( F,S,Length ); END;
  366. END WrLngReal;
  367. PROCEDURE RdBool(F: File) : BOOLEAN;
  368. VAR S : ARRAY[0..80] OF CHAR;
  369. BEGIN
  370. RdItem( F,S );
  371. RETURN Compare(S,TrueStr) = 0;
  372. END RdBool;
  373. PROCEDURE RdShtInt(F: File) : SHORTINT;
  374. VAR
  375. S : ARRAY[0..80] OF CHAR;
  376. i : LONGINT;
  377. BEGIN
  378. RdItem( F,S );
  379. i := StrToInt( S,10,OK );
  380. OK := OK AND (i >= -80H) AND (i <= 7FH);
  381. RETURN SHORTINT( i );
  382. END RdShtInt;
  383. PROCEDURE RdInt(F: File) : INTEGER;
  384. VAR
  385. S : ARRAY[0..80] OF CHAR;
  386. i : LONGINT;
  387. BEGIN
  388. RdItem( F,S );
  389. i := StrToInt( S,10,OK );
  390. OK := OK AND (i >= -8000H) AND (i <= 7FFFH);
  391. RETURN INTEGER(i);
  392. END RdInt;
  393. PROCEDURE RdLngInt(F: File) : LONGINT;
  394. VAR S : ARRAY[0..80] OF CHAR;
  395. BEGIN
  396. RdItem( F,S );
  397. RETURN StrToInt( S,10,OK );
  398. END RdLngInt;
  399. PROCEDURE RdShtCard(F: File) : SHORTCARD;
  400. VAR
  401. S : ARRAY[0..80] OF CHAR;
  402. i : LONGCARD;
  403. BEGIN
  404. RdItem( F,S );
  405. i := StrToCard( S,10,OK );
  406. OK := OK AND (i < 0FFH);
  407. RETURN SHORTINT( i );
  408. END RdShtCard;
  409. PROCEDURE RdCard(F: File) : CARDINAL;
  410. VAR
  411. S : ARRAY[0..80] OF CHAR;
  412. i : LONGCARD;
  413. BEGIN
  414. RdItem( F,S );
  415. i := StrToCard( S,10,OK );
  416. OK := OK AND (i < 10000H);
  417. RETURN INTEGER( i );
  418. END RdCard;
  419. PROCEDURE RdLngCard(F: File) : LONGCARD;
  420. VAR S : ARRAY[0..80] OF CHAR;
  421. BEGIN
  422. RdItem( F,S );
  423. RETURN StrToCard( S,10,OK );
  424. END RdLngCard;
  425. PROCEDURE RdShtHex(F: File) : SHORTCARD;
  426. VAR
  427. S : ARRAY[0..80] OF CHAR;
  428. i : LONGCARD;
  429. BEGIN
  430. RdItem( F,S );
  431. i := StrToCard( S,16,OK );
  432. OK := OK AND (i < 0FFH);
  433. RETURN SHORTINT( i );
  434. END RdShtHex;
  435. PROCEDURE RdHex(F: File) : CARDINAL;
  436. VAR
  437. S : ARRAY[0..80] OF CHAR;
  438. i : LONGCARD;
  439. BEGIN
  440. RdItem( F,S );
  441. i := StrToCard( S,16,OK );
  442. OK := OK AND (i < 10000H);
  443. RETURN INTEGER( i );
  444. END RdHex;
  445. PROCEDURE RdLngHex(F: File) : LONGCARD;
  446. VAR S : ARRAY[0..80] OF CHAR;
  447. BEGIN
  448. RdItem( F,S );
  449. RETURN StrToCard( S,16,OK );
  450. END RdLngHex ;
  451. PROCEDURE RdReal(F: File): REAL;
  452. VAR
  453. S : ARRAY[0..80] OF CHAR;
  454. r,a : LONGREAL;
  455. BEGIN
  456. RdItem( F,S );
  457. r := StrToReal( S,OK );
  458. a := ABS( r );
  459. OK := OK AND (a >= 1.2E-38 ) AND (a <= 3.4E38 );
  460. RETURN VAL( REAL,r );
  461. END RdReal;
  462. PROCEDURE RdLngReal(F: File) : LONGREAL;
  463. VAR S : ARRAY[0..80] OF CHAR;
  464. BEGIN
  465. RdItem( F,S );
  466. RETURN StrToReal( S,OK );
  467. END RdLngReal;
  468. PROCEDURE WrBin(F: File; Buf: ARRAY OF BYTE; Count: CARDINAL);
  469. VAR i : CARDINAL;
  470. BEGIN
  471. OK := TRUE;
  472. i := 0;
  473. IF (F > MaxHandle) OR (BufInf[F] = NIL) THEN
  474. Write( F,Buf,Count );
  475. OK := (IOR = 0);
  476. ELSE
  477. WITH BufInf[F]^ DO
  478. IF RWPos <= EOB THEN (* last was read *)
  479. Flush(F);
  480. END;
  481. i := 0;
  482. WHILE Count > i DO
  483. WHILE (RWPos < BufSize) AND ( Count > i ) DO
  484. Buffer[ RWPos ] := SHORTCARD(Buf[i]);
  485. INC( i );
  486. INC( RWPos );
  487. END;
  488. IF RWPos = BufSize THEN
  489. Write( F,Buffer,BufSize );
  490. RWPos := 0;
  491. END;
  492. END;
  493. END;
  494. END;
  495. END WrBin;
  496. PROCEDURE RdBin(F: File; VAR Buf: ARRAY OF BYTE; Count: CARDINAL) : CARDINAL;
  497. VAR i,h,j : CARDINAL;
  498. BEGIN
  499. i := 0;
  500. OK := TRUE;
  501. EOF := FALSE;
  502. IF Count > 0 THEN
  503. IF (F > MaxHandle) OR (BufInf[F] = NIL) THEN
  504. i := Read( F,Buf,Count );
  505. OK := (IOR=0);
  506. ELSE
  507. WITH BufInf[F]^ DO
  508. IF RWPos > EOB THEN (* Last was write *) Flush( F ); END;
  509. i := 0;
  510. LOOP
  511. IF Count = i THEN EXIT; END;
  512. IF RWPos >= EOB THEN
  513. EOB := Read( F,Buffer,BufSize );
  514. OK := (IOR=0);
  515. RWPos := 0;
  516. IF EOB=0 THEN EXIT; END;
  517. END;
  518. WHILE (RWPos < EOB) AND (Count > i) DO
  519. Buf[i] := BYTE(Buffer[ RWPos ]);
  520. INC( i );
  521. INC( RWPos );
  522. END;
  523. END;
  524. END;
  525. END;
  526. IF (i = 0) THEN EOF := TRUE; END;
  527. END;
  528. RETURN i;
  529. END RdBin;
  530. PROCEDURE GetName(name: ARRAY OF CHAR; VAR fn: PathStr);
  531. BEGIN
  532. Copy(fn,name);
  533. fn[SIZE(fn)-1] := CHR(0);
  534. END GetName;
  535. PROCEDURE Open(Name: ARRAY OF CHAR) : File;
  536. VAR
  537. r : Registers;
  538. fn: PathStr;
  539. BEGIN
  540. GetName(Name,fn);
  541. WITH r DO
  542. DS := Seg(fn);
  543. DX := Ofs(fn);
  544. CX := 0;
  545. AX := 3D02H; (* open for read and write *)
  546. Lib.Dos(r);
  547. IF ((BITSET{CarryFlag} * Flags) # BITSET{}) AND (AX = 5) THEN
  548. (* access denied *)
  549. AX := 3D00H; (* open for read *)
  550. Lib.Dos(r);
  551. END;
  552. ErrorCheckNamed(r,'Open',fn);
  553. IF IOR = 0 THEN
  554. IF AX <= MaxHandle THEN BufInf[AX] := NIL; END;
  555. RETURN AX;
  556. END ;
  557. RETURN MAX(CARDINAL);
  558. END;
  559. END Open;
  560. PROCEDURE Exists(Name: ARRAY OF CHAR) : BOOLEAN;
  561. VAR d : DirEntry;
  562. r : Registers ;
  563. b : BOOLEAN ;
  564. BEGIN
  565. r.AX := 2F00H ; (* save DTA *)
  566. Lib.Dos(r);
  567. b := ReadFirstEntry(Name,FileAttr{},d);
  568. r.AX := 1A00H ;
  569. r.DS := r.ES ;
  570. r.DX := r.BX ;
  571. Lib.Dos(r); (* restore DTA *)
  572. RETURN b;
  573. END Exists;
  574. PROCEDURE Append(Name: ARRAY OF CHAR) : File;
  575. VAR F : CARDINAL;
  576. BEGIN
  577. F := Open( Name );
  578. Seek( F,Size( F ) );
  579. RETURN F;
  580. END Append;
  581. PROCEDURE Create(Name: ARRAY OF CHAR) : File;
  582. VAR
  583. r : Registers;
  584. fn: PathStr;
  585. BEGIN
  586. GetName(Name,fn);
  587. WITH r DO
  588. DS := Seg(fn);
  589. DX := Ofs(fn);
  590. CX := 0;
  591. AH := 3CH;
  592. Lib.Dos(r); (* Create, open for read and write *)
  593. ErrorCheckNamed(r,'Create',fn);
  594. IF IOR = 0 THEN
  595. IF AX <= MaxHandle THEN BufInf[AX] := NIL; END;
  596. RETURN AX;
  597. END ;
  598. RETURN MAX(CARDINAL);
  599. END;
  600. END Create;
  601. PROCEDURE Close(F: File);
  602. VAR
  603. r : Registers;
  604. x : FileInf;
  605. BEGIN
  606. Flush( F );
  607. IF F <= MaxHandle THEN
  608. BufInf[F] := NIL;
  609. END;
  610. WITH r DO
  611. BX := F;
  612. AH := 3EH; (* close file *)
  613. Lib.Dos(r);
  614. ErrorCheck(r,'Close');
  615. END;
  616. END Close;
  617. PROCEDURE GetPos(F: File) : LONGCARD;
  618. VAR
  619. r : Registers;
  620. x : FileInf;
  621. conv : RECORD
  622. CASE : BOOLEAN OF
  623. | TRUE : lo,hi: CARDINAL;
  624. | FALSE : long : LONGCARD;
  625. END;
  626. END;
  627. BEGIN
  628. WITH r DO
  629. CX := 0;
  630. DX := 0;
  631. AX := 4201H; (* seek relative *)
  632. BX := F;
  633. Lib.Dos(r);
  634. ErrorCheck(r,'GetPos');
  635. conv.lo := AX;
  636. conv.hi := DX;
  637. IF (F <= MaxHandle) THEN
  638. x := BufInf[F];
  639. IF (x # NIL) THEN
  640. WITH x^ DO
  641. IF RWPos > EOB THEN
  642. INC(conv.long,VAL(LONGCARD,RWPos));
  643. ELSIF RWPos < EOB THEN
  644. DEC(conv.long,VAL(LONGCARD,EOB-RWPos));
  645. END;
  646. END;
  647. END;
  648. END;
  649. RETURN conv.long;
  650. END;
  651. END GetPos;
  652. PROCEDURE Seek( F : File; pos:LONGCARD );
  653. VAR
  654. EOBpos : LONGCARD;
  655. r : Registers;
  656. conv : RECORD
  657. CASE : BOOLEAN OF
  658. | TRUE : lo,hi: CARDINAL;
  659. | FALSE : long : LONGCARD;
  660. END;
  661. END;
  662. BEGIN
  663. IF (F<=MaxHandle) AND (BufInf[F]<>NIL) THEN
  664. WITH BufInf[F]^ DO
  665. IF (EOB>0) AND (RWPos<=EOB) THEN
  666. (* there are read bytes in the buffer *)
  667. (* find out where we are in the file *)
  668. WITH r DO
  669. CX := 0; DX := 0;
  670. AX := 4201H; (* seek relative *)
  671. BX := F;
  672. Lib.Dos(r); ErrorCheck(r,'Seek');
  673. conv.lo := AX; conv.hi := DX; EOBpos := conv.long;
  674. END;
  675. IF (pos>=EOBpos-LONGCARD(EOB)) AND (pos<EOBpos) THEN
  676. (* we can seek within the buffer *)
  677. RWPos := EOB - CARDINAL(EOBpos-pos);
  678. RETURN;
  679. END;
  680. ELSE
  681. IF RWPos > EOB THEN (* last was write, bring DOS up to date *)
  682. Write( F,Buffer,RWPos );
  683. END;
  684. END;
  685. (* the buffer contents are finished with now *)
  686. RWPos := 0;
  687. EOB := 0;
  688. END;
  689. END;
  690. (* we haven't done an in-buffer seek - so get DOS to do it for us *)
  691. conv.long := pos;
  692. WITH r DO
  693. CX := conv.hi;
  694. DX := conv.lo;
  695. AX := 4200H; (* seek absolute *)
  696. BX := F;
  697. Lib.Dos(r);
  698. ErrorCheck(r,'Seek');
  699. END;
  700. END Seek;
  701. PROCEDURE Size(F: File) : LONGCARD;
  702. VAR
  703. r : Registers;
  704. conv1,
  705. conv2 : RECORD
  706. CASE : BOOLEAN OF
  707. | TRUE : lo,hi: CARDINAL;
  708. | FALSE : long : LONGCARD;
  709. END;
  710. END;
  711. BEGIN
  712. Flush( F );
  713. WITH r DO
  714. CX := 0;
  715. DX := 0;
  716. AX := 4201H; (* seek relative *)
  717. BX := F;
  718. Lib.Dos(r);
  719. conv1.hi := DX;
  720. conv1.lo := AX;
  721. CX := 0;
  722. DX := 0;
  723. AX := 4202H; (* seek relative to end *)
  724. Lib.Dos(r);
  725. conv2.hi := DX;
  726. conv2.lo := AX;
  727. CX := conv1.hi;
  728. DX := conv1.lo;
  729. AX := 4200H; (* seek absolute *)
  730. Lib.Dos(r);
  731. ErrorCheck(r,'Size');
  732. END;
  733. RETURN conv2.long;
  734. END Size;
  735. PROCEDURE Erase(Name:ARRAY OF CHAR);
  736. VAR
  737. r : Registers;
  738. fn : PathStr;
  739. BEGIN
  740. GetName(Name,fn);
  741. WITH r DO
  742. DS := Seg(fn);
  743. DX := Ofs(fn);
  744. AH := 41H;
  745. Lib.Dos(r);
  746. IF ((BITSET{CarryFlag} * Flags) # BITSET{}) AND (AX = 2) THEN
  747. Flags := BITSET{};
  748. END;
  749. ErrorCheckNamed(r,'Erase',fn);
  750. END;
  751. END Erase;
  752. PROCEDURE Rename(Name,newname: ARRAY OF CHAR);
  753. VAR
  754. r : Registers;
  755. fn,fn2: PathStr;
  756. BEGIN
  757. GetName(Name,fn);
  758. GetName(newname,fn2);
  759. WITH r DO
  760. DS := Seg(fn);
  761. DX := Ofs(fn);
  762. ES := Seg(fn2);
  763. DI := Ofs(fn2);
  764. AH := 56H;
  765. Lib.Dos(r);
  766. ErrorCheckNamed(r,'Rename',fn);
  767. END;
  768. END Rename;
  769. PROCEDURE ReadFirstEntry ( DirName : ARRAY OF CHAR;
  770. Attr : FileAttr;
  771. VAR D : DirEntry) : BOOLEAN;
  772. VAR
  773. r : Registers;
  774. fn : PathStr;
  775. BEGIN
  776. GetName(DirName,fn);
  777. WITH r DO
  778. AH := 1AH;
  779. DS := Seg(D);
  780. DX := Ofs(D);
  781. Lib.Dos(r); (* set DTA *)
  782. AH := 4EH;
  783. DS := Seg(fn);
  784. DX := Ofs(fn);
  785. CL := SHORTCARD(Attr);
  786. Lib.Dos(r);
  787. IF ((BITSET{CarryFlag} * Flags) # BITSET{}) AND (AX = 18) THEN
  788. IOR := 0;
  789. RETURN FALSE;
  790. END;
  791. ErrorCheckNamed(r,'ReadFirstEntry',fn);
  792. END;
  793. RETURN TRUE;
  794. END ReadFirstEntry;
  795. PROCEDURE ReadNextEntry(VAR D: DirEntry) : BOOLEAN;
  796. VAR
  797. r : Registers;
  798. BEGIN
  799. WITH r DO
  800. AH := 1AH;
  801. DS := Seg(D);
  802. DX := Ofs(D);
  803. Lib.Dos(r); (* set DTA *)
  804. AH := 4FH;
  805. Lib.Dos(r);
  806. IF ((BITSET{CarryFlag} * Flags) # BITSET{}) AND (AX = 18) THEN
  807. IOR := 0;
  808. RETURN FALSE;
  809. END;
  810. ErrorCheck(r,'ReadNextEntry');
  811. END;
  812. RETURN TRUE;
  813. END ReadNextEntry;
  814. PROCEDURE ChDir(Name: ARRAY OF CHAR);
  815. VAR
  816. r : Registers;
  817. fn : PathStr;
  818. BEGIN
  819. GetName(Name,fn);
  820. WITH r DO
  821. IF fn[1] = ':' THEN
  822. AH := 0EH;
  823. DL := SHORTCARD(CAP(fn[0]))-SHORTCARD('A');
  824. Lib.Dos(r);
  825. END;
  826. DS := Seg(fn);
  827. DX := Ofs(fn);
  828. AH := 3BH;
  829. Lib.Dos(r);
  830. ErrorCheckNamed(r,'ChDir',fn);
  831. END;
  832. END ChDir;
  833. PROCEDURE MkDir(Name: ARRAY OF CHAR);
  834. VAR
  835. r : Registers;
  836. fn : PathStr;
  837. BEGIN
  838. GetName(Name,fn);
  839. WITH r DO
  840. DS := Seg(fn);
  841. DX := Ofs(fn);
  842. AH := 39H;
  843. Lib.Dos(r);
  844. ErrorCheckNamed(r,'MkDir',fn);
  845. END;
  846. END MkDir;
  847. PROCEDURE RmDir(Name: ARRAY OF CHAR);
  848. VAR
  849. r : Registers;
  850. fn : PathStr;
  851. BEGIN
  852. GetName(Name,fn);
  853. WITH r DO
  854. DS := Seg(fn);
  855. DX := Ofs(fn);
  856. AH := 3AH;
  857. Lib.Dos(r);
  858. ErrorCheckNamed(r,'RmDir',fn);
  859. END;
  860. END RmDir;
  861. PROCEDURE GetDir(drive: SHORTCARD; VAR Name: ARRAY OF CHAR);
  862. VAR
  863. r : Registers;
  864. fn : PathStr;
  865. BEGIN
  866. WITH r DO
  867. DS := Seg(fn);
  868. SI := Ofs(fn);
  869. DL := drive;
  870. AH := 47H;
  871. Lib.Dos(r);
  872. ErrorCheck(r,'GetDir');
  873. END;
  874. Copy(Name,fn);
  875. END GetDir;
  876. PROCEDURE InitBufInf;
  877. VAR i : CARDINAL;
  878. BEGIN
  879. FOR i := 0 TO MaxHandle DO BufInf[i] := NIL; END;
  880. END InitBufInf;
  881. PROCEDURE AssignBuffer(F: File; VAR Buf: ARRAY OF BYTE);
  882. BEGIN
  883. IF (F <= MaxHandle) AND ( HIGH(Buf) > SIZE(BufRec) ) THEN
  884. BufInf[F] := ADR(Buf);
  885. WITH BufInf[F]^ DO
  886. RWPos := 0;
  887. EOB := 0;
  888. BufSize := HIGH(Buf)-SIZE(BufRec)+2;
  889. END;
  890. END;
  891. END AssignBuffer;
  892. BEGIN
  893. Eng := FALSE;
  894. IOcheck := TRUE;
  895. OK := TRUE;
  896. ChopOff := FALSE;
  897. Separators := CHARSET{CHR(9),CHR(10),CHR(13),CHR(26),' '};
  898. InitBufInf;
  899. END FIO.
  900.