home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0000 - 0009 / ibm0000-0009 / ibm0003.tar / ibm0003 / TPOWER54.ZIP / DEMOSRC.ARC / REP.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-07-10  |  9.7 KB  |  325 lines

  1. {$S-,R-,V-,I-,B-,F-}
  2. {$M 4000,65536,655360}
  3.  
  4. {*********************************************************}
  5. {*                      REP.PAS 5.07                     *}
  6. {*                    Command repeater                   *}
  7. {*     An example program for Turbo Professional 5.0     *}
  8. {*        Copyright (c) TurboPower Software 1987.        *}
  9. {* Portions copyright (c) Sunny Hill Software 1985, 1986 *}
  10. {*     and used under license to TurboPower Software     *}
  11. {*                 All rights reserved.                  *}
  12. {*********************************************************}
  13.  
  14. program Rep;
  15.   {-Repeat commands}
  16.  
  17. uses
  18.   Dos,                       {standard DOS/BIOS routines}
  19.   TpString,                  {Turbo Professional string handling routines}
  20.   TpCmdLin,                  {Turbo Professional command line parsing routines}
  21.   TpDos,                     {Turbo Professional DOS call routines}
  22.   TpInt,                     {Turbo Professional ISR management}
  23.   TpMacro;                   {Turbo Professional macro engine}
  24.  
  25. var
  26.   StdErr : Text;             {File for screen status}
  27.   StdErrBuf : Char;          {Buffer for writing to StdErr}
  28.   ConIn : Boolean;           {True if input is from keyboard}
  29.   Query : Boolean;           {True to prompt before processing each command}
  30.   HaveKeys : Boolean;        {True if macro keystrokes specified}
  31.   Command : string;          {Mask for command to execute}
  32.   ActualCommand : string;    {Actual command after tokens inserted}
  33.   Keys : string;             {Keys to send to command}
  34.   InputLine : string;        {Line from input stream}
  35.   Repeats : Integer;         {Number of times to repeat}
  36.   R : Integer;               {Which repeat is happening}
  37.  
  38.   procedure FatalError(msg : string);
  39.     {-Report message and halt}
  40.   begin
  41.     RemoveMacros;
  42.     WriteLn(StdErr);
  43.     if msg <> '' then
  44.       WriteLn(StdErr, msg);
  45.     Halt(1);
  46.   end;
  47.  
  48.   procedure WriteHelp;
  49.     {-Show a brief help screen and halt}
  50.   begin
  51.     WriteLn('Usage: REP "Command" [Options] [<InputStream]');
  52.     WriteLn('Options:');
  53.     WriteLn('   /K KeyList - Pass keys in KeyList to Command');
  54.     WriteLn('   /Q - Query before proceeding');
  55.     WriteLn('   /R n - Repeat Command n times');
  56.     WriteLn('Command:');
  57.     WriteLn('  May not directly specify input or output redirection, but may');
  58.     WriteLn('  contain the following parser symbols:');
  59.     WriteLn('     @n - nth word in the input line (for n in 1..9)');
  60.     WriteLn('     @0 - whole input line');
  61.     WriteLn('     @B - discretionary DOS backslash \');
  62.     WriteLn('     @D - directory name from first word of input line');
  63.     WriteLn('     @F - filename from first word of input line');
  64.     WriteLn('     @I - input redirection symbol <');
  65.     WriteLn('     @O - output redirection symbol >');
  66.     WriteLn('     @P - piping symbol |');
  67.     WriteLn('KeyList:');
  68.     WriteLn('  May contain normal ASCII characters or specify them by number.');
  69.     WriteLn('     #nnn - ASCII character nnn (decimal)');
  70.     WriteLn('  Enter #0#Scan for extended scan codes (e.g., #0#59 = <F1>).');
  71.     WriteLn('  May also contain parser symbols as described above.');
  72.     Halt(1);
  73.   end;
  74.  
  75.   procedure Initialize;
  76.     {-Initialize globals}
  77.   begin
  78.  
  79.     {Open StdErr for status reporting}
  80.     if not(OpenStdDev(StdErr, 2)) then begin
  81.       WriteLn('Error opening StdErr');
  82.       Halt(1);
  83.     end else
  84.       {Force buffer flush every character}
  85.       SetTextBuf(StdErr, StdErrBuf, 1);
  86.  
  87.     {Is standard input coming from keyboard?}
  88.     ConIn := HandleIsConsole(0);
  89.  
  90.     Command := '';
  91.     Keys := '';
  92.     Query := False;
  93.     Repeats := 1;
  94.   end;
  95.  
  96.   procedure GetParameters;
  97.     {-Analyze command line for parameters}
  98.   var
  99.     I : Integer;
  100.     Arg : string;
  101.   begin
  102.     I := 1;
  103.     while I <= ParamCount do begin
  104.       Arg := ParamStr(I);
  105.  
  106.       if (Length(Arg) = 2) and ((Arg[1] = '/') or (Arg[1] = '-')) then
  107.         {A command directive}
  108.         case Upcase(Arg[2]) of
  109.           'K' : Keys := GetArgString(I, True, True);
  110.           'R' : Repeats := GetArgNumber(I);
  111.           'Q' : Query := True;
  112.         else
  113.           FatalError('Unrecognized option: '+Arg);
  114.         end
  115.  
  116.       else if Command = '' then begin
  117.         {Convert escapes and ascii numerals into a full match string}
  118.         Dec(I);
  119.         Command := GetArgString(I, True, False);
  120.  
  121.       end else
  122.         FatalError('More than one command string specified');
  123.  
  124.       case CmdLineError of
  125.         1 : FatalError('Missing argument after '+ParamStr(I));
  126.         2 : FatalError('Invalid argument: '+ParamStr(I));
  127.         3 : FatalError('Program error in unit TpCmdLin');
  128.       end;
  129.  
  130.       {On to next parameter}
  131.       Inc(I);
  132.     end;
  133.  
  134.     if Command = '' then
  135.       FatalError('No command specified');
  136.  
  137.     HaveKeys := (Keys <> '');
  138.   end;
  139.  
  140.   procedure RunExec(var Command : string; HaveKeys : Boolean);
  141.     {-Execute the specified command and check for error}
  142.   var
  143.     ExecStatus : Integer;
  144.   begin
  145.     if not(Query) then
  146.       WriteLn(StdErr, Command, ^M^J);
  147.  
  148.     if HaveKeys then begin
  149.       {Play the macro for the command}
  150.       MacrosOn;
  151.       StartMacro(@ScrapMacro);
  152.     end;
  153.  
  154.     {Run the command}
  155.     ExecStatus := execdos(Command, True, nil);
  156.  
  157.     {Check for errors}
  158.     case ExecStatus of
  159.       0 : {Success} ;
  160.       -1 : FatalError('Insufficient free list memory');
  161.       -2 : FatalError('DOS setblock error');
  162.       -3 : FatalError('DOS setblock error after EXEC');
  163.       -4 : FatalError('Insufficient DOS memory');
  164.     else
  165.       FatalError('DOS error '+long2str(ExecStatus));
  166.     end;
  167.  
  168.     {Turn off macros until next time}
  169.     if HaveKeys then
  170.       MacrosOff;
  171.  
  172.   end;
  173.  
  174.   function ConvertTokens(var Mask, Line : string) : string;
  175.     {-Replace tokens in mask with counterparts from line}
  176.   var
  177.     Mpos : Word;
  178.     Lpos : Integer;
  179.     OutStr : string;
  180.   begin
  181.     {Scan the mask}
  182.     Mpos := 1;
  183.     OutStr := '';
  184.     while Mpos <= Length(Mask) do begin
  185.       if Mask[Mpos] = '@' then begin
  186.         Inc(Mpos);
  187.  
  188.         case Upcase(Mask[Mpos]) of
  189.           '@' :              {Single at sign}
  190.             OutStr := OutStr+'@';
  191.           '0' :              {Whole line}
  192.             OutStr := OutStr+Line;
  193.           '1'..'9' :         {Nth word}
  194.             OutStr := OutStr+ParamStrPos(Line, Ord(Mask[Mpos])-Ord('0'), Lpos);
  195.           'B' :              {Discretionary backslash}
  196.             OutStr := addbackslash(OutStr);
  197.           'D' :              {Directory of first word}
  198.             OutStr := OutStr+justpathname(ParamStrPos(Line, 1, Lpos));
  199.           'F' :              {Filename of first word}
  200.             OutStr := OutStr+justfilename(ParamStrPos(Line, 1, Lpos));
  201.           'I' :              {Input redirection symbol}
  202.             OutStr := OutStr+'<';
  203.           'O' :              {Output redirection symbol}
  204.             OutStr := OutStr+'>';
  205.           'P' :              {Piping symbol}
  206.             OutStr := OutStr+'|';
  207.         else
  208.           OutStr := OutStr+Mask[Mpos];
  209.         end;
  210.  
  211.       end else
  212.         OutStr := OutStr+Mask[Mpos];
  213.  
  214.       Inc(Mpos);
  215.     end;
  216.  
  217.     ConvertTokens := OutStr;
  218.   end;
  219.  
  220.   procedure BuildMacro(Line : string);
  221.     {-Convert line into a macro, stored in TempMacro}
  222.   var
  223.     ActualKeys : string;
  224.     Alen : Byte absolute ActualKeys;
  225.     I : Word;
  226.   begin
  227.     {Replace tokens with their values}
  228.     ActualKeys := ConvertTokens(Keys, Line);
  229.  
  230.     {Convert to macro format, storing in the ScrapMacro}
  231.     with ScrapMacro do begin
  232.       numkeys := 0;
  233.       I := 1;
  234.       while I <= Alen do begin
  235.         if (ActualKeys[I] = #0) and (I < Alen) then begin
  236.           Inc(I);
  237.           Inc(numkeys);
  238.           {Scan code in high byte, #0 in low}
  239.           keyarray[numkeys] := Ord(ActualKeys[I]) shl 8;
  240.         end else begin
  241.           Inc(numkeys);
  242.           keyarray[numkeys] := chartomacro(ActualKeys[I]);
  243.         end;
  244.         Inc(I);
  245.       end;
  246.       keyarray[Succ(numkeys)] := endofmacro;
  247.     end;
  248.   end;
  249.  
  250.   function ReadKeyIn(List : string) : Char;
  251.     {-Read via BIOS until key matches one in list}
  252.   var
  253.     C : Char;
  254.     Regs : registers;
  255.   begin
  256.     with Regs do
  257.       repeat
  258.         ah := 0;
  259.         intr($16, Regs);
  260.         C := Upcase(Char(al));
  261.         if pos(C, List) <> 0 then begin
  262.           ReadKeyIn := C;
  263.           Exit;
  264.         end;
  265.       until False;
  266.   end;
  267.  
  268.   function DoQuery(Command : string) : Char;
  269.     {-Assure we should go ahead with command}
  270.   var
  271.     C : Char;
  272.   begin
  273.     if Query then begin
  274.       WriteLn(StdErr, 'Command: ', stupcase(Command));
  275.       Write(StdErr, 'OK to proceed? Y/N/Q ');
  276.       C := ReadKeyIn('YNQ');
  277.       WriteLn(StdErr);
  278.       DoQuery := C;
  279.     end else
  280.       DoQuery := 'Y';
  281.   end;
  282.  
  283. begin
  284.  
  285.   Initialize;
  286.   WriteLn(StdErr, 'Command Repeater. Copyright (c) 1987 by TurboPower Software. Version 5.07');
  287.   WriteLn(StdErr);
  288.  
  289.   if ParamCount = 0 then
  290.     WriteHelp
  291.   else
  292.     GetParameters;
  293.  
  294.   if ConIn then begin
  295.     {Std input not redirected, just repeat the command}
  296.     for R := 1 to Repeats do begin
  297.       if HaveKeys then
  298.         BuildMacro('');
  299.       RunExec(Command, HaveKeys);
  300.     end;
  301.  
  302.   end else begin
  303.     {Std input redirected}
  304.     while not(eof) do begin
  305.       ReadLn(InputLine);
  306.       if IoResult <> 0 then
  307.         FatalError('Error reading input stream');
  308.       if InputLine <> '' then begin
  309.         ActualCommand := ConvertTokens(Command, InputLine);
  310.         if HaveKeys then
  311.           BuildMacro(InputLine);
  312.         case DoQuery(ActualCommand) of
  313.           'Q' : FatalError('');
  314.           'Y' : RunExec(ActualCommand, HaveKeys);
  315.           'N' : ;
  316.         end;
  317.       end;
  318.     end;
  319.  
  320.   end;
  321.  
  322.   {Give back interrupts we took}
  323.   RemoveMacros;
  324. end.
  325.