{-------------------------------------------------------------
{
{ File: ParseCmd.pas
{
{ Abstract:
{
{    Parse the command line, interpreting switches, for the fortran 
{    consolidator. 
{
{------------------------------------------------------------}




{-------------------------------------------------------------}
{
{ Change Log:
{
{ 3 june 82 Rosemary
{ Remove QUIET/VERBOSE information from Writehelpmessage
{
{ 26 may 82  Rosemary
{ Allow /LIBRARY switch in consolidator
{
{--------------------------------------------------------------}

PROCEDURE ParseCommandLine(VAR ins : PArgRec);
{-------------------------------------------------------------
{
{ Abstract:
{
{    Parse the command line, interpreting switches 
{
{ Environment:
{
{ Side Effects:
{
{    - Sets initial switch values.
{
{ Calls:
{
{     ReportError
{
{     InitSwitchAr
{
{     NextId
{
{     ParseCmdArgs
{
{     ParseStringArgs
{
{     InitStaticSwitchVars
{
{     InitDynamicSwitchVars
{
{     InterpretArgs
{
{------------------------------------------------------------}



label
 999;
         


CONST

 numSwitches = 6;
 defLibExtension='.LIB';

TYPE

 Switch_type =     {segments and stat}
  (t_dummy,
   t_help,
   t_quiet, t_verbose,
   t_extern,
   t_debug, t_nodebug);

CONST
 last_of_switch_type = t_nodebug;
   


   
VAR

 rootFileName: PathName;     { InFileName without .FOR extension }
 libfilename: PathName;      { LIBRARY filename }
 
 switches: PSwitchRec;
 err: String;
 switchAr: CmdArray;
 ok: BOOLEAN;
 c: CHAR;
 s: CString;
 isSwitch: BOOLEAN;
 i: INTEGER;
 
 valid_command_line: BOOLEAN;

 switch_info : ARRAY[switch_type] OF RECORD
                                       seen: boolean;
                                       arg: CString;
                                       complement: switch_type;
                                     END;

 allow_arg: SET OF Switch_type;
 
 outs: PArgRec;



PROCEDURE ReportError(err: ErrorType; param: CString);
{-------------------------------------------------------------
{
{ Abstract:
{
{     Reports errors in the command line to the user.
{
{ Parameters:
{
{     err - a variable of an enumerated type which indicates the nature
{           of the error.
{
{     param - a string which is used in constructing the error message.
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effects:
{
{     - Writes an error message to the standard file Output (via StdError).
{
{     - Sets the global variable valid_command_line to false.
{
{ Calls:
{
{     StdError
{
{------------------------------------------------------------}

BEGIN
StdError(err, param, false);
valid_command_line := false;
END;

PROCEDURE InterpretArgs;
{-------------------------------------------------------------
{
{ Abstract:
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effect:
{
{ Calls:
{
{     save_switch_info
{
{     WriteHelpMessage
{
{     DoIns
{
{     DoOuts
{
{     DoSwitches
{
{     prepare_files
{
{ Design:
{
{------------------------------------------------------------}
VAR
    TempOutFileName: PathName;
    TempFid,Blks,Bits: integer;
    

PROCEDURE WriteHelpMessage;
{-------------------------------------------------------------
{
{ Abstract:
{
{     Displays help message to the user.
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effect:
{
{ Calls:
{
{     GetConfirm
{
{     UniqueCmdIndex
{
{     ReportError
{
{ Design:
{
{------------------------------------------------------------}

VAR
 prompt: String;
 i, index: integer;
 s: pSwitchRec;
 need_help: boolean;
  
BEGIN
prompt := 'Would you like information about switches? ';

repeat
need_help := false;
writeln;
writeln('':4, 'Consolidate uses a list of .SEG and .PSG files to');
writeln('':4, 'fix unresolved references in .PSG files, changing them');
writeln('':4, 'to .SEG files');
writeln;
writeln('':4, 'Command line is of the form:                 ');
writeln('':8, 'Consolidate <seg_or_psg_file_name> {,<seg_or_psg_file_name>}',
              ' {/switch}');
writeln;

i := GetConfirm(NullIdleProc(**), true, prompt, 2, s);

while s <> nil do
 BEGIN
 ConvUpper(s^.switch);
 IF UniqueCmdIndex(s^.switch, SwitchAr, NumSwitches) <> ord(t_help)
  THEN
  IF not need_help
   THEN
   ReportError(ErAnyError, '** Only HELP switch is allowed here.');
 need_help := true;
 s := s^.next;
 END;
 
until not need_help;

IF i = 1 THEN
 BEGIN
 writeln;
 writeln('':4, 'The valid switches are: ');
 writeln;
 writeln('':8,
'/HELP  - prints the help message.');
 writeln;
{ writeln('':8,
'/QUIET    - disables display of procedure and function names.');
 writeln;
 writeln('':8,
'/VERBOSE  - enables display of procedure and function names. (default)');
 writeln; }
 writeln('':8,
'/LIBRARY[=string] - specifies file containing names of external modules');
 writeln;
 END;
END;

PROCEDURE DoSwitches;
{-------------------------------------------------------------
{
{ Abstract:
{
{     Process switch information.
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effects:
{
{
{ Design:
{
{------------------------------------------------------------}

VAR
 index: switch_type;
 
BEGIN
index := t_dummy;

REPEAT
index := Succ(index);

IF switch_info[index].seen THEN
  
 CASE index OF
   
    { QUIET: complement is VERBOSE }
  t_quiet: noisy := off;

    { VERBOSE: complement is QUIET }
  t_verbose: noisy := on;

    { LIBRARY }
  t_extern:
    begin
    Extern:=on;
    with switch_info[index] do
      begin
      if arg='' then ReportError(erAnyError,
                           'Null String for LIBRARY switch not allowed')
        else begin
        s:=substr(arg,length(arg)-defextlen+1,defextlen);
        convupper(s);
        if s=deflibextension then libfilename:=arg else
          libfilename:=concat(arg,deflibextension);
        end;
      end; { with }
    end;
    
    { DEBUG: complement is NODEBUG }
  t_debug: debug := on;

    { NODEBUG: complement is DEBUG }
  t_nodebug: debug := off;

 END; {case}
UNTIL (index = last_of_switch_type) or (not valid_command_line);
END;

PROCEDURE Save_Switch_Info;
{-------------------------------------------------------------
{
{ Abstract:
{
{     Process the list of switches.
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effects:
{
{ Calls:
{
{     UniqueCmdIndex
{
{     ReportError
{
{ Design:
{
{------------------------------------------------------------}

VAR
 index: integer;
 s: switch_type;
                 

PROCEDURE Init_Switch_Info;
{-------------------------------------------------------------
{
{ Abstract:
{
{ Environment:
{
{ Side Effects:
{
{ Design:
{
{------------------------------------------------------------}

VAR
 sw: Switch_type;
 
BEGIN
FOR sw := t_dummy TO last_of_switch_type DO
 WITH switch_info[sw] DO BEGIN
                           seen := false;
                           arg := '';
                         END;

switch_info[t_dummy    ].complement := t_dummy;
switch_info[t_help     ].complement := t_dummy;
switch_info[t_quiet    ].complement := t_verbose;
switch_info[t_verbose  ].complement := t_quiet;
switch_info[t_extern   ].complement := t_dummy;
switch_info[t_debug    ].complement := t_nodebug;
switch_info[t_nodebug  ].complement := t_debug;

allow_arg := [t_extern];

END;

BEGIN { Save_Switch_Info }
Init_switch_info;

while (switches <> nil) and (valid_command_line) do
 BEGIN
 ConvUpper(switches^.switch);
 index := UniqueCmdIndex(switches^.switch, SwitchAr, NumSwitches); 

 IF (1 <= index) and (index <= NumSwitches)
  THEN
  with switch_info[ recast(index, switch_type) ] do
   BEGIN
   seen := true;
   arg := switches^.arg;
   IF complement <> t_dummy THEN
    BEGIN
    switch_info[complement].seen := false;
    switch_info[complement].arg := '';
    END;
   END

  ELSE
  case index of
   NumSwitches + 1:
    ReportError(ErBadSwitch, switches^.switch);
   NumSwitches + 2:
    ReportError(ErSwNotUnique, switches^.switch);
  END; {case}
 
 switches := switches^.next;
 END;

s := t_dummy;
while (s <> last_of_switch_type) and (valid_command_line) do
 BEGIN
 s := succ(s);
 IF not (s in allow_arg)
  THEN
  IF switch_info[s].arg <> ''
   THEN
   ReportError(ErNoSwParam, SwitchAr[ord(s)]);
 END;
 
END; { Save_Switch_Info }

BEGIN { InterpretArgs }
IF valid_command_line THEN save_switch_info;

IF valid_command_line and switch_info[t_help].seen 
    THEN BEGIN
           WriteHelpMessage;
           valid_command_line := false;
         END;
 
IF valid_command_line THEN DoSwitches;

IF valid_command_line and Extern then
  begin
  Tempfid:=FSSearchist(FSSysSearchlist,Libfilename,Blks,Bits);
  if Tempfid=0 then ReportError(erAnyError,
                          concat(Libfilename,' does not exist'))
    else reset(Extfile,Libfilename);
  end;

END; { InterpretArgs }

PROCEDURE InitSwitchAr;
{-------------------------------------------------------------
{
{ Abstract:
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effect:
{
{ Calls:
{
{ Design:
{
{------------------------------------------------------------}

BEGIN
{$R-}

SwitchAr[ ord(t_help     ) ] := 'HELP'     ;
SwitchAr[ ord(t_quiet    ) ] := 'QUIET'    ;
SwitchAr[ ord(t_verbose  ) ] := 'VERBOSE'  ;
SwitchAr[ ord(t_extern   ) ] := 'LIBRARY' ;
SwitchAr[ ord(t_debug    ) ] := 'DEBUG'    ;
SwitchAr[ ord(t_nodebug  ) ] := 'NODEBUG'  ;

{$R=}
END;

PROCEDURE InitDynamicSwitchVars;
{-------------------------------------------------------------
{
{ Abstract:
{
{     Initialize dynamic switch-associated variables.
{
{ Environment:
{
{     Internal to ParseCommandLine.
{
{ Side Effect:
{
{ Calls:
{
{ Design:
{
{------------------------------------------------------------}

BEGIN
Noisy := true;
Extern:= false;
Debug := false;
END;

BEGIN { ParseCommandLine }

InitSwitchAr;

s := '';
err := '';

c := NextId(s, isSwitch);          {remove "Consolidate"}
IF (c <> ' ') and (c <> CCR) THEN
  BEGIN
   ReportError(ErIllCharAfter, 'Consolidate');
   goto 999;
  END
else
  BEGIN
 
    ok := ParseCmdArgs(ins, outs, switches, err);

    repeat
      valid_command_line := true;

      IF not ok THEN ReportError(ErAnyError, err)
                ELSE BEGIN
                       InitDynamicSwitchVars;
                       InterpretArgs;
                     END;

999:
      IF not valid_command_line THEN
          BEGIN
            write('In,In {,In} :');
            readln(s);
            ok := ParseStringArgs(s, ins, outs, switches, err);
          END;

    until valid_command_line;

  END;
 
END;  { ParseCommandLine }