IMPLEMENTATION MODULE Tools; (* VAX 11/780: Sohail Aslam *) FROM FileSystem IMPORT Eof; FROM InOut IMPORT EOL , in , out , OpenInput , OpenOutput , CloseInput , CloseOutput , Read , ReadLn , Write , WriteLn , WriteInt , WriteCard , Done , WriteString ; CONST BUFSIZE = 83; VAR bp : INTEGER; buf: ARRAY [1..BUFSIZE] OF Character; (* Warning -- Print warning message but don't die *) PROCEDURE Warning( msg : ARRAY OF CHAR (* in *) ); BEGIN WriteString( msg ); WriteLn; END Warning; (* FatalError -- Print error message and die *) PROCEDURE FatalError( msg : ARRAY OF CHAR (* in *) ); BEGIN WriteString( msg ); WriteLn; HALT END FatalError; PROCEDURE ReadChar( VAR c : Character (* out *) ): Character; (* Read character for "in". *) VAR ch : CHAR; BEGIN Read( ch ) ; IF NOT Done THEN c := ENDFILE; RETURN c END; IF ch = EOL THEN ReadLn; c := NEWLINE; RETURN c END; (* normal Character *) c := ORD ( ch ); RETURN c END ReadChar; (* Getc -- get one Character, possibly pushed back, from Standard Input *) PROCEDURE Getc ( VAR c : Character (* Out *) ) : Character; BEGIN IF bp > 0 THEN c := buf[bp] ELSE bp := 1; buf[bp] := ReadChar( c ); END; IF c # ENDFILE THEN bp := bp - 1; END; RETURN c END Getc; (* PutBack -- push characters back onto input *) PROCEDURE PutBack( c : Character (* in *) ); BEGIN IF bp >= BUFSIZE THEN FatalError("Tools -- too many characters pushed back" ); END; bp := bp + 1; buf[bp] := c; END PutBack; (* Pbstr -- push back an entire string onto input *) PROCEDURE Pbstr( VAR s : String (* in *) ); VAR i : CARDINAL; c : Character; BEGIN FOR i := Strlen( s ) TO 1 BY -1 DO c := s[i]; PutBack( c ); END; END Pbstr; (* GetLine ( vax-11 ) -- get a line from stdinput *) PROCEDURE GetLine ( VAR s : String (* out *); maxsize : CARDINAL (* in *) ) : BOOLEAN; VAR i : CARDINAL; c : Character; BEGIN i := 1; REPEAT s[i] := Getc ( c ); i := i + 1 UNTIL ( c = ENDFILE ) OR (c = NEWLINE) OR (i >= maxsize ); IF c = ENDFILE THEN (* went one too far *) i := i - 1 END; s[i] := ENDSTR; RETURN c <> ENDFILE END GetLine; (* Putc -- put one Character on Standard output *) PROCEDURE Putc ( c : Character (* In *) ); BEGIN IF c = NEWLINE THEN WriteLn ELSE Write( CHR ( c ) ) END END Putc; (* PutStr -- Put out a string of type character to Stdout *) PROCEDURE PutStr ( VAR Str : String (* In *) ); VAR i : CARDINAL; BEGIN i := 1; WHILE Str[ i ] <> ENDSTR DO Putc( Str[ i ] ); INC( i ) END END PutStr; (* EchoInput -- Echo next line of input in Standard input *) PROCEDURE EchoInput( ); VAR s : String; BEGIN IF GetLine( s, MAXSTR-1 ) THEN PutStr( s ); Pbstr ( s ); (* put it back *) ELSE PutBack( ENDFILE ); END; END EchoInput; (* PutQStr -- Put out a string to stdout *) PROCEDURE PutQStr ( Str : ARRAY OF CHAR (* In *) ); VAR i, j : CARDINAL; c : CARDINAL; OutStr : String; len : CARDINAL; BEGIN i := 0; j := 1; len := HIGH( Str ); LOOP IF( j <= MAXSTR ) AND ( i <= len ) AND ( Str[i] <> 0C ) THEN c := ORD( Str[ i ] ); OutStr[ j ] := c; IF c = BACKSLASH THEN INC( i ); IF i > len THEN (* single \ *) EXIT END; c := ORD( Str[ i ] ); IF c = LETN THEN OutStr[ j ] := NEWLINE; INC( i ) ELSIF c = LETT THEN OutStr[ j ] := TAB; INC( i ) ELSIF c = BACKSLASH THEN OutStr[ j ] := BACKSLASH ELSE DEC( i ) END END; INC( j ); INC( i ) ELSE EXIT END END; (* LOOP *) FOR i := 1 TO j-1 DO Putc( OutStr[ i ] ) END END PutQStr; (* Scopy -- copy string In starting at i into Out starting a j *) PROCEDURE Scopy( VAR In : String (* in *); i : CARDINAL (* in *); VAR Out : String (* out *); j : CARDINAL (* in *) ); BEGIN WHILE In[i] # ENDSTR DO Out[j] := In[i]; INC( i ); INC( j ) END; Out[j] := ENDSTR END Scopy; (* MakeStr -- convert an ARRAY OF CHAR to string of type String. *) PROCEDURE MakeStr( cs : ARRAY OF CHAR (* in *); VAR s : String (*out *) ); VAR i : CARDINAL; BEGIN i := 0; WHILE( i <= HIGH( cs ) ) AND ( cs[i] # 0C ) DO s[i+1] := ORD( cs[i] ); INC( i ) END; s[i+1] := ENDSTR END MakeStr; (* MakeCString -- convert a String type string to ARRAY OF CHAR *) PROCEDURE MakeCString( VAR s : String; (* in *) VAR cs: ARRAY OF CHAR (* out *) ); VAR I, J, hics : CARDINAL; c : Character; BEGIN I := 1; J := 0; hics := HIGH( cs ); WHILE( s[I] # ENDSTR ) AND ( J < hics ) DO c := s[I]; cs[J] := CHR( c ); INC( I ); INC( J ) END; cs[ J ] := 0C END MakeCString; (* Strlen -- return length of a string *) PROCEDURE Strlen( VAR s : String (* in *) ) : CARDINAL; VAR i : CARDINAL; BEGIN i := 0; WHILE s[i+1] # ENDSTR DO INC( i ) END; RETURN i END Strlen; PROCEDURE Strcmp( VAR s1 : String; VAR s2 : String ): INTEGER; (* Compare the two strings s1 and s2. Function value returned is < 0 if s1 < s2, equal to 0 if s1 = s2, > 0 if s1 > s2. *) VAR j : CARDINAL; BEGIN j := 1; WHILE ( s1[j] = s2[j] ) DO IF ( s1[j] = ENDSTR ) OR ( s2[j] = ENDSTR ) THEN RETURN s1[j] - s2[j] END; INC ( j ) END; (* mismatch found at j *) RETURN s1[j] - s2[j] END Strcmp; (* Strloc -- Locate a character in a string *) PROCEDURE Strloc( VAR s : String (* in *); c : Character (* in *) ): CARDINAL; VAR i : CARDINAL; BEGIN FOR i := 1 TO Strlen( s ) DO IF s[i] = c THEN RETURN i END END; RETURN 0 END Strloc; (* Ctoi -- convert string Integer *) PROCEDURE Ctoi ( VAR s : String (* in *) ) : INTEGER; VAR i, n, sign : INTEGER; BEGIN i := 1; WHILE ( s[i] = BLANK ) OR (s[i] = TAB ) DO INC( i ) END; IF ( s[i] = MINUS ) THEN sign := -1 ELSE sign := 1 END; IF ( s[i] = PLUS ) OR ( s[i] = MINUS ) THEN INC( i ) END; n := 0; WHILE ( s[i] >= DIG0 ) AND ( s[i] <= DIG9 ) DO n := 10 * n + s[i] - DIG0; INC( i ) END; RETURN sign * n END Ctoi; (* Ctor -- convert string to REAL. Exponential forms not allowed, i.e 1.09e-05 *) PROCEDURE Ctor( VAR s : String (* in *) ) : REAL; VAR i : CARDINAL; whole : INTEGER; Fstr : String; fraction : REAL; BEGIN (* break string into two at the decimal point *) i := Strloc( s, DECIMAL ); Fstr[1] := ENDSTR; (* Null string *) IF i > 0 THEN Scopy( s, i+1, Fstr, 1 ); s[i] := ENDSTR END; (* Convert whole and fraction strings into integers *) whole := Ctoi( s ); IF Strlen( Fstr ) > 0 THEN fraction := FLOAT( Ctoi( Fstr ) ) ; FOR i := 1 TO Strlen( Fstr ) DO fraction := fraction/10.0 END; RETURN FLOAT( whole ) + fraction END; RETURN FLOAT( whole ) END Ctor; (* NullString -- null a string by setting its length to 0 *) PROCEDURE NullString( VAR str : String (* out *) ); BEGIN str[1] := ENDSTR END NullString; BEGIN (* initialiation *) bp := 0; END Tools.