text.inc 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  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. begin
  374. If InOutRes <> 0 then exit;
  375. case f.mode of
  376. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  377. begin
  378. { Write EOL }
  379. WriteBuffer(f,(@sLineBreak+1)^,length(sLineBreak));
  380. { Flush }
  381. if f.FlushFunc<>nil then
  382. FileFunc(f.FlushFunc)(f);
  383. end;
  384. fmInput: InOutRes:=105
  385. else InOutRes:=103;
  386. end;
  387. end;
  388. Procedure Write_Str(Len : Longint;var f : TextRec;const s : String);[Public,Alias:'FPC_WRITE_TEXT_SHORTSTR'];
  389. Begin
  390. If (InOutRes<>0) then
  391. exit;
  392. case f.mode of
  393. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  394. begin
  395. If Len>Length(s) Then
  396. WriteBlanks(f,Len-Length(s));
  397. WriteBuffer(f,s[1],Length(s));
  398. end;
  399. fmInput: InOutRes:=105
  400. else InOutRes:=103;
  401. end;
  402. End;
  403. Procedure Write_Array(Len : Longint;var f : TextRec;const s : array of char);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_ARRAY'];
  404. var
  405. ArrayLen : longint;
  406. p : pchar;
  407. Begin
  408. If (InOutRes<>0) then
  409. exit;
  410. case f.mode of
  411. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  412. begin
  413. p:=pchar(@s);
  414. ArrayLen:=StrLen(p);
  415. if ArrayLen>sizeof(s) then
  416. ArrayLen:=sizeof(s);
  417. If Len>ArrayLen Then
  418. WriteBlanks(f,Len-ArrayLen);
  419. WriteBuffer(f,p^,ArrayLen);
  420. end;
  421. fmInput: InOutRes:=105
  422. else InOutRes:=103;
  423. end;
  424. End;
  425. Procedure Write_PChar(Len : Longint;var f : TextRec;p : PChar);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_POINTER'];
  426. var
  427. PCharLen : longint;
  428. Begin
  429. If (p=nil) or (InOutRes<>0) then
  430. exit;
  431. case f.mode of
  432. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  433. begin
  434. PCharLen:=StrLen(p);
  435. If Len>PCharLen Then
  436. WriteBlanks(f,Len-PCharLen);
  437. WriteBuffer(f,p^,PCharLen);
  438. end;
  439. fmInput: InOutRes:=105
  440. else InOutRes:=103;
  441. end;
  442. End;
  443. Procedure Write_Text_AnsiString (Len : Longint; Var f : TextRec; S : AnsiString);[Public,alias:'FPC_WRITE_TEXT_ANSISTR'];
  444. {
  445. Writes a AnsiString to the Text file T
  446. }
  447. var
  448. SLen : longint;
  449. begin
  450. If (pointer(S)=nil) or (InOutRes<>0) then
  451. exit;
  452. case f.mode of
  453. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  454. begin
  455. SLen:=Length(s);
  456. If Len>SLen Then
  457. WriteBlanks(f,Len-SLen);
  458. WriteBuffer(f,PChar(S)^,SLen);
  459. end;
  460. fmInput: InOutRes:=105
  461. else InOutRes:=103;
  462. end;
  463. end;
  464. Procedure Write_SInt(Len : Longint;var t : TextRec;l : ValSInt);[Public,Alias:'FPC_WRITE_TEXT_SINT'];
  465. var
  466. s : String;
  467. Begin
  468. If (InOutRes<>0) then
  469. exit;
  470. Str(l,s);
  471. Write_Str(Len,t,s);
  472. End;
  473. Procedure Write_UInt(Len : Longint;var t : TextRec;l : ValUInt);[Public,Alias:'FPC_WRITE_TEXT_UINT'];
  474. var
  475. s : String;
  476. Begin
  477. If (InOutRes<>0) then
  478. exit;
  479. Str(L,s);
  480. Write_Str(Len,t,s);
  481. End;
  482. procedure write_qword(len : longint;var t : textrec;q : qword);[public,alias:'FPC_WRITE_TEXT_QWORD'];
  483. var
  484. s : string;
  485. begin
  486. if (InOutRes<>0) then
  487. exit;
  488. qword_str(q,s);
  489. write_str(len,t,s);
  490. end;
  491. procedure write_int64(len : longint;var t : textrec;i : int64);[public,alias:'FPC_WRITE_TEXT_INT64'];
  492. var
  493. s : string;
  494. begin
  495. if (InOutRes<>0) then
  496. exit;
  497. int64_str(i,s);
  498. write_str(len,t,s);
  499. end;
  500. Procedure Write_Float(rt,fixkomma,Len : Longint;var t : TextRec;r : ValReal);[Public,Alias:'FPC_WRITE_TEXT_FLOAT'];
  501. var
  502. s : String;
  503. Begin
  504. If (InOutRes<>0) then
  505. exit;
  506. Str_real(Len,fixkomma,r,treal_type(rt),s);
  507. Write_Str(Len,t,s);
  508. End;
  509. Procedure Write_Boolean(Len : Longint;var t : TextRec;b : Boolean);[Public,Alias:'FPC_WRITE_TEXT_BOOLEAN'];
  510. Begin
  511. If (InOutRes<>0) then
  512. exit;
  513. { Can't use array[boolean] because b can be >0 ! }
  514. if b then
  515. Write_Str(Len,t,'TRUE')
  516. else
  517. Write_Str(Len,t,'FALSE');
  518. End;
  519. Procedure Write_Char(Len : Longint;var t : TextRec;c : Char);[Public,Alias:'FPC_WRITE_TEXT_CHAR'];
  520. Begin
  521. If (InOutRes<>0) then
  522. exit;
  523. if (TextRec(t).mode<>fmOutput) Then
  524. begin
  525. if TextRec(t).mode=fmClosed then
  526. InOutRes:=103
  527. else
  528. InOutRes:=105;
  529. exit;
  530. end;
  531. If Len>1 Then
  532. WriteBlanks(t,Len-1);
  533. If t.BufPos+1>=t.BufSize Then
  534. FileFunc(t.InOutFunc)(t);
  535. t.Bufptr^[t.BufPos]:=c;
  536. Inc(t.BufPos);
  537. End;
  538. {*****************************************************************************
  539. Read(Ln)
  540. *****************************************************************************}
  541. Function NextChar(var f:TextRec;var s:string):Boolean;
  542. begin
  543. if f.BufPos<f.BufEnd then
  544. begin
  545. if length(s)<high(s) then
  546. begin
  547. inc(s[0]);
  548. s[length(s)]:=f.BufPtr^[f.BufPos];
  549. end;
  550. Inc(f.BufPos);
  551. If f.BufPos>=f.BufEnd Then
  552. FileFunc(f.InOutFunc)(f);
  553. NextChar:=true;
  554. end
  555. else
  556. NextChar:=false;
  557. end;
  558. Function IgnoreSpaces(var f:TextRec):Boolean;
  559. {
  560. Removes all leading spaces,tab,eols from the input buffer, returns true if
  561. the buffer is empty
  562. }
  563. var
  564. s : string;
  565. begin
  566. s:='';
  567. IgnoreSpaces:=false;
  568. while f.Bufptr^[f.BufPos] in [#9,#10,#13,' '] do
  569. if not NextChar(f,s) then
  570. exit;
  571. IgnoreSpaces:=true;
  572. end;
  573. procedure ReadNumeric(var f:TextRec;var s:string);
  574. {
  575. Read numeric input, if buffer is empty then return True
  576. }
  577. begin
  578. repeat
  579. if not NextChar(f,s) then
  580. exit;
  581. until (length(s)=high(s)) or (f.BufPtr^[f.BufPos] in [#9,#10,#13,' ']);
  582. end;
  583. Procedure Read_End(var f:TextRec);[Public,Alias:'FPC_READ_END'];
  584. begin
  585. if f.FlushFunc<>nil then
  586. FileFunc(f.FlushFunc)(f);
  587. end;
  588. Procedure ReadLn_End(var f : TextRec);[Public,Alias:'FPC_READLN_END'];
  589. var prev: char;
  590. Begin
  591. { Check error and if file is open and load buf if empty }
  592. If (InOutRes<>0) then
  593. exit;
  594. if (f.mode<>fmInput) Then
  595. begin
  596. case TextRec(f).mode of
  597. fmOutPut,fmAppend:
  598. InOutRes:=104
  599. else
  600. InOutRes:=103;
  601. end;
  602. exit;
  603. end;
  604. if f.BufPos>=f.BufEnd Then
  605. begin
  606. FileFunc(f.InOutFunc)(f);
  607. if (f.BufPos>=f.BufEnd) then
  608. { Flush if set }
  609. begin
  610. if (f.FlushFunc<>nil) then
  611. FileFunc(f.FlushFunc)(f);
  612. exit;
  613. end;
  614. end;
  615. repeat
  616. prev := f.BufPtr^[f.BufPos];
  617. inc(f.BufPos);
  618. { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
  619. { #13#10 = Dos), so if we've got #10, we can safely exit }
  620. if prev = #10 then
  621. exit;
  622. if f.BufPos>=f.BufEnd Then
  623. begin
  624. FileFunc(f.InOutFunc)(f);
  625. if (f.BufPos>=f.BufEnd) then
  626. { Flush if set }
  627. begin
  628. if (f.FlushFunc<>nil) then
  629. FileFunc(f.FlushFunc)(f);
  630. exit;
  631. end;
  632. end;
  633. if (prev=#13) then
  634. { is there also a #10 after it? }
  635. begin
  636. if (f.BufPtr^[f.BufPos]=#10) then
  637. { yes, skip that one as well }
  638. inc(f.BufPos);
  639. exit;
  640. end;
  641. until false;
  642. End;
  643. Function ReadPCharLen(var f:TextRec;s:pchar;maxlen:longint):longint;
  644. var
  645. sPos,len : Longint;
  646. p,startp,maxp : pchar;
  647. Begin
  648. ReadPCharLen:=0;
  649. { Check error and if file is open }
  650. If (InOutRes<>0) then
  651. exit;
  652. if (f.mode<>fmInput) Then
  653. begin
  654. case TextRec(f).mode of
  655. fmOutPut,fmAppend:
  656. InOutRes:=104
  657. else
  658. InOutRes:=103;
  659. end;
  660. exit;
  661. end;
  662. { Read maximal until Maxlen is reached }
  663. sPos:=0;
  664. repeat
  665. If f.BufPos>=f.BufEnd Then
  666. begin
  667. FileFunc(f.InOutFunc)(f);
  668. If f.BufPos>=f.BufEnd Then
  669. break;
  670. end;
  671. p:[email protected]^[f.BufPos];
  672. if SPos+f.BufEnd-f.BufPos>MaxLen then
  673. maxp:[email protected]^[f.BufPos+MaxLen-SPos]
  674. else
  675. maxp:[email protected]^[f.BufEnd];
  676. startp:=p;
  677. { search linefeed }
  678. while (p<maxp) and not(P^ in [#10,#13]) do
  679. inc(p);
  680. { calculate read bytes }
  681. len:=p-startp;
  682. inc(f.BufPos,Len);
  683. Move(startp^,s[sPos],Len);
  684. inc(sPos,Len);
  685. { was it a LF or CR? then leave }
  686. if (spos=MaxLen) or
  687. ((p<maxp) and (p^ in [#10,#13])) then
  688. break;
  689. until false;
  690. ReadPCharLen:=spos;
  691. End;
  692. Procedure Read_String(var f : TextRec;var s : String);[Public,Alias:'FPC_READ_TEXT_SHORTSTR'];
  693. Begin
  694. s[0]:=chr(ReadPCharLen(f,pchar(@s[1]),high(s)));
  695. End;
  696. Procedure Read_PChar(var f : TextRec;var s : PChar);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER'];
  697. Begin
  698. pchar(s+ReadPCharLen(f,s,$7fffffff))^:=#0;
  699. End;
  700. Procedure Read_Array(var f : TextRec;var s : array of char);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY'];
  701. Begin
  702. pchar(pchar(@s)+ReadPCharLen(f,pchar(@s),high(s)))^:=#0;
  703. End;
  704. Procedure Read_AnsiString(var f : TextRec;var s : AnsiString);[Public,Alias:'FPC_READ_TEXT_ANSISTR'];
  705. var
  706. slen,len : longint;
  707. Begin
  708. slen:=0;
  709. Repeat
  710. // SetLength will reallocate the length.
  711. SetLength(S,slen+255);
  712. len:=ReadPCharLen(f,pchar(Pointer(S)+slen),255);
  713. inc(slen,len);
  714. Until len<255;
  715. // Set actual length
  716. SetLength(S,Slen);
  717. End;
  718. Function Read_Char(var f : TextRec):char;[Public,Alias:'FPC_READ_TEXT_CHAR'];
  719. Begin
  720. Read_Char:=#0;
  721. { Check error and if file is open }
  722. If (InOutRes<>0) then
  723. exit;
  724. if (f.mode<>fmInput) Then
  725. begin
  726. case TextRec(f).mode of
  727. fmOutPut,fmAppend:
  728. InOutRes:=104
  729. else
  730. InOutRes:=103;
  731. end;
  732. exit;
  733. end;
  734. { Read next char or EOF }
  735. If f.BufPos>=f.BufEnd Then
  736. begin
  737. FileFunc(f.InOutFunc)(f);
  738. If f.BufPos>=f.BufEnd Then
  739. exit(#26);
  740. end;
  741. Read_Char:=f.Bufptr^[f.BufPos];
  742. inc(f.BufPos);
  743. end;
  744. Function Read_SInt(var f : TextRec):ValSInt;[Public,Alias:'FPC_READ_TEXT_SINT'];
  745. var
  746. hs : String;
  747. code : Longint;
  748. Begin
  749. Read_SInt:=0;
  750. { Leave if error or not open file, else check for empty buf }
  751. If (InOutRes<>0) then
  752. exit;
  753. if (f.mode<>fmInput) Then
  754. begin
  755. case TextRec(f).mode of
  756. fmOutPut,fmAppend:
  757. InOutRes:=104
  758. else
  759. InOutRes:=103;
  760. end;
  761. exit;
  762. end;
  763. If f.BufPos>=f.BufEnd Then
  764. FileFunc(f.InOutFunc)(f);
  765. hs:='';
  766. if IgnoreSpaces(f) then
  767. ReadNumeric(f,hs);
  768. Val(hs,Read_SInt,code);
  769. If code<>0 Then
  770. InOutRes:=106;
  771. End;
  772. Function Read_UInt(var f : TextRec):ValUInt;[Public,Alias:'FPC_READ_TEXT_UINT'];
  773. var
  774. hs : String;
  775. code : longint;
  776. Begin
  777. Read_UInt:=0;
  778. { Leave if error or not open file, else check for empty buf }
  779. If (InOutRes<>0) then
  780. exit;
  781. if (f.mode<>fmInput) Then
  782. begin
  783. case TextRec(f).mode of
  784. fmOutPut,fmAppend:
  785. InOutRes:=104
  786. else
  787. InOutRes:=103;
  788. end;
  789. exit;
  790. end;
  791. If f.BufPos>=f.BufEnd Then
  792. FileFunc(f.InOutFunc)(f);
  793. hs:='';
  794. if IgnoreSpaces(f) then
  795. ReadNumeric(f,hs);
  796. val(hs,Read_UInt,code);
  797. If code<>0 Then
  798. InOutRes:=106;
  799. End;
  800. Function Read_Float(var f : TextRec):ValReal;[Public,Alias:'FPC_READ_TEXT_FLOAT'];
  801. var
  802. hs : string;
  803. code : Word;
  804. begin
  805. Read_Float:=0.0;
  806. { Leave if error or not open file, else check for empty buf }
  807. If (InOutRes<>0) then
  808. exit;
  809. if (f.mode<>fmInput) Then
  810. begin
  811. case TextRec(f).mode of
  812. fmOutPut,fmAppend:
  813. InOutRes:=104
  814. else
  815. InOutRes:=103;
  816. end;
  817. exit;
  818. end;
  819. If f.BufPos>=f.BufEnd Then
  820. FileFunc(f.InOutFunc)(f);
  821. hs:='';
  822. if IgnoreSpaces(f) then
  823. ReadNumeric(f,hs);
  824. val(hs,Read_Float,code);
  825. If code<>0 Then
  826. InOutRes:=106;
  827. end;
  828. function Read_QWord(var f : textrec) : qword;[public,alias:'FPC_READ_TEXT_QWORD'];
  829. var
  830. hs : String;
  831. code : longint;
  832. Begin
  833. Read_QWord:=0;
  834. { Leave if error or not open file, else check for empty buf }
  835. If (InOutRes<>0) then
  836. exit;
  837. if (f.mode<>fmInput) Then
  838. begin
  839. case TextRec(f).mode of
  840. fmOutPut,fmAppend:
  841. InOutRes:=104
  842. else
  843. InOutRes:=103;
  844. end;
  845. exit;
  846. end;
  847. If f.BufPos>=f.BufEnd Then
  848. FileFunc(f.InOutFunc)(f);
  849. hs:='';
  850. if IgnoreSpaces(f) then
  851. ReadNumeric(f,hs);
  852. val(hs,Read_QWord,code);
  853. If code<>0 Then
  854. InOutRes:=106;
  855. End;
  856. function Read_Int64(var f : textrec) : int64;[public,alias:'FPC_READ_TEXT_INT64'];
  857. var
  858. hs : String;
  859. code : Longint;
  860. Begin
  861. Read_Int64:=0;
  862. { Leave if error or not open file, else check for empty buf }
  863. If (InOutRes<>0) then
  864. exit;
  865. if (f.mode<>fmInput) Then
  866. begin
  867. case TextRec(f).mode of
  868. fmOutPut,fmAppend:
  869. InOutRes:=104
  870. else
  871. InOutRes:=103;
  872. end;
  873. exit;
  874. end;
  875. If f.BufPos>=f.BufEnd Then
  876. FileFunc(f.InOutFunc)(f);
  877. hs:='';
  878. if IgnoreSpaces(f) then
  879. ReadNumeric(f,hs);
  880. Val(hs,Read_Int64,code);
  881. If code<>0 Then
  882. InOutRes:=106;
  883. End;
  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.5 2001-03-21 23:29:40 florian
  908. + sLineBreak and misc. stuff for Kylix compatiblity
  909. Revision 1.4 2000/11/23 13:14:02 jonas
  910. * fix for web bug 1210 from Peter (merged)
  911. Revision 1.3 2000/07/14 10:33:10 michael
  912. + Conditionals fixed
  913. Revision 1.2 2000/07/13 11:33:46 michael
  914. + removed logs
  915. }