(* PushBackInput.mod provides a method for pushing back and consuming input. Copyright (C) 2001-2023 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . *) IMPLEMENTATION MODULE PushBackInput ; FROM FIO IMPORT ReadChar, IsNoError, EOF, OpenToRead, WriteChar, StdErr ; FROM DynamicStrings IMPORT string, Length, char ; FROM ASCII IMPORT nul, cr, lf ; FROM Debug IMPORT Halt ; FROM StrLib IMPORT StrCopy, StrLen ; FROM NumberIO IMPORT WriteCard ; FROM StrIO IMPORT WriteString, WriteLn ; FROM StdIO IMPORT Write, PushOutput, PopOutput ; FROM libc IMPORT exit ; IMPORT FIO ; CONST MaxPushBackStack = 8192 ; MaxFileName = 4096 ; VAR FileName : ARRAY [0..MaxFileName] OF CHAR ; CharStack : ARRAY [0..MaxPushBackStack] OF CHAR ; ExitStatus: CARDINAL ; Column, StackPtr, LineNo : CARDINAL ; Debugging : BOOLEAN ; (* GetCh - gets a character from either the push back stack or from file, f. *) PROCEDURE GetCh (f: File) : CHAR ; VAR ch: CHAR ; BEGIN IF StackPtr>0 THEN DEC(StackPtr) ; IF Debugging THEN Write(CharStack[StackPtr]) END ; RETURN( CharStack[StackPtr] ) ELSE IF EOF(f) OR (NOT IsNoError(f)) THEN ch := nul ELSE REPEAT ch := ReadChar(f) UNTIL (ch#cr) OR EOF(f) OR (NOT IsNoError(f)) ; IF ch=lf THEN Column := 0 ; INC(LineNo) ELSE INC(Column) END END ; IF Debugging THEN Write(ch) END ; RETURN( ch ) END END GetCh ; (* PutStr - pushes a dynamic string onto the push back stack. The string, s, is not deallocated. *) PROCEDURE PutStr (s: String) ; VAR i: CARDINAL ; BEGIN i := Length (s) ; WHILE i > 0 DO DEC (i) ; IF PutCh (char (s, i)) # char (s, i) THEN Halt('assert failed', __FILE__, __FUNCTION__, __LINE__) END END END PutStr ; (* PutString - pushes a string onto the push back stack. *) PROCEDURE PutString (a: ARRAY OF CHAR) ; VAR l: CARDINAL ; BEGIN l := StrLen (a) ; WHILE l > 0 DO DEC (l) ; IF PutCh (a[l]) # a[l] THEN Halt ('assert failed', __FILE__, __FUNCTION__, __LINE__) END END END PutString ; (* PutCh - pushes a character onto the push back stack, it also returns the character which has been pushed. *) PROCEDURE PutCh (ch: CHAR) : CHAR ; BEGIN IF StackPtrColumn THEN RETURN( 0 ) ELSE RETURN( Column-StackPtr ) END END GetColumnPosition ; (* GetCurrentLine - returns the current line number. *) PROCEDURE GetCurrentLine () : CARDINAL ; BEGIN RETURN( LineNo ) END GetCurrentLine ; (* Init - initialize global variables. *) PROCEDURE Init ; BEGIN ExitStatus := 0 ; StackPtr := 0 ; LineNo := 1 ; Column := 0 END Init ; BEGIN SetDebug(FALSE) ; Init END PushBackInput.