text.inc 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  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. {$ifdef INT64}
  479. procedure write_qword(len : longint;var t : textrec;q : qword);[public,alias:'FPC_WRITE_TEXT_QWORD'];
  480. var
  481. s : string;
  482. begin
  483. if (InOutRes<>0) then
  484. exit;
  485. qword_str(q,s);
  486. write_str(len,t,s);
  487. end;
  488. procedure write_int64(len : longint;var t : textrec;i : int64);[public,alias:'FPC_WRITE_TEXT_INT64'];
  489. var
  490. s : string;
  491. begin
  492. if (InOutRes<>0) then
  493. exit;
  494. int64_str(i,s);
  495. write_str(len,t,s);
  496. end;
  497. {$endif INT64}
  498. Procedure Write_Float(rt,fixkomma,Len : Longint;var t : TextRec;r : ValReal);[Public,Alias:'FPC_WRITE_TEXT_FLOAT'];
  499. var
  500. s : String;
  501. Begin
  502. If (InOutRes<>0) then
  503. exit;
  504. Str_real(Len,fixkomma,r,treal_type(rt),s);
  505. Write_Str(Len,t,s);
  506. End;
  507. Procedure Write_Boolean(Len : Longint;var t : TextRec;b : Boolean);[Public,Alias:'FPC_WRITE_TEXT_BOOLEAN'];
  508. Begin
  509. If (InOutRes<>0) then
  510. exit;
  511. { Can't use array[boolean] because b can be >0 ! }
  512. if b then
  513. Write_Str(Len,t,'TRUE')
  514. else
  515. Write_Str(Len,t,'FALSE');
  516. End;
  517. Procedure Write_Char(Len : Longint;var t : TextRec;c : Char);[Public,Alias:'FPC_WRITE_TEXT_CHAR'];
  518. Begin
  519. If (InOutRes<>0) then
  520. exit;
  521. if (TextRec(t).mode<>fmOutput) Then
  522. begin
  523. if TextRec(t).mode=fmClosed then
  524. InOutRes:=103
  525. else
  526. InOutRes:=105;
  527. exit;
  528. end;
  529. If Len>1 Then
  530. WriteBlanks(t,Len-1);
  531. If t.BufPos+1>=t.BufSize Then
  532. FileFunc(t.InOutFunc)(t);
  533. t.Bufptr^[t.BufPos]:=c;
  534. Inc(t.BufPos);
  535. End;
  536. {*****************************************************************************
  537. Read(Ln)
  538. *****************************************************************************}
  539. Function NextChar(var f:TextRec;var s:string):Boolean;
  540. begin
  541. if f.BufPos<f.BufEnd then
  542. begin
  543. if length(s)<high(s) then
  544. begin
  545. inc(s[0]);
  546. s[length(s)]:=f.BufPtr^[f.BufPos];
  547. end;
  548. Inc(f.BufPos);
  549. If f.BufPos>=f.BufEnd Then
  550. FileFunc(f.InOutFunc)(f);
  551. NextChar:=true;
  552. end
  553. else
  554. NextChar:=false;
  555. end;
  556. Function IgnoreSpaces(var f:TextRec):Boolean;
  557. {
  558. Removes all leading spaces,tab,eols from the input buffer, returns true if
  559. the buffer is empty
  560. }
  561. var
  562. s : string;
  563. begin
  564. s:='';
  565. IgnoreSpaces:=false;
  566. while f.Bufptr^[f.BufPos] in [#9,#10,#13,' '] do
  567. if not NextChar(f,s) then
  568. exit;
  569. IgnoreSpaces:=true;
  570. end;
  571. procedure ReadNumeric(var f:TextRec;var s:string);
  572. {
  573. Read numeric input, if buffer is empty then return True
  574. }
  575. begin
  576. repeat
  577. if not NextChar(f,s) then
  578. exit;
  579. until (length(s)=high(s)) or (f.BufPtr^[f.BufPos] in [#9,#10,#13,' ']);
  580. end;
  581. Procedure Read_End(var f:TextRec);[Public,Alias:'FPC_READ_END'];
  582. begin
  583. if f.FlushFunc<>nil then
  584. FileFunc(f.FlushFunc)(f);
  585. end;
  586. Procedure ReadLn_End(var f : TextRec);[Public,Alias:'FPC_READLN_END'];
  587. var prev: char;
  588. Begin
  589. { Check error and if file is open and load buf if empty }
  590. If (InOutRes<>0) then
  591. exit;
  592. if (f.mode<>fmInput) Then
  593. begin
  594. case TextRec(f).mode of
  595. fmOutPut,fmAppend:
  596. InOutRes:=104
  597. else
  598. InOutRes:=103;
  599. end;
  600. exit;
  601. end;
  602. if f.BufPos>=f.BufEnd Then
  603. begin
  604. FileFunc(f.InOutFunc)(f);
  605. if (f.BufPos>=f.BufEnd) then
  606. { Flush if set }
  607. begin
  608. if (f.FlushFunc<>nil) then
  609. FileFunc(f.FlushFunc)(f);
  610. exit;
  611. end;
  612. end;
  613. repeat
  614. prev := f.BufPtr^[f.BufPos];
  615. inc(f.BufPos);
  616. { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
  617. { #13#10 = Dos), so if we've got #10, we can safely exit }
  618. if prev = #10 then
  619. exit;
  620. if f.BufPos>=f.BufEnd Then
  621. begin
  622. FileFunc(f.InOutFunc)(f);
  623. if (f.BufPos>=f.BufEnd) then
  624. { Flush if set }
  625. begin
  626. if (f.FlushFunc<>nil) then
  627. FileFunc(f.FlushFunc)(f);
  628. exit;
  629. end;
  630. end;
  631. if (prev=#13) then
  632. { is there also a #10 after it? }
  633. begin
  634. if (f.BufPtr^[f.BufPos]=#10) then
  635. { yes, skip that one as well }
  636. inc(f.BufPos);
  637. exit;
  638. end;
  639. until false;
  640. End;
  641. Function ReadPCharLen(var f:TextRec;s:pchar;maxlen:longint):longint;
  642. var
  643. sPos,len : Longint;
  644. p,startp,maxp : pchar;
  645. Begin
  646. ReadPCharLen:=0;
  647. { Check error and if file is open }
  648. If (InOutRes<>0) then
  649. exit;
  650. if (f.mode<>fmInput) Then
  651. begin
  652. case TextRec(f).mode of
  653. fmOutPut,fmAppend:
  654. InOutRes:=104
  655. else
  656. InOutRes:=103;
  657. end;
  658. exit;
  659. end;
  660. { Read maximal until Maxlen is reached }
  661. sPos:=0;
  662. repeat
  663. If f.BufPos>=f.BufEnd Then
  664. begin
  665. FileFunc(f.InOutFunc)(f);
  666. If f.BufPos>=f.BufEnd Then
  667. break;
  668. end;
  669. p:[email protected]^[f.BufPos];
  670. if SPos+f.BufEnd-f.BufPos>MaxLen then
  671. maxp:[email protected]^[f.BufPos+MaxLen-SPos]
  672. else
  673. maxp:[email protected]^[f.BufEnd];
  674. startp:=p;
  675. { search linefeed }
  676. while (p<maxp) and not(P^ in [#10,#13]) do
  677. inc(p);
  678. { calculate read bytes }
  679. len:=p-startp;
  680. inc(f.BufPos,Len);
  681. Move(startp^,s[sPos],Len);
  682. inc(sPos,Len);
  683. { was it a LF or CR? then leave }
  684. if (spos=MaxLen) or
  685. ((p<maxp) and (p^ in [#10,#13])) then
  686. break;
  687. until false;
  688. ReadPCharLen:=spos;
  689. End;
  690. Procedure Read_String(var f : TextRec;var s : String);[Public,Alias:'FPC_READ_TEXT_SHORTSTR'];
  691. Begin
  692. s[0]:=chr(ReadPCharLen(f,pchar(@s[1]),high(s)));
  693. End;
  694. Procedure Read_PChar(var f : TextRec;var s : PChar);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER'];
  695. Begin
  696. pchar(s+ReadPCharLen(f,s,$7fffffff))^:=#0;
  697. End;
  698. Procedure Read_Array(var f : TextRec;var s : array of char);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY'];
  699. Begin
  700. pchar(pchar(@s)+ReadPCharLen(f,pchar(@s),high(s)))^:=#0;
  701. End;
  702. Procedure Read_AnsiString(var f : TextRec;var s : AnsiString);[Public,Alias:'FPC_READ_TEXT_ANSISTR'];
  703. var
  704. slen,len : longint;
  705. Begin
  706. slen:=0;
  707. Repeat
  708. // SetLength will reallocate the length.
  709. SetLength(S,slen+255);
  710. len:=ReadPCharLen(f,pchar(Pointer(S)+slen),255);
  711. inc(slen,len);
  712. Until len<255;
  713. // Set actual length
  714. SetLength(S,Slen);
  715. End;
  716. Function Read_Char(var f : TextRec):char;[Public,Alias:'FPC_READ_TEXT_CHAR'];
  717. Begin
  718. Read_Char:=#0;
  719. { Check error and if file is open }
  720. If (InOutRes<>0) then
  721. exit;
  722. if (f.mode<>fmInput) Then
  723. begin
  724. case TextRec(f).mode of
  725. fmOutPut,fmAppend:
  726. InOutRes:=104
  727. else
  728. InOutRes:=103;
  729. end;
  730. exit;
  731. end;
  732. { Read next char or EOF }
  733. If f.BufPos>=f.BufEnd Then
  734. begin
  735. FileFunc(f.InOutFunc)(f);
  736. If f.BufPos>=f.BufEnd Then
  737. exit(#26);
  738. end;
  739. Read_Char:=f.Bufptr^[f.BufPos];
  740. inc(f.BufPos);
  741. end;
  742. Function Read_SInt(var f : TextRec):ValSInt;[Public,Alias:'FPC_READ_TEXT_SINT'];
  743. var
  744. hs : String;
  745. code : Longint;
  746. Begin
  747. Read_SInt:=0;
  748. { Leave if error or not open file, else check for empty buf }
  749. If (InOutRes<>0) then
  750. exit;
  751. if (f.mode<>fmInput) Then
  752. begin
  753. case TextRec(f).mode of
  754. fmOutPut,fmAppend:
  755. InOutRes:=104
  756. else
  757. InOutRes:=103;
  758. end;
  759. exit;
  760. end;
  761. If f.BufPos>=f.BufEnd Then
  762. FileFunc(f.InOutFunc)(f);
  763. hs:='';
  764. if IgnoreSpaces(f) then
  765. ReadNumeric(f,hs);
  766. Val(hs,Read_SInt,code);
  767. If code<>0 Then
  768. InOutRes:=106;
  769. End;
  770. Function Read_UInt(var f : TextRec):ValUInt;[Public,Alias:'FPC_READ_TEXT_UINT'];
  771. var
  772. hs : String;
  773. code : longint;
  774. Begin
  775. Read_UInt:=0;
  776. { Leave if error or not open file, else check for empty buf }
  777. If (InOutRes<>0) then
  778. exit;
  779. if (f.mode<>fmInput) Then
  780. begin
  781. case TextRec(f).mode of
  782. fmOutPut,fmAppend:
  783. InOutRes:=104
  784. else
  785. InOutRes:=103;
  786. end;
  787. exit;
  788. end;
  789. If f.BufPos>=f.BufEnd Then
  790. FileFunc(f.InOutFunc)(f);
  791. hs:='';
  792. if IgnoreSpaces(f) then
  793. ReadNumeric(f,hs);
  794. val(hs,Read_UInt,code);
  795. If code<>0 Then
  796. InOutRes:=106;
  797. End;
  798. Function Read_Float(var f : TextRec):ValReal;[Public,Alias:'FPC_READ_TEXT_FLOAT'];
  799. var
  800. hs : string;
  801. code : Word;
  802. begin
  803. Read_Float:=0.0;
  804. { Leave if error or not open file, else check for empty buf }
  805. If (InOutRes<>0) then
  806. exit;
  807. if (f.mode<>fmInput) Then
  808. begin
  809. case TextRec(f).mode of
  810. fmOutPut,fmAppend:
  811. InOutRes:=104
  812. else
  813. InOutRes:=103;
  814. end;
  815. exit;
  816. end;
  817. If f.BufPos>=f.BufEnd Then
  818. FileFunc(f.InOutFunc)(f);
  819. hs:='';
  820. if IgnoreSpaces(f) then
  821. ReadNumeric(f,hs);
  822. val(hs,Read_Float,code);
  823. If code<>0 Then
  824. InOutRes:=106;
  825. end;
  826. {$ifdef INT64}
  827. function Read_QWord(var f : textrec) : qword;[public,alias:'FPC_READ_TEXT_QWORD'];
  828. var
  829. hs : String;
  830. code : longint;
  831. Begin
  832. Read_QWord:=0;
  833. { Leave if error or not open file, else check for empty buf }
  834. If (InOutRes<>0) then
  835. exit;
  836. if (f.mode<>fmInput) Then
  837. begin
  838. case TextRec(f).mode of
  839. fmOutPut,fmAppend:
  840. InOutRes:=104
  841. else
  842. InOutRes:=103;
  843. end;
  844. exit;
  845. end;
  846. If f.BufPos>=f.BufEnd Then
  847. FileFunc(f.InOutFunc)(f);
  848. hs:='';
  849. if IgnoreSpaces(f) then
  850. ReadNumeric(f,hs);
  851. val(hs,Read_QWord,code);
  852. If code<>0 Then
  853. InOutRes:=106;
  854. End;
  855. function Read_Int64(var f : textrec) : int64;[public,alias:'FPC_READ_TEXT_INT64'];
  856. var
  857. hs : String;
  858. code : Longint;
  859. Begin
  860. Read_Int64:=0;
  861. { Leave if error or not open file, else check for empty buf }
  862. If (InOutRes<>0) then
  863. exit;
  864. if (f.mode<>fmInput) Then
  865. begin
  866. case TextRec(f).mode of
  867. fmOutPut,fmAppend:
  868. InOutRes:=104
  869. else
  870. InOutRes:=103;
  871. end;
  872. exit;
  873. end;
  874. If f.BufPos>=f.BufEnd Then
  875. FileFunc(f.InOutFunc)(f);
  876. hs:='';
  877. if IgnoreSpaces(f) then
  878. ReadNumeric(f,hs);
  879. Val(hs,Read_Int64,code);
  880. If code<>0 Then
  881. InOutRes:=106;
  882. End;
  883. {$endif INT64}
  884. {*****************************************************************************
  885. Initializing
  886. *****************************************************************************}
  887. procedure OpenStdIO(var f:text;mode,hdl:longint);
  888. begin
  889. Assign(f,'');
  890. TextRec(f).Handle:=hdl;
  891. TextRec(f).Mode:=mode;
  892. TextRec(f).Closefunc:=@FileCloseFunc;
  893. case mode of
  894. fmInput :
  895. TextRec(f).InOutFunc:=@FileReadFunc;
  896. fmOutput :
  897. begin
  898. TextRec(f).InOutFunc:=@FileWriteFunc;
  899. TextRec(f).FlushFunc:=@FileWriteFunc;
  900. end;
  901. else
  902. HandleError(102);
  903. end;
  904. end;
  905. {
  906. $Log$
  907. Revision 1.72 2000-03-24 10:26:18 jonas
  908. * changed a lot of "if fm.mode = fmClosed then" to case statements,
  909. because if f is not yet initialized, the mode is invalid and can
  910. contain another value even though the file is closed
  911. + check if a file is open in writeln_end (caused crash if used on
  912. not opened files)
  913. Revision 1.71 2000/03/19 08:36:41 peter
  914. * length check for readnumeric
  915. Revision 1.70 2000/03/17 21:27:56 jonas
  916. * fixed declaration of val_int64 (removed destsize parameter)
  917. * fixed val_int64 and val_qword so they reject invalid input
  918. (u >= base)
  919. * when reading a number, invalid input is removed from the input
  920. buffer (+ it should be faster as well)
  921. Revision 1.69 2000/02/09 16:59:31 peter
  922. * truncated log
  923. Revision 1.68 2000/01/31 12:11:53 jonas
  924. * committed the rest of my fix :)
  925. Revision 1.67 2000/01/31 10:15:43 pierre
  926. * Jonas' fix for bug811
  927. Revision 1.66 2000/01/23 12:22:37 florian
  928. * reading of 64 bit type implemented
  929. Revision 1.65 2000/01/20 20:19:37 florian
  930. * writing of int64/qword fixed
  931. Revision 1.64 2000/01/08 17:08:36 jonas
  932. + Mac linebreak (#13) support for readln
  933. Revision 1.63 2000/01/07 16:41:36 daniel
  934. * copyright 2000
  935. Revision 1.62 2000/01/07 16:32:25 daniel
  936. * copyright 2000 added
  937. Revision 1.61 1999/12/02 17:40:06 peter
  938. * read_int64 dummy added
  939. Revision 1.60 1999/11/06 14:35:39 peter
  940. * truncated log
  941. Revision 1.59 1999/10/26 12:25:19 peter
  942. * inoutres 103 for closed files, just like delphi
  943. Revision 1.58 1999/10/04 20:42:45 peter
  944. * read ansistring speedup (no length(s) calls anymore)
  945. Revision 1.57 1999/09/10 17:14:43 peter
  946. * remove CR when reading one char less then size
  947. Revision 1.56 1999/09/10 15:40:33 peter
  948. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  949. Revision 1.55 1999/09/08 16:12:24 peter
  950. * fixed inoutres for diskfull
  951. Revision 1.54 1999/09/07 07:44:58 peter
  952. * fixed array of char writing which didn't write the last char
  953. Revision 1.53 1999/08/19 11:16:14 peter
  954. * settextbuf size is now longint
  955. Revision 1.52 1999/08/03 21:58:45 peter
  956. * small speed improvements
  957. Revision 1.51 1999/07/26 09:43:24 florian
  958. + write helper routine for in64 implemented
  959. }