home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / STDIN.ZIP / STDIN.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1988-02-26  |  5.7 KB  |  209 lines

  1. unit StdIn;
  2.  
  3. { A unit to accept standard input from a file via command line
  4.   redirection and then revert to keyboard input automatically.
  5.  
  6.   Version 1.0 -   2/26/1988 - First general release
  7.  
  8.   Scott Bussinger
  9.   Professional Practice Systems
  10.   110 South 131st Street
  11.   Tacoma, WA  98444
  12.   (206)531-8944
  13.   Compuserve 72247,2671 }
  14.  
  15.  
  16. interface
  17.  
  18. uses Dos;
  19.  
  20. procedure AssignStdIn(var F: text);
  21.   { Assign the standard input channel to a file }
  22.  
  23. function KeyPressed: boolean;
  24.   { Check the standard input device to see if a character is available }
  25.  
  26. function ReadKey: char;
  27.   { Get a character from the standard input device }
  28.  
  29.  
  30. implementation
  31.  
  32. const StandardErrorHandle = 2;
  33.  
  34. var ExitSave: pointer;
  35.     ModeSave: boolean;
  36.  
  37. function SetDeviceMode(Handle: word;SetRawMode: boolean): boolean;
  38.   { Return the current value of the device raw/cooked mode and set to new mode }
  39.   var Regs: Registers;
  40.   begin
  41.   with Regs do
  42.     begin
  43.     AX := $4400;                                 { Get the current device status }
  44.     BX := Handle;
  45.     MsDos(Regs);
  46.     SetDeviceMode := odd(DX shr 5);              { Test the current value of RAW bit }
  47.     AX := $4401;                                 { Set the new device status }
  48.     BX := Handle;
  49.     DX := DX and $00DF;                          { Clear the RAW bit }
  50.     if SetRawMode then
  51.       inc(DX,32);                                { Turn the RAW bit on }
  52.     MsDos(Regs)
  53.     end
  54.   end;
  55.  
  56. function TestHandle(Handle: word): boolean;
  57.   { Check to see if the handle has data available, automatically
  58.     switching handle to standard input device if file is exhausted }
  59.   var Regs: Registers;
  60.  
  61.   function CheckEOF: boolean;
  62.     { Check to see if handle is at EOF }
  63.     begin
  64.     with Regs do
  65.       begin
  66.       AX := $4406;                               { Check the file input status to see if we're at EOF }
  67.       BX := Handle;
  68.       MsDos(Regs);
  69.       CheckEOF := AL = 0
  70.       end
  71.     end;
  72.  
  73.   begin
  74.   with Regs do
  75.     begin
  76.     AX := $4400;                                 { Find out whether standard input has been redirected }
  77.     BX := Handle;
  78.     MsDos(Regs);
  79.     if not odd(DX) then                          { It's not the standard input device }
  80.       if CheckEOF then                           { Are we at EOF? }
  81.         begin
  82.         AH := $46;                               { Force the standard input file back to the standard error device }
  83.         BX := StandardErrorHandle;
  84.         CX := Handle;
  85.         MsDos(Regs)
  86.         end;
  87.     TestHandle := not CheckEOF                   { Find out if there is data available }
  88.     end
  89.   end;
  90.  
  91. function ReadBytes(    Handle: word;
  92.                    var NumBytes: word;
  93.                    var Buffer): word;
  94.   { Read some bytes from the handle into the buffer -- returns an error code }
  95.   var Regs: Registers;
  96.   begin
  97.   with Regs do
  98.     begin
  99.     AH := $3F;                                   { Read a buffer-full from the handle }
  100.     BX := Handle;
  101.     CX := NumBytes;
  102.     DS := seg(Buffer);
  103.     DX := ofs(Buffer);
  104.     MsDos(Regs);
  105.     if odd(Flags)
  106.      then
  107.       ReadBytes := AX                            { Signal an error }
  108.      else
  109.       begin
  110.       ReadBytes := 0;                            { Everything's fine }
  111.       NumBytes := AX                             { Return number of bytes read }
  112.       end
  113.     end
  114.   end;
  115.  
  116. function KeyPressed: boolean;
  117.   { Check the standard input device to see if a character is available }
  118.   begin
  119.   KeyPressed := TestHandle(TextRec(Input).Handle)
  120.   end;
  121.  
  122. function ReadKey: char;
  123.   { Get a character from the standard input device }
  124.   var Ch: char;
  125.       NumBytes: word;
  126.   begin
  127.   repeat                                         { Wait for data }
  128.   until TestHandle(TextRec(Input).Handle);
  129.   NumBytes := 1;                                 { Only get one byte }
  130.   NumBytes := ReadBytes(TextRec(Input).Handle,NumBytes,Ch);
  131.   ReadKey := Ch
  132.   end;
  133.  
  134. {$F+}
  135. function StdInOpen(var F: TextRec): word;
  136. {$F-}
  137.   { Open a channel to the standard input device }
  138.   begin
  139.   with F do
  140.     if Mode = fmInput
  141.      then
  142.       begin
  143.       Handle := 0;                               { Simply assign the standard input handle }
  144.       StdInOpen := 0
  145.       end
  146.      else
  147.       StdInOpen := $0005                         { Error out with a 'File Access Denied' }
  148.   end;
  149.  
  150. {$F+}
  151. function StdInIn(var F: TextRec): word;
  152. {$F-}
  153.   { Do the actual input from the standard input device }
  154.   var DontCare: boolean;
  155.       Regs: Registers;
  156.   begin
  157.   with F do
  158.     with Regs do
  159.       begin
  160.       DontCare := TestHandle(Handle);            { Possibly redirect input back to standard input }
  161.       BufPos := 0;                               { Clear the input buffer }
  162.       BufEnd := BufSize;                         { Default to full buffer }
  163.       StdInIn := ReadBytes(Handle,BufEnd,BufPtr^){ Read in some data }
  164.       end
  165.   end;
  166.  
  167. {$F+}
  168. function StdInIgnore(var F: TextRec): word;
  169. {$F-}
  170.   { This function does nothing }
  171.   begin
  172.   StdInIgnore := 0
  173.   end;
  174.  
  175. procedure AssignStdIn(var F: text);
  176.   { Assign the standard input channel to a file }
  177.   begin
  178.   with TextRec(F) do
  179.     begin
  180.     Mode := fmClosed;
  181.     BufSize := sizeof(Buffer);
  182.     BufPtr := @Buffer;
  183.     OpenFunc := @StdInOpen;
  184.     InOutFunc := @StdInIn;
  185.     FlushFunc := @StdInIgnore;
  186.     CloseFunc := @StdInIgnore;
  187.     Name[0] := #0
  188.     end
  189.   end;
  190.  
  191. {$F+}
  192. procedure ExitHandler;
  193. {$F-}
  194.   { Restore the standard input device mode }
  195.   var DontCare: boolean;
  196.   begin
  197.   ExitProc := ExitSave;
  198.   DontCare := SetDeviceMode(StandardErrorHandle,ModeSave)
  199.   end;
  200.  
  201. begin
  202. ExitSave := ExitProc;
  203. ExitProc := @ExitHandler;
  204. ModeSave := SetDeviceMode(StandardErrorHandle,true);
  205. close(Input);
  206. AssignStdIn(Input);
  207. reset(Input)
  208. end.
  209.