blob: f828b4652118ad74aa3946902c1c0293e3dfd389 [file] [log] [blame]
(* PushBackInput.mod provides a method for pushing back and consuming input.
Copyright (C) 2001-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
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
<http://www.gnu.org/licenses/>. *)
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 StackPtr<MaxPushBackStack
THEN
CharStack[StackPtr] := ch ;
INC(StackPtr)
ELSE
Halt('max push back stack exceeded, increase MaxPushBackStack',
__FILE__, __FUNCTION__, __LINE__)
END ;
RETURN( ch )
END PutCh ;
(*
Open - opens a file for reading.
*)
PROCEDURE Open (a: ARRAY OF CHAR) : File ;
BEGIN
Init ;
StrCopy(a, FileName) ;
RETURN( OpenToRead(a) )
END Open ;
(*
Close - closes the opened file.
*)
PROCEDURE Close (f: File) ;
BEGIN
FIO.Close(f)
END Close ;
(*
ErrChar - writes a char, ch, to stderr.
*)
PROCEDURE ErrChar (ch: CHAR) ;
BEGIN
WriteChar(StdErr, ch)
END ErrChar ;
(*
Error - emits an error message with the appropriate file, line combination.
*)
PROCEDURE Error (a: ARRAY OF CHAR) ;
BEGIN
PushOutput(ErrChar) ;
WriteString(FileName) ; Write(':') ; WriteCard(LineNo, 0) ; Write(':') ; WriteString(a) ; WriteLn ;
PopOutput ;
FIO.Close(StdErr) ;
exit(1)
END Error ;
(*
WarnError - emits an error message with the appropriate file, line combination.
It does not terminate but when the program finishes an exit status of
1 will be issued.
*)
PROCEDURE WarnError (a: ARRAY OF CHAR) ;
BEGIN
PushOutput(ErrChar) ;
WriteString(FileName) ; Write(':') ; WriteCard(LineNo, 0) ; Write(':') ; WriteString(a) ; WriteLn ;
PopOutput ;
ExitStatus := 1
END WarnError ;
(*
WarnString - emits an error message with the appropriate file, line combination.
It does not terminate but when the program finishes an exit status of
1 will be issued.
*)
PROCEDURE WarnString (s: String) ;
VAR
p : POINTER TO CHAR ;
BEGIN
p := string(s) ;
WriteString(FileName) ; Write(':') ; WriteCard(LineNo, 0) ; Write(':') ;
REPEAT
IF p#NIL
THEN
IF p^=lf
THEN
WriteLn ;
WriteString(FileName) ; Write(':') ; WriteCard(LineNo, 0) ; Write(':')
ELSE
Write(p^)
END ;
INC(p)
END ;
UNTIL (p=NIL) OR (p^=nul) ;
ExitStatus := 1
END WarnString ;
(*
GetExitStatus - returns the exit status which will be 1 if any warnings were issued.
*)
PROCEDURE GetExitStatus () : CARDINAL ;
BEGIN
RETURN( ExitStatus )
END GetExitStatus ;
(*
SetDebug - sets the debug flag on or off.
*)
PROCEDURE SetDebug (d: BOOLEAN) ;
BEGIN
Debugging := d
END SetDebug ;
(*
GetColumnPosition - returns the column position of the current character.
*)
PROCEDURE GetColumnPosition () : CARDINAL ;
BEGIN
IF StackPtr>Column
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.