[comp.lang.pascal] I/O with VAX Pascal

djung@eco.economics.adelaide.edu.au (06/02/90)

Question:

  Does anyone know the best way (I don't know any way) to do character by
character I/O using VAX Pascal?
  I wish to write some interactive code - reading arrow keys etc -
but VMS buffers I/O, so I don't get any input until the user hits return.

Any help or pointers would be appreciated.

			Thanks,
				-David Jung.

   djung@eco.ua.oz.au         (Eco is internet 129.127.4.9)
or csdljung@medusa.ua.oz.au   (Medusa is internet 129.127.104.1)

ronp@usenet.umr.edu (Ron Pacheco) (06/03/90)

In article <38995.26678cba@eco.economics.adelaide.edu.au> djung@eco.economics.adelaide.edu.au writes:
>Question:
>
>  Does anyone know the best way (I don't know any way) to do character by
>character I/O using VAX Pascal?
>  I wish to write some interactive code - reading arrow keys etc -
>but VMS buffers I/O, so I don't get any input until the user hits return.
>
>Any help or pointers would be appreciated.
>
>			Thanks,
>				-David Jung.
>
>   djung@eco.ua.oz.au         (Eco is internet 129.127.4.9)
>or csdljung@medusa.ua.oz.au   (Medusa is internet 129.127.104.1)

I have posted an example of reading a single from the terminal in VAX Pascal.
As previosly mentioned, this cannot be done directly via VAX Pascal statements
as all I/O (well, most I/O most of the time) is buffered.

This message contains two source files: READKEY.PAS is a MODULE which contains
the routines to read keystrokes, DOREADKEY.PAS is a PROGRAM which demonstrates
the use of the module.

This code was used in a lecture as a demonstration of using a VMS system
service, and so is well documented.  Using the VMS System Service reference,
you should be able to make any modifications you might find necessary.

To rebuild:

   $ PASCAL READKEY             ! Compile READKEY.PAS
   $ PASCAL DOREADKEY           ! Compile DOREADKEY.PAS
   $ LINK   DOREADKEY,READKEY   ! Link objects to form DOREADKEY.EXE

Ron Pacheco
ronp@cs.umr.edu

----- START OF READKEY.PAS ----------------------------------------------------
[INHERIT('SYS$LIBRARY:STARLET')] MODULE Read_Key;

{ This is a VAX Pascal MODULE which implements a READKEY function.  The
  function is callable from any VAX language (although VAX BASIC has a
  built-in INKEY$ function).  The MODULE inherits the system environment
  file (STARLET) in order to access the $ASSIGN and $QIOW system calls. }



{ Declare an unsigned word (2 bytes) type.  This is required because an IO
  channel on the VAX is identified by an unsigned word. }

TYPE  Word_Unsigned = [WORD] 0..65535;



{ Declare a MODULE global variable to store the channel assigned to the
  terminal. }

VAR   TermChannel: Word_Unsigned;



{ - NOTE ON SYSTEM CALLS -

  All VAX/VMS system calls return a status code in an unsigned longword (4
  bytes).  Although many, many codes are defined, the important thing about
  the code is the first bit.  If the first bit of the code is set, then the
  system call was successful.

  The two functions in this MODULE have been written to return the status
  code returned by the system call used in the function. }



[GLOBAL] FUNCTION AssignChannel(Channel: Word_Unsigned): Unsigned;

{ This function assigns a channel to the terminal.  This should be called
  only ONCE per image execution. }

BEGIN
   TermChannel := Channel;
   AssignChannel := $ASSIGN('SYS$COMMAND',TermChannel);
END; { PROCEDURE AssignChannel }



[GLOBAL] FUNCTION ReadKey(VAR Key: Integer): Unsigned;

{ This function reads a single keystroke from the keyboard and returns the
  ASCII code of the key which was pressed. }

VAR   Ch:   Char;
      Stat: Unsigned;

BEGIN
   Stat := $QIOW(,TermChannel,113,,,,Ch,1);
   Key := Ord(Ch);
   ReadKey := Stat;
END; { FUNCTION ReadKey }

END. { MODULE Read_Key }
----- END OF READKEY.PAS ------------------------------------------------------

----- START OF DOREADKEY.PAS --------------------------------------------------
PROGRAM DoReadKey(Output);

{ Pascal demo program for calling the READKEY function. }



{ Declare an unsigned word for use in the external definition of the
  AssignChannel function. }

TYPE  Word_Unsigned = [WORD] 0..65535;



{ Declare a variable for storing the ASCII code of the key pressed. }

VAR   Key: Integer;



{ Declare the external functions. }

FUNCTION AssignChannel(Channel: Word_Unsigned): UNSIGNED; EXTERNAL;
FUNCTION ReadKey(VAR Key: Integer): UNSIGNED; EXTERNAL;



BEGIN

   { Assign a channel and check for error. }
   If Not Odd(AssignChannel(1)) Then
      Writeln('Error Assigning Channel')
   Else BEGIN

      { Go into an infinite loop for demonstration purposes. }
      REPEAT

         { Read a keystroke and check for error.  If everything went ok then
           print the value returned. }
         If  Not Odd(ReadKey(Key)) Then
            Writeln('Error Reading Key')
         Else Writeln(Key);

      UNTIL False;
   END; { If }
END. { PROGRAM DoReadKey }
----- END OF DOREADKEY.PAS ----------------------------------------------------

--
------------------------------------------------------------------------
Ron Pacheco  "puh-check'-oh"  8-)              NET Mail: ronp@cs.umr.edu

reagan@hiyall.enet.dec.com (John R. Reagan) (06/04/90)

In article <38995.26678cba@eco.economics.adelaide.edu.au>, djung@eco.economics.adelaide.edu.au writes...
>Question:
> 
>  Does anyone know the best way (I don't know any way) to do character by
>character I/O using VAX Pascal?
>  I wish to write some interactive code - reading arrow keys etc -
>but VMS buffers I/O, so I don't get any input until the user hits return.
> 
>Any help or pointers would be appreciated.
> 

You do character I/O, you can either call $QIOW directly or use
the screen package (SMG$READ_KEYSTROKE).

---
John Reagan
Digital Equipment Corporation
reagan@hiyall.dec.com
---

merriman@ccavax.camb.com (06/05/90)

In article <1069@umriscc.isc.umr.edu>, ronp@usenet.umr.edu (Ron Pacheco) writes:
> In article <38995.26678cba@eco.economics.adelaide.edu.au> djung@eco.economics.adelaide.edu.au writes:
>>Question:
>>
>>  Does anyone know the best way (I don't know any way) to do character by
>>character I/O using VAX Pascal?
>>  I wish to write some interactive code - reading arrow keys etc -
>>but VMS buffers I/O, so I don't get any input until the user hits return.
>>
>>Any help or pointers would be appreciated.
>>
>>			Thanks,
>>				-David Jung.
>>
>>   djung@eco.ua.oz.au         (Eco is internet 129.127.4.9)
>>or csdljung@medusa.ua.oz.au   (Medusa is internet 129.127.104.1)
> 
> I have posted an example of reading a single from the terminal in VAX Pascal.
> As previosly mentioned, this cannot be done directly via VAX Pascal statements
> as all I/O (well, most I/O most of the time) is buffered.
> 
> This message contains two source files: READKEY.PAS is a MODULE which contains
> the routines to read keystrokes, DOREADKEY.PAS is a PROGRAM which demonstrates
> the use of the module.
> 
[ stuff deleted]

> 
> [GLOBAL] FUNCTION ReadKey(VAR Key: Integer): Unsigned;
> 
> { This function reads a single keystroke from the keyboard and returns the
>   ASCII code of the key which was pressed. }
> 
> VAR   Ch:   Char;
>       Stat: Unsigned;
> 
> BEGIN
>    Stat := $QIOW(,TermChannel,113,,,,Ch,1);
>    Key := Ord(Ch);
>    ReadKey := Stat;
> END; { FUNCTION ReadKey }
> 
> END. { MODULE Read_Key }
> ----- END OF READKEY.PAS ------------------------------------------------------

You should always provide an I/O status block (IOSB) for QIO operations, and
check both the system call status return and the status code in the IOSB 
for success. Also, I would use the symbolic value for the function code --
these values are defined in STARLET.PEN. Here is my version of ReadKey:

 [GLOBAL] FUNCTION ReadKey(VAR Key: Integer): Unsigned;
 
 { This function reads a single keystroke from the keyboard and returns the
   ASCII code of the key which was pressed. }
{ Note that if the QIO operation fails, the value returned to
Key is undefined. } 

 TYPE
       IOSB = RECORD
               code: [WORD] 0..65535;
               count: [WORD] 0..65535;
               info: unsigned;
             END;

 VAR   Ch:   Char;
       Stat: Unsigned;
       stat_block: IOSB;
 
 BEGIN
    Stat := $QIOW(,TermChannel,IO$_READVBLK,stat_block,,,Ch,1);
    Key := Ord(Ch);
    IF NOT ODD(Stat) THEN
        ReadKey := Stat
    ELSE
        ReadKey = stat_block.code;
 END; { FUNCTION ReadKey }
 
 END. { MODULE Read_Key }

See Chapter 7 of Introduction of VMS Sysytem Services for details,
especially section 7.10 -- I/O Completion Status.

> Ron Pacheco  "puh-check'-oh"  8-)              NET Mail: ronp@cs.umr.edu

George Merriman, Cambridge Computer Associates

djung@eco.economics.adelaide.edu.au (06/05/90)

Thanks go to Ron for the helpful hints.  Was a big help actually.

Ron: I tried to E-Mail you personally using a couple of different addresses,
 but all my mail bounced.

Thanks again.
					-David Jung.

csdljung@medusa.ua.oz.au   OR   djung@eco.ua.oz.au