text.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. {
  2. This file is part of the Free Pascal Run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {****************************************************************************
  11. subroutines For TextFile handling
  12. ****************************************************************************}
  13. Procedure FileCloseFunc(Var t:TextRec);
  14. Begin
  15. Do_Close(t.Handle);
  16. t.Handle:=UnusedHandle;
  17. End;
  18. Procedure FileReadFunc(var t:TextRec);
  19. Begin
  20. t.BufEnd:=Do_Read(t.Handle,t.Bufptr,t.BufSize);
  21. t.BufPos:=0;
  22. End;
  23. Procedure FileWriteFunc(var t:TextRec);
  24. var
  25. i : longint;
  26. Begin
  27. i:=Do_Write(t.Handle,t.Bufptr,t.BufPos);
  28. if i<>t.BufPos then
  29. InOutRes:=101;
  30. t.BufPos:=0;
  31. End;
  32. Procedure FileOpenFunc(var t:TextRec);
  33. var
  34. Flags : Longint;
  35. Begin
  36. Case t.mode Of
  37. fmInput : Flags:=$10000;
  38. fmOutput : Flags:=$11001;
  39. fmAppend : Flags:=$10101;
  40. else
  41. begin
  42. InOutRes:=102;
  43. exit;
  44. end;
  45. End;
  46. Do_Open(t,PChar(@t.Name),Flags);
  47. t.CloseFunc:=@FileCloseFunc;
  48. t.FlushFunc:=nil;
  49. if t.Mode=fmInput then
  50. t.InOutFunc:=@FileReadFunc
  51. else
  52. begin
  53. t.InOutFunc:=@FileWriteFunc;
  54. { Only install flushing if its a NOT a file, and only check if there
  55. was no error opening the file, becuase else we always get a bad
  56. file handle error 6 (PFV) }
  57. if (InOutRes=0) and
  58. Do_Isdevice(t.Handle) then
  59. t.FlushFunc:=@FileWriteFunc;
  60. end;
  61. End;
  62. Procedure assign(var t:Text;const s:String);
  63. Begin
  64. FillChar(t,SizeOf(TextRec),0);
  65. { only set things that are not zero }
  66. TextRec(t).Handle:=UnusedHandle;
  67. TextRec(t).mode:=fmClosed;
  68. TextRec(t).BufSize:=TextRecBufSize;
  69. TextRec(t).Bufptr:=@TextRec(t).Buffer;
  70. TextRec(t).OpenFunc:=@FileOpenFunc;
  71. Case DefaultTextLineBreakStyle Of
  72. tlbsLF: TextRec(t).LineEnd := #10;
  73. tlbsCRLF: TextRec(t).LineEnd := #13#10;
  74. tlbsCR: TextRec(t).LineEnd := #13;
  75. End;
  76. Move(s[1],TextRec(t).Name,Length(s));
  77. End;
  78. Procedure assign(var t:Text;p:pchar);
  79. begin
  80. Assign(t,StrPas(p));
  81. end;
  82. Procedure assign(var t:Text;c:char);
  83. begin
  84. Assign(t,string(c));
  85. end;
  86. Procedure Close(var t : Text);[IOCheck];
  87. Begin
  88. if InOutRes<>0 then
  89. Exit;
  90. case TextRec(t).mode of
  91. fmInput,fmOutPut,fmAppend:
  92. Begin
  93. { Write pending buffer }
  94. If Textrec(t).Mode=fmoutput then
  95. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  96. { Only close functions not connected to stdout.}
  97. If ((TextRec(t).Handle<>StdInputHandle) and
  98. (TextRec(t).Handle<>StdOutputHandle) and
  99. (TextRec(t).Handle<>StdErrorHandle)) Then
  100. FileFunc(TextRec(t).CloseFunc)(TextRec(t));
  101. TextRec(t).mode := fmClosed;
  102. { Reset buffer for safety }
  103. TextRec(t).BufPos:=0;
  104. TextRec(t).BufEnd:=0;
  105. End
  106. else inOutRes := 103;
  107. End;
  108. End;
  109. Procedure OpenText(var t : Text;mode,defHdl:Longint);
  110. Begin
  111. Case TextRec(t).mode Of {This gives the fastest code}
  112. fmInput,fmOutput,fmInOut : Close(t);
  113. fmClosed : ;
  114. else
  115. Begin
  116. InOutRes:=102;
  117. exit;
  118. End;
  119. End;
  120. TextRec(t).mode:=mode;
  121. TextRec(t).bufpos:=0;
  122. TextRec(t).bufend:=0;
  123. FileFunc(TextRec(t).OpenFunc)(TextRec(t));
  124. { reset the mode to closed when an error has occured }
  125. if InOutRes<>0 then
  126. TextRec(t).mode:=fmClosed;
  127. End;
  128. Procedure Rewrite(var t : Text);[IOCheck];
  129. Begin
  130. If InOutRes<>0 then
  131. exit;
  132. OpenText(t,fmOutput,1);
  133. End;
  134. Procedure Reset(var t : Text);[IOCheck];
  135. Begin
  136. If InOutRes<>0 then
  137. exit;
  138. OpenText(t,fmInput,0);
  139. End;
  140. Procedure Append(var t : Text);[IOCheck];
  141. Begin
  142. If InOutRes<>0 then
  143. exit;
  144. OpenText(t,fmAppend,1);
  145. End;
  146. Procedure Flush(var t : Text);[IOCheck];
  147. Begin
  148. If InOutRes<>0 then
  149. exit;
  150. if TextRec(t).mode<>fmOutput then
  151. begin
  152. if TextRec(t).mode=fmInput then
  153. InOutRes:=105
  154. else
  155. InOutRes:=103;
  156. exit;
  157. end;
  158. { Not the flushfunc but the inoutfunc should be used, becuase that
  159. writes the data, flushfunc doesn't need to be assigned }
  160. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  161. End;
  162. Procedure Erase(var t:Text);[IOCheck];
  163. Begin
  164. If InOutRes <> 0 then
  165. exit;
  166. If TextRec(t).mode=fmClosed Then
  167. Do_Erase(PChar(@TextRec(t).Name));
  168. End;
  169. Procedure Rename(var t : text;p:pchar);[IOCheck];
  170. Begin
  171. If InOutRes <> 0 then
  172. exit;
  173. If TextRec(t).mode=fmClosed Then
  174. Begin
  175. Do_Rename(PChar(@TextRec(t).Name),p);
  176. { check error code of do_rename }
  177. If InOutRes = 0 then
  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. Eof:=CtrlZMarksEOF and (TextRec(t).Bufptr^[TextRec(t).BufPos]=#26);
  220. end;
  221. Function Eof:Boolean;
  222. Begin
  223. Eof:=Eof(Input);
  224. End;
  225. Function SeekEof (Var t : Text) : Boolean;
  226. var
  227. oldfilepos, oldbufpos, oldbufend, reads: longint;
  228. isdevice: boolean;
  229. Begin
  230. If (InOutRes<>0) then
  231. exit(true);
  232. if (TextRec(t).mode<>fmInput) Then
  233. begin
  234. if TextRec(t).mode=fmOutPut then
  235. InOutRes:=104
  236. else
  237. InOutRes:=103;
  238. exit(true);
  239. end;
  240. { try to save the current position in the file, seekeof() should not move }
  241. { the current file position (JM) }
  242. oldbufpos := TextRec(t).BufPos;
  243. oldbufend := TextRec(t).BufEnd;
  244. reads := 0;
  245. oldfilepos := -1;
  246. isdevice := Do_IsDevice(TextRec(t).handle);
  247. repeat
  248. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  249. begin
  250. { signal that the we will have to do a seek }
  251. inc(reads);
  252. if not isdevice and
  253. (reads = 1) then
  254. begin
  255. oldfilepos := Do_FilePos(TextRec(t).handle) - TextRec(t).BufEnd;
  256. InOutRes:=0;
  257. end;
  258. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  259. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  260. begin
  261. { if we only did a read in which we didn't read anything, the }
  262. { old buffer is still valid and we can simply restore the }
  263. { pointers (JM) }
  264. dec(reads);
  265. SeekEof := true;
  266. break;
  267. end;
  268. end;
  269. case TextRec(t).Bufptr^[TextRec(t).BufPos] of
  270. #26 : if CtrlZMarksEOF then
  271. begin
  272. SeekEof := true;
  273. break;
  274. end;
  275. #10,#13,
  276. #9,' ' : ;
  277. else
  278. begin
  279. SeekEof := false;
  280. break;
  281. end;
  282. end;
  283. inc(TextRec(t).BufPos);
  284. until false;
  285. { restore file position if not working with a device }
  286. if not isdevice then
  287. { if we didn't modify the buffer, simply restore the BufPos and BufEnd }
  288. { (the latter becuase it's now probably set to zero because nothing was }
  289. { was read anymore) }
  290. if (reads = 0) then
  291. begin
  292. TextRec(t).BufPos:=oldbufpos;
  293. TextRec(t).BufEnd:=oldbufend;
  294. end
  295. { otherwise return to the old filepos and reset the buffer }
  296. else
  297. begin
  298. do_seek(TextRec(t).handle,oldfilepos);
  299. InOutRes:=0;
  300. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  301. TextRec(t).BufPos:=oldbufpos;
  302. end;
  303. End;
  304. Function SeekEof : Boolean;
  305. Begin
  306. SeekEof:=SeekEof(Input);
  307. End;
  308. Function Eoln(var t:Text) : Boolean;
  309. Begin
  310. If (InOutRes<>0) then
  311. exit(true);
  312. if (TextRec(t).mode<>fmInput) Then
  313. begin
  314. if TextRec(t).mode=fmOutPut then
  315. InOutRes:=104
  316. else
  317. InOutRes:=103;
  318. exit(true);
  319. end;
  320. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  321. begin
  322. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  323. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  324. exit(true);
  325. end;
  326. if CtrlZMarksEOF and (TextRec (T).BufPtr^[TextRec (T).BufPos] = #26) then
  327. exit (true);
  328. Eoln:=(TextRec(t).Bufptr^[TextRec(t).BufPos] in [#10,#13]);
  329. End;
  330. Function Eoln : Boolean;
  331. Begin
  332. Eoln:=Eoln(Input);
  333. End;
  334. Function SeekEoln (Var t : Text) : Boolean;
  335. Begin
  336. If (InOutRes<>0) then
  337. exit(true);
  338. if (TextRec(t).mode<>fmInput) Then
  339. begin
  340. if TextRec(t).mode=fmOutput then
  341. InOutRes:=104
  342. else
  343. InOutRes:=103;
  344. exit(true);
  345. end;
  346. repeat
  347. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  348. begin
  349. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  350. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  351. exit(true);
  352. end;
  353. case TextRec(t).Bufptr^[TextRec(t).BufPos] of
  354. #26: if CtrlZMarksEOF then
  355. exit (true);
  356. #10,#13 : exit(true);
  357. #9,' ' : ;
  358. else
  359. exit(false);
  360. end;
  361. inc(TextRec(t).BufPos);
  362. until false;
  363. End;
  364. Function SeekEoln : Boolean;
  365. Begin
  366. SeekEoln:=SeekEoln(Input);
  367. End;
  368. Procedure SetTextBuf(Var F : Text; Var Buf; Size : Longint);
  369. Begin
  370. TextRec(f).BufPtr:=@Buf;
  371. TextRec(f).BufSize:=Size;
  372. TextRec(f).BufPos:=0;
  373. TextRec(f).BufEnd:=0;
  374. End;
  375. Procedure SetTextLineEnding(Var f:Text; Ending:string);
  376. Begin
  377. TextRec(F).LineEnd:=Ending;
  378. End;
  379. Function fpc_get_input:PText;compilerproc;
  380. begin
  381. fpc_get_input:=@Input;
  382. end;
  383. Function fpc_get_output:PText;compilerproc;
  384. begin
  385. fpc_get_output:=@Output;
  386. end;
  387. {*****************************************************************************
  388. Write(Ln)
  389. *****************************************************************************}
  390. Procedure fpc_WriteBuffer(var f:Text;const b;len:longint);[Public,Alias:'FPC_WRITEBUFFER'];
  391. var
  392. p : pchar;
  393. left,
  394. idx : longint;
  395. begin
  396. p:=pchar(@b);
  397. idx:=0;
  398. left:=TextRec(f).BufSize-TextRec(f).BufPos;
  399. while len>left do
  400. begin
  401. move(p[idx],TextRec(f).Bufptr^[TextRec(f).BufPos],left);
  402. dec(len,left);
  403. inc(idx,left);
  404. inc(TextRec(f).BufPos,left);
  405. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  406. left:=TextRec(f).BufSize-TextRec(f).BufPos;
  407. end;
  408. move(p[idx],TextRec(f).Bufptr^[TextRec(f).BufPos],len);
  409. inc(TextRec(f).BufPos,len);
  410. end;
  411. Procedure fpc_WriteBlanks(var f:Text;len:longint);[Public,Alias:'FPC_WRITEBLANKS'];
  412. var
  413. left : longint;
  414. begin
  415. left:=TextRec(f).BufSize-TextRec(f).BufPos;
  416. while len>left do
  417. begin
  418. FillChar(TextRec(f).Bufptr^[TextRec(f).BufPos],left,' ');
  419. dec(len,left);
  420. inc(TextRec(f).BufPos,left);
  421. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  422. left:=TextRec(f).BufSize-TextRec(f).BufPos;
  423. end;
  424. FillChar(TextRec(f).Bufptr^[TextRec(f).BufPos],len,' ');
  425. inc(TextRec(f).BufPos,len);
  426. end;
  427. Procedure fpc_Write_End(var f:Text);[Public,Alias:'FPC_WRITE_END']; iocheck; compilerproc;
  428. begin
  429. if TextRec(f).FlushFunc<>nil then
  430. FileFunc(TextRec(f).FlushFunc)(TextRec(f));
  431. end;
  432. Procedure fpc_Writeln_End(var f:Text);[Public,Alias:'FPC_WRITELN_END']; iocheck; compilerproc;
  433. begin
  434. If InOutRes <> 0 then exit;
  435. case TextRec(f).mode of
  436. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  437. begin
  438. { Write EOL }
  439. fpc_WriteBuffer(f,TextRec(f).LineEnd[1],length(TextRec(f).LineEnd));
  440. { Flush }
  441. if TextRec(f).FlushFunc<>nil then
  442. FileFunc(TextRec(f).FlushFunc)(TextRec(f));
  443. end;
  444. fmInput: InOutRes:=105
  445. else InOutRes:=103;
  446. end;
  447. end;
  448. Procedure fpc_Write_Text_ShortStr(Len : Longint;var f : Text;const s : String); iocheck; [Public,Alias:'FPC_WRITE_TEXT_SHORTSTR']; compilerproc;
  449. Begin
  450. If (InOutRes<>0) then
  451. exit;
  452. case TextRec(f).mode of
  453. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  454. begin
  455. If Len>Length(s) Then
  456. fpc_WriteBlanks(f,Len-Length(s));
  457. fpc_WriteBuffer(f,s[1],Length(s));
  458. end;
  459. fmInput: InOutRes:=105
  460. else InOutRes:=103;
  461. end;
  462. End;
  463. { provide local access to write_str }
  464. procedure Write_Str(Len : Longint;var f : Text;const s : String); iocheck; [external name 'FPC_WRITE_TEXT_SHORTSTR'];
  465. Procedure fpc_Write_Text_Pchar_as_Array(Len : Longint;var f : Text;const s : array of char); iocheck; [Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_ARRAY']; compilerproc;
  466. var
  467. ArrayLen : longint;
  468. p : pchar;
  469. Begin
  470. If (InOutRes<>0) then
  471. exit;
  472. case TextRec(f).mode of
  473. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  474. begin
  475. p:=pchar(@s);
  476. { can't use StrLen, since that one could try to read past the end }
  477. { of the heap (JM) }
  478. ArrayLen:=IndexByte(p^,high(s)+1,0);
  479. { IndexByte returns -1 if not found (JM) }
  480. if ArrayLen = -1 then
  481. ArrayLen := high(s)+1;
  482. If Len>ArrayLen Then
  483. fpc_WriteBlanks(f,Len-ArrayLen);
  484. fpc_WriteBuffer(f,p^,ArrayLen);
  485. end;
  486. fmInput: InOutRes:=105
  487. else InOutRes:=103;
  488. end;
  489. End;
  490. Procedure fpc_Write_Text_PChar_As_Pointer(Len : Longint;var f : Text;p : PChar); iocheck; [Public,Alias:'FPC_WRITE_TEXT_PCHAR_AS_POINTER']; compilerproc;
  491. var
  492. PCharLen : longint;
  493. Begin
  494. If (p=nil) or (InOutRes<>0) then
  495. exit;
  496. case TextRec(f).mode of
  497. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  498. begin
  499. PCharLen:=StrLen(p);
  500. If Len>PCharLen Then
  501. fpc_WriteBlanks(f,Len-PCharLen);
  502. fpc_WriteBuffer(f,p^,PCharLen);
  503. end;
  504. fmInput: InOutRes:=105
  505. else InOutRes:=103;
  506. end;
  507. End;
  508. Procedure fpc_Write_Text_AnsiStr (Len : Longint; Var f : Text; S : AnsiString); iocheck; [Public,alias:'FPC_WRITE_TEXT_ANSISTR']; compilerproc;
  509. {
  510. Writes a AnsiString to the Text file T
  511. }
  512. var
  513. SLen : longint;
  514. begin
  515. If (InOutRes<>0) then
  516. exit;
  517. case TextRec(f).mode of
  518. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  519. begin
  520. SLen:=Length(s);
  521. If Len>SLen Then
  522. fpc_WriteBlanks(f,Len-SLen);
  523. if slen > 0 then
  524. fpc_WriteBuffer(f,PChar(S)^,SLen);
  525. end;
  526. fmInput: InOutRes:=105
  527. else InOutRes:=103;
  528. end;
  529. end;
  530. Procedure fpc_Write_Text_WideStr (Len : Longint; Var f : Text; S : WideString); iocheck; [Public,alias:'FPC_WRITE_TEXT_WIDESTR']; compilerproc;
  531. {
  532. Writes a WideString to the Text file T
  533. }
  534. var
  535. SLen : longint;
  536. begin
  537. If (pointer(S)=nil) or (InOutRes<>0) then
  538. exit;
  539. case TextRec(f).mode of
  540. fmOutput { fmAppend gets changed to fmOutPut in do_open (JM) }:
  541. begin
  542. SLen:=Length(s);
  543. If Len>SLen Then
  544. fpc_WriteBlanks(f,Len-SLen);
  545. fpc_WriteBuffer(f,PChar(AnsiString(S))^,SLen);
  546. end;
  547. fmInput: InOutRes:=105
  548. else InOutRes:=103;
  549. end;
  550. end;
  551. Procedure fpc_Write_Text_SInt(Len : Longint;var t : Text;l : ValSInt); iocheck; [Public,Alias:'FPC_WRITE_TEXT_SINT']; compilerproc;
  552. var
  553. s : String;
  554. Begin
  555. If (InOutRes<>0) then
  556. exit;
  557. Str(l,s);
  558. Write_Str(Len,t,s);
  559. End;
  560. Procedure fpc_Write_Text_UInt(Len : Longint;var t : Text;l : ValUInt); iocheck; [Public,Alias:'FPC_WRITE_TEXT_UINT']; compilerproc;
  561. var
  562. s : String;
  563. Begin
  564. If (InOutRes<>0) then
  565. exit;
  566. Str(L,s);
  567. Write_Str(Len,t,s);
  568. End;
  569. {$ifndef CPU64}
  570. procedure fpc_write_text_qword(len : longint;var t : text;q : qword); iocheck; [public,alias:'FPC_WRITE_TEXT_QWORD']; compilerproc;
  571. var
  572. s : string;
  573. begin
  574. if (InOutRes<>0) then
  575. exit;
  576. str(q,s);
  577. write_str(len,t,s);
  578. end;
  579. procedure fpc_write_text_int64(len : longint;var t : text;i : int64); iocheck; [public,alias:'FPC_WRITE_TEXT_INT64']; compilerproc;
  580. var
  581. s : string;
  582. begin
  583. if (InOutRes<>0) then
  584. exit;
  585. str(i,s);
  586. write_str(len,t,s);
  587. end;
  588. {$endif CPU64}
  589. Procedure fpc_Write_Text_Float(rt,fixkomma,Len : Longint;var t : Text;r : ValReal); iocheck; [Public,Alias:'FPC_WRITE_TEXT_FLOAT']; compilerproc;
  590. var
  591. s : String;
  592. Begin
  593. If (InOutRes<>0) then
  594. exit;
  595. Str_real(Len,fixkomma,r,treal_type(rt),s);
  596. Write_Str(Len,t,s);
  597. End;
  598. Procedure fpc_Write_Text_Boolean(Len : Longint;var t : Text;b : Boolean); iocheck; [Public,Alias:'FPC_WRITE_TEXT_BOOLEAN']; compilerproc;
  599. Begin
  600. If (InOutRes<>0) then
  601. exit;
  602. { Can't use array[boolean] because b can be >0 ! }
  603. if b then
  604. Write_Str(Len,t,'TRUE')
  605. else
  606. Write_Str(Len,t,'FALSE');
  607. End;
  608. Procedure fpc_Write_Text_Char(Len : Longint;var t : Text;c : Char); iocheck; [Public,Alias:'FPC_WRITE_TEXT_CHAR']; compilerproc;
  609. Begin
  610. If (InOutRes<>0) then
  611. exit;
  612. if (TextRec(t).mode<>fmOutput) Then
  613. begin
  614. if TextRec(t).mode=fmClosed then
  615. InOutRes:=103
  616. else
  617. InOutRes:=105;
  618. exit;
  619. end;
  620. If Len>1 Then
  621. fpc_WriteBlanks(t,Len-1);
  622. If TextRec(t).BufPos+1>=TextRec(t).BufSize Then
  623. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  624. TextRec(t).Bufptr^[TextRec(t).BufPos]:=c;
  625. Inc(TextRec(t).BufPos);
  626. End;
  627. Procedure fpc_Write_Text_WideChar(Len : Longint;var t : Text;c : WideChar); iocheck; [Public,Alias:'FPC_WRITE_TEXT_WIDECHAR']; compilerproc;
  628. var
  629. ch : char;
  630. Begin
  631. If (InOutRes<>0) then
  632. exit;
  633. if (TextRec(t).mode<>fmOutput) Then
  634. begin
  635. if TextRec(t).mode=fmClosed then
  636. InOutRes:=103
  637. else
  638. InOutRes:=105;
  639. exit;
  640. end;
  641. If Len>1 Then
  642. fpc_WriteBlanks(t,Len-1);
  643. If TextRec(t).BufPos+1>=TextRec(t).BufSize Then
  644. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  645. ch:=c;
  646. TextRec(t).Bufptr^[TextRec(t).BufPos]:=ch;
  647. Inc(TextRec(t).BufPos);
  648. End;
  649. {*****************************************************************************
  650. Read(Ln)
  651. *****************************************************************************}
  652. Function NextChar(var f:Text;var s:string):Boolean;
  653. begin
  654. NextChar:=false;
  655. if (TextRec(f).BufPos<TextRec(f).BufEnd) then
  656. if not (CtrlZMarksEOF) or (TextRec(f).Bufptr^[TextRec(f).BufPos]<>#26) then
  657. begin
  658. if length(s)<high(s) then
  659. begin
  660. inc(s[0]);
  661. s[length(s)]:=TextRec(f).BufPtr^[TextRec(f).BufPos];
  662. end;
  663. Inc(TextRec(f).BufPos);
  664. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  665. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  666. NextChar:=true;
  667. end;
  668. end;
  669. Function IgnoreSpaces(var f:Text):Boolean;
  670. {
  671. Removes all leading spaces,tab,eols from the input buffer, returns true if
  672. the buffer is empty
  673. }
  674. var
  675. s : string;
  676. begin
  677. s:='';
  678. IgnoreSpaces:=false;
  679. { Return false when already at EOF }
  680. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  681. exit;
  682. (* Check performed separately to avoid accessing memory outside buffer *)
  683. if CtrlZMarksEOF and (TextRec(f).Bufptr^[TextRec(f).BufPos]=#26) then
  684. exit;
  685. while (TextRec(f).Bufptr^[TextRec(f).BufPos] <= ' ') do
  686. begin
  687. if not NextChar(f,s) then
  688. exit;
  689. { EOF? }
  690. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  691. break;
  692. if CtrlZMarksEOF and (TextRec(f).Bufptr^[TextRec(f).BufPos]=#26) then
  693. break;
  694. end;
  695. IgnoreSpaces:=true;
  696. end;
  697. procedure ReadNumeric(var f:Text;var s:string);
  698. {
  699. Read numeric input, if buffer is empty then return True
  700. }
  701. begin
  702. repeat
  703. if not NextChar(f,s) then
  704. exit;
  705. until (length(s)=high(s)) or (TextRec(f).BufPtr^[TextRec(f).BufPos] <= ' ');
  706. end;
  707. Procedure fpc_Read_End(var f:Text);[Public,Alias:'FPC_READ_END']; iocheck; compilerproc;
  708. begin
  709. if TextRec(f).FlushFunc<>nil then
  710. FileFunc(TextRec(f).FlushFunc)(TextRec(f));
  711. end;
  712. Procedure fpc_ReadLn_End(var f : Text);[Public,Alias:'FPC_READLN_END']; iocheck; compilerproc;
  713. var prev: char;
  714. Begin
  715. { Check error and if file is open and load buf if empty }
  716. If (InOutRes<>0) then
  717. exit;
  718. if (TextRec(f).mode<>fmInput) Then
  719. begin
  720. case TextRec(f).mode of
  721. fmOutPut,fmAppend:
  722. InOutRes:=104
  723. else
  724. InOutRes:=103;
  725. end;
  726. exit;
  727. end;
  728. if TextRec(f).BufPos>=TextRec(f).BufEnd Then
  729. begin
  730. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  731. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  732. { Flush if set }
  733. begin
  734. if (TextRec(f).FlushFunc<>nil) then
  735. FileFunc(TextRec(f).FlushFunc)(TextRec(f));
  736. exit;
  737. end;
  738. end;
  739. if CtrlZMarksEOF and (TextRec (F).BufPtr^ [TextRec (F).BufPos] = #26) then
  740. Exit;
  741. repeat
  742. prev := TextRec(f).BufPtr^[TextRec(f).BufPos];
  743. inc(TextRec(f).BufPos);
  744. { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
  745. { #13#10 = Dos), so if we've got #10, we can safely exit }
  746. if prev = #10 then
  747. exit;
  748. {$ifdef MACOS}
  749. if prev = #13 then
  750. {StdInput on macos never have dos line ending, so this is safe.}
  751. if TextRec(f).Handle = StdInputHandle then
  752. exit;
  753. {$endif MACOS}
  754. if TextRec(f).BufPos>=TextRec(f).BufEnd Then
  755. begin
  756. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  757. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  758. { Flush if set }
  759. begin
  760. if (TextRec(f).FlushFunc<>nil) then
  761. FileFunc(TextRec(f).FlushFunc)(TextRec(f));
  762. exit;
  763. end;
  764. end;
  765. if CtrlZMarksEOF and (TextRec (F).BufPtr^ [TextRec (F).BufPos] = #26) then
  766. Exit;
  767. if (prev=#13) then
  768. { is there also a #10 after it? }
  769. begin
  770. if (TextRec(f).BufPtr^[TextRec(f).BufPos]=#10) then
  771. { yes, skip that one as well }
  772. inc(TextRec(f).BufPos);
  773. exit;
  774. end;
  775. until false;
  776. End;
  777. Function ReadPCharLen(var f:Text;s:pchar;maxlen:longint):longint;
  778. var
  779. sPos,len : Longint;
  780. p,startp,maxp : pchar;
  781. Begin
  782. ReadPCharLen:=0;
  783. { Check error and if file is open }
  784. If (InOutRes<>0) then
  785. exit;
  786. if (TextRec(f).mode<>fmInput) Then
  787. begin
  788. case TextRec(f).mode of
  789. fmOutPut,fmAppend:
  790. InOutRes:=104
  791. else
  792. InOutRes:=103;
  793. end;
  794. exit;
  795. end;
  796. { Read maximal until Maxlen is reached }
  797. sPos:=0;
  798. repeat
  799. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  800. begin
  801. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  802. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  803. break;
  804. end;
  805. p:=@TextRec(f).Bufptr^[TextRec(f).BufPos];
  806. if SPos+TextRec(f).BufEnd-TextRec(f).BufPos>MaxLen then
  807. maxp:=@TextRec(f).BufPtr^[TextRec(f).BufPos+MaxLen-SPos]
  808. else
  809. maxp:=@TextRec(f).Bufptr^[TextRec(f).BufEnd];
  810. startp:=p;
  811. { search linefeed }
  812. while (p<maxp) and not(P^ in [#10,#13]) do
  813. inc(p);
  814. { calculate read bytes }
  815. len:=p-startp;
  816. inc(TextRec(f).BufPos,Len);
  817. Move(startp^,s[sPos],Len);
  818. inc(sPos,Len);
  819. { was it a LF or CR? then leave }
  820. if (spos=MaxLen) or
  821. ((p<maxp) and (p^ in [#10,#13])) then
  822. break;
  823. until false;
  824. ReadPCharLen:=spos;
  825. End;
  826. Procedure fpc_Read_Text_ShortStr(var f : Text;out s : String); iocheck; [Public,Alias:'FPC_READ_TEXT_SHORTSTR']; compilerproc;
  827. Begin
  828. s[0]:=chr(ReadPCharLen(f,pchar(@s[1]),high(s)));
  829. End;
  830. Procedure fpc_Read_Text_PChar_As_Pointer(var f : Text;out s : PChar); iocheck; [Public,Alias:'FPC_READ_TEXT_PCHAR_AS_POINTER']; compilerproc;
  831. Begin
  832. pchar(s+ReadPCharLen(f,s,$7fffffff))^:=#0;
  833. End;
  834. Procedure fpc_Read_Text_PChar_As_Array(var f : Text;out s : array of char); iocheck; [Public,Alias:'FPC_READ_TEXT_PCHAR_AS_ARRAY']; compilerproc;
  835. var
  836. len: longint;
  837. Begin
  838. len := ReadPCharLen(f,pchar(@s),high(s)+1);
  839. if len <= high(s) then
  840. s[len] := #0;
  841. End;
  842. Procedure fpc_Read_Text_AnsiStr(var f : Text;out s : AnsiString); iocheck; [Public,Alias:'FPC_READ_TEXT_ANSISTR']; compilerproc;
  843. var
  844. slen,len : longint;
  845. Begin
  846. slen:=0;
  847. Repeat
  848. // SetLength will reallocate the length.
  849. SetLength(S,slen+255);
  850. len:=ReadPCharLen(f,pchar(Pointer(S)+slen),255);
  851. inc(slen,len);
  852. Until len<255;
  853. // Set actual length
  854. SetLength(S,Slen);
  855. End;
  856. procedure fpc_Read_Text_Char(var f : Text; out c: char); iocheck; [Public,Alias:'FPC_READ_TEXT_CHAR'];compilerproc;
  857. Begin
  858. c:=#0;
  859. { Check error and if file is open }
  860. If (InOutRes<>0) then
  861. exit;
  862. if (TextRec(f).mode<>fmInput) Then
  863. begin
  864. case TextRec(f).mode of
  865. fmOutPut,fmAppend:
  866. InOutRes:=104
  867. else
  868. InOutRes:=103;
  869. end;
  870. exit;
  871. end;
  872. { Read next char or EOF }
  873. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  874. begin
  875. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  876. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  877. begin
  878. c := #26;
  879. exit;
  880. end;
  881. end;
  882. c:=TextRec(f).Bufptr^[TextRec(f).BufPos];
  883. inc(TextRec(f).BufPos);
  884. end;
  885. Procedure fpc_Read_Text_SInt(var f : Text; out l : ValSInt); iocheck; [Public,Alias:'FPC_READ_TEXT_SINT']; compilerproc;
  886. var
  887. hs : String;
  888. code : longint;
  889. Begin
  890. l:=0;
  891. { Leave if error or not open file, else check for empty buf }
  892. If (InOutRes<>0) then
  893. exit;
  894. if (TextRec(f).mode<>fmInput) Then
  895. begin
  896. case TextRec(f).mode of
  897. fmOutPut,fmAppend:
  898. InOutRes:=104
  899. else
  900. InOutRes:=103;
  901. end;
  902. exit;
  903. end;
  904. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  905. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  906. hs:='';
  907. if IgnoreSpaces(f) then
  908. begin
  909. { When spaces were found and we are now at EOF,
  910. then we return 0 }
  911. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  912. exit;
  913. if CtrlZMarksEOF and (TextRec(f).Bufptr^[TextRec(f).BufPos]=#26) then
  914. exit;
  915. ReadNumeric(f,hs);
  916. end;
  917. if (hs = '') then
  918. L := 0
  919. else
  920. begin
  921. Val(hs,l,code);
  922. if Code <> 0 then
  923. InOutRes:=106;
  924. end;
  925. End;
  926. Procedure fpc_Read_Text_UInt(var f : Text; out u : ValUInt); iocheck; [Public,Alias:'FPC_READ_TEXT_UINT']; compilerproc;
  927. var
  928. hs : String;
  929. code : longint;
  930. Begin
  931. u:=0;
  932. { Leave if error or not open file, else check for empty buf }
  933. If (InOutRes<>0) then
  934. exit;
  935. if (TextRec(f).mode<>fmInput) Then
  936. begin
  937. case TextRec(f).mode of
  938. fmOutPut,fmAppend:
  939. InOutRes:=104
  940. else
  941. InOutRes:=103;
  942. end;
  943. exit;
  944. end;
  945. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  946. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  947. hs:='';
  948. if IgnoreSpaces(f) then
  949. begin
  950. { When spaces were found and we are now at EOF,
  951. then we return 0 }
  952. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  953. exit;
  954. ReadNumeric(f,hs);
  955. end;
  956. val(hs,u,code);
  957. If code<>0 Then
  958. InOutRes:=106;
  959. End;
  960. procedure fpc_Read_Text_Float(var f : Text; out v : ValReal); iocheck; [Public,Alias:'FPC_READ_TEXT_FLOAT']; compilerproc;
  961. var
  962. hs : string;
  963. code : Word;
  964. begin
  965. v:=0.0;
  966. { Leave if error or not open file, else check for empty buf }
  967. If (InOutRes<>0) then
  968. exit;
  969. if (TextRec(f).mode<>fmInput) Then
  970. begin
  971. case TextRec(f).mode of
  972. fmOutPut,fmAppend:
  973. InOutRes:=104
  974. else
  975. InOutRes:=103;
  976. end;
  977. exit;
  978. end;
  979. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  980. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  981. hs:='';
  982. if IgnoreSpaces(f) then
  983. begin
  984. { When spaces were found and we are now at EOF,
  985. then we return 0 }
  986. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  987. exit;
  988. ReadNumeric(f,hs);
  989. end;
  990. val(hs,v,code);
  991. If code<>0 Then
  992. InOutRes:=106;
  993. end;
  994. {$ifndef cpu64}
  995. procedure fpc_Read_Text_QWord(var f : text; out q : qword); iocheck; [public,alias:'FPC_READ_TEXT_QWORD']; compilerproc;
  996. var
  997. hs : String;
  998. code : longint;
  999. Begin
  1000. q:=0;
  1001. { Leave if error or not open file, else check for empty buf }
  1002. If (InOutRes<>0) then
  1003. exit;
  1004. if (TextRec(f).mode<>fmInput) Then
  1005. begin
  1006. case TextRec(f).mode of
  1007. fmOutPut,fmAppend:
  1008. InOutRes:=104
  1009. else
  1010. InOutRes:=103;
  1011. end;
  1012. exit;
  1013. end;
  1014. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  1015. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  1016. hs:='';
  1017. if IgnoreSpaces(f) then
  1018. begin
  1019. { When spaces were found and we are now at EOF,
  1020. then we return 0 }
  1021. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  1022. exit;
  1023. ReadNumeric(f,hs);
  1024. end;
  1025. val(hs,q,code);
  1026. If code<>0 Then
  1027. InOutRes:=106;
  1028. End;
  1029. procedure fpc_Read_Text_Int64(var f : text; out i : int64); iocheck; [public,alias:'FPC_READ_TEXT_INT64']; compilerproc;
  1030. var
  1031. hs : String;
  1032. code : Longint;
  1033. Begin
  1034. i:=0;
  1035. { Leave if error or not open file, else check for empty buf }
  1036. If (InOutRes<>0) then
  1037. exit;
  1038. if (TextRec(f).mode<>fmInput) Then
  1039. begin
  1040. case TextRec(f).mode of
  1041. fmOutPut,fmAppend:
  1042. InOutRes:=104
  1043. else
  1044. InOutRes:=103;
  1045. end;
  1046. exit;
  1047. end;
  1048. If TextRec(f).BufPos>=TextRec(f).BufEnd Then
  1049. FileFunc(TextRec(f).InOutFunc)(TextRec(f));
  1050. hs:='';
  1051. if IgnoreSpaces(f) then
  1052. begin
  1053. { When spaces were found and we are now at EOF,
  1054. then we return 0 }
  1055. if (TextRec(f).BufPos>=TextRec(f).BufEnd) then
  1056. exit;
  1057. ReadNumeric(f,hs);
  1058. end;
  1059. Val(hs,i,code);
  1060. If code<>0 Then
  1061. InOutRes:=106;
  1062. End;
  1063. {$endif CPU64}
  1064. {*****************************************************************************
  1065. Initializing
  1066. *****************************************************************************}
  1067. procedure OpenStdIO(var f:text;mode,hdl:longint);
  1068. begin
  1069. Assign(f,'');
  1070. TextRec(f).Handle:=hdl;
  1071. TextRec(f).Mode:=mode;
  1072. TextRec(f).Closefunc:=@FileCloseFunc;
  1073. case mode of
  1074. fmInput :
  1075. TextRec(f).InOutFunc:=@FileReadFunc;
  1076. fmOutput :
  1077. begin
  1078. TextRec(f).InOutFunc:=@FileWriteFunc;
  1079. TextRec(f).FlushFunc:=@FileWriteFunc;
  1080. end;
  1081. else
  1082. HandleError(102);
  1083. end;
  1084. end;