MODULE PrintEnv ;

FROM GlobalString IMPORT GetGlobalStringName , GetGlobalString ;

FROM Program IMPORT Verbosity , HelpRequired , IdentifyRequired ;

IMPORT Program ;

IMPORT Debug ;

FROM String IMPORT LengthC ;

FROM DecodeArg IMPORT DecodedInformation , DecodeInit , DecodeEnd ,
                      GetNumberOfValues , GetStringArg , GetStateArg ;


FROM IO IMPORT FindOutput , SelectOutput , CloseStream , WriteByte ;


CONST
   StringNotFound                 = -1 ;
   NoMatchFound                   = -2 ;

(* ========================================================================= *)

PROCEDURE Instr( Ch : CHAR ; Target : ARRAY OF CHAR ) : BOOLEAN ;
VAR
   I                        : CARDINAL ;
BEGIN
   FOR I := 0 TO HIGH( Target ) DO
      IF Target[ I ] = Ch THEN
         RETURN TRUE ;
      END (* if *) ;
   END (* for *) ;
   RETURN FALSE ;
END Instr ;

(* ========================================================================= *)
(* Performs wild card match between Wild ( containing '*'s ) and Target.  *)

CONST

PROCEDURE Matches( VAR Wild , Target : ARRAY OF CHAR ) : BOOLEAN ;
VAR
   WildLength                     : CARDINAL ;
   TargetLength                   : CARDINAL ;

   PROCEDURE Match( WildIndex , TargetIndex : CARDINAL ) : BOOLEAN ;
   BEGIN
      WHILE TargetIndex < TargetLength DO
         IF WildIndex < WildLength THEN
            IF Wild[ WildIndex ] = '*' THEN
               IF Match( WildIndex + 1 , TargetIndex ) THEN
                  RETURN TRUE ;
               END (* if *) ;
            ELSIF Wild[ WildIndex ] = Target[ TargetIndex ] THEN
               INC( WildIndex ) ;
            ELSE
               RETURN FALSE ;
            END (* if *) ;
         ELSE
            RETURN FALSE ;
         END (* if *) ;
         INC( TargetIndex ) ;
      END (* while *) ;
      RETURN WildIndex + 1 >= WildLength ;
   END Match ;

VAR
   Index                     : CARDINAL ;
BEGIN
   WildLength := LengthC( Wild ) ;
   TargetLength := LengthC( Target ) ;
   RETURN Match( 0 , 0 ) ;
END Matches ;


(* ------------------------------------------------------------------------- *)

PROCEDURE Check( This : INTEGER ) : BOOLEAN ;
BEGIN
   IF This < 0 THEN
      IF Result = 0 THEN
         Result := This ;
      END (* if *) ;
      RETURN FALSE ;
   ELSE
      RETURN TRUE ;
   END (* if *) ;
END Check ;

(* ------------------------------------------------------------------------- *)

PROCEDURE Wrch( Ch : CHAR ) ;
VAR
   Junk                    : INTEGER ;
BEGIN
   Junk := WriteByte( INTEGER( Ch ) ) ;
   IF Junk < 0 THEN
      Debug.WriteS( "*NWriteByte failed : Result = " ) ;
      Debug.WriteH( Junk ) ;
      Debug.WriteS( "*N" ) ;
      IF Result = 0 THEN
         Result := Junk ;
      END (* if *) ;
   END (* if *) ;
END Wrch ;

(* ------------------------------------------------------------------------- *)

PROCEDURE WriteS( Text : ARRAY OF CHAR ) ;
VAR
Index                   : CARDINAL ;
   Ch                      : CHAR ;
BEGIN
   Index := 0 ;
   Length := LengthC( Text ) ;
   WHILE Index < Length DO
      Ch := Text[ Index ] ;
      IF Ch = '*' THEN
         INC( Index ) ;
         Ch := Text[ Index ] ;
         IF Ch = 'N' THEN
            Ch := 012C ;
         ELSE
            Wrch( '*' ) ;
         END (* if *) ;
      END (* if *) ;
      Wrch( Ch ) ;
      INC( Index ) ;
   END (* while *) ;
END WriteS ;

(* ------------------------------------------------------------------------- *)

PROCEDURE PrintEnvString( VAR StringName : ARRAY OF CHAR ) ;

   PROCEDURE WriteEscapedCh( Ch : CHAR ) ;
   BEGIN
      IF ( Ch = '"' ) OR ( Ch = '|' ) THEN
         Wrch( '|' ) ;
      END (* if *) ;
      Wrch( Ch ) ;
   END WriteEscapedCh ;


VAR
   Buffer                        : ARRAY [ 0..255 ] OF CHAR ;
   Length                        : CARDINAL ;
   NameLength                    : CARDINAL ;
   Index                         : CARDINAL ;
   ThisResult                    : INTEGER ;
