text.inc 23 KB

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