[Back to CMDLINE SWAG index] [Back to Main SWAG index] [Original]

    {
    This unit will allow you to access the original command line as it was
    originally entered by the user.  Here is the source code for the CmdLine
    object.  It was developed by Computer Mavericks, using information gleened
    from the info-pascal internet forum.  In the spirit of the forum, this is
    offered into the public domain.  If you use it, think kind thoughs of Lee
    Crites and the small staff here at CM.

    This was written using Borland Pascal 7.0's BPW in Real Mode.  (after all,
    you'll probably not have to many command line parameters to check if you
    are working in Windows or OS2, right???  It requires the STRINGS unit that
    comes with BP7.  If you are working in TP6/TP5.5, and don't have access to
    this, we do (should I say <did>) have a unit for doing null terminated
    strings for each of those releases that we might be able to send out.  As
    I remember, we took the BPW 1.0 Strings unit and played around with it
    until it compiled in TP6, so I don't know which version that I still have
    access to (it's been a while since I looked at our last tp6 archives).

    I threw this together over the weekend, and tested it using the whoami
    program and test.bat file.  There might still be a problem floating around
    in there somewhere.  This is about the first time that I've really sent
    out some source code like this, and really haven't gone through it with a
    fine tooth comb.  If there are bugs or (more importantly) imporvements
    that some of you can see, please let me know.
    }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    { =-=-=-=-=                                                   =-=-=-=-= }
    { =-=                                                               =-= }
    {                               CMDLINE.PAS                             }
    { This unit contains the following:                                     }
    {    -- CMDLINE, a mute object that will parse the physical command     }
    {       line as input by the user, and return the information that was  }
    {       requested.                                                      }
    { =-=                                                               =-= }
    { =-=-=-=-=                                                   =-=-=-=-= }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    {$D-} { debugging information off }
    {$X+} { allow extended syntax }
    {$V+} { require same var type }
    {$R-} { range checking off }
    {$E+} { Add 8087 software emulation code }
    {$N+} { Use the 8087 software emulation code }
    {$I-} { Enable IOResult for I/O checking }
    {$B-} { Short-cut boolean evauation }
    {$O+} { Allow this to be a part of an overlay }
    Unit CmdLine;
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Interface
    Uses Strings;  { Strings is a BP7 unit.  I have a TP6 version available }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Type
      TCmdLine = Object
         Constructor Init;
         Destructor Done; Virtual;
         { this will return the information requested -- the whole reason   }
         { for doing this in the first place.  It will return TRUE if the   }
         { ParmStrIn was found, otherwise false. This way you can check for }
         { switches entered with no data, since StrBack would otherwise be  }
         { null.                                                            }
         Function  GetParameter(ParmStrIn:String;Var StrBack:String):Boolean;
         Function  GetCommandLine:String;                 { the entire line }
         Function  GetActualProgram:String;       { the actual name entered }
         Function  GetCallingProgram:String;     { the fully qulaified name }
         Function  GetLaunchingProgram:String; { what environment called me }
         Procedure Trim;        { remove leading, trailing, multiple spaces }
         Procedure Capitalize;                   { just what it sounds like }
         Procedure Restore;                 { restores the original version }
         Function  GetDivideChars:String;      { returns the dividing chars }
         Procedure SetDivideChars(NewDivideChars:String);       { sets them }

         Private
         DivideChars:String;             { the chars that signal a new parm }
         CommandLine,OriginalCommandLine:String;  { just what the name says }
         LaunchingProgram,CallingProgram,ActualProgram:String;
         End; { TCmdLine }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Var
      CommandLine:TCmdLine;
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    {PAGE}
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Implementation
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Const
      NONE = '<NONE>';
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Procedure MakeCaps(Var ss:String);
    Var xx,ll:Byte;
    Begin
      ll := Length(ss);
      For xx := 1 to ll Do ss[xx] := UpCase(ss[xx]);
    End; { MakeCaps }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Procedure TrimString(Var ss:String);
    Var xx:Integer;
    Begin
      If (length(ss) < 1) Then exit;
      { remove leading spaces }
      While (ss[1] = chr(32)) Do Begin delete(ss,1,1);
      If (length(ss) < 1) Then exit; End;
      { remove trailing spaces }
      While (ss[length(ss)] = chr(32)) Do Delete(ss,length(ss),1);
      { remove imbedded spaces }
      xx := pos('  ',ss);
      While (xx <> 0) Do Begin Delete(ss,xx,1); xx := Pos('  ',ss); End;
    End; { TrimString }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Procedure TCmdLine.Capitalize;
    Begin
      MakeCaps(CommandLine);
    End; { Capitalize }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Destructor TCmdLine.Done;   { I'm not sure what can/should be done here }
    Begin
    End; { CmdLine }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Function TCmdLine.GetActualProgram:String;
    Begin
      GetActualProgram := ActualProgram;
    End; { GetActualProgram }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Function TCmdLine.GetCallingProgram:String;
    Begin
      GetCallingProgram := CallingProgram;
    End; { GetCallingProgram }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Function TCmdLine.GetCommandLine:String;
    Begin
      GetCommandLine := CommandLine;
    End; { GetCommandLine }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Function TCmdLine.GetDivideChars:String;
    Begin
      GetDivideChars := DivideChars;
    End; { GetDivideChars }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Function TCmdLine.GetLaunchingProgram:String;
    Begin
      GetLaunchingProgram := LaunchingProgram;
    End; { GetLaunchingProgram }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Function TCmdLine.GetParameter(ParmStrIn:String;Var StrBack:String):Boolean;
    Const AM:Char = Chr(254);
    Var ss,PrmStr:String; ssLen,ParmLen:Integer;
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Procedure SkipQuote(Var xx:Integer;WhichQuote:Char);
      Begin
        Inc(xx);
        While (xx <= ssLen) Do Begin
          If (ss[xx] = WhichQuote) Then Exit;
          Inc(xx);
          End;
      End; { SkipQuote }
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Procedure Setup;
      Var xx,ll:Integer;
      Begin
        ss := CommandLine; MakeCaps(ss);
        PrmStr := ParmStrIn; MakeCaps(PrmStr);
        ssLen := Length(ss); ParmLen := Length(PrmStr);
        { change all dividechars into AMs }
        xx := 0;
        While (xx <= ssLen) Do Begin
           Inc(xx);
           Case ss[xx] Of
             '''','"','`': SkipQuote(xx,ss[xx]);
             Else If (Pos(ss[xx],DivideChars) > 0) Then ss[xx] := AM;
             End; { case }
           End; { while }
      End; { Setup }
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Function IsThisIt(Var Start:Integer):Boolean;
      Var xx:Integer;
      Begin
        IsThisIt := False;
        For xx := 1 to ParmLen Do Begin
          If (ss[Start+xx] <> PrmStr[xx]) Then Exit;
          End; { yy }
        Start := Start+ParmLen;
        IsThisIt := True;
      End; { IsThisIt }
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Function FindIt:Boolean;
      Var xx,yy,l1:Integer;
      Begin
        FindIt := False; StrBack := '';
        l1 := ssLen - ParmLen; If (l1 < 1) Then Exit;
        xx := 0;
        While (xx <= l1) Do Begin
           Inc(xx);
           If (ss[xx] = AM) Then Begin
              If IsThisIt(xx) Then Begin
                 FindIt := True; yy := 0;
                 { find the next AM, and copy the string out }
                 While (xx+yy <= ssLen) And (ss[xx+yy] <> AM) Do Inc(yy);
                 StrBack := Copy(CommandLine,xx+1,yy-1);
                 { delete trailing space(s), if there }
                 While (StrBack[Length(StrBack)] = ' ') Do
                    Delete(StrBack,Length(StrBack),1);
                 { we've got the answer, get out }
                 Exit;
                 End; { this is it }
              End; { found }
           End; { xx }
      End; { FindIt }
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Begin
      { default to not found }
      GetParameter := False; StrBack := '';
      If (Length(CommandLine) < 1) or (CommandLine = NONE) Then Exit;
      If (Length(ParmStrIn) < 1) Then Exit;

      Setup; GetParameter := FindIt;
    End; { GetParameter }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Constructor TCmdLine.Init;
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Function LaunchedBy:String;
      Var ParentSeg:^word; p:pchar;
      Begin
        ParentSeg := ptr(PrefixSeg,$0016); p := ptr(ParentSeg^-1,8);
        LaunchedBy := StrPas(p);
      End; { LaunchedBy }
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Function RealCommandLine:String;
      Var ss:String;
      Begin
        ss := StrPas(ptr(PrefixSeg,130));
        If (Ord(ss[0]) > 0) Then ss[0] := Chr(Ord(ss[0])-1);
        RealCommandLine := ss;
      End; { RealCommandLine }
      { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
      Function ActualProgramName:String;
      Var cc:Char; ss:String; p:PChar; xx,yy:Byte;
      Begin
        p := ptr(PrefixSeg,228); ss := ''; xx := 0; yy := 0;
        Repeat
          cc := p[xx];
          If (cc <> #0)
             Then Begin
                  If (Ord(cc) > 47) and (Ord(cc) < 126) Then Begin
                     ss := ss+' '; ss[Ord(ss[0])] := p[xx]; End;
                  End
             Else Begin Inc(yy); If (yy = 1) Then ss := ss+'.'; End;
          Inc(xx);
          Until (xx > 12) or (yy > 1);
          If (ss[Ord(ss[0])] = '.') Then ss[0] := Chr(Ord(ss[0])-1);
        ActualProgramName := ss;
      End; { ActualProgramName }
      { -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Begin
      LaunchingProgram := LaunchedBy;        { what environment launched me }
      OriginalCommandLine := RealCommandLine;   { the original command line }
      If (Length(OriginalCommandLine) < 1) Then OriginalCommandLine := NONE;
      CommandLine := OriginalCommandLine;                { default to exact }
      CallingProgram := ActualProgramName;     { just what the user entered }
      ActualProgram := ParamStr(0);   { BP returns the fully qualitied name }

      SetDivideChars('-/');                   { set the default DivideChars }
    End; { Init }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Procedure TCmdLine.Restore;
    Begin
      CommandLine := OriginalCommandLine;
    End; { Restore }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Procedure TCmdLine.SetDivideChars(NewDivideChars:String);
    Begin
      DivideChars := NewDivideChars;
    End; { SetDivideChars }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Procedure TCmdLine.Trim;
    Begin
      TrimString(CommandLine);
    End; { Trim }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }
    Begin { main block }
      CommandLine.Init;
    End. { main block }
    { =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= }

    { This is a test program showing some of the cmdline object functions }
    Program whoami;
    Uses DOS, CRT, CmdLine;
    Var ss:String;
    begin
      { show some general information that it returns }
      WriteLn('I was launched by [',CommandLine.GetLaunchingProgram,']');
      WriteLn('Program executed was [',CommandLine.GetCallingProgram,']');
      WriteLn('BP returnd [',CommandLine.GetActualProgram,']');
      WriteLn('Command line was [',CommandLine.GetCommandLine,']');

      { these will change the part that you can use }
      CommandLine.Capitalize; CommandLine.Trim;
      WriteLn('Fixed command line [',CommandLine.GetCommandLine,']');

      { this will return it to it's original value }
      CommandLine.Restore;
      WriteLn('Restored command line [',CommandLine.GetCommandLine,']');

      { check for the existance of some parameter }
      If CommandLine.GetParameter('s',ss)
         Then WriteLn('Parameter "s" was [',ss,']')
         Else WriteLn('Parameter "s" was not found');
      If CommandLine.GetParameter('ss',ss)
         Then WriteLn('Parameter "ss" was [',ss,']')
         Else WriteLn('Parameter "ss" was not found');
    end.

    {
    ------------------------------ test.bat ------------------------------
    @Echo Off
    whoami /a:france/b 'this-is "the" way'  /chest /store /left
    whoami /aaa-bbb/s"this 'is'-it"   /sss
    whoami -ss/shell

    }

[Back to CMDLINE SWAG index] [Back to Main SWAG index] [Original]