text.inc 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  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. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {
  12. Possible Defines:
  13. EOF_CTRLZ Is Ctrl-Z (#26) a EOF mark for textfiles
  14. SHORT_LINEBREAK Use short Linebreaks #10 instead of #10#13
  15. SHORT_LINEBREAK is defined in the Linux system unit (syslinux.pp)
  16. }
  17. {****************************************************************************
  18. subroutines For TextFile handling
  19. ****************************************************************************}
  20. Procedure FileCloseFunc(Var t:TextRec);
  21. Begin
  22. Do_Close(t.Handle);
  23. t.Handle:=UnusedHandle;
  24. End;
  25. Procedure FileReadFunc(var t:TextRec);
  26. Begin
  27. t.BufEnd:=Do_Read(t.Handle,Longint(t.Bufptr),t.BufSize);
  28. t.BufPos:=0;
  29. End;
  30. Procedure FileWriteFunc(var t:TextRec);
  31. var
  32. i : longint;
  33. Begin
  34. i:=Do_Write(t.Handle,Longint(t.Bufptr),t.BufPos);
  35. if i<>t.BufPos then
  36. InOutRes:=101;
  37. t.BufPos:=0;
  38. End;
  39. Procedure FileOpenFunc(var t:TextRec);
  40. var
  41. Flags : Longint;
  42. Begin
  43. Case t.mode Of
  44. fmInput : Flags:=$10000;
  45. fmOutput : Flags:=$11001;
  46. fmAppend : Flags:=$10101;
  47. else
  48. begin
  49. InOutRes:=102;
  50. exit;
  51. end;
  52. End;
  53. Do_Open(t,PChar(@t.Name),Flags);
  54. t.CloseFunc:=@FileCloseFunc;
  55. t.FlushFunc:=nil;
  56. if t.Mode=fmInput then
  57. t.InOutFunc:=@FileReadFunc
  58. else
  59. begin
  60. t.InOutFunc:=@FileWriteFunc;
  61. { Only install flushing if its a NOT a file, and only check if there
  62. was no error opening the file, becuase else we always get a bad
  63. file handle error 6 (PFV) }
  64. if (InOutRes=0) and
  65. Do_Isdevice(t.Handle) then
  66. t.FlushFunc:=@FileWriteFunc;
  67. end;
  68. End;
  69. Procedure assign(var t:Text;const s:String);
  70. Begin
  71. FillChar(t,SizEof(TextRec),0);
  72. { only set things that are not zero }
  73. TextRec(t).Handle:=UnusedHandle;
  74. TextRec(t).mode:=fmClosed;
  75. TextRec(t).BufSize:=TextRecBufSize;
  76. TextRec(t).Bufptr:=@TextRec(t).Buffer;
  77. TextRec(t).OpenFunc:=@FileOpenFunc;
  78. Move(s[1],TextRec(t).Name,Length(s));
  79. End;
  80. Procedure assign(var t:Text;p:pchar);
  81. begin
  82. Assign(t,StrPas(p));
  83. end;
  84. Procedure assign(var t:Text;c:char);
  85. begin
  86. Assign(t,string(c));
  87. end;
  88. Procedure Close(var t : Text);[IOCheck];
  89. Begin
  90. if InOutRes<>0 then
  91. Exit;
  92. case TextRec(t).mode of
  93. fmInput,fmOutPut,fmAppend:
  94. Begin
  95. { Write pending buffer }
  96. If Textrec(t).Mode=fmoutput then
  97. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  98. { Only close functions not connected to stdout.}
  99. If ((TextRec(t).Handle<>StdInputHandle) and
  100. (TextRec(t).Handle<>StdOutputHandle) and
  101. (TextRec(t).Handle<>StdErrorHandle)) Then
  102. FileFunc(TextRec(t).CloseFunc)(TextRec(t));
  103. TextRec(t).mode := fmClosed;
  104. { Reset buffer for safety }
  105. TextRec(t).BufPos:=0;
  106. TextRec(t).BufEnd:=0;
  107. End
  108. else inOutRes := 103;
  109. End;
  110. End;
  111. Procedure OpenText(var t : Text;mode,defHdl:Longint);
  112. Begin
  113. Case TextRec(t).mode Of {This gives the fastest code}
  114. fmInput,fmOutput,fmInOut : Close(t);
  115. fmClosed : ;
  116. else
  117. Begin
  118. InOutRes:=102;
  119. exit;
  120. End;
  121. End;
  122. TextRec(t).mode:=mode;
  123. TextRec(t).bufpos:=0;
  124. TextRec(t).bufend:=0;
  125. FileFunc(TextRec(t).OpenFunc)(TextRec(t));
  126. { reset the mode to closed when an error has occured }
  127. if InOutRes<>0 then
  128. TextRec(t).mode:=fmClosed;
  129. End;
  130. Procedure Rewrite(var t : Text);[IOCheck];
  131. Begin
  132. If InOutRes<>0 then
  133. exit;
  134. OpenText(t,fmOutput,1);
  135. End;
  136. Procedure Reset(var t : Text);[IOCheck];
  137. Begin
  138. If InOutRes<>0 then
  139. exit;
  140. OpenText(t,fmInput,0);
  141. End;
  142. Procedure Append(var t : Text);[IOCheck];
  143. Begin
  144. If InOutRes<>0 then
  145. exit;
  146. OpenText(t,fmAppend,1);
  147. End;
  148. Procedure Flush(var t : Text);[IOCheck];
  149. Begin
  150. If InOutRes<>0 then
  151. exit;
  152. if TextRec(t).mode<>fmOutput then
  153. begin
  154. if TextRec(t).mode=fmInput then
  155. InOutRes:=105
  156. else
  157. InOutRes:=103;
  158. exit;
  159. end;
  160. { Not the flushfunc but the inoutfunc should be used, becuase that
  161. writes the data, flushfunc doesn't need to be assigned }
  162. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  163. End;
  164. Procedure Erase(var t:Text);[IOCheck];
  165. Begin
  166. If InOutRes <> 0 then
  167. exit;
  168. If TextRec(t).mode=fmClosed Then
  169. Do_Erase(PChar(@TextRec(t).Name));
  170. End;
  171. Procedure Rename(var t : text;p:pchar);[IOCheck];
  172. Begin
  173. If InOutRes <> 0 then
  174. exit;
  175. If TextRec(t).mode=fmClosed Then
  176. Begin
  177. Do_Rename(PChar(@TextRec(t).Name),p);
  178. Move(p^,TextRec(t).Name,StrLen(p)+1);
  179. End;
  180. End;
  181. Procedure Rename(var t : Text;const s : string);[IOCheck];
  182. var
  183. p : array[0..255] Of Char;
  184. Begin
  185. If InOutRes <> 0 then
  186. exit;
  187. Move(s[1],p,Length(s));
  188. p[Length(s)]:=#0;
  189. Rename(t,Pchar(@p));
  190. End;
  191. Procedure Rename(var t : Text;c : char);[IOCheck];
  192. var
  193. p : array[0..1] Of Char;
  194. Begin
  195. If InOutRes <> 0 then
  196. exit;
  197. p[0]:=c;
  198. p[1]:=#0;
  199. Rename(t,Pchar(@p));
  200. End;
  201. Function Eof(Var t: Text): Boolean;[IOCheck];
  202. Begin
  203. If (InOutRes<>0) then
  204. exit(true);
  205. if (TextRec(t).mode<>fmInput) Then
  206. begin
  207. if TextRec(t).mode=fmOutput then
  208. InOutRes:=104
  209. else
  210. InOutRes:=103;
  211. exit(true);
  212. end;
  213. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  214. begin
  215. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  216. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  217. exit(true);
  218. end;
  219. {$ifdef EOF_CTRLZ}
  220. Eof:=(TextRec(t).Bufptr^[TextRec(t).BufPos]=#26);
  221. {$else}
  222. Eof:=false;
  223. {$endif EOL_CTRLZ}
  224. end;
  225. Function Eof:Boolean;
  226. Begin
  227. Eof:=Eof(Input);
  228. End;
  229. Function SeekEof (Var t : Text) : Boolean;
  230. Begin
  231. If (InOutRes<>0) then
  232. exit(true);
  233. if (TextRec(t).mode<>fmInput) Then
  234. begin
  235. if TextRec(t).mode=fmOutPut then
  236. InOutRes:=104
  237. else
  238. InOutRes:=103;
  239. exit(true);
  240. end;
  241. repeat
  242. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  243. begin
  244. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  245. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  246. exit(true);
  247. end;
  248. case TextRec(t).Bufptr^[TextRec(t).BufPos] of
  249. #26 : exit(true);
  250. #10,#13,
  251. #9,' ' : ;
  252. else
  253. exit(false);
  254. end;
  255. inc(TextRec(t).BufPos);
  256. until false;
  257. End;
  258. Function SeekEof : Boolean;
  259. Begin
  260. SeekEof:=SeekEof(Input);
  261. End;
  262. Function Eoln(var t:Text) : Boolean;
  263. Begin
  264. If (InOutRes<>0) then
  265. exit(true);
  266. if (TextRec(t).mode<>fmInput) Then
  267. begin
  268. if TextRec(t).mode=fmOutPut then
  269. InOutRes:=104
  270. else
  271. InOutRes:=103;
  272. exit(true);
  273. end;
  274. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  275. begin
  276. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  277. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  278. exit(true);
  279. end;
  280. Eoln:=(TextRec(t).Bufptr^[TextRec(t).BufPos] in [#10,#13]);
  281. End;
  282. Function Eoln : Boolean;
  283. Begin
  284. Eoln:=Eoln(Input);
  285. End;
  286. Function SeekEoln (Var t : Text) : Boolean;
  287. Begin
  288. If (InOutRes<>0) then
  289. exit(true);
  290. if (TextRec(t).mode<>fmInput) Then
  291. begin
  292. if TextRec(t).mode=fmOutput then
  293. InOutRes:=104
  294. else
  295. InOutRes:=103;
  296. exit(true);
  297. end;
  298. repeat
  299. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  300. begin
  301. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  302. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  303. exit(true);
  304. end;
  305. case TextRec(t).Bufptr^[TextRec(t).BufPos] of
  306. #26,
  307. #10,#13 : exit(true);
  308. #9,' ' : ;
  309. else
  310. exit(false);
  311. end;
  312. inc(TextRec(t).BufPos);
  313. until false;
  314. End;
  315. Function SeekEoln : Boolean;
  316. Begin
  317. SeekEoln:=SeekEoln(Input);
  318. End;
  319. Procedure SetTextBuf(Var F : Text; Var Buf);[INTERNPROC: In_settextbuf_file_x];
  320. Procedure SetTextBuf(Var F : Text; Var Buf; Size : Longint);
  321. Begin
  322. TextRec(f).BufPtr:=@Buf;
  323. TextRec(f).BufSize:=Size;
  324. TextRec(f).BufPos:=0;
  325. TextRec(f).BufEnd:=0;
  326. End;
  327. {*****************************************************************************
  328. Write(Ln)
  329. *****************************************************************************}
  330. Procedure WriteBuffer(var f:TextRec;var b;len:longint);
  331. var
  332. p : pchar;
  333. left,
  334. idx : longint;
  335. begin
  336. p:=pchar(@b);
  337. idx:=0;
  338. left:=f.BufSize-f.BufPos;
  339. while len>left do
  340. begin
  341. move(p[idx],f.Bufptr^[f.BufPos],left);
  342. dec(len,left);
  343. inc(idx,left);
  344. inc(f.BufPos,left);
  345. FileFunc(f.InOutFunc)(f);
  346. left:=f.BufSize-f.BufPos;
  347. end;
  348. move(p[idx],f.Bufptr^[f.BufPos],len);
  349. inc(f.BufPos,len);
  350. end;
  351. Procedure WriteBlanks(var f:TextRec;len:longint);
  352. var
  353. left : longint;
  354. begin
  355. left:=f.BufSize-f.BufPos;
  356. while len>left do
  357. begin
  358. FillChar(f.Bufptr^[f.BufPos],left,' ');
  359. dec(len,left);
  360. inc(f.BufPos,left);
  361. FileFunc(f.InOutFunc)(f);
  362. left:=f.BufSize-f.BufPos;
  363. end;
  364. FillChar(f.Bufptr^[f.BufPos],len,' ');
  365. inc(f.BufPos,len);
  366. end;
  367. Procedure Write_End(var f:TextRec);[Public,Alias:'FPC_WRITE_END'];
  368. begin
  369. if f.FlushFunc<>nil then
  370. FileFunc(f.FlushFunc)(f);
  371. end;
  372. Procedure Writeln_End(var f:TextRec);[Public,Alias:'FPC_WRITELN_END'];
  373. const
  374. {$IFDEF SHORT_LINEBREAK}
  375. eollen=1;
  376. eol : array[0..0] of char=(#10);
  377. {$ELSE SHORT_LINEBREAK}
  378. eollen=2;
  379. eol : array[0..1] of char=(#13,#10);
  380. {$ENDIF SHORT_LINEBREAK}
  381. begin
  382. If InOutRes <> 0 then exit;
  383. case f.mode of
  384. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  385. begin
  386. { Write EOL }
  387. WriteBuffer(f,eol,eollen);
  388. { Flush }
  389. if f.FlushFunc<>nil then
  390. FileFunc(f.FlushFunc)(f);
  391. end;
  392. fmInput: InOutRes:=105
  393. else InOutRes:=103;
  394. end;
  395. end;
  396. Procedure Write_Str(Len : Longint;var f : TextRec;const s : String);[Public,Alias:'FPC_WRITE_TEXT_SHORTSTR'];
  397. Begin
  398. If (InOutRes<>0) then
  399. exit;
  400. case f.mode of
  401. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  402. begin
  403. If Len>Length(s) Then
  404. WriteBlanks(f,Len-Length(s));
  405. WriteBuffer(f,s[1],Length(s));
  406. end;
  407. fmInput: InOutRes:=105
  408. else InOutRes:=103;
  409. end;
  410. End;
  411. Procedure Write_Array(Len : Longint;var f : TextRec;const s : array of char);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_ARRAY'];
  412. var
  413. ArrayLen : longint;
  414. p : pchar;
  415. Begin
  416. If (InOutRes<>0) then
  417. exit;
  418. case f.mode of
  419. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  420. begin
  421. p:=pchar(@s);
  422. ArrayLen:=StrLen(p);
  423. if ArrayLen>sizeof(s) then
  424. ArrayLen:=sizeof(s);
  425. If Len>ArrayLen Then
  426. WriteBlanks(f,Len-ArrayLen);
  427. WriteBuffer(f,p^,ArrayLen);
  428. end;
  429. fmInput: InOutRes:=105
  430. else InOutRes:=103;
  431. end;
  432. End;
  433. Procedure Write_PChar(Len : Longint;var f : TextRec;p : PChar);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_POINTER'];
  434. var
  435. PCharLen : longint;
  436. Begin
  437. If (p=nil) or (InOutRes<>0) then
  438. exit;
  439. case f.mode of
  440. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  441. begin
  442. PCharLen:=StrLen(p);
  443. If Len>PCharLen Then
  444. WriteBlanks(f,Len-PCharLen);
  445. WriteBuffer(f,p^,PCharLen);
  446. end;
  447. fmInput: InOutRes:=105
  448. else InOutRes:=103;
  449. end;
  450. End;
  451. Procedure Write_Text_AnsiString (Len : Longint; Var T : TextRec; S : Pointer);[Public,alias:'FPC_WRITE_TEXT_ANSISTR'];
  452. {
  453. Writes a AnsiString to the Text file T
  454. }
  455. begin
  456. If S=Nil then
  457. exit;
  458. Write_pchar (Len,t,PChar(S));
  459. end;
  460. Procedure Write_SInt(Len : Longint;var t : TextRec;l : ValSInt);[Public,Alias:'FPC_WRITE_TEXT_SINT'];
  461. var
  462. s : String;
  463. Begin
  464. If (InOutRes<>0) then
  465. exit;
  466. Str(l,s);
  467. Write_Str(Len,t,s);
  468. End;
  469. Procedure Write_UInt(Len : Longint;var t : TextRec;l : ValUInt);[Public,Alias:'FPC_WRITE_TEXT_UINT'];
  470. var
  471. s : String;
  472. Begin
  473. If (InOutRes<>0) then
  474. exit;
  475. Str(L,s);
  476. Write_Str(Len,t,s);
  477. End;
  478. procedure write_qword(len : longint;var t : textrec;q : qword);[public,alias:'FPC_WRITE_TEXT_QWORD'];
  479. var
  480. s : string;
  481. begin
  482. if (InOutRes<>0) then
  483. exit;
  484. qword_str(q,s);
  485. write_str(len,t,s);
  486. end;
  487. procedure write_int64(len : longint;var t : textrec;i : int64);[public,alias:'FPC_WRITE_TEXT_INT64'];
  488. var
  489. s : string;
  490. begin
  491. if (InOutRes<>0) then
  492. exit;
  493. int64_str(i,s);
  494. write_str(len,t,s);
  495. end;
  496. Procedure Write_Float(rt,fixkomma,Len : Longint;var t : TextRec;r : ValReal);[Public,Alias:'FPC_WRITE_TEXT_FLOAT'];
  497. var
  498. s : String;
  499. Begin
  500. If (InOutRes<>0) then
  501. exit;
  502. Str_real(Len,fixkomma,r,treal_type(rt),s);
  503. Write_Str(Len,t,s);
  504. End;
  505. Procedure Write_Boolean(Len : Longint;var t : TextRec;b : Boolean);[Public,Alias:'FPC_WRITE_TEXT_BOOLEAN'];
  506. Begin
  507. If (InOutRes<>0) then
  508. exit;
  509. { Can't use array[boolean] because b can be >0 ! }
  510. if b then
  511. Write_Str(Len,t,'TRUE')
  512. else
  513. Write_Str(Len,t,'FALSE');
  514. End;
  515. Procedure Write_Char(Len : Longint;var t : TextRec;c : Char);[Public,Alias:'FPC_WRITE_TEXT_CHAR'];
  516. Begin
  517. If (InOutRes<>0) then
  518. exit;
  519. if (TextRec(t).mode<>fmOutput) Then
  520. begin
  521. if TextRec(t).mode=fmClosed then
  522. InOutRes:=103
  523. else
  524. InOutRes:=105;
  525. exit;
  526. end;
  527. If Len>1 Then
  528. WriteBlanks(t,Len-1);
  529. If t.BufPos+1>=t.BufSize Then
  530. FileFunc(t.InOutFunc)(t);
  531. t.Bufptr^[t.BufPos]:=c;
  532. Inc(t.BufPos);
  533. End;
  534. {*****************************************************************************
  535. Read(Ln)
  536. *****************************************************************************}
  537. Function NextChar(var f:TextRec;var s:string):Boolean;
  538. begin
  539. if f.BufPos<f.BufEnd then
  540. begin
  541. if length(s)<high(s) then
  542. begin
  543. inc(s[0]);
  544. s[length(s)]:=f.BufPtr^[f.BufPos];
  545. end;
  546. Inc(f.BufPos);
  547. If f.BufPos>=f.BufEnd Then
  548. FileFunc(f.InOutFunc)(f);
  549. NextChar:=true;
  550. end
  551. else
  552. NextChar:=false;
  553. end;
  554. Function IgnoreSpaces(var f:TextRec):Boolean;
  555. {
  556. Removes all leading spaces,tab,eols from the input buffer, returns true if
  557. the buffer is empty
  558. }
  559. var
  560. s : string;
  561. begin
  562. s:='';
  563. IgnoreSpaces:=false;
  564. while f.Bufptr^[f.BufPos] in [#9,#10,#13,' '] do
  565. if not NextChar(f,s) then
  566. exit;
  567. IgnoreSpaces:=true;
  568. end;
  569. procedure ReadNumeric(var f:TextRec;var s:string);
  570. {
  571. Read numeric input, if buffer is empty then return True
  572. }
  573. begin
  574. repeat
  575. if not NextChar(f,s) then
  576. exit;
  577. until (length(s)=high(s)) or (f.BufPtr^[f.BufPos] in [#9,#10,#13,' ']);
  578. end;
  579. Procedure Read_End(var f:TextRec);[Public,Alias:'FPC_READ_END'];
  580. begin
  581. if f.FlushFunc<>nil then
  582. FileFunc(f.FlushFunc)(f);
  583. end;
  584. Procedure ReadLn_End(var f : TextRec);[Public,Alias:'FPC_READLN_END'];
  585. var prev: char;
  586. Begin
  587. { Check error and if file is open and load buf if empty }
  588. If (InOutRes<>0) then
  589. exit;
  590. if (f.mode<>fmInput) Then
  591. begin
  592. case TextRec(f).mode of
  593. fmOutPut,fmAppend:
  594. InOutRes:=104
  595. else
  596. InOutRes:=103;
  597. end;
  598. exit;
  599. end;
  600. if f.BufPos>=f.BufEnd Then
  601. begin
  602. FileFunc(f.InOutFunc)(f);
  603. if (f.BufPos>=f.BufEnd) then
  604. { Flush if set }
  605. begin
  606. if (f.FlushFunc<>nil) then
  607. FileFunc(f.FlushFunc)(f);
  608. exit;
  609. end;
  610. end;
  611. repeat
  612. prev := f.BufPtr^[f.BufPos];
  613. inc(f.BufPos);
  614. { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
  615. { #13#10 = Dos), so if we've got #10, we can safely exit }
  616. if prev = #10 then
  617. exit;
  618. if f.BufPos>=f.BufEnd Then
  619. begin
  620. FileFunc(f.InOutFunc)(f);
  621. if (f.BufPos>=f.BufEnd) then
  622. { Flush if set }
  623. begin
  624. if (f.FlushFunc<>nil) then
  625. FileFunc(f.FlushFunc)(f);
  626. exit;
  627. end;
  628. end;
  629. if (prev=#13) then
  630. { is there also a #10 after it? }
  631. begin
  632. if (f.BufPtr^[f.BufPos]=#10) then
  633. { yes, skip that one as well }
  634. inc(f.BufPos);
  635. exit;
  636. end;
  637. until false;
  638. End;
  639. Function ReadPCharLen(var f:TextRec;s:pchar;maxlen:longint):longint;
  640. var
  641. sPos,len : Longint;
  642. p,startp,maxp : pchar;
  643. Begin
  644. ReadPCharLen:=0;
  645. { Check error and if file is open }
  646. If (InOutRes<>0) then
  647. exit;
  648. if (f.mode<>fmInput) Then
  649. begin
  650. case TextRec(f).mode of
  651. fmOutPut,fmAppend:
  652. InOutRes:=104
  653. else
  654. InOutRes:=103;
  655. end;
  656. exit;
  657. end;
  658. { Read maximal until Maxlen is reached }
  659. sPos:=0;
  660. repeat
  661. If f.BufPos>=f.BufEnd Then
  662. begin
  663. FileFunc(f.InOutFunc)(f);
  664. If f.BufPos>=f.BufEnd Then
  665. break;
  666. end;
  667. p:[email protected]^[f.BufPos];
  668. if SPos+f.BufEnd-f.BufPos>MaxLen then
  669. maxp:[email protected]^[f.BufPos+MaxLen-SPos]
  670. else
  671. maxp:[email protected]^[f.BufEnd];
  672. startp:=p;
  673. { search linefeed }
  674. while (p<maxp) and not(P^ in [#10,#13]) do
  675. inc(p);
  676. { calculate read bytes }
  677. len:=p-startp;
  678. inc(f.BufPos,Len);
  679. Move(startp^,s[sPos],Len);
  680. inc(sPos,Len);
  681. { was it a LF or CR? then leave }
  682. if (spos=MaxLen) or
  683. ((p<maxp) and (p^ in [#10,#13])) then
  684. break;
  685. until false;
  686. ReadPCharLen:=spos;
  687. End;
  688. Procedure Read_String(var f : TextRec;var s : String);[Public,Alias:'FPC_READ_TEXT_SHORTSTR'];
  689. Begin
  690. s[0]:=chr(ReadPCharLen(f,pchar(@s[1]),high(s)));
  691. End;
  692. Procedure Read_PChar(var f : TextRec;var s : PChar);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER'];
  693. Begin
  694. pchar(s+ReadPCharLen(f,s,$7fffffff))^:=#0;
  695. End;
  696. Procedure Read_Array(var f : TextRec;var s : array of char);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY'];
  697. Begin
  698. pchar(pchar(@s)+ReadPCharLen(f,pchar(@s),high(s)))^:=#0;
  699. End;
  700. Procedure Read_AnsiString(var f : TextRec;var s : AnsiString);[Public,Alias:'FPC_READ_TEXT_ANSISTR'];
  701. var
  702. slen,len : longint;
  703. Begin
  704. slen:=0;
  705. Repeat
  706. // SetLength will reallocate the length.
  707. SetLength(S,slen+255);
  708. len:=ReadPCharLen(f,pchar(Pointer(S)+slen),255);
  709. inc(slen,len);
  710. Until len<255;
  711. // Set actual length
  712. SetLength(S,Slen);
  713. End;
  714. Function Read_Char(var f : TextRec):char;[Public,Alias:'FPC_READ_TEXT_CHAR'];
  715. Begin
  716. Read_Char:=#0;
  717. { Check error and if file is open }
  718. If (InOutRes<>0) then
  719. exit;
  720. if (f.mode<>fmInput) Then
  721. begin
  722. case TextRec(f).mode of
  723. fmOutPut,fmAppend:
  724. InOutRes:=104
  725. else
  726. InOutRes:=103;
  727. end;
  728. exit;
  729. end;
  730. { Read next char or EOF }
  731. If f.BufPos>=f.BufEnd Then
  732. begin
  733. FileFunc(f.InOutFunc)(f);
  734. If f.BufPos>=f.BufEnd Then
  735. exit(#26);
  736. end;
  737. Read_Char:=f.Bufptr^[f.BufPos];
  738. inc(f.BufPos);
  739. end;
  740. Function Read_SInt(var f : TextRec):ValSInt;[Public,Alias:'FPC_READ_TEXT_SINT'];
  741. var
  742. hs : String;
  743. code : Longint;
  744. Begin
  745. Read_SInt:=0;
  746. { Leave if error or not open file, else check for empty buf }
  747. If (InOutRes<>0) then
  748. exit;
  749. if (f.mode<>fmInput) Then
  750. begin
  751. case TextRec(f).mode of
  752. fmOutPut,fmAppend:
  753. InOutRes:=104
  754. else
  755. InOutRes:=103;
  756. end;
  757. exit;
  758. end;
  759. If f.BufPos>=f.BufEnd Then
  760. FileFunc(f.InOutFunc)(f);
  761. hs:='';
  762. if IgnoreSpaces(f) then
  763. ReadNumeric(f,hs);
  764. Val(hs,Read_SInt,code);
  765. If code<>0 Then
  766. InOutRes:=106;
  767. End;
  768. Function Read_UInt(var f : TextRec):ValUInt;[Public,Alias:'FPC_READ_TEXT_UINT'];
  769. var
  770. hs : String;
  771. code : longint;
  772. Begin
  773. Read_UInt:=0;
  774. { Leave if error or not open file, else check for empty buf }
  775. If (InOutRes<>0) then
  776. exit;
  777. if (f.mode<>fmInput) Then
  778. begin
  779. case TextRec(f).mode of
  780. fmOutPut,fmAppend:
  781. InOutRes:=104
  782. else
  783. InOutRes:=103;
  784. end;
  785. exit;
  786. end;
  787. If f.BufPos>=f.BufEnd Then
  788. FileFunc(f.InOutFunc)(f);
  789. hs:='';
  790. if IgnoreSpaces(f) then
  791. ReadNumeric(f,hs);
  792. val(hs,Read_UInt,code);
  793. If code<>0 Then
  794. InOutRes:=106;
  795. End;
  796. Function Read_Float(var f : TextRec):ValReal;[Public,Alias:'FPC_READ_TEXT_FLOAT'];
  797. var
  798. hs : string;
  799. code : Word;
  800. begin
  801. Read_Float:=0.0;
  802. { Leave if error or not open file, else check for empty buf }
  803. If (InOutRes<>0) then
  804. exit;
  805. if (f.mode<>fmInput) Then
  806. begin
  807. case TextRec(f).mode of
  808. fmOutPut,fmAppend:
  809. InOutRes:=104
  810. else
  811. InOutRes:=103;
  812. end;
  813. exit;
  814. end;
  815. If f.BufPos>=f.BufEnd Then
  816. FileFunc(f.InOutFunc)(f);
  817. hs:='';
  818. if IgnoreSpaces(f) then
  819. ReadNumeric(f,hs);
  820. val(hs,Read_Float,code);
  821. If code<>0 Then
  822. InOutRes:=106;
  823. end;
  824. function Read_QWord(var f : textrec) : qword;[public,alias:'FPC_READ_TEXT_QWORD'];
  825. var
  826. hs : String;
  827. code : longint;
  828. Begin
  829. Read_QWord:=0;
  830. { Leave if error or not open file, else check for empty buf }
  831. If (InOutRes<>0) then
  832. exit;
  833. if (f.mode<>fmInput) Then
  834. begin
  835. case TextRec(f).mode of
  836. fmOutPut,fmAppend:
  837. InOutRes:=104
  838. else
  839. InOutRes:=103;
  840. end;
  841. exit;
  842. end;
  843. If f.BufPos>=f.BufEnd Then
  844. FileFunc(f.InOutFunc)(f);
  845. hs:='';
  846. if IgnoreSpaces(f) then
  847. ReadNumeric(f,hs);
  848. val(hs,Read_QWord,code);
  849. If code<>0 Then
  850. InOutRes:=106;
  851. End;
  852. function Read_Int64(var f : textrec) : int64;[public,alias:'FPC_READ_TEXT_INT64'];
  853. var
  854. hs : String;
  855. code : Longint;
  856. Begin
  857. Read_Int64:=0;
  858. { Leave if error or not open file, else check for empty buf }
  859. If (InOutRes<>0) then
  860. exit;
  861. if (f.mode<>fmInput) Then
  862. begin
  863. case TextRec(f).mode of
  864. fmOutPut,fmAppend:
  865. InOutRes:=104
  866. else
  867. InOutRes:=103;
  868. end;
  869. exit;
  870. end;
  871. If f.BufPos>=f.BufEnd Then
  872. FileFunc(f.InOutFunc)(f);
  873. hs:='';
  874. if IgnoreSpaces(f) then
  875. ReadNumeric(f,hs);
  876. Val(hs,Read_Int64,code);
  877. If code<>0 Then
  878. InOutRes:=106;
  879. End;
  880. {*****************************************************************************
  881. Initializing
  882. *****************************************************************************}
  883. procedure OpenStdIO(var f:text;mode,hdl:longint);
  884. begin
  885. Assign(f,'');
  886. TextRec(f).Handle:=hdl;
  887. TextRec(f).Mode:=mode;
  888. TextRec(f).Closefunc:=@FileCloseFunc;
  889. case mode of
  890. fmInput :
  891. TextRec(f).InOutFunc:=@FileReadFunc;
  892. fmOutput :
  893. begin
  894. TextRec(f).InOutFunc:=@FileWriteFunc;
  895. TextRec(f).FlushFunc:=@FileWriteFunc;
  896. end;
  897. else
  898. HandleError(102);
  899. end;
  900. end;
  901. {
  902. $Log$
  903. Revision 1.3 2000-07-14 10:33:10 michael
  904. + Conditionals fixed
  905. Revision 1.2 2000/07/13 11:33:46 michael
  906. + removed logs
  907. }