text.inc 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Run time library.
  4. Copyright (c) 1993,97 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. EXTENDED_EOF Use extended EOF checking for textfile, necessary for
  14. Pipes and Sockets under Linux
  15. EOF_CTRLZ Is Ctrl-Z (#26) a EOF mark for textfiles
  16. SHORT_LINEBREAK Use short Linebreaks #10 instead of #10#13
  17. Both EXTENDED_EOF and SHORT_LINEBREAK are defined in the Linux system
  18. unit (syslinux.pp)
  19. }
  20. {****************************************************************************
  21. subroutines For TextFile handling
  22. ****************************************************************************}
  23. Procedure FileCloseFunc(Var t:TextRec);
  24. Begin
  25. Do_Close(t.Handle);
  26. t.Handle:=UnusedHandle;
  27. End;
  28. Procedure FileReadFunc(var t:TextRec);
  29. Begin
  30. t.BufEnd:=Do_Read(t.Handle,Longint(t.Bufptr),t.BufSize);
  31. t.BufPos:=0;
  32. End;
  33. Procedure FileWriteFunc(var t:TextRec);
  34. Begin
  35. Do_Write(t.Handle,Longint(t.Bufptr),t.BufPos);
  36. t.BufPos:=0;
  37. End;
  38. Procedure FileOpenFunc(var t:TextRec);
  39. var
  40. Flags : Longint;
  41. Begin
  42. Case t.mode Of
  43. fmInput : Flags:=$1000;
  44. fmOutput : Flags:=$1101;
  45. fmAppend : Flags:=$1011;
  46. else
  47. RunError(102);
  48. End;
  49. Do_Open(t,PChar(@t.Name),Flags);
  50. t.CloseFunc:=@FileCloseFunc;
  51. t.FlushFunc:=nil;
  52. if t.Mode=fmInput then
  53. t.InOutFunc:=@FileReadFunc
  54. else
  55. begin
  56. t.InOutFunc:=@FileWriteFunc;
  57. { Only install flushing if its a NOT a file }
  58. if 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:=128;
  69. TextRec(t).Bufptr:=@TextRec(t).Buffer;
  70. TextRec(t).OpenFunc:=@FileOpenFunc;
  71. Move(s[1],TextRec(t).Name,Length(s));
  72. End;
  73. Procedure assign(var t:Text;p:pchar);
  74. begin
  75. Assign(t,StrPas(p));
  76. end;
  77. Procedure assign(var t:Text;c:char);
  78. begin
  79. Assign(t,string(c));
  80. end;
  81. Procedure Close(var t : Text);[Public,Alias: 'CLOSE_TEXT',IOCheck];
  82. Begin
  83. if InOutRes <> 0 then Exit;
  84. If (TextRec(t).mode<>fmClosed) Then
  85. Begin
  86. { Write pending buffer }
  87. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  88. TextRec(t).mode:=fmClosed;
  89. { Only close functions not connected to stdout.}
  90. If ((TextRec(t).Handle<>StdInputHandle) or
  91. (TextRec(t).Handle<>StdOutputHandle) or
  92. (TextRec(t).Handle<>StdErrorHandle)) Then
  93. FileFunc(TextRec(t).CloseFunc)(TextRec(t));
  94. End;
  95. End;
  96. Procedure OpenText(var t : Text;mode,defHdl:Longint);
  97. Begin
  98. Case TextRec(t).mode Of {This gives the fastest code}
  99. fmInput,fmOutput,fmInOut : Close(t);
  100. fmClosed : ;
  101. else
  102. Begin
  103. InOutRes:=102;
  104. exit;
  105. End;
  106. End;
  107. TextRec(t).mode:=word(mode);
  108. FileFunc(TextRec(t).OpenFunc)(TextRec(t))
  109. End;
  110. Procedure Rewrite(var t : Text);[IOCheck];
  111. Begin
  112. If InOutRes <> 0 then exit;
  113. OpenText(t,fmOutput,1);
  114. End;
  115. Procedure Reset(var t : Text);[IOCheck];
  116. Begin
  117. If InOutRes <> 0 then exit;
  118. OpenText(t,fmInput,0);
  119. End;
  120. Procedure Append(var t : Text);[IOCheck];
  121. Begin
  122. If InOutRes <> 0 then exit;
  123. OpenText(t,fmAppend,1);
  124. End;
  125. Procedure Flush(var t : Text);[IOCheck];
  126. Begin
  127. If InOutRes <> 0 then exit;
  128. If TextRec(t).mode<>fmOutput Then
  129. exit;
  130. { Not the flushfunc but the inoutfunc should be used, becuase that
  131. writes the data, flushfunc doesn't need to be assigned }
  132. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  133. End;
  134. Procedure Erase(var t:Text);[IOCheck];
  135. Begin
  136. If InOutRes <> 0 then exit;
  137. If TextRec(t).mode=fmClosed Then
  138. Do_Erase(PChar(@TextRec(t).Name));
  139. End;
  140. Procedure Rename(var t : text;p:pchar);[IOCheck];
  141. Begin
  142. If InOutRes <> 0 then exit;
  143. If TextRec(t).mode=fmClosed Then
  144. Begin
  145. Do_Rename(PChar(@TextRec(t).Name),p);
  146. Move(p,TextRec(t).Name,StrLen(p)+1);
  147. End;
  148. End;
  149. Procedure Rename(var t : Text;const s : string);[IOCheck];
  150. var
  151. p : array[0..255] Of Char;
  152. Begin
  153. If InOutRes <> 0 then exit;
  154. Move(s[1],p,Length(s));
  155. p[Length(s)]:=#0;
  156. Rename(t,Pchar(@p));
  157. End;
  158. Procedure Rename(var t : Text;c : char);[IOCheck];
  159. var
  160. p : array[0..1] Of Char;
  161. Begin
  162. If InOutRes <> 0 then exit;
  163. p[0]:=c;
  164. p[1]:=#0;
  165. Rename(t,Pchar(@p));
  166. End;
  167. Function Eof(Var t: Text): Boolean;[IOCheck];
  168. Begin
  169. If InOutRes <> 0 then exit;
  170. {$IFNDEF EXTENDED_EOF}
  171. {$IFDEF EOF_CTRLZ}
  172. Eof:=TextRec(t).Buffer[TextRec(t).BufPos]=#26;
  173. If Eof Then
  174. Exit;
  175. {$ENDIF EOL_CTRLZ}
  176. Eof:=(Do_FileSize(TextRec(t).Handle)<=Do_FilePos(TextRec(t).Handle));
  177. If Eof Then
  178. Eof:=TextRec(t).BufEnd <= TextRec(t).BufPos;
  179. {$ELSE EXTENDED_EOF}
  180. { The previous method will NOT work on stdin and pipes or sockets.
  181. So how to do it ?
  182. 1) Check if characters in buffer - Yes ? Eof=false;
  183. 2) Read buffer full. If 0 Chars Read : Eof !
  184. Michael.}
  185. If TextRec(T).mode=fmClosed Then { Sanity Check }
  186. Begin
  187. Eof:=True;
  188. Exit;
  189. End;
  190. If (TextRec(T).BufPos < TextRec(T).BufEnd) Then
  191. Begin
  192. Eof:=False;
  193. Exit
  194. End;
  195. TextRec(T).BufPos:=0;
  196. TextRec(T).BufEnd:=Do_Read(TextRec(T).Handle,Longint(TextRec(T).BufPtr),TextRec(T).BufSize);
  197. If TextRec(T).BufEnd<0 Then
  198. TextRec(T).BufEnd:=0;
  199. Eof:=(TextRec(T).BufEnd=0);
  200. {$ENDIF EXTENDED_EOF}
  201. End;
  202. Function Eof:Boolean;
  203. Begin
  204. Eof:=Eof(Input);
  205. End;
  206. Function SeekEof (Var F : Text) : Boolean;
  207. Var
  208. TR : ^TextRec;
  209. Temp : Longint;
  210. Begin
  211. TR:=@TextRec(f);
  212. If TR^.mode<>fmInput Then exit (true);
  213. SeekEof:=True;
  214. {No data in buffer ? Fill it }
  215. If TR^.BufPos>=TR^.BufEnd Then
  216. FileFunc(TR^.InOutFunc)(TR^);
  217. Temp:=TR^.BufPos;
  218. while (TR^.BufPos<TR^.BufEnd) Do
  219. Begin
  220. If (TR^.Bufptr^[Temp] In [#9,#10,#13,' ']) Then
  221. Inc(Temp)
  222. else
  223. Begin
  224. SeekEof:=False;
  225. TR^.BufPos:=Temp;
  226. exit;
  227. End;
  228. If Temp>=TR^.BufEnd Then
  229. Begin
  230. FileFunc(TR^.InOutFunc)(TR^);
  231. Temp:=TR^.BufPos+1;
  232. End;
  233. End;
  234. End;
  235. Function SeekEof : Boolean;
  236. Begin
  237. SeekEof:=SeekEof(Input);
  238. End;
  239. Function Eoln(var t:Text) : Boolean;
  240. Begin
  241. { maybe we need new data }
  242. If TextRec(t).BufPos>=TextRec(t).BufEnd Then
  243. FileFunc(TextRec(t).InOutFunc)(TextRec(t));
  244. Eoln:=Eof(t) or (TextRec(t).Bufptr^[TextRec(t).BufPos] In [#10,#13]);
  245. End;
  246. Function Eoln : Boolean;
  247. Begin
  248. Eoln:=Eoln(Input);
  249. End;
  250. Function SeekEoln (Var F : Text) : Boolean;
  251. Var
  252. TR : ^TextRec;
  253. Temp : Longint;
  254. Begin
  255. TR:=@TextRec(f);
  256. If TR^.mode<>fmInput Then
  257. exit (true);
  258. SeekEoln:=True;
  259. {No data in buffer ? Fill it }
  260. If TR^.BufPos>=TR^.BufEnd Then
  261. FileFunc(TR^.InOutFunc)(TR^);
  262. Temp:=TR^.BufPos;
  263. while (TR^.BufPos<TR^.BufEnd) Do
  264. Begin
  265. Case (TR^.Bufptr^[Temp]) Of
  266. #10 : Exit;
  267. #9,' ' : Inc(Temp)
  268. else
  269. Begin
  270. SeekEoln:=False;
  271. TR^.BufPos:=Temp;
  272. exit;
  273. End;
  274. End;
  275. If Temp>=TR^.BufEnd Then
  276. Begin
  277. FileFunc(TR^.InOutFunc)(TR^);
  278. Temp:=TR^.BufPos+1;
  279. End;
  280. End;
  281. End;
  282. Function SeekEoln : Boolean;
  283. Begin
  284. SeekEoln:=SeekEoln(Input);
  285. End;
  286. Procedure SetTextBuf(Var F : Text; Var Buf);[INTERNPROC: In_settextbuf_file_x];
  287. Procedure SetTextBuf(Var F : Text; Var Buf; Size : Word);
  288. Begin
  289. TextRec(f).BufPtr:=@Buf;
  290. TextRec(f).BufSize:=Size;
  291. TextRec(f).BufPos:=0;
  292. TextRec(f).BufEnd:=0;
  293. End;
  294. {*****************************************************************************
  295. Write(Ln)
  296. *****************************************************************************}
  297. Procedure WriteBuffer(var f:TextRec;var b;len:longint);
  298. var
  299. p : pchar;
  300. left,
  301. idx : longint;
  302. begin
  303. p:=pchar(@b);
  304. idx:=0;
  305. left:=f.BufSize-f.BufPos;
  306. while len>left do
  307. begin
  308. move(p[idx],f.Bufptr^[f.BufPos],left);
  309. dec(len,left);
  310. inc(idx,left);
  311. inc(f.BufPos,left);
  312. FileFunc(f.InOutFunc)(f);
  313. left:=f.BufSize-f.BufPos;
  314. end;
  315. move(p[idx],f.Bufptr^[f.BufPos],len);
  316. inc(f.BufPos,len);
  317. end;
  318. Procedure WriteBlanks(var f:TextRec;len:longint);
  319. var
  320. left : longint;
  321. begin
  322. left:=f.BufSize-f.BufPos;
  323. while len>left do
  324. begin
  325. FillChar(f.Bufptr^[f.BufPos],left,' ');
  326. dec(len,left);
  327. inc(f.BufPos,left);
  328. FileFunc(f.InOutFunc)(f);
  329. left:=f.BufSize-f.BufPos;
  330. end;
  331. FillChar(f.Bufptr^[f.BufPos],len,' ');
  332. inc(f.BufPos,len);
  333. end;
  334. Procedure Write_End(var f:TextRec);[Public,Alias:'WRITE_END'];
  335. begin
  336. if f.FlushFunc<>nil then
  337. FileFunc(f.FlushFunc)(f);
  338. end;
  339. Procedure Writeln_End(var f:TextRec);[Public,Alias:'WRITELN_END'];
  340. const
  341. {$IFDEF SHORT_LINEBREAK}
  342. eollen=1;
  343. eol : array[0..0] of char=(#10);
  344. {$ELSE SHORT_LINEBREAK}
  345. eollen=2;
  346. eol : array[0..1] of char=(#13,#10);
  347. {$ENDIF SHORT_LINEBREAK}
  348. begin
  349. If InOutRes <> 0 then exit;
  350. { Write EOL }
  351. WriteBuffer(f,eol,eollen);
  352. { Flush }
  353. if f.FlushFunc<>nil then
  354. FileFunc(f.FlushFunc)(f);
  355. end;
  356. Procedure Write_Str(Len : Longint;var f : TextRec;const s : String);[Public,Alias: 'WRITE_TEXT_STRING'];
  357. Begin
  358. If InOutRes <> 0 then exit;
  359. If f.mode<>fmOutput Then
  360. exit;
  361. If Len>Length(s) Then
  362. WriteBlanks(f,Len-Length(s));
  363. WriteBuffer(f,s[1],Length(s));
  364. End;
  365. Type
  366. array00 = array[0..0] Of Char;
  367. Procedure Write_Array(Len : Longint;var f : TextRec;const p : array00);[Public,Alias: 'WRITE_TEXT_PCHAR_AS_ARRAY'];
  368. var
  369. ArrayLen : longint;
  370. Begin
  371. If InOutRes <> 0 then exit;
  372. If f.mode<>fmOutput Then
  373. exit;
  374. ArrayLen:=StrLen(p);
  375. If Len>ArrayLen Then
  376. WriteBlanks(f,Len-ArrayLen);
  377. WriteBuffer(f,p,ArrayLen);
  378. End;
  379. Procedure Write_PChar(Len : Longint;var f : TextRec;p : PChar);[Public,Alias: 'WRITE_TEXT_PCHAR_AS_POINTER'];
  380. var
  381. PCharLen : longint;
  382. Begin
  383. If InOutRes <> 0 then exit;
  384. If f.mode<>fmOutput Then
  385. exit;
  386. PCharLen:=StrLen(p);
  387. If Len>PCharLen Then
  388. WriteBlanks(f,Len-PCharLen);
  389. WriteBuffer(f,p^,PCharLen);
  390. End;
  391. Procedure Write_LongInt(Len : Longint;var t : TextRec;l : Longint);[Public,Alias: 'WRITE_TEXT_LONGINT'];
  392. var
  393. s : String;
  394. Begin
  395. If InOutRes <> 0 then exit;
  396. Str(l,s);
  397. Write_Str(Len,t,s);
  398. End;
  399. Procedure Write_Real(fixkomma,Len : Longint;var t : TextRec;r : real);[Public,Alias: 'WRITE_TEXT_REAL'];
  400. var
  401. s : String;
  402. Begin
  403. If InOutRes <> 0 then exit;
  404. {$ifdef i386}
  405. Str_real(Len,fixkomma,r,rt_s64real,s);
  406. {$else}
  407. Str_real(Len,fixkomma,r,rt_s32real,s);
  408. {$endif}
  409. Write_Str(Len,t,s);
  410. End;
  411. Procedure Write_Cardinal(Len : Longint;var t : TextRec;l : cardinal);[Public,Alias: 'WRITE_TEXT_CARDINAL'];
  412. var
  413. s : String;
  414. Begin
  415. If InOutRes <> 0 then exit;
  416. Str(L,s);
  417. Write_Str(Len,t,s);
  418. End;
  419. {$ifdef SUPPORT_SINGLE}
  420. Procedure Write_Single(fixkomma,Len : Longint;var t : TextRec;r : single);[Public,Alias: 'WRITE_TEXT_SINGLE'];
  421. var
  422. s : String;
  423. Begin
  424. If InOutRes <> 0 then exit;
  425. Str_real(Len,fixkomma,r,rt_s32real,s);
  426. Write_Str(Len,t,s);
  427. End;
  428. {$endif SUPPORT_SINGLE}
  429. {$ifdef SUPPORT_EXTENDED}
  430. Procedure Write_Extended(fixkomma,Len : Longint;var t : TextRec;r : extended);[Public,Alias: 'WRITE_TEXT_EXTENDED'];
  431. var
  432. s : String;
  433. Begin
  434. If InOutRes <> 0 then exit;
  435. Str_real(Len,fixkomma,r,rt_s80real,s);
  436. Write_Str(Len,t,s);
  437. End;
  438. {$endif SUPPORT_EXTENDED}
  439. {$ifdef SUPPORT_COMP}
  440. Procedure Write_Comp(fixkomma,Len : Longint;var t : TextRec;r : comp);[Public,Alias: 'WRITE_TEXT_COMP'];
  441. var
  442. s : String;
  443. Begin
  444. If InOutRes <> 0 then exit;
  445. Str_real(Len,fixkomma,r,rt_s64bit,s);
  446. Write_Str(Len,t,s);
  447. End;
  448. {$endif SUPPORT_COMP}
  449. Procedure Write_Fixed(fixkomma,Len : Longint;var t : TextRec;r : fixed);[Public,Alias: 'WRITE_TEXT_FIXED'];
  450. var
  451. s : String;
  452. Begin
  453. If InOutRes <> 0 then exit;
  454. Str_real(Len,fixkomma,r,rt_f32bit,s);
  455. Write_Str(Len,t,s);
  456. End;
  457. Procedure Write_Boolean(Len : Longint;var t : TextRec;b : Boolean);[Public,Alias: 'WRITE_TEXT_BOOLEAN'];
  458. Begin
  459. If InOutRes <> 0 then exit;
  460. { Can't use array[boolean] because b can be >0 ! }
  461. if b then
  462. Write_Str(Len,t,'TRUE')
  463. else
  464. Write_Str(Len,t,'FALSE');
  465. End;
  466. Procedure Write_Char(Len : Longint;var t : TextRec;c : Char);[Public,Alias: 'WRITE_TEXT_CHAR'];
  467. Begin
  468. If InOutRes <> 0 then exit;
  469. If t.mode<>fmOutput Then
  470. exit;
  471. If Len>1 Then
  472. WriteBlanks(t,Len-1);
  473. If t.BufPos+1>=t.BufSize Then
  474. FileFunc(t.InOutFunc)(t);
  475. t.Bufptr^[t.BufPos]:=c;
  476. Inc(t.BufPos);
  477. End;
  478. {$IFNDEF NEW_READWRITE}
  479. Procedure w(var t : TextRec);[Public,Alias: 'WRITELN_TEXT'];
  480. var
  481. hs : String;
  482. Begin
  483. If InOutRes <> 0 then exit;
  484. {$IFDEF SHORT_LINEBREAK}
  485. hs:=#10;
  486. {$ELSE}
  487. hs:=#13#10;
  488. {$ENDIF}
  489. Write_Str(0,t,hs);
  490. End;
  491. {$ENDIF NEW_READWRITE}
  492. {*****************************************************************************
  493. Read(Ln)
  494. *****************************************************************************}
  495. Function OpenInput(var f:TextRec):boolean;
  496. begin
  497. If f.mode=fmInput Then
  498. begin
  499. { No characters in the buffer? Load them ! }
  500. If f.BufPos>=f.BufEnd Then
  501. FileFunc(f.InOutFunc)(f);
  502. OpenInput:=true;
  503. end
  504. else
  505. OpenInput:=false;
  506. end;
  507. Function NextChar(var f:TextRec;var s:string):Boolean;
  508. begin
  509. if f.BufPos<f.BufEnd then
  510. begin
  511. s:=s+f.BufPtr^[f.BufPos];
  512. Inc(f.BufPos);
  513. If f.BufPos>=f.BufEnd Then
  514. FileFunc(f.InOutFunc)(f);
  515. NextChar:=true;
  516. end
  517. else
  518. NextChar:=false;
  519. end;
  520. Function IgnoreSpaces(var f:TextRec):Boolean;
  521. {
  522. Removes all leading spaces,tab,eols from the input buffer, returns true if
  523. the buffer is empty
  524. }
  525. var
  526. s : string;
  527. begin
  528. s:='';
  529. IgnoreSpaces:=false;
  530. while f.Bufptr^[f.BufPos] in [#9,#10,#13,' '] do
  531. if not NextChar(f,s) then
  532. exit;
  533. IgnoreSpaces:=true;
  534. end;
  535. Function ReadSign(var f:TextRec;var s:string):Boolean;
  536. {
  537. Read + and - sign, return true if buffer is empty
  538. }
  539. begin
  540. ReadSign:=(not (f.Bufptr^[f.BufPos] in ['-','+'])) or NextChar(f,s);
  541. end;
  542. Function ReadBase(var f:TextRec;var s:string;var Base:longint):boolean;
  543. {
  544. Read the base $ For 16 and % For 2, if buffer is empty return true
  545. }
  546. begin
  547. case f.BufPtr^[f.BufPos] of
  548. '$' : Base:=16;
  549. '%' : Base:=2;
  550. else
  551. Base:=10;
  552. end;
  553. ReadBase:=(Base=10) or NextChar(f,s);
  554. end;
  555. Function ReadNumeric(var f:TextRec;var s:string;base:longint):Boolean;
  556. {
  557. Read numeric input, if buffer is empty then return True
  558. }
  559. var
  560. c : char;
  561. begin
  562. ReadNumeric:=false;
  563. c:=f.BufPtr^[f.BufPos];
  564. while ((base>=10) and (c in ['0'..'9'])) or
  565. ((base=16) and (c in ['A'..'F','a'..'f'])) or
  566. ((base=2) and (c in ['0'..'1'])) do
  567. begin
  568. if not NextChar(f,s) then
  569. exit;
  570. c:=f.BufPtr^[f.BufPos];
  571. end;
  572. ReadNumeric:=true;
  573. end;
  574. Procedure Read_End(var f:TextRec);[Public,Alias:'READ_END'];
  575. begin
  576. if f.FlushFunc<>nil then
  577. FileFunc(f.FlushFunc)(f);
  578. end;
  579. Procedure ReadLn_End(var f : TextRec);[Public,Alias: 'READLN_END'];
  580. Begin
  581. If InOutRes <> 0 then exit;
  582. if not OpenInput(f) then
  583. exit;
  584. { Read until a linebreak }
  585. while (f.BufPos<f.BufEnd) do
  586. begin
  587. inc(f.BufPos);
  588. if (f.BufPtr^[f.BufPos-1]=#10) then
  589. exit;
  590. If f.BufPos>=f.BufEnd Then
  591. FileFunc(f.InOutFunc)(f);
  592. end;
  593. { Flush if set }
  594. if f.FlushFunc<>nil then
  595. FileFunc(f.FlushFunc)(f);
  596. End;
  597. {$ifndef MAXLENREADSTRING}
  598. Procedure Read_String(var f : TextRec;var s : String);[Public,Alias: 'READ_TEXT_STRING'];
  599. var
  600. Temp,sPos : Word;
  601. Begin
  602. { Delete the string }
  603. s:='';
  604. If InOutRes <> 0 then exit;
  605. if not OpenInput(f) then
  606. exit;
  607. Temp:=f.BufPos;
  608. sPos:=1;
  609. while (f.BufPos<f.BufEnd) and (f.Bufptr^[Temp]<>#10) Do
  610. Begin
  611. { search linefeed }
  612. while (f.Bufptr^[Temp]<>#10) and (Temp<f.BufEnd) Do
  613. Inc(Temp);
  614. { copy String. Take 255 char limit in account.}
  615. If sPos+Temp-f.BufPos<=255 Then
  616. Begin
  617. Move (f.Bufptr^[f.BufPos],s[sPos],Temp-f.BufPos);
  618. sPos:=sPos+Temp-f.BufPos;
  619. { Remove #13 from a #13#10 break }
  620. If s[sPos-1]=#13 Then
  621. dec(sPos);
  622. End
  623. else
  624. Begin
  625. If (sPos<=255) Then
  626. Move(f.Bufptr^[f.BufPos],s[sPos],256-sPos);
  627. sPos:=256
  628. End;
  629. { update f.BufPos }
  630. f.BufPos:=Temp;
  631. If Temp>=f.BufEnd Then
  632. Begin
  633. FileFunc(f.InOutFunc)(f);
  634. Temp:=f.BufPos;
  635. End
  636. End;
  637. s[0]:=chr(sPos-1);
  638. End;
  639. {$ELSE}
  640. Procedure Read_String(Maxlen : Longint;var f : TextRec;var s : String);[Public,Alias: 'READ_TEXT_STRING'];
  641. var
  642. Temp,sPos,nrread : Word;
  643. Begin
  644. { Delete the string }
  645. s:='';
  646. If InOutRes <> 0 then exit;
  647. if not OpenInput(f) then
  648. exit;
  649. Temp:=f.BufPos;
  650. sPos:=1;
  651. NrRead:=0;
  652. while (f.BufPos<f.BufEnd) and ((f.Bufptr^[Temp]<>#10) and (NrRead<Maxlen)) Do
  653. Begin
  654. { search linefeed or length of string }
  655. while ((f.Bufptr^[Temp]<>#10) and (NrRead<Maxlen)) and (Temp<f.BufEnd) Do
  656. begin
  657. Temp:=Temp+1;
  658. NrRead:=NrRead+1;
  659. end;
  660. { copy String. Take 255 char limit in account.}
  661. If sPos+Temp-f.BufPos<=255 Then
  662. Begin
  663. Move (f.Bufptr^[f.BufPos],s[sPos],Temp-f.BufPos);
  664. sPos:=sPos+Temp-f.BufPos;
  665. { Remove #13 from a #13#10 break }
  666. If s[sPos-1]=#13 Then
  667. dec(sPos);
  668. End
  669. else
  670. Begin
  671. If (sPos<=255) Then
  672. Move(f.Bufptr^[f.BufPos],s[sPos],256-sPos);
  673. sPos:=256
  674. End;
  675. { update f.BufPos }
  676. f.BufPos:=Temp;
  677. If Temp>=f.BufEnd Then
  678. Begin
  679. FileFunc(f.InOutFunc)(f);
  680. Temp:=f.BufPos;
  681. End
  682. End;
  683. s[0]:=chr(sPos-1);
  684. End;
  685. {$ENDIF MAXLENREADSTRING}
  686. Procedure Read_Char(var f : TextRec;var c : Char);[Public,Alias: 'READ_TEXT_CHAR'];
  687. Begin
  688. c:=#0;
  689. If InOutRes <> 0 then exit;
  690. if not OpenInput(f) then
  691. exit;
  692. If f.BufPos>=f.BufEnd Then
  693. c:=#26
  694. else
  695. c:=f.Bufptr^[f.BufPos];
  696. Inc(f.BufPos);
  697. End;
  698. Procedure Read_PChar(var f : TextRec;var s : PChar);[Public,Alias:'READ_TEXT_PCHAR_AS_POINTER'];
  699. var
  700. p : PChar;
  701. Temp : byte;
  702. Begin
  703. { Delete the string }
  704. s^:=#0;
  705. If InOutRes <> 0 then exit;
  706. p:=s;
  707. if not OpenInput(f) then
  708. exit;
  709. Temp:=f.BufPos;
  710. while (f.BufPos<f.BufEnd) and (f.Bufptr^[Temp]<>#10) Do
  711. Begin
  712. { search linefeed }
  713. while (f.Bufptr^[Temp]<>#10) and (Temp<f.BufEnd) Do
  714. inc(Temp);
  715. { copy string. }
  716. Move (f.Bufptr^[f.BufPos],p^,Temp-f.BufPos);
  717. Inc(Longint(p),Temp-f.BufPos);
  718. If pchar(p-1)^=#13 Then
  719. dec(p);
  720. { update f.BufPos }
  721. f.BufPos:=Temp;
  722. If Temp>=f.BufEnd Then
  723. Begin
  724. FileFunc(f.InOutFunc)(f);
  725. Temp:=f.BufPos;
  726. End
  727. End;
  728. p^:=#0;
  729. End;
  730. Procedure Read_Array(var f : TextRec;var s : array00);[Public,Alias:'READ_TEXT_PCHAR_AS_ARRAY'];
  731. var
  732. p : PChar;
  733. Temp : byte;
  734. Begin
  735. { Delete the string }
  736. s[0]:=#0;
  737. If InOutRes <> 0 then exit;
  738. p:=pchar(@s);
  739. if not OpenInput(f) then
  740. exit;
  741. Temp:=f.BufPos;
  742. while (f.BufPos<f.BufEnd) and (f.Bufptr^[Temp]<>#10) Do
  743. Begin
  744. { search linefeed }
  745. while (f.Bufptr^[Temp]<>#10) and (Temp<f.BufEnd) Do
  746. inc(Temp);
  747. { copy string. }
  748. Move (f.Bufptr^[f.BufPos],p^,Temp-f.BufPos);
  749. Inc(Longint(p),Temp-f.BufPos);
  750. If pchar(p-1)^=#13 Then
  751. dec(p);
  752. { update f.BufPos }
  753. f.BufPos:=Temp;
  754. If Temp>=f.BufEnd Then
  755. Begin
  756. FileFunc(f.InOutFunc)(f);
  757. Temp:=f.BufPos;
  758. End
  759. End;
  760. p^:=#0;
  761. End;
  762. Procedure Read_Longint(var f : TextRec;var l : Longint);[Public,Alias: 'READ_TEXT_LONGINT'];
  763. var
  764. hs : String;
  765. code : Word;
  766. base : longint;
  767. Begin
  768. l:=0;
  769. If InOutRes <> 0 then exit;
  770. hs:='';
  771. if not OpenInput(f) then
  772. exit;
  773. if IgnoreSpaces(f) and ReadSign(f,hs) and ReadBase(f,hs,Base) then
  774. ReadNumeric(f,hs,Base);
  775. Val(hs,l,code);
  776. If code<>0 Then
  777. RunError(106);
  778. End;
  779. Procedure Read_Integer(var f : TextRec;var l : Integer);[Public,Alias: 'READ_TEXT_INTEGER'];
  780. var
  781. ll : Longint;
  782. Begin
  783. l:=0;
  784. If InOutRes <> 0 then exit;
  785. Read_Longint(f,ll);
  786. If (ll<-32768) or (ll>32767) Then
  787. RunError(106);
  788. l:=ll;
  789. End;
  790. Procedure Read_Word(var f : TextRec;var l : Word);[Public,Alias: 'READ_TEXT_WORD'];
  791. var
  792. ll : Longint;
  793. Begin
  794. l:=0;
  795. If InOutRes <> 0 then exit;
  796. Read_Longint(f,ll);
  797. If (ll<0) or (ll>$ffff) Then
  798. RunError(106);
  799. l:=ll;
  800. End;
  801. Procedure Read_Byte(var f : TextRec;var l : byte);[Public,Alias: 'READ_TEXT_BYTE'];
  802. var
  803. ll : Longint;
  804. Begin
  805. l:=0;
  806. If InOutRes <> 0 then exit;
  807. Read_Longint(f,ll);
  808. If (ll<0) or (ll>255) Then
  809. RunError(106);
  810. l:=ll;
  811. End;
  812. Procedure Read_Shortint(var f : TextRec;var l : shortint);[Public,Alias: 'READ_TEXT_SHORTINT'];
  813. var
  814. ll : Longint;
  815. Begin
  816. l:=0;
  817. If InOutRes <> 0 then exit;
  818. Read_Longint(f,ll);
  819. If (ll<-128) or (ll>127) Then
  820. RunError(106);
  821. l:=ll;
  822. End;
  823. Procedure Read_Cardinal(var f : TextRec;var l : cardinal);[Public,Alias: 'READ_TEXT_CARDINAL'];
  824. var
  825. hs : String;
  826. code : Word;
  827. base : longint;
  828. Begin
  829. l:=0;
  830. If InOutRes <> 0 then exit;
  831. hs:='';
  832. if not OpenInput(f) then
  833. exit;
  834. if IgnoreSpaces(f) and ReadSign(f,hs) and ReadBase(f,hs,Base) then
  835. ReadNumeric(f,hs,Base);
  836. val(hs,l,code);
  837. If code<>0 Then
  838. RunError(106);
  839. End;
  840. Procedure Read_Real(var f : TextRec;var d : Real);[Public,Alias: 'READ_TEXT_REAL'];
  841. var
  842. hs : String;
  843. code : Word;
  844. Begin
  845. d:=0.0;
  846. If InOutRes <> 0 then exit;
  847. hs:='';
  848. if not OpenInput(f) then
  849. exit;
  850. if IgnoreSpaces(f) and ReadSign(f,hs) and ReadNumeric(f,hs,10) then
  851. begin
  852. { First check for a . }
  853. if (f.Bufptr^[f.BufPos]='.') and (f.BufPos<f.BufEnd) Then
  854. begin
  855. hs:=hs+'.';
  856. Inc(f.BufPos);
  857. If f.BufPos>=f.BufEnd Then
  858. FileFunc(f.InOutFunc)(f);
  859. ReadNumeric(f,hs,10);
  860. end;
  861. { Also when a point is found check for a E }
  862. if (f.Bufptr^[f.BufPos] in ['e','E']) and (f.BufPos<f.BufEnd) Then
  863. begin
  864. hs:=hs+'E';
  865. Inc(f.BufPos);
  866. If f.BufPos>=f.BufEnd Then
  867. FileFunc(f.InOutFunc)(f);
  868. if ReadSign(f,hs) then
  869. ReadNumeric(f,hs,10);
  870. end;
  871. end;
  872. val(hs,d,code);
  873. If code<>0 Then
  874. RunError(106);
  875. End;
  876. {$ifdef SUPPORT_EXTENDED}
  877. Procedure Read_Extended(var f : TextRec;var d : extended);[Public,Alias: 'READ_TEXT_EXTENDED'];
  878. var
  879. hs : String;
  880. code : Word;
  881. Begin
  882. d:=0.0;
  883. If InOutRes <> 0 then exit;
  884. hs:='';
  885. if not OpenInput(f) then
  886. exit;
  887. if IgnoreSpaces(f) and ReadSign(f,hs) and ReadNumeric(f,hs,10) then
  888. begin
  889. { First check for a . }
  890. if (f.Bufptr^[f.BufPos]='.') and (f.BufPos<f.BufEnd) Then
  891. begin
  892. hs:=hs+'.';
  893. Inc(f.BufPos);
  894. If f.BufPos>=f.BufEnd Then
  895. FileFunc(f.InOutFunc)(f);
  896. ReadNumeric(f,hs,10);
  897. end;
  898. { Also when a point is found check for a E }
  899. if (f.Bufptr^[f.BufPos] in ['e','E']) and (f.BufPos<f.BufEnd) Then
  900. begin
  901. hs:=hs+'E';
  902. Inc(f.BufPos);
  903. If f.BufPos>=f.BufEnd Then
  904. FileFunc(f.InOutFunc)(f);
  905. if ReadSign(f,hs) then
  906. ReadNumeric(f,hs,10);
  907. end;
  908. end;
  909. val(hs,d,code);
  910. If code<>0 Then
  911. RunError(106);
  912. End;
  913. {$endif SUPPORT_EXTENDED}
  914. {$ifdef SUPPORT_COMP}
  915. Procedure Read_Comp(var f : TextRec;var d : comp);[Public,Alias: 'READ_TEXT_COMP'];
  916. var
  917. hs : String;
  918. code : Word;
  919. Begin
  920. d:=comp(0.0);
  921. If InOutRes <> 0 then exit;
  922. hs:='';
  923. if not OpenInput(f) then
  924. exit;
  925. if IgnoreSpaces(f) and ReadSign(f,hs) and ReadNumeric(f,hs,10) then
  926. begin
  927. { First check for a . }
  928. if (f.Bufptr^[f.BufPos]='.') and (f.BufPos<f.BufEnd) Then
  929. begin
  930. hs:=hs+'.';
  931. Inc(f.BufPos);
  932. If f.BufPos>=f.BufEnd Then
  933. FileFunc(f.InOutFunc)(f);
  934. ReadNumeric(f,hs,10);
  935. end;
  936. { Also when a point is found check for a E }
  937. if (f.Bufptr^[f.BufPos] in ['e','E']) and (f.BufPos<f.BufEnd) Then
  938. begin
  939. hs:=hs+'E';
  940. Inc(f.BufPos);
  941. If f.BufPos>=f.BufEnd Then
  942. FileFunc(f.InOutFunc)(f);
  943. if ReadSign(f,hs) then
  944. ReadNumeric(f,hs,10);
  945. end;
  946. end;
  947. val(hs,d,code);
  948. If code<>0 Then
  949. RunError(106);
  950. End;
  951. {$endif SUPPORT_COMP}
  952. {$IFNDEF NEW_READWRITE}
  953. Procedure r(var f : TextRec);[Public,Alias: 'READLN_TEXT'];
  954. Begin
  955. If InOutRes <> 0 then exit;
  956. if not OpenInput(f) then
  957. exit;
  958. while (f.BufPos<f.BufEnd) do
  959. begin
  960. inc(f.BufPos);
  961. if (f.BufPtr^[f.BufPos-1]=#10) then
  962. exit;
  963. If f.BufPos>=f.BufEnd Then
  964. FileFunc(f.InOutFunc)(f);
  965. end;
  966. End;
  967. {$ENDIF NEW_READWRITE}
  968. {*****************************************************************************
  969. Initializing
  970. *****************************************************************************}
  971. procedure OpenStdIO(var f:text;mode:word;hdl:longint);
  972. begin
  973. Assign(f,'');
  974. TextRec(f).Handle:=hdl;
  975. TextRec(f).Mode:=mode;
  976. TextRec(f).Closefunc:=@FileCloseFunc;
  977. case mode of
  978. fmInput : TextRec(f).InOutFunc:=@FileReadFunc;
  979. fmOutput : begin
  980. TextRec(f).InOutFunc:=@FileWriteFunc;
  981. TextRec(f).FlushFunc:=@FileWriteFunc;
  982. end;
  983. else
  984. RunError(102);
  985. end;
  986. end;
  987. {
  988. $Log$
  989. Revision 1.15 1998-07-06 15:56:43 michael
  990. Added length checking for string reading
  991. Revision 1.14 1998/07/02 12:14:56 carl
  992. + Each IOCheck routine now check InOutRes before, just like TP
  993. Revision 1.13 1998/07/01 15:30:00 peter
  994. * better readln/writeln
  995. Revision 1.12 1998/07/01 14:48:10 carl
  996. * bugfix of WRITE_TEXT_BOOLEAN , was not TP compatible
  997. + added explicit typecast in OpenText
  998. Revision 1.11 1998/06/25 09:44:22 daniel
  999. + RTLLITE directive to compile minimal RTL.
  1000. Revision 1.10 1998/06/04 23:46:03 peter
  1001. * comp,extended are only i386 added support_comp,support_extended
  1002. Revision 1.9 1998/06/02 16:47:56 pierre
  1003. * bug for boolean values greater than one fixed
  1004. Revision 1.8 1998/05/31 14:14:54 peter
  1005. * removed warnings using comp()
  1006. Revision 1.7 1998/05/27 00:19:21 peter
  1007. * fixed crt input
  1008. Revision 1.6 1998/05/21 19:31:01 peter
  1009. * objects compiles for linux
  1010. + assign(pchar), assign(char), rename(pchar), rename(char)
  1011. * fixed read_text_as_array
  1012. + read_text_as_pchar which was not yet in the rtl
  1013. Revision 1.5 1998/05/12 10:42:45 peter
  1014. * moved getopts to inc/, all supported OS's need argc,argv exported
  1015. + strpas, strlen are now exported in the systemunit
  1016. * removed logs
  1017. * removed $ifdef ver_above
  1018. Revision 1.4 1998/04/07 22:40:46 florian
  1019. * final fix of comp writing
  1020. }