BEGIN
   IF GetGlobalString( Buffer , Length , StringName ) < 0 THEN
      IF Result = 0 THEN
         Result := StringNotFound ;
      END (* if *) ;
      Debug.WriteS( "String not found*N" ) ;
      RETURN ;
   END (* if *) ;
   IF Commands THEN
      WriteS( ".set " ) ;
      Wrch( '"' ) ;
   END (* if *) ;
   NameLength := LengthC( StringName ) ;
   Index := 0 ;
   WHILE Index < NameLength DO
      WriteEscapedCh( StringName[ Index ] ) ;
      INC( Index ) ;
   END (* while *) ;
   IF Commands THEN
      Wrch( '"' ) ;
   END (* if *) ;
   REPEAT
      Wrch( ' ' ) ;
      INC( Index ) ;
   UNTIL Index >= 20 ;
   Wrch( '"' ) ;
   Index := 0 ;
   WHILE Index < Length DO
      WriteEscapedCh( Buffer[ Index ] ) ;
      INC( Index ) ;
   END (* while *) ;
   Wrch( '"' ) ;
   WriteS( "*N" ) ;
END PrintEnvString ;

(* ------------------------------------------------------------------------- *)

PROCEDURE PrintMatchingEnvStrings( VAR StringName : ARRAY OF CHAR ) ;
VAR
   Index                        : CARDINAL ;
   Buffer                       : ARRAY [ 0..255 ] OF CHAR ;
   Length                       : CARDINAL ;
   Matched                      : BOOLEAN ;
BEGIN
   Index := 0 ;
   Matched := FALSE ;
   WHILE GetGlobalStringName( Buffer , Length , Index ) >= 0 DO
(* DRL Bug *)
      Length := LengthC( Buffer ) ;
      Buffer[ Length ] := 0C ;
      IF Matches( StringName , Buffer ) THEN
         PrintEnvString( Buffer ) ;
         Matched := TRUE ;
      END (* if *) ;
      INC( Index ) ;
   END (* while *) ;
   IF NOT Matched THEN
      Debug.WriteS( "*NNo match with *'" ) ;
      Debug.WriteS( Parameter ) ;
      Debug.WriteS( "*'*N" ) ;
      Result := NoMatchFound ;
   END (* if *) ;
END PrintMatchingEnvStrings ;

(* ------------------------------------------------------------------------- *)

PROCEDURE GiveHelp() ;
BEGIN
   WriteS( Version ) ;
   WriteS( "Prints current Envronment String names and values*N" ) ;
   WriteS( "Keywords :*N" ) ;
   WriteS( "  Name     : List of ( wild card ) names to print*N" ) ;
   WriteS( "  To       : Where to print the output*N" ) ;
   WriteS( "  Commands : Output '.set name value' for CLI input*N" ) ;
   WriteS( "  Identify : Prints name and version number*N" ) ;
   WriteS( "  Help     : Prints this information*N" ) ;
END GiveHelp ;

(* ------------------------------------------------------------------------- *)

VAR
VAR
   Result                     : INTEGER ;
   Commands                   : BOOLEAN ;
   Index                      : CARDINAL ;
   Output                     : INTEGER ;
   NumberOfFiles              : CARDINAL ;
   Parameter                  : ARRAY [ 0..255 ] OF CHAR ;
   Length                     : CARDINAL ;
   Handle                     : DecodedInformation ;
   Junk                       : BOOLEAN ;
   KeyString                  : ARRAY [ 0..80 ] OF CHAR ;
   Version                    : ARRAY [ 0..30 ] OF CHAR ;
   ArgumentString             : ARRAY [ 0..255] OF CHAR ;
   ArgumentLength             : CARDINAL ;

BEGIN
   Result := 0 ;
   KeyString := "Name/?[ * ] To/K[ Output: ] Commands/S Identify/S Help/S" ;
   Version := "PrintEnv Version 0.01/07*N" ;

   ArgumentLength := Program.Arguments (ArgumentString);
   IF Check( DecodeInit( Handle , KeyString , ArgumentString ) ) THEN
   END (* if *) ;   
   IF HelpRequired( Handle , Result ) THEN
      GiveHelp() ;
      Program.Stop (0) ;
   ELSE
      IF IdentifyRequired( Handle , Result ) THEN
         WriteS( Version ) ;
         IF Result < 0 THEN
            Program.Stop (0) ;
         END (* if *) ;
      END (* if *) ;
   END (* if *) ;
   IF Result = 0 THEN
      Junk := Check( GetStateArg( Commands , "Commands" , Handle ) ) ;
      Junk := Check( GetNumberOfValues( NumberOfFiles , "Name" , Handle ) ) ;
      IF Check( GetStringArg( Parameter , Length , "To" , 1 , Handle ) ) THEN
         Parameter[ Length ] := 0C ;
         Output := FindOutput( Parameter ) ;
         Junk := Check( Output ) AND Check( SelectOutput( Output ) ) ;
      END (* if *) ;
      Index := 1 ;
      WHILE ( Result = 0 ) AND ( Index <= NumberOfFiles ) DO
         IF Check( GetStringArg( Parameter , Length ,
                                   "Name" , Index , Handle ) ) THEN
            Parameter[ Length ] := 0C ;
            IF Instr( '*' , Parameter ) THEN
               PrintMatchingEnvStrings( Parameter ) ;
            ELSE
               PrintEnvString( Parameter ) ;
            END (* if *) ;
         END (* if *) ;
         INC( Index ) ;
      END (* while *) ;
      IF Output >= 0 THEN
         Junk := Check( CloseStream( Output ) ) ;
      END (* if *) ;
      Junk := Check( DecodeEnd( Handle ) ) ;
   END (* if *) ;
   Program.Stop (Result) ;

END PrintEnv.
