text.inc 23 KB

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