text.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  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. { check error code of do_rename }
  179. If InOutRes = 0 then
  180. Move(p^,TextRec(t).Name,StrLen(p)+1);
  181. End;
  182. End;
  183. Procedure Rename(var t : Text;const s : string);[IOCheck];
  184. var
  185. p : array[0..255] Of Char;
  186. Begin
  187. If InOutRes <> 0 then
  188. exit;
  189. Move(s[1],p,Length(s));
  190. p[Length(s)]:=#0;
  191. Rename(t,Pchar(@p));
  192. End;
  193. Procedure Rename(var t : Text;c : char);[IOCheck];
  194. var
  195. p : array[0..1] Of Char;
  196. Begin
  197. If InOutRes <> 0 then
  198. exit;
  199. p[0]:=c;
  200. p[1]:=#0;
  201. Rename(t,Pchar(@p));
  202. End;
  203. Function Eof(Var t: Text): Boolean;[IOCheck];
  204. Begin
  205. If (InOutRes<>0) then
  206. exit(true);
  207. if (TextRec(t).mode<>fmInput) Then
  208. begin
  209. if TextRec(t).mode=fmOutput then
  210. InOutRes:=104
  211. else
  212. InOutRes:=103;
  213. exit(true);
  214. end;
  215. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  216. begin
  217. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  218. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  219. exit(true);
  220. end;
  221. {$ifdef EOF_CTRLZ}
  222. Eof:=(TextRec(t).Bufptr^[TextRec(t).BufPos]=#26);
  223. {$else}
  224. Eof:=false;
  225. {$endif EOL_CTRLZ}
  226. end;
  227. Function Eof:Boolean;
  228. Begin
  229. Eof:=Eof(Input);
  230. End;
  231. Function SeekEof (Var t : Text) : Boolean;
  232. Begin
  233. If (InOutRes<>0) then
  234. exit(true);
  235. if (TextRec(t).mode<>fmInput) Then
  236. begin
  237. if TextRec(t).mode=fmOutPut then
  238. InOutRes:=104
  239. else
  240. InOutRes:=103;
  241. exit(true);
  242. end;
  243. repeat
  244. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  245. begin
  246. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  247. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  248. exit(true);
  249. end;
  250. case TextRec(t).Bufptr^[TextRec(t).BufPos] of
  251. #26 : exit(true);
  252. #10,#13,
  253. #9,' ' : ;
  254. else
  255. exit(false);
  256. end;
  257. inc(TextRec(t).BufPos);
  258. until false;
  259. End;
  260. Function SeekEof : Boolean;
  261. Begin
  262. SeekEof:=SeekEof(Input);
  263. End;
  264. Function Eoln(var t:Text) : Boolean;
  265. Begin
  266. If (InOutRes<>0) then
  267. exit(true);
  268. if (TextRec(t).mode<>fmInput) Then
  269. begin
  270. if TextRec(t).mode=fmOutPut then
  271. InOutRes:=104
  272. else
  273. InOutRes:=103;
  274. exit(true);
  275. end;
  276. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  277. begin
  278. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  279. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  280. exit(true);
  281. end;
  282. Eoln:=(TextRec(t).Bufptr^[TextRec(t).BufPos] in [#10,#13]);
  283. End;
  284. Function Eoln : Boolean;
  285. Begin
  286. Eoln:=Eoln(Input);
  287. End;
  288. Function SeekEoln (Var t : Text) : Boolean;
  289. Begin
  290. If (InOutRes<>0) then
  291. exit(true);
  292. if (TextRec(t).mode<>fmInput) Then
  293. begin
  294. if TextRec(t).mode=fmOutput then
  295. InOutRes:=104
  296. else
  297. InOutRes:=103;
  298. exit(true);
  299. end;
  300. repeat
  301. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  302. begin
  303. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  304. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  305. exit(true);
  306. end;
  307. case TextRec(t).Bufptr^[TextRec(t).BufPos] of
  308. #26,
  309. #10,#13 : exit(true);
  310. #9,' ' : ;
  311. else
  312. exit(false);
  313. end;
  314. inc(TextRec(t).BufPos);
  315. until false;
  316. End;
  317. Function SeekEoln : Boolean;
  318. Begin
  319. SeekEoln:=SeekEoln(Input);
  320. End;
  321. Procedure SetTextBuf(Var F : Text; Var Buf);[INTERNPROC: In_settextbuf_file_x];
  322. Procedure SetTextBuf(Var F : Text; Var Buf; Size : Longint);
  323. Begin
  324. TextRec(f).BufPtr:=@Buf;
  325. TextRec(f).BufSize:=Size;
  326. TextRec(f).BufPos:=0;
  327. TextRec(f).BufEnd:=0;
  328. End;
  329. {*****************************************************************************
  330. Write(Ln)
  331. *****************************************************************************}
  332. Procedure WriteBuffer(var f:TextRec;const b;len:longint);
  333. var
  334. p : pchar;
  335. left,
  336. idx : longint;
  337. begin
  338. p:=pchar(@b);
  339. idx:=0;
  340. left:=f.BufSize-f.BufPos;
  341. while len>left do
  342. begin
  343. move(p[idx],f.Bufptr^[f.BufPos],left);
  344. dec(len,left);
  345. inc(idx,left);
  346. inc(f.BufPos,left);
  347. FileFunc(f.InOutFunc)(f);
  348. left:=f.BufSize-f.BufPos;
  349. end;
  350. move(p[idx],f.Bufptr^[f.BufPos],len);
  351. inc(f.BufPos,len);
  352. end;
  353. Procedure WriteBlanks(var f:TextRec;len:longint);
  354. var
  355. left : longint;
  356. begin
  357. left:=f.BufSize-f.BufPos;
  358. while len>left do
  359. begin
  360. FillChar(f.Bufptr^[f.BufPos],left,' ');
  361. dec(len,left);
  362. inc(f.BufPos,left);
  363. FileFunc(f.InOutFunc)(f);
  364. left:=f.BufSize-f.BufPos;
  365. end;
  366. FillChar(f.Bufptr^[f.BufPos],len,' ');
  367. inc(f.BufPos,len);
  368. end;
  369. Procedure Write_End(var f:TextRec);[Public,Alias:'FPC_WRITE_END'];
  370. begin
  371. if f.FlushFunc<>nil then
  372. FileFunc(f.FlushFunc)(f);
  373. end;
  374. Procedure Writeln_End(var f:TextRec);[Public,Alias:'FPC_WRITELN_END'];
  375. const
  376. {$IFDEF SHORT_LINEBREAK}
  377. eollen=1;
  378. eol : array[0..0] of char=(#10);
  379. {$ELSE SHORT_LINEBREAK}
  380. {$ifdef MAC_LINEBREAK}
  381. eollen=1;
  382. eol : array[0..0] of char=(#13);
  383. {$else MAC_LINEBREAK}
  384. eollen=2;
  385. eol : array[0..1] of char=(#13,#10);
  386. {$endif MAC_LINEBREAK}
  387. {$ENDIF SHORT_LINEBREAK}
  388. begin
  389. If InOutRes <> 0 then exit;
  390. case f.mode of
  391. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  392. begin
  393. { Write EOL }
  394. WriteBuffer(f,(@sLineBreak+1)^,length(sLineBreak));
  395. { Flush }
  396. if f.FlushFunc<>nil then
  397. FileFunc(f.FlushFunc)(f);
  398. end;
  399. fmInput: InOutRes:=105
  400. else InOutRes:=103;
  401. end;
  402. end;
  403. Procedure Write_Str(Len : Longint;var f : TextRec;const s : String);[Public,Alias:'FPC_WRITE_TEXT_SHORTSTR'];
  404. Begin
  405. If (InOutRes<>0) then
  406. exit;
  407. case f.mode of
  408. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  409. begin
  410. If Len>Length(s) Then
  411. WriteBlanks(f,Len-Length(s));
  412. WriteBuffer(f,s[1],Length(s));
  413. end;
  414. fmInput: InOutRes:=105
  415. else InOutRes:=103;
  416. end;
  417. End;
  418. Procedure Write_Array(Len : Longint;var f : TextRec;const s : array of char);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_ARRAY'];
  419. var
  420. ArrayLen : longint;
  421. p : pchar;
  422. Begin
  423. If (InOutRes<>0) then
  424. exit;
  425. case f.mode of
  426. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  427. begin
  428. p:=pchar(@s);
  429. { can't use StrLen, since that one could try to read past the end }
  430. { of the heap (JM) }
  431. ArrayLen:=IndexByte(p^,high(s)+1,0);
  432. { IndexByte returns -1 if not found (JM) }
  433. if ArrayLen = -1 then
  434. ArrayLen := high(s)+1;
  435. If Len>ArrayLen Then
  436. WriteBlanks(f,Len-ArrayLen);
  437. WriteBuffer(f,p^,ArrayLen);
  438. end;
  439. fmInput: InOutRes:=105
  440. else InOutRes:=103;
  441. end;
  442. End;
  443. Procedure Write_PChar(Len : Longint;var f : TextRec;p : PChar);[Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_POINTER'];
  444. var
  445. PCharLen : longint;
  446. Begin
  447. If (p=nil) or (InOutRes<>0) then
  448. exit;
  449. case f.mode of
  450. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  451. begin
  452. PCharLen:=StrLen(p);
  453. If Len>PCharLen Then
  454. WriteBlanks(f,Len-PCharLen);
  455. WriteBuffer(f,p^,PCharLen);
  456. end;
  457. fmInput: InOutRes:=105
  458. else InOutRes:=103;
  459. end;
  460. End;
  461. Procedure Write_Text_AnsiString (Len : Longint; Var f : TextRec; S : AnsiString);[Public,alias:'FPC_WRITE_TEXT_ANSISTR'];
  462. {
  463. Writes a AnsiString to the Text file T
  464. }
  465. var
  466. SLen : longint;
  467. begin
  468. If (pointer(S)=nil) or (InOutRes<>0) then
  469. exit;
  470. case f.mode of
  471. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  472. begin
  473. SLen:=Length(s);
  474. If Len>SLen Then
  475. WriteBlanks(f,Len-SLen);
  476. WriteBuffer(f,PChar(S)^,SLen);
  477. end;
  478. fmInput: InOutRes:=105
  479. else InOutRes:=103;
  480. end;
  481. end;
  482. {$ifdef HASWIDESTRING}
  483. Procedure Write_Text_WideString (Len : Longint; Var f : TextRec; S : WideString);[Public,alias:'FPC_WRITE_TEXT_WIDESTR'];
  484. {
  485. Writes a WideString to the Text file T
  486. }
  487. var
  488. SLen : longint;
  489. begin
  490. If (pointer(S)=nil) or (InOutRes<>0) then
  491. exit;
  492. case f.mode of
  493. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  494. begin
  495. SLen:=Length(s);
  496. If Len>SLen Then
  497. WriteBlanks(f,Len-SLen);
  498. WriteBuffer(f,PChar(AnsiString(S))^,SLen);
  499. end;
  500. fmInput: InOutRes:=105
  501. else InOutRes:=103;
  502. end;
  503. end;
  504. {$endif HASWIDESTRING}
  505. Procedure Write_SInt(Len : Longint;var t : TextRec;l : ValSInt);[Public,Alias:'FPC_WRITE_TEXT_SINT'];
  506. var
  507. s : String;
  508. Begin
  509. If (InOutRes<>0) then
  510. exit;
  511. Str(l,s);
  512. Write_Str(Len,t,s);
  513. End;
  514. Procedure Write_UInt(Len : Longint;var t : TextRec;l : ValUInt);[Public,Alias:'FPC_WRITE_TEXT_UINT'];
  515. var
  516. s : String;
  517. Begin
  518. If (InOutRes<>0) then
  519. exit;
  520. Str(L,s);
  521. Write_Str(Len,t,s);
  522. End;
  523. procedure write_qword(len : longint;var t : textrec;q : qword);[public,alias:'FPC_WRITE_TEXT_QWORD'];
  524. var
  525. s : string;
  526. begin
  527. if (InOutRes<>0) then
  528. exit;
  529. qword_str(q,s);
  530. write_str(len,t,s);
  531. end;
  532. procedure write_int64(len : longint;var t : textrec;i : int64);[public,alias:'FPC_WRITE_TEXT_INT64'];
  533. var
  534. s : string;
  535. begin
  536. if (InOutRes<>0) then
  537. exit;
  538. int64_str(i,s);
  539. write_str(len,t,s);
  540. end;
  541. Procedure Write_Float(rt,fixkomma,Len : Longint;var t : TextRec;r : ValReal);[Public,Alias:'FPC_WRITE_TEXT_FLOAT'];
  542. var
  543. s : String;
  544. Begin
  545. If (InOutRes<>0) then
  546. exit;
  547. Str_real(Len,fixkomma,r,treal_type(rt),s);
  548. Write_Str(Len,t,s);
  549. End;
  550. Procedure Write_Boolean(Len : Longint;var t : TextRec;b : Boolean);[Public,Alias:'FPC_WRITE_TEXT_BOOLEAN'];
  551. Begin
  552. If (InOutRes<>0) then
  553. exit;
  554. { Can't use array[boolean] because b can be >0 ! }
  555. if b then
  556. Write_Str(Len,t,'TRUE')
  557. else
  558. Write_Str(Len,t,'FALSE');
  559. End;
  560. Procedure Write_Char(Len : Longint;var t : TextRec;c : Char);[Public,Alias:'FPC_WRITE_TEXT_CHAR'];
  561. Begin
  562. If (InOutRes<>0) then
  563. exit;
  564. if (TextRec(t).mode<>fmOutput) Then
  565. begin
  566. if TextRec(t).mode=fmClosed then
  567. InOutRes:=103
  568. else
  569. InOutRes:=105;
  570. exit;
  571. end;
  572. If Len>1 Then
  573. WriteBlanks(t,Len-1);
  574. If t.BufPos+1>=t.BufSize Then
  575. FileFunc(t.InOutFunc)(t);
  576. t.Bufptr^[t.BufPos]:=c;
  577. Inc(t.BufPos);
  578. End;
  579. {$ifdef HASWIDECHAR}
  580. Procedure Write_WideChar(Len : Longint;var t : TextRec;c : WideChar);[Public,Alias:'FPC_WRITE_TEXT_WIDECHAR'];
  581. var
  582. ch : char;
  583. Begin
  584. If (InOutRes<>0) then
  585. exit;
  586. if (TextRec(t).mode<>fmOutput) Then
  587. begin
  588. if TextRec(t).mode=fmClosed then
  589. InOutRes:=103
  590. else
  591. InOutRes:=105;
  592. exit;
  593. end;
  594. If Len>1 Then
  595. WriteBlanks(t,Len-1);
  596. If t.BufPos+1>=t.BufSize Then
  597. FileFunc(t.InOutFunc)(t);
  598. ch:=c;
  599. t.Bufptr^[t.BufPos]:=ch;
  600. Inc(t.BufPos);
  601. End;
  602. {$endif HASWIDECHAR}
  603. {*****************************************************************************
  604. Read(Ln)
  605. *****************************************************************************}
  606. Function NextChar(var f:TextRec;var s:string):Boolean;
  607. begin
  608. if f.BufPos<f.BufEnd then
  609. begin
  610. if length(s)<high(s) then
  611. begin
  612. inc(s[0]);
  613. s[length(s)]:=f.BufPtr^[f.BufPos];
  614. end;
  615. Inc(f.BufPos);
  616. If f.BufPos>=f.BufEnd Then
  617. FileFunc(f.InOutFunc)(f);
  618. NextChar:=true;
  619. end
  620. else
  621. NextChar:=false;
  622. end;
  623. Function IgnoreSpaces(var f:TextRec):Boolean;
  624. {
  625. Removes all leading spaces,tab,eols from the input buffer, returns true if
  626. the buffer is empty
  627. }
  628. var
  629. s : string;
  630. begin
  631. s:='';
  632. IgnoreSpaces:=false;
  633. while f.Bufptr^[f.BufPos] in [#9,#10,#13,' '] do
  634. if not NextChar(f,s) then
  635. exit;
  636. IgnoreSpaces:=true;
  637. end;
  638. procedure ReadNumeric(var f:TextRec;var s:string);
  639. {
  640. Read numeric input, if buffer is empty then return True
  641. }
  642. begin
  643. repeat
  644. if not NextChar(f,s) then
  645. exit;
  646. until (length(s)=high(s)) or (f.BufPtr^[f.BufPos] in [#9,#10,#13,' ']);
  647. end;
  648. Procedure Read_End(var f:TextRec);[Public,Alias:'FPC_READ_END'];
  649. begin
  650. if f.FlushFunc<>nil then
  651. FileFunc(f.FlushFunc)(f);
  652. end;
  653. Procedure ReadLn_End(var f : TextRec);[Public,Alias:'FPC_READLN_END'];
  654. var prev: char;
  655. Begin
  656. { Check error and if file is open and load buf if empty }
  657. If (InOutRes<>0) then
  658. exit;
  659. if (f.mode<>fmInput) Then
  660. begin
  661. case TextRec(f).mode of
  662. fmOutPut,fmAppend:
  663. InOutRes:=104
  664. else
  665. InOutRes:=103;
  666. end;
  667. exit;
  668. end;
  669. if f.BufPos>=f.BufEnd Then
  670. begin
  671. FileFunc(f.InOutFunc)(f);
  672. if (f.BufPos>=f.BufEnd) then
  673. { Flush if set }
  674. begin
  675. if (f.FlushFunc<>nil) then
  676. FileFunc(f.FlushFunc)(f);
  677. exit;
  678. end;
  679. end;
  680. repeat
  681. prev := f.BufPtr^[f.BufPos];
  682. inc(f.BufPos);
  683. { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
  684. { #13#10 = Dos), so if we've got #10, we can safely exit }
  685. if prev = #10 then
  686. exit;
  687. if f.BufPos>=f.BufEnd Then
  688. begin
  689. FileFunc(f.InOutFunc)(f);
  690. if (f.BufPos>=f.BufEnd) then
  691. { Flush if set }
  692. begin
  693. if (f.FlushFunc<>nil) then
  694. FileFunc(f.FlushFunc)(f);
  695. exit;
  696. end;
  697. end;
  698. if (prev=#13) then
  699. { is there also a #10 after it? }
  700. begin
  701. if (f.BufPtr^[f.BufPos]=#10) then
  702. { yes, skip that one as well }
  703. inc(f.BufPos);
  704. exit;
  705. end;
  706. until false;
  707. End;
  708. Function ReadPCharLen(var f:TextRec;s:pchar;maxlen:longint):longint;
  709. var
  710. sPos,len : Longint;
  711. p,startp,maxp : pchar;
  712. Begin
  713. ReadPCharLen:=0;
  714. { Check error and if file is open }
  715. If (InOutRes<>0) then
  716. exit;
  717. if (f.mode<>fmInput) Then
  718. begin
  719. case TextRec(f).mode of
  720. fmOutPut,fmAppend:
  721. InOutRes:=104
  722. else
  723. InOutRes:=103;
  724. end;
  725. exit;
  726. end;
  727. { Read maximal until Maxlen is reached }
  728. sPos:=0;
  729. repeat
  730. If f.BufPos>=f.BufEnd Then
  731. begin
  732. FileFunc(f.InOutFunc)(f);
  733. If f.BufPos>=f.BufEnd Then
  734. break;
  735. end;
  736. p:[email protected]^[f.BufPos];
  737. if SPos+f.BufEnd-f.BufPos>MaxLen then
  738. maxp:[email protected]^[f.BufPos+MaxLen-SPos]
  739. else
  740. maxp:[email protected]^[f.BufEnd];
  741. startp:=p;
  742. { search linefeed }
  743. while (p<maxp) and not(P^ in [#10,#13]) do
  744. inc(p);
  745. { calculate read bytes }
  746. len:=p-startp;
  747. inc(f.BufPos,Len);
  748. Move(startp^,s[sPos],Len);
  749. inc(sPos,Len);
  750. { was it a LF or CR? then leave }
  751. if (spos=MaxLen) or
  752. ((p<maxp) and (p^ in [#10,#13])) then
  753. break;
  754. until false;
  755. ReadPCharLen:=spos;
  756. End;
  757. Procedure Read_String(var f : TextRec;var s : String);[Public,Alias:'FPC_READ_TEXT_SHORTSTR'];
  758. Begin
  759. s[0]:=chr(ReadPCharLen(f,pchar(@s[1]),high(s)));
  760. End;
  761. Procedure Read_PChar(var f : TextRec;var s : PChar);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER'];
  762. Begin
  763. pchar(s+ReadPCharLen(f,s,$7fffffff))^:=#0;
  764. End;
  765. Procedure Read_Array(var f : TextRec;var s : array of char);[Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY'];
  766. Begin
  767. pchar(pchar(@s)+ReadPCharLen(f,pchar(@s),high(s)))^:=#0;
  768. End;
  769. Procedure Read_AnsiString(var f : TextRec;var s : AnsiString);[Public,Alias:'FPC_READ_TEXT_ANSISTR'];
  770. var
  771. slen,len : longint;
  772. Begin
  773. slen:=0;
  774. Repeat
  775. // SetLength will reallocate the length.
  776. SetLength(S,slen+255);
  777. len:=ReadPCharLen(f,pchar(Pointer(S)+slen),255);
  778. inc(slen,len);
  779. Until len<255;
  780. // Set actual length
  781. SetLength(S,Slen);
  782. End;
  783. Function Read_Char(var f : TextRec):char;[Public,Alias:'FPC_READ_TEXT_CHAR'];
  784. Begin
  785. Read_Char:=#0;
  786. { Check error and if file is open }
  787. If (InOutRes<>0) then
  788. exit;
  789. if (f.mode<>fmInput) Then
  790. begin
  791. case TextRec(f).mode of
  792. fmOutPut,fmAppend:
  793. InOutRes:=104
  794. else
  795. InOutRes:=103;
  796. end;
  797. exit;
  798. end;
  799. { Read next char or EOF }
  800. If f.BufPos>=f.BufEnd Then
  801. begin
  802. FileFunc(f.InOutFunc)(f);
  803. If f.BufPos>=f.BufEnd Then
  804. exit(#26);
  805. end;
  806. Read_Char:=f.Bufptr^[f.BufPos];
  807. inc(f.BufPos);
  808. end;
  809. Function Read_SInt(var f : TextRec):ValSInt;[Public,Alias:'FPC_READ_TEXT_SINT'];
  810. var
  811. hs : String;
  812. code : Longint;
  813. Begin
  814. Read_SInt:=0;
  815. { Leave if error or not open file, else check for empty buf }
  816. If (InOutRes<>0) then
  817. exit;
  818. if (f.mode<>fmInput) Then
  819. begin
  820. case TextRec(f).mode of
  821. fmOutPut,fmAppend:
  822. InOutRes:=104
  823. else
  824. InOutRes:=103;
  825. end;
  826. exit;
  827. end;
  828. If f.BufPos>=f.BufEnd Then
  829. FileFunc(f.InOutFunc)(f);
  830. hs:='';
  831. if IgnoreSpaces(f) then
  832. ReadNumeric(f,hs);
  833. Val(hs,Read_SInt,code);
  834. If code<>0 Then
  835. InOutRes:=106;
  836. End;
  837. Function Read_UInt(var f : TextRec):ValUInt;[Public,Alias:'FPC_READ_TEXT_UINT'];
  838. var
  839. hs : String;
  840. code : longint;
  841. Begin
  842. Read_UInt:=0;
  843. { Leave if error or not open file, else check for empty buf }
  844. If (InOutRes<>0) then
  845. exit;
  846. if (f.mode<>fmInput) Then
  847. begin
  848. case TextRec(f).mode of
  849. fmOutPut,fmAppend:
  850. InOutRes:=104
  851. else
  852. InOutRes:=103;
  853. end;
  854. exit;
  855. end;
  856. If f.BufPos>=f.BufEnd Then
  857. FileFunc(f.InOutFunc)(f);
  858. hs:='';
  859. if IgnoreSpaces(f) then
  860. ReadNumeric(f,hs);
  861. val(hs,Read_UInt,code);
  862. If code<>0 Then
  863. InOutRes:=106;
  864. End;
  865. Function Read_Float(var f : TextRec):ValReal;[Public,Alias:'FPC_READ_TEXT_FLOAT'];
  866. var
  867. hs : string;
  868. code : Word;
  869. begin
  870. Read_Float:=0.0;
  871. { Leave if error or not open file, else check for empty buf }
  872. If (InOutRes<>0) then
  873. exit;
  874. if (f.mode<>fmInput) Then
  875. begin
  876. case TextRec(f).mode of
  877. fmOutPut,fmAppend:
  878. InOutRes:=104
  879. else
  880. InOutRes:=103;
  881. end;
  882. exit;
  883. end;
  884. If f.BufPos>=f.BufEnd Then
  885. FileFunc(f.InOutFunc)(f);
  886. hs:='';
  887. if IgnoreSpaces(f) then
  888. ReadNumeric(f,hs);
  889. val(hs,Read_Float,code);
  890. If code<>0 Then
  891. InOutRes:=106;
  892. end;
  893. function Read_QWord(var f : textrec) : qword;[public,alias:'FPC_READ_TEXT_QWORD'];
  894. var
  895. hs : String;
  896. code : longint;
  897. Begin
  898. Read_QWord:=0;
  899. { Leave if error or not open file, else check for empty buf }
  900. If (InOutRes<>0) then
  901. exit;
  902. if (f.mode<>fmInput) Then
  903. begin
  904. case TextRec(f).mode of
  905. fmOutPut,fmAppend:
  906. InOutRes:=104
  907. else
  908. InOutRes:=103;
  909. end;
  910. exit;
  911. end;
  912. If f.BufPos>=f.BufEnd Then
  913. FileFunc(f.InOutFunc)(f);
  914. hs:='';
  915. if IgnoreSpaces(f) then
  916. ReadNumeric(f,hs);
  917. val(hs,Read_QWord,code);
  918. If code<>0 Then
  919. InOutRes:=106;
  920. End;
  921. function Read_Int64(var f : textrec) : int64;[public,alias:'FPC_READ_TEXT_INT64'];
  922. var
  923. hs : String;
  924. code : Longint;
  925. Begin
  926. Read_Int64:=0;
  927. { Leave if error or not open file, else check for empty buf }
  928. If (InOutRes<>0) then
  929. exit;
  930. if (f.mode<>fmInput) Then
  931. begin
  932. case TextRec(f).mode of
  933. fmOutPut,fmAppend:
  934. InOutRes:=104
  935. else
  936. InOutRes:=103;
  937. end;
  938. exit;
  939. end;
  940. If f.BufPos>=f.BufEnd Then
  941. FileFunc(f.InOutFunc)(f);
  942. hs:='';
  943. if IgnoreSpaces(f) then
  944. ReadNumeric(f,hs);
  945. Val(hs,Read_Int64,code);
  946. If code<>0 Then
  947. InOutRes:=106;
  948. End;
  949. {*****************************************************************************
  950. Initializing
  951. *****************************************************************************}
  952. procedure OpenStdIO(var f:text;mode,hdl:longint);
  953. begin
  954. Assign(f,'');
  955. TextRec(f).Handle:=hdl;
  956. TextRec(f).Mode:=mode;
  957. TextRec(f).Closefunc:=@FileCloseFunc;
  958. case mode of
  959. fmInput :
  960. TextRec(f).InOutFunc:=@FileReadFunc;
  961. fmOutput :
  962. begin
  963. TextRec(f).InOutFunc:=@FileWriteFunc;
  964. TextRec(f).FlushFunc:=@FileWriteFunc;
  965. end;
  966. else
  967. HandleError(102);
  968. end;
  969. end;
  970. {
  971. $Log$
  972. Revision 1.11 2001-07-21 15:53:28 jonas
  973. * really fixed write_array this time :/ (merged)
  974. Revision 1.10 2001/07/16 13:53:21 jonas
  975. * correctly fixed potential buffer overrun in write_array
  976. Revision 1.9 2001/07/08 21:00:18 peter
  977. * various widestring updates, it works now mostly without charset
  978. mapping supported
  979. Revision 1.8 2001/06/27 21:37:38 peter
  980. * v10 merges
  981. Revision 1.7 2001/06/04 11:43:51 peter
  982. * Formal const to var fixes
  983. * Hexstr(int64) added
  984. Revision 1.6 2001/04/08 13:21:30 jonas
  985. * fixed potential buffer overflow in FPC_WRITE_TEXT_PCHAR_AS_ARRAY (merged)
  986. Revision 1.5 2001/03/21 23:29:40 florian
  987. + sLineBreak and misc. stuff for Kylix compatiblity
  988. Revision 1.4 2000/11/23 13:14:02 jonas
  989. * fix for web bug 1210 from Peter (merged)
  990. Revision 1.3 2000/07/14 10:33:10 michael
  991. + Conditionals fixed
  992. Revision 1.2 2000/07/13 11:33:46 michael
  993. + removed logs
  994. }