text.inc 29 KB

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