UCR Stdlib Standard Input Routines


UCR StdLib Standard Input Routines
13.1 - Interface
13.2 - Generic Interface
13.3 - Buffered vs. Raw Input Formats
13.4 - Getc, GetcCS, GetcStk
13.4.1 - Calling Conventions and Assertions
13.4.2 - Getc Addressing Modes
13.4.3 - Syntax & Examples
13.5 - Peekc, PeekcCS, PeekcStk
13.5.1 - Calling Conventions and Assertions
13.5.2 - Peekc Addressing Modes
13.5.3 - Syntax & Examples
13.6 - Gets, GetsCS, GetsStk, Getsm
13.6.1 - Calling Conventions and Assertions
13.6.2 - Gets Addressing Modes
13.6.3 - Syntax & Examples
13.7 - GetcLen, GetcLenCS, GetcLenStk
13.7.1 - Calling Conventions and Assertions
13.7.2 - GetcLen Addressing Modes
13.7.3 - Syntax & Examples
13.8 - FlushGetc
13.8.1 - Calling Conventions and Assertions
13.8.2 - FlushGetc Addressing Modes
13.8.3 - Syntax & Examples
13.9 - rawGetc
13.9.1 - Calling Conventions and Assertions
13.9.2 - RawGetc Addressing Modes
13.9.3 - Syntax & Examples
13.10 - rawGets, rawGetsCS, rawGetsStk, rawGetsm
13.10.1 - Calling Conventions and Assertions
13.10.2 - RawGets Addressing Modes
13.10.3 - Syntax & Examples
13.11 - GetcStdIn
13.11.1 - Calling Conventions and Assertions
13.11.2 - GetcStdIn Addressing Modes
13.11.3 - Syntax & Examples
13.12 - GetcBIOS
13.12.1 - Calling Conventions and Assertions
13.12.2 - GetcBIOS Addressing Modes
13.12.3 - Syntax & Examples
13.13 - SetInAdrs, GetInAdrs
13.13.1 - Calling Conventions and Assertions
13.13.2 - GetInAdrs, SetInAdrs Addressing Modes
13.13.3 - Syntax & Examples
13.14 - PushInAdrs, PopInAdrs
13.14.1 - Calling Conventions and Assertions
13.14.2 - PushInAdrs, PopInAdrs Addressing Modes
13.14.3 - Syntax & Examples
13.15 - ResetStdIn
13.15.1 - Calling Conventions and Assertions
13.15.2 - ResetStdIn Addressing Modes
13.15.3 - Syntax & Examples
13.16 - tstKbd
13.16.1 - Calling Conventions and Assertions
13.16.2 - TestKbd Addressing Modes
13.16.3 - Syntax & Examples
13.17 - tstInput
13.17.1 - Calling Conventions and Assertions
13.17.2 - TstInput Addressing Modes
13.17.3 - Syntax & Examples
13.18 - Geth, GethCS, GethStk, Gethl
13.18.1 - Calling Conventions and Assertions
13.18.2 - Geth, Gethl Addressing Modes
13.18.3 - Syntax & Examples
13.19 - Geti
13.19.1 - Calling Conventions and Assertions
13.19.2 - Geti Addressing Modes
13.19.3 - Syntax & Examples
13.20 - Getu
13.20.1 - Calling Conventions and Assertions
13.20.2 - Getu Addressing Modes
13.20.3 - Syntax & Examples
13.21 - Getl
13.21.1 - Calling Conventions and Assertions
13.21.2 - Getl Addressing Modes
13.21.3 - Syntax & Examples
13.22 - Getul
13.22.1 - Calling Conventions and Assertions
13.22.2 - Getul Addressing Modes
13.22.3 - Syntax & Examples
13.23 - Getf
13.23.1 - Calling Conventions and Assertions
13.23.2 - Getf Addressing Modes
13.23.3 - Syntax & Examples
13.24 - Scanf, Scanff
13.24.1 - Calling Conventions and Assertions
13.24.2 - Syntax & Examples
13.24.3 - Alternate Syntax
13.25 - GetTermChar, SetTermChar
13.25.1 - Calling Conventions and Assertions
13.25.2 - Syntax & Examples


UCR StdLib Standard Input Routines

The stdlib Standard Input package provides routines that let you read data from the standard input device. There are two primary forms of input: "buffered" and "raw." The "raw" input routines read their data directly from the standard input device. For example, a call to the stdlib "rawGetc" routine reads a character directly from the standard input device. The buffered input routines, on the other hand, read a line of data at a time from the standard input device and then return characters from this input buffer as the program requests them.

The standard input package provides functions that read characters, strings, numeric values, and other types of data. You may specify raw or buffered formats for string and character inputs, numeric inputs always use the buffered format.


13.1 Interface

To access the routines in the declarations package, your assembly language module must include the file "stdin.a" during assembly. You can accomplish this with either of the following include statements in your assembly code:




	include	stdin.a
or
	include	ucrlib.a

The stdin.a include file exports several symbols. The UCR Standard Library prefaces all "private" names with a dollar sign ("$"). You should not call any routine in this package that begins with this symbol unless otherwise advised. To avoid name conflicts, you should not define any symbols in your programs that begin with a dollar sign ("$"). Note that future versions of the stdlib (that remain compatible with this release) may change "private" names. To remain compatible with future releases, you must not refer to these "private" names within your programs.

Source code appearing in this chapter is current as of Version Two, Release 40. There may be minor changes between this source code and the current release.


13.2 Generic Interface

Many of the standard library routines use a common generic programmer's interface. Such routines let you pass parameters to them in several different locations. Common examples include in the registers, by value in the code stream (CSi), by reference in the code stream (CS), by value on the top of stack (TOS), and by reference on the top of stack (Stk). Typically, there are separate invocation macros defined for each of these variants, e.g.,




	IsAlNum			;Passed in AL register.

	IsAlNumCS
	dword	chrPtr		;Passed by reference in code stream.

	push	'a'		;Passed by value on the stack.
	IsAlNumTOS

	push	seg chrVar		;Passed by reference on the stack.
	push	offset chrVar
	IsAlNumStk

In addition to the above forms there are two other suffixes generally applied to stdlib routine names: "m" and "x". The "m" suffix stands for "malloc". Routines with the "m" suffix typically generate a string result and malloc storage for the string on the heap, returning a pointer to this string in the ES:DI register pair. The routines with an "x" suffix also process strings. Most stdlib routines preserve the value of the ES:DI registers when processing strings; typically, they leave the ES:DI register pair pointing at the start of the string. The routines with an "x" suffix do not preserve ES:DI, they generally leave ES:DI pointing at the zero byte of the string they processed or generated.

To make it easier to use all these different variants, the standard library typically defines a macro for each routine that lets you specify various operands using stdlib "addressing modes." The allowable addressing modes vary by routines, but they typically take one of the following forms:




	name		;If operand field is blank, use "plain" version.
	name	var	;Generally passes address of var in code stream (CS).
	name	const	;Pushes const onto TOS and uses nameTOS routine.
	name	[wvar]	;Pushes DS followed by value of wVar variable
			; (assumed to be a word) and calls nameSTK
	name	[dVar]	;Pushes dword value of dVar onto stk, calls nameStk.

Since not all of these "addressing modes" are applicable to all instructions, and some instructions allow different sets of operands (including multiple operands), there are lots of special cases. Such cases are noted after the explaination for each particular routine.


13.3 Buffered vs. Raw Input Formats

The stdlib Standard Input package provides two sets of three complementary routines for reading characters and strings: (getc, gets, and getsm) and (rawgetc, rawgets, and rawgetsm). The raw* routines (obviously) provide the raw operations, the other set provide the buffered input routines.

The rawGetc routine is the basic character input routine in the Standard Input package. This routine jumps to the procedure that reads a character from the current input device (typically the DOS standard input device). The rawGets and rawGetsm (get a string) routines call rawGetc to read a line of data directly from the standard input device.

The buffered input routines, on the other hand, read entire lines of data from the standard input device into an internal buffer and then extract characters from this buffer. When these routines exhaust the characters in the buffer, they read another line of text from the standard input device and reset the buffer pointers to the beginning of the buffer and start over.

Buffered input allows the user to type an entire line and edit that line (e.g., using the backspace or ESC keys) before committing that data to the program. The rawGetc routine, on the other hand, simply returns the backspace character like any other key and relies upon the user program to perform any necessary editing.

There is one detail you must consider when using buffered and raw I/O in a program: if you intermix calls to the raw and buffered routines, you may get strange results. For example, if you call the Getc (buffered) function to read a character from the standard input, this will force the system to read an entire line of text. Subsequent calls to Getc read characters from that same line. However, if you intermix calls to rawGetc with calls to Getc, the rawGetc calls will read directly from the standard input ignoring the characters in the internal buffer. This will appear to the user as though the data is being read out of order.

Because buffered I/O is somewhat "safer," the numeric input routines all use buffered I/O. Therefore, as a general rule, you should attempt to use buffered I/O for all your input operations. Reserve raw input for the situations where you have to guarantee that the input is coming directly from the standard input device.


13.4 Getc, GetcCS, GetcStk

The Getc routine reads a single character from the input buffer and returns this character in the AL register. Getc returns the carry flag clear if no error occurs. Assuming exceptions are not active, Getc will return the carry flag set if an error occurs (while reading the buffered line of text from the standard input). If exceptions are active, Getc (actually the call to rawGets that reads the line of text into the buffer) will raise an appropriate exception. See the rawGets routine for more details on the possible exceptions.


13.4.1 Calling Conventions and Assertions


13.4.2 Getc Addressing Modes

Getc Addressing Modes
Name Plain CS TOS Stk X CSi
Getc X X - X - -

The getc macro allows the following operands:

Getc Extended Syntax (Single/No Operands)
Name   byteVar Num const [word Var] [dword Var] String Const
Getc X X - X X -


13.4.3 Syntax & Examples




cvar    byte    ?
wvar    word    cvar
dvar    dword   cvar
         .
         .
         .
        print   "Enter Y or N:"
        getc
        toupper
        cmp     al, 'Y'
        je      EnteredYes
         .
         .
         .
        print   "Enter a character: "
        getcCS
        dword   cvar
        printf  "You entered %c\n", cvar
         .
         .
         .
        print   "Enter a character: "
        pshadrs cvar
        getcStk
        printf  "You entered %c\n", cvar
         .
         .
         .


        getc            ;Leaves character in AL
        getc    cvar    ;Leaves character in byte var cvar.
        getc    [wvar]  ;ds:wvar is near ptr to dest location.
        getc    [dvar]  ;dvar contains far ptr to dest location.
         .
         .
         .
        print   "Enter a character:"
        getc    cvar
        printf  "You entered %c\n", cvar
         .
         .
         .
        print   "Enter a character:"
        getc    [wvar]
        print   "You entered "
        putc    cvar
        putcr
         .
         .
         .
        print   "Enter a character:"
        getc    [dvar]
        print   "You entered "
        putc    cvar
        putcr


13.5 Peekc, PeekcCS, PeekcStk

Peekc is very similar to Getc except it does not remove the character it reads from the input buffer. If there is data in the internal Getc buffer, Peekc returns the first character in that buffer. Future calls that would normally return a character from the buffer will return the same character Peekc read from the buffer.

If the buffer is empty when you call Peekc, the system will read a new line of text from the standard input and then return a copy of the first character in the buffer without removing that character from the buffer.

Peekc returns the carry flag clear if no error occurs. Assuming exceptions are not active, Peekc will return the carry flag set if an error occurs (while reading the buffered line of text from the standard input). If exceptions are active, Peekc (actually the call to rawGets that reads the line of text into the buffer) will raise an appropriate exception. See the rawGets routine for more details on the possible exceptions.


13.5.1 Calling Conventions and Assertions


13.5.2 Peekc Addressing Modes

Peekc Addressing Modes
Name Plain CS TOS Stk X CSi
Peekc X X - X - -

The peekc macro allows the following operands:

Peekc Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
Peekc X X - X X -


13.5.3 Syntax & Examples




	print	"Enter Y or N:"
	peekc
	toupper
	cmp	al, 'Y'
	je	EnteredYes
	 .
	 .
	 .

	print	"Enter Y or N:"
	peekcCS
	byte	YorNChar
	cmp	YorNChar, 'Y'
	je	EnteredYes
	 .
	 .
	 .

	pshadrs	YorNChar
	peekcStk
	cmp	YorNChar, 'Y'
	je	EnteredYes
	 .
	 .
	 .


	getc			;Returns character in AL
	getc	CharVar		;Puts char in CharVar
	getc	[wVar]		;Stores char where wVar points in DS
	getc	[dVar]		;Stores char where dVar points

13.6 Gets, GetsCS, GetsStk, Getsm

Gets copies the remaining data in the internal buffer to the string variable at the address contained in ES:DI. If the internal buffer is empty, Gets will read a new line of text from the standard input and copy that entire string to the location specified by ES:DI. After a call to Gets, the internal buffer will be empty. Any future call that reads data from the internal buffer will force a new input line to be read from the standard input (via rawgets).

GetsCS works like Gets except a pointer to the destination string follows the call in the code stream; it does not use the value in ES:DI.

GetsStk is very similar to Gets except it expects the address of the destination string on the stack rather than in the ES:DI register pair.

Getsm allocates storage on the heap and copies the contents of the internal buffer to the storage allocated on the heap. Getsm returns the address of this heap object in the ES:DI register pair.

These routines all return the error status in the carry flag. If the carry is set on return, then some sort of error occured while attempting to input the line of text. If exceptions are enabled, these calls will raise an appropriate exception. This is typically an EOF, file I/O error, or memory allocation (getsm) exception.

If you use Getc to read all of the characters from the input buffer except the terminating carriage return, a call to Gets, GetsStk, or Getsm will ignore this last "character" in the buffer and read a new line of text from the user. The next buffered get* call will force the system to read a new line of text from the standard input device.


13.6.1 Calling Conventions and Assertions


13.6.2 Gets Addressing Modes

Gets Addressing Modes
Name Plain CS TOS Stk X CSi M
Gets X X - X - - X

The gets macro allows the following operands:

Gets Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
Gets X X - X X -


13.6.3 Syntax & Examples




Name	byte	256 dup (0)
	 .
	 .
	 .
	print	"Enter your name:"
	lesi	Name
	gets
	printf	"Hello %s\n", Name
	 .
	 .
	 .
Gets calls GetcCS with the address of "byteVar" following in the code stream.

Gets assumes the word variable contains a DS-relative near pointer. It pushes the value of DS onto the stack followed by the value of the word variable. Then it calls GetsStk.

Gets assumes the dword variable contains a far pointer. It pushes the value of the dword variable onto the stack and calls GetsStk.


13.7 GetcLen, GetcLenCS, GetcLenStk

GetcLen returns (in CX or in a specified word variable) the number of unprocessed characters left in the internal input buffer (this does not include the terminating zero byte).


13.7.1 Calling Conventions and Assertions


13.7.2 GetcLen Addressing Modes

GetcLen Addressing Modes
Name Plain CS TOS Stk X CSi
GetcLen X X - X   -

The GetcLen macro allows the following operands:

GetcLen Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
GetcLen X X - X X -


13.7.3 Syntax & Examples

GetcLenxxx macros without any parameters.




	getc
	mov	Char1, al
	getc
	mov	Char2, al
	GetcLen
	print	"There are "
	puti
	print	" characters left in the buffer."
	  .
	  .
	  .




	getc
	mov	Char1, al
	getc
	mov	Char2, al
	GetcLenCS
	dword	BufLen
	printf	"There are %d characters left in the buffer.\n",BufLen
	  .
	  .
	  .

	getc
	mov	Char1, al
	getc
	mov	Char2, al
	pshAdrs	BufLen
	GetcLenStk
	printf	"There are %d characters left in the buffer.\n",BufLen
	  .
	  .
	  .

The GetcLen macro also allows an extended syntax with operands specifying the particular "addressing mode" for the destination value:

	getcLen			;Returns length in CX.
	getcLen	wVar		;Stores length into wVar (word variable)
	getcLen	[wVar]		;Stores length where wVar points in DS.
	getcLen	[dvar]		;Stores length where dVar points.

13.8 FlushGetc

FlushGetc flushes (clears) the internal character buffer. The next call to a get* routine will force a new line of text to be read after a call to the FlushGetc function.


13.8.1 Calling Conventions and Assertions


13.8.2 FlushGetc Addressing Modes

FlushGetc Addressing Modes
Name Plain CS TOS Stk X CSi
FlushGetc X - - - - -

The FlushGetc macro allows the following operands:

FlushGetc Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
FlushGetc X - - - - -


13.8.3 Syntax & Examples

FlushGetc does not require any parameters.




	print	"Enter a line of text:"
	FlushGetc
	getsm
	print	"You entered: "
	puts
	free
	 .
	 .
	 .

13.9 rawGetc

The rawGetc routine is one of the lowest level routines in the Standard input package. All of the other routines that input data except GetcBIOS and GetcStdIn read their characters from the standard input device by calling rawGetc. The rawGetc routine, in turn, transfers control to the current stdlib "Standard Input Device." It does this by jumping indirectly through the "GetcAdrs" pointer that contains the address of the current standard input device. Normally, this pointer contains the address of the GetcStdIn routine (GetcStdIn reads a character from the DOS standard input device). You can redirect the source of the standard library's standard input device by changing the address in this pointer variable. See the "SetInAdrs" and "GetInAdrs" routines for more details.


13.9.1 Calling Conventions and Assertions


13.9.2 RawGetc Addressing Modes

RawGetc Addressing Modes
Name Plain CS TOS Stk X CSi
RawGetc X - - - - -

The RawGetc macro allows the following operands:

RawGetc Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
RawGetc X - - - - -


13.9.3 Syntax & Examples




	print	"Enter Y or N:"
	rawgetc
	tolower
	cmp	al, 'y'
	je	EnteredYes
	 .
	 .
	 .

13.10 rawGets, rawGetsCS, rawGetsStk, rawGetsm

These routines are comparable to the Gets, GetsStk, and Getsm routines except they read their data directly from the standard input device (rawGetc) rather than from the input Getc buffer. See the Gets, GetsStk, and Getsm routines for more details.

These routines ignore any non-ASCII characters. If you press a cursor control key or a function key, that key is not placed in the destination string. Since the buffered input routines read data from the standard input device via calls to rawGets, this also means that you cannot read non-ASCII characters using buffered I/O routines like Getc, PeekC, Gets, etc.


13.10.1 Calling Conventions and Assertions


13.10.2 RawGets Addressing Modes

RawGets Addressing Modes
Name Plain CS TOS Stk X CSi M
RawGets X X - X - - X

The RawGets macro allows the following operands:

RawGets Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
RawGets X X - X X -


13.10.3 Syntax & Examples




Name	byte	256 dup (0)
	 .
	 .
	 .
	print	"Enter your name:"
	lesi	Name
	rawgets
	printf	"Hello %s\n", Name
	 .
	 .
	 .
	print	"Enter your name again:"
	rawGetsCS
	dword	Name
	printf	"Hi again, %s\n", Name
	 .
	 .
	 .
	print	"Enter your name again:"
	push	seg Name
	push	offset Name
	rawGetsStk
	printf	"Hi again, %s\n", Name
	 .
	 .
	 .
	print	"Enter your name yet a third time:"
	rawgetsm
	print	"Are you sure you're "
	puts
	putc	'?'
	putcr
	free

	rawGets		;Stores string at ES:DI

	rawGets	bVar	;Stores string starting at location bVar

	rawGets	[wVar]	;Stores string at address pointed at by wVar.

	rawGets	[dVar]	;Stores string at far address in dVar.

13.11 GetcStdIn

This routine reads a single character from the DOS standard input device. By default, this is the routine that rawGetc (and therefore, all the other character input routines) calls in order to read a character from the standard input device. GetcStdIn does no internal buffering of its own, hence it is a "raw" input routine (of course, DOS and/or BIOS may do some buffering, but that is outside the control of the stdlib). GetcStdIn returns the character read in the AL register.

GetcStdIn begins by checking to see if it is reading data directly from some device (e.g., the keyboard) or from a file. The behavior of the system changes somewhat if you are reading data from a file (via input redirection) rather than a device. GetcStdIn processes the input stream differently so that any routines calling GetcStdIn (e.g., rawGetc) see a unified view of the system and don't have to do any special handling of their own. One difference, for example, concerns end of line sequences. GetcStdIn assumes that data coming from a hardware device terminates each line with a CR (but no corresponding LF); it assumes that data coming from a file terminates each line with a CR/LF sequence. GetcStdIn eats the line feed in a CR/LF sequence if reading data from a file. It simply passes line feeds read from a device (like the keyboard).

GetcStdIn checks for device/file I/O errors and end of file (control-Z on a device, true end of file when reading from a file). If a device or file I/O error occurs, GetcStdIn will raise the $FileIO exception if exceptions are active. Otherwise, it will set the carry flag and return the appropriate DOS error code in the AX register. If end of file occurs, GetcStdIn will raise the $EndOfFile exception, if exceptions are active; otherwise it will return with the carry flag clear and AH=0. If no error occurs, GetcStdIn returns with the carry flag clear, the ASCII code in AL, and AH=1.

GetcStdIn call DOS to read a character from the standard input device. Therefore, it inherits all the properties of the DOS standard input device. In particular, if the current input device is the keyboard and the user presses a non-ASCII key (e.g., a function or cursor control key), then GetcStdIn returns two characters: a zero byte followed by the scan code for that particular key. GetcStdIn does not do any special handling on non-ASCII characters. That is still the application program's responsibility to manage.


13.11.1 Calling Conventions and Assertions


13.11.2 GetcStdIn Addressing Modes

GetcStdIn Addressing Modes
Name Plain CS TOS Stk X CSi M
GetcStdIn X - - - - - -

The GetcStdIn macro allows the following operands:

GetcStdIn Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
GetcStdIn X - - - - -


13.11.3 Syntax & Examples

GetcStdIn does not require any parameters.




                print   "If inputing data from the keyboard, "
                print   "press control-Z to stop.",nl
                
GCLoop:         getcStdIn
                jc      IOError
                cmp     ah, 0
                je      EOFError
                cmp     al, 0
                je      NonASCIIChar
                print   "You pressed: "
                putc
                putcr
                jmp     GCLoop

NonASCIIChar:   GetcStdIn
                jc      IOError
                cmp     ah, 0
                je      EOFError
                print   "You pressed a non-ASCII character whose "
                print   "scan code is "
                puth
                putcr
                jmp     GCLoop
                
IOError:        print   "I/O error #"
                puti
                print   " occured during read.",nl
                jmp     Done
                
EOFError:       print   "End of file encountered.",nl
Done:


13.12 GetcBIOS

GetcBIOS calls the PC's BIOS routines to directly read a character from the system keyboard (or from the system's keyboard typeahead buffer if there are any keys in that buffer). GetcBIOS uses the same system interface as GetcStdIn except it will not raise any exceptions or return any error (it always returns with the carry clear and AH=1).

Unlike the PC BIOS int 16h functions, GetcBIOS does not return the scan code in AH and a zero in AL if the user presses a non-ASCII character. GetcBIOS preprocesses such keystrokes and returns the same two-character sequences that GetcStdIn returns.

Note that GetcBIOS does not check for end of file, therefore it always returns a one in the AH register. If you press the control-Z key, GetcBIOS will return the ASCII code for control-Z. Likewise, GetcBIOS does not handle control-C any differently than other keys. It just returns the ASCII code for control-C (03).


13.12.1 Calling Conventions and Assertions


13.12.2 GetcBIOS Addressing Modes

GetcBIOS Addressing Modes
Name Plain CS TOS Stk X CSi M
GetcBIOS X X - X - - X

The GetcBIOS macro allows the following operands:

GetcBIOS Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
GetcBIOS X - - - - -


13.12.3 Syntax & Examples

GetcBIOS does not require any parameters.




controlZ        =       26

                print   "If inputing data from the keyboard, "
                print   "press control-Z to stop.",nl
                
GCLoop:         getcStdIn
                cmp     al, controlZ
                je      Done
                cmp     al, 0
                je      NonASCIIChar
                print   "You pressed: "
                putc
                putcr
                jmp     GCLoop

NonASCIIChar:   GetcStdIn
                print   "You pressed a non-ASCII character whose "
                print   "scan code is "
                puth
                putcr
                jmp     GCLoop
                
Done:

13.13 SetInAdrs, GetInAdrs

The Standard Input package provides the ability to redirect the standard input device, independent of DOS' redirection capabilities. All of the routines in the standard input package that read characters (except GetcStdIn and GetcBIOS) ultimately call the rawGetc routine to read characters from the standard input device. The rawGetc routine jumps to an appropriate handler to actually read the character from the current input device; this is usually the GetcStdIn function. However, rawGetc transfers control to the handler by jumping to the function whose address appears in the internal GetcAdrs pointer variable. By changing the value of this pointer, you can redirect the input to a different input device handler function.

Thet GetInAdrs and GetInAdrs (along with the PushInAdrs and PopInAdrs) functions provide you with the ability to maintain the GetcAdrs pointer. GetInAdrs returns the current value of this (far) pointer in the ES:DI register pair. This allows you to save the current value so you can restore it later after you are done redirecting the standard input. The SetInAdrs copies the value in the ES:DI register pair to the GetcAdrs pointer. Presumably, you would load the address of an appropriate input device handler into ES:DI before calling SetInAdrs.

An input device handler should read a single character from it associated device and return the ASCII code (or whatever code you want to use) in the AL register. It should also return an error status in the carry flag (C=1 for error, C=0 for success). If an error occurs, you can return a DOS error code in the AX register. The character device handler should return the EOF status in AH (AH=0 for end of file, AH=1 for not end of file). Note that when returning end of file, you should clear the carry flag.

If exceptions are active, you can raise an appropriate exception when EOF or an input error occurs. Your device handler should explicitly check to see if exceptions are active (using the GetXEnabled call) before raising any exceptions.

Input handlers must be far procedures and must preserve all registers except AX.


13.13.1 Calling Conventions and Assertions


13.13.2 GetInAdrs, SetInAdrs Addressing Modes

GetInAdrs, SetInAdrs Addressing Modes
Name Plain CS TOS Stk X CSi M
GetInAdrs X - - - - - -
SetInAdrs X - - - - - -

The GetInAdrs and SetInAdrs macros allow the following operands:

GetInAdrs/SetInAdrs Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
GetInAdrs X - - - - -
SetInAdrs X - - - - -


13.13.3 Syntax & Examples

The following is a typical device handler. This particular device handler reads characters from the DOS standard input device without checking for end of file or control-C.




DOSInput        proc    far
                mov     ah, 7           ;DOS char read w/o ^c chk
                int     21h
                mov     ah, 1           ;Cannot detect EOF.
                ret
DOSInput        endp

ASCIIOnly       proc    far
AOLoop:         GetcStdIn
                jc      Done            ;Bail if error.
                cmp     ah, 0
                je      Done            ;Bail if EOF.
                
                cmp     al, 0           ;Non-ASCII character?
                jne     Done
                GetcStdIn               ;Eat scan code
                jmp     AOLoop          ; and get the next char.
                
Done:           ret
ASCIIOnly       endp

The following example demonstrates how to use the SetInAdrs and GetInAdrs functions to redirect the standard input device:




GetcAdrsSave    dword   ?
                 .
                 .
                 .
                GetInAdrs
                mov     word ptr GetcAdrsSave, di
                mov     word ptr GetcAdrsSave+2, es
                
                lesi    DOSInput
                SetInAdrs
                 .
                 .      ;Input statements in this section
                 .      ; read their data using the DOSInput
                 .      ; character handler (no ctrl-C checking).
                 .
                lesi    ASCIIOnly
                SetInAdrs
                 .
                 .      ;Input statements in this section
                 .      ; read their data using the ASCIIOnly
                 .      ; character handler.  Therefore, the
                 .      ; input routines will only see ASCII
                 .      ; characters, all other keypresses
                 .      ; are ignored.
                 .
                les     di, GetcAdrsSave        ;Restore the address
                SetInAdrs                       ; of the original
                 .                              ; input handler.
                 .
                 .

13.14 PushInAdrs, PopInAdrs

PushInAdrs and PopInAdrs are very similar to the GetInAdrs and SetInAdrs insofar as they let you manipulate the GetcAdrs pointer. The primary difference between these routines and the Get/SetInAdrs routines is that the Push/PopInadrs routines preserve the current GetcAdrs on an internal stack rather than requiring you to explicitly save this pointer yourself.

The PushInAdrs function pushes the current GetcAdrs pointer onto an internal stack. It then copies the pointer in ES:DI to GetcAdrs. Therefore, PushInAdrs roughly corresonds to the SetInAdrs routine with the added benefit of automatically preserving the previous pointer value. The internal GetcAdrs stack contains enough storage to hold 16 (nested) addresses you've pushed on the stack. This should be far more than any one program will ever need (most programs would need only one or two positions) assuming there isn't a programming error like forgetting to pop values you've pushed. If a stack overflow occurs and exceptions are active, PushInAdrs will raise the $GetcStkErr exception. If exceptions are not active, then PushInAdrs returns with the carry flag set and it does not change the current value of the GetcAdrs pointer nor does it change any value on the stack (in other words, the call is ignored).

The PopInAdrs pops an address off the internal stack and stores this address into the GetcAdrs pointer. This restores GetcAdrs with the address of the previous character input device handler. PopInAdrs returns with the carry flag clear if it sucessfully restored the GetcAdrs pointer. If stack underflow occurs (i.e., you call PopInAdrs when there is no data on the internal stack), PopInAdrs will raise a $GetcStkErr exception if exceptions are active. It will return with the carry flag set and store the address of the GetcStdIn routine into GetcAdrs if exceptions are not active.


13.14.1 Calling Conventions and Assertions


13.14.2 PushInAdrs, PopInAdrs Addressing Modes

PushInAdrs, PopInAdrs Addressing Modes
Name Plain CS TOS Stk X CSi M
PushInAdrs X            
PopInAdrs X            

The PushInAdrs and PopInAdrs macros allow the following operands:

PushInAdrs/PopInAdrs Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
PushInAdrs X - - - - -
PopInAdrs X - - - - -


13.14.3 Syntax & Examples

The following code sequence uses the character handlers developed for SetInAdrs and GetInAdrs. Please see the example for those routines for more details.




                 .
                 .
                 .
                lesi    DOSInput
                PushInAdrs
                 .
                 .      ;Input statements in this section
                 .      ; read their data using the DOSInput
                 .      ; character handler (no ctrl-C checking).
                 .
                lesi    ASCIIOnly
                SetInAdrs
                 .
                 .      ;Input statements in this section
                 .      ; read their data using the ASCIIOnly
                 .      ; character handler.  Therefore, the
                 .      ; input routines will only see ASCII
                 .      ; characters, all other keypresses
                 .      ; are ignored.
                 .
                PopInAdrs                       ;Restore the address
                 .                              ; of the original
                 .                              ; input handler.
                 .

13.15 ResetStdIn

The ResetStdIn routine initializes the stdlib Standard Input Device. It stores the address of the GetcStdIn routine into the GetcAdrs pointer and it initializes the internal Getc stack. It also flushes any characters currently setting in the Standard Input internal buffer.


13.15.1 Calling Conventions and Assertions


13.15.2 ResetStdIn Addressing Modes

ResetStdIn Addressing Modes
Name Plain CS TOS Stk X CSi M
ResetStdIn X            

The ResetStdIn macro allows the following operands:

ResetStdIn Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
ResetStdIn X - - - - -


13.15.3 Syntax & Examples

ResetStdIn requires no parameters.




	.
	.
	.
	ResetStdIn
	.
	.	;Standard input behaves just as it did on program startup
	.	; at this point.

13.16 tstKbd

The tstKbd routine checks to see if there is any kind of key in the PC's keyboard type ahead buffer. This routine returns zero in AX if there are no keys available; it returns one in AX if there is at least one keycode ready to be read. This routine also compares AX against zero just before returning, so the zero flag also indicates whether a key is available (Z=1 for no key, Z=0 for key available).

Note that many routines in the standard input package, including all buffered I/O routines, throw out any non-ASCII characters. Therefore, although tstKbd might claim keystrokes are available, a call to one of these routines that throw away non-ASCII characters may have to wait until the user presses an actual ASCII character at the keyboard. GetcBIOS, GetcStdIn and rawGetc (assuming GetcAdrs points at GetcStdIn or GetcBIOS) are the only routines in the standard input package that will return non-ASCII characters like function keys or cursor control keys. Therefore, you would typically call one of these three routines after testing the system status with a tstKbd call, assuming you did not want a delay if tstKbd returns true. See the tstASCII function for additional details.


13.16.1 Calling Conventions and Assertions


13.16.2 TestKbd Addressing Modes

TstKbd Addressing Modes
Name Plain CS TOS Stk X CSi M
TstKbd X            

The TestKbd macro allows the following operands:

TestKbd Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
TestKbd X - - - - -


13.16.3 Syntax & Examples

tstKbd requires no parameters.




; The following loop continuously checks the keyboard to
; see if a key is available.  If not, it executes the
; "Background" procedure on each iteration of the loop.
;
; This allows background processing to commence as long
; as the user does not press a key on the keyboard.

TstLoop:        tstKbd
                jne     GotAKey
                call    Background
                jmp     TstLoop
                
GotAKey:        rawgetc            ;Read the key pressed from the user
                 .
                 .
                 .

13.17 tstInput

The tstInput routine is very similar to the tstKbd routine. The primary difference is that tstInput will only return one in AX if there are some ASCII characters currently in the system's type ahead buffer. If there are no characters in the buffer, or if the characters in the buffer are all non-ASCII (i.e., function key and cursor control key) characters, tstInput will return zero in the AX register.


13.17.1 Calling Conventions and Assertions


13.17.2 TstInput Addressing Modes

TstInput Addressing Modes
Name Plain CS TOS Stk X CSi M
TstInput X            

The TestInput macro allows the following operands:

TestInput Extended Syntax
Name   byteVar Num const [word Var] [dword Var] String Const
TestInput X - - - - -


13.17.3 Syntax & Examples

tstInput requires no parameters.




; The following loop continuously checks the keyboard to
; see if a key is available.  If not, it executes the
; "Background" procedure on each iteration of the loop.
;
; This allows background processing to commence as long
; as the user does not press a key on the keyboard.

TstLoop:        tstInput
                jne     GotAKey
                call    Background
                jmp     TstLoop
                
GotAKey:        gets            ;Read a line of text from the user.
                 .
                 .
                 .

13.18 Geth, GethCS, GethStk, Gethl

Geth reads a 16-bit hexadecimal value from the standard input and returns its value in the AX register. Gethl reads a 32-bit value from the standard input and returns its value in EAX. They will skip any leading spaces before the value, as necessary.

If exceptions are enabled, these routines will raise an overflow exception if the value will not fit into 16 bits (Geth) or 32 bits (Gethl). These routines will raise a $Conversion exception if there are any illegal characters in the number. The regular expression that defines a legal hexadecimal value is:




ws* ["0"-"9","A"-"F","a"-"f"] 
	[["0"-"9", "A"-"F", "a"-"f", "_"]* ["0"-"9", "A"-"F", "a"-"f"]]? 
		[ws | ","]

In English, this regular expression says that a hexadecimal value may begin with zero or more whitespace characters, followed by a single hexadecimal digit (0-0, A-F, a-f), followed by zero or more hexadecimal characters and underscores (although an underscore cannot end the value), followed by whitespace or a comma.

Other possible exceptions include $EndOfFile and $FileIO. These exceptions, of course, assume that the standard input is redirected from a file.

If exceptions are not enabled, Geth and Gethl return the carry flag set if an error occurs.

If the hexadecimal value ends with the comma character, the Geth and Gethl routines will remove the comma from the standard input stream. However, if the hexadecimal value ends with a whitespace character, Geth and Gethl will not remove the whitespace character from the standard input stream.


13.18.1 Calling Conventions and Assertions


13.18.2 Geth, Gethl Addressing Modes

Geth, Gethl Addressing Modes
Name Plain CS TOS Stk X CSi
Geth X X - X - -
Gethl X X - X - -

The Geth and Gethl macros allow the following operands:

Geth, Gethl Extended Syntax
Name   Var Num const [word Var] [dword Var] String Const
Geth X word - X X -
Gethl X dword - X X -


13.18.3 Syntax & Examples

Standard calls to Geth, GethCS, GethStk, Gethl, GethlCS, and GethlStk:




                cout    "Enter a 16-bit hex value:"
                geth
                cout    "You entered: ",ax,nl

                gethCS
                dword   wVar

                pshAdrs wVar
                gethStk


                cout    "Enter a 32-bit hex value: "
                gethl
                cout    "You entered: ",eax,nl

                getlhcs
                dword    dVar

                pshadrs  dVar
                getlhStk


13.19 Geti

Geti reads a 16-bit signed integer value from the standard input and returns its value in AX. This value must be in the range -32768..+32767. The regular expression for signed integers is




ws* ["-"]? ["0"-"9"] [["0"-"9","_"]* ["0"-"9"]]? [ws | ","]

In English, this means that a valid integer value can be preceeded by zero or more whitespace characters, followed by an optional minus sign, followed by at least one decimal digit, followed by zero or more decimal digits or underscores (although the number must end with a digit), followed by a comma or whitespace.

Geti can raise the following exceptions:




$Conversion-		If the decimal string contains illegal characters.
$Overflow-		If the value is outside the range -32768..+32767.
$EndOfFile-		If end of file occurs while reading the input.
$FileIO-		If a file I/O error occurs while reading the input.
$Break-		If the user presses control-C while inputting the data.

Geti will only raise an exception if exceptions are enabled. It will return the carry flag set if an error occurs and exceptions are not active.


13.19.1 Calling Conventions and Assertions


13.19.2 Geti Addressing Modes

Geti Addressing Modes
Name Plain CS TOS Stk X CSi
Geti X X - X - -

The Geti macro allows the following operands:

Geti Extended Syntax
Name   wordVar Num const [word Var] [dword Var] String Const
Geti X X - X X -


13.19.3 Syntax & Examples

Standard calls to Geti, GetiCS, and GetiStk:




                print   "Enter an integer: "
                geti
                print   "You entered: "
                puti
                putc

                getiCS
                dword   wVar

                pshadrs wVar
                getiStk

                geti     wVar
                geti     [wVar]
                geti     [dVar]

13.20 Getu

Getu is identical to Geti except it inputs 16-bit unsigned values in the range 0..65535. The regular expression is




	ws* ["0"-"9"] [["0"-"9","_"]* ["0"-"9"]]? [ws | ","]

See the description of Geti for more details about Getu.


13.20.1 Calling Conventions and Assertions


13.20.2 Getu Addressing Modes

Getu Addressing Modes
Name Plain CS TOS Stk X CSi
Getu X X - X - -

The Getu macro allows the following operands:

Getu Extended Syntax
Name   wordVar Num const [word Var] [dword Var] String Const
Getu X X - X X -


13.20.3 Syntax & Examples

Standard calls to Getu, GetuCS, and GetuStk:




                print   "Enter an unsigned 16-bit integer: "
                getu
                print   "You entered: "
                putu
                putcr

                getuCS
                dword   wVar

                pshadrs wVar
                getuStk

                getu     wVar
                getu     [wVar]
                getu     [dVar]

13.21 Getl

Getl is identical to Geti except it reads 32-bit signed integers from the standard input and returns their value in the EAX register. It raises an overflow exception if the value is outside the range -2147483648..+2147483647. Otherwise, its behavoir is identical to Geti's.


13.21.1 Calling Conventions and Assertions


13.21.2 Getl Addressing Modes

Getl Addressing Modes
Name Plain CS TOS Stk X CSi
Getl X X - X - -

The Getl macro allows the following operands:

Getl Extended Syntax
Name   dword Var Num const [word Var] [dword Var] String Const
Getl X X - X X -


13.21.3 Syntax & Examples

Getl, GetlCS, and GetlStk standard syntax:




                print   "Enter a signed 32-bit integer: "
                getl
                print   "You entered: "
                putl
                putcr

                getlCS
                dword   dVar

                pshadrs dVar
                getlStk

                getl     dVar
                getl     [wVar]
                getl     [dVar]

13.22 Getul

Getul is identical to Getu except it reads 32-bit unsigned integers from the standard input and returns their value in the EAX register. It raises an overflow exception if the value is outside the range 0..4294967295. Otherwise, its behavoir is identical to Getu's.


13.22.1 Calling Conventions and Assertions


13.22.2 Getul Addressing Modes

Getul Addressing Modes
Name Plain CS TOS Stk X CSi
Getul X X - X - -

The Getul macro allows the following operands:

Getul Extended Syntax
Name   dword Var Num const [word Var] [dword Var] String Const
Getul X X - X X -


13.22.3 Syntax & Examples

Standard syntax or the Getul, GetulCS, and GetulStk routines:




                print   "Enter a signed 32-bit unsigned integer: "
                getul
                print   "You entered: "
                putul
                putcr

                getulCS
                dword   dVar

                pshadrs dVar
                getulStk

                getul     dVar
                getul     [wVar]
                getul     [dVar]


13.23 Getf

Getf reads a floating point value from the standard input device and pushes the 80-bit result onto the FPU stack. The floating point input value can appear in decimal or scientific notation.

Getf can raise the following exceptions:




$Conversion-		If the decimal string contains illegal characters.
$Overflow-		If the value is outside the range 10**-4930..10**+4930
$EndOfFile-		If end of file occurs while reading the input.
$FileIO-		If a file I/O error occurs while reading the input.
$Break-		If the user presses control-C while inputting the data.

Getf will only raise an exception if exceptions are enabled. It will return the carry flag set if an error occurs and exceptions are not active.


13.23.1 Calling Conventions and Assertions


13.23.2 Getf Addressing Modes

Getul Addressing Modes
Name Plain CS TOS Stk X CSi
Getul X - - - - -

The Getf macro allows the following operands:

Getf Extended Syntax
Name   Var Num const [word Var] [dword Var] String Const
Getf X - - - - -


13.23.3 Syntax & Examples

Getf does not require any operands.




                print   "Enter a floating point value: "
                getf
                print   "You entered: "
                mov     ax, 15
                pute
                putcr

13.24 Scanf, Scanff

The stdlib Scanf routine provides a convient way to read different types of values from the standard input. It uses a format string much like the PRINTF function to determine the types of values to input from the user. The general form of the call is




	scanf
	byte	"format string", 0
	dword	<Parameter list>

The format string consists of a list of format items. A format item takes one of the following forms:




%i	Input an integer
%^i	Input a *integer

%d	Input an integer
%^d	Input a *integer

%u	Input an unsigned integer
%^u	Input an unsigned *integer

%li	Input a 32-bit integer
%^li	Input a 32-bit *integer

%ld	Input a 32-bit integer
%^ld	Input a 32-bit *integer

%lu	Input a 32-bit unsigned integer
%^lu	Input a 32-bit unsigned *integer

%x	Input a 16-bit hex value
%^x	Input a 16-bit hex value and store it through a pointer

%lx	Input a 32-bit hex value
%^lx	Input a 32-bit hex value and store it through a pointer

%h	Input an 8-bit hex value
%^h	Input an 8-bit hex value and store it through a pointer

%c	Input a character
%^c	Input a ^character

%s	Input a string
%^s	Input a *string

%f	Input a float
%^f	Input a *float

%g	Input a double
%^g	Input a *double

There must be at least one character following each format item in the scanf format string. Typically, this would be a space or the string's zero terminating byte. This character is know as the terminating character. Scanf will allow this character (along with whitespace, a comma, or an end of line) to terminate any given input. If the terminating character is a space or a zero byte, then Scanf only allows whitespace as a termination value.

For each format item in the format string, there must be a corresponding double word address following the format string. Consider the following example:




	scanf
	byte	"%d %d %c",0
	dword	IntVar1, IntVar2, CharVar

If a space appears in the format string, then Scanf will automatically skip all whitespace characters before inputting the next value. This is the normal condition for numeric input (via calls to geti, getu, getf, etc). Note, however, that Scanf extends this behavior to characters and strings as well. In the example above, if the user had typed "1 2 c" then Scanf would have place the character "c" into CharVar rather than a space. If you want to read the space as a character, you would need to call Getc.

The character immediately following a format item is special. Scanf will allow the input value corresponding to that format item to end on that character even if that would normally be illegal. For example, consider the following Scanf call:




	scanf
	byte	"%i: %i)",0
	dword	i,j

If any other character appears in the format string, Scanf will remove that character from the standard input if it is the next character to be read from the standard input. Otherwise, Scanf ignores that character in the format string. Note that anywhere a space appears in the format string, Scanf will remove zero or more white space values (rather than just one) from the standard input. Consider the following example:




	scanf
	byte	" -%d (%d)",0
	dword	i,j

In this example, the first character of the format string is a blank. Therefore, Scanf will skip any number of whitespace characters that appear at the beginning of the line. The "-" symbol tells Scanf to eat a minus sign, if that's the next character on the input. Then Scanf reads an integer value into variable I. Next, it skips any amount of whitespace and eats a possible open parenthesis. Then it reads an integer variable into J and (possibly) eats a closing parenthesis. Note that this code attempts to prevent the user from entering negative numbers for variable I (although if the user presses "--1" s/he would still succeed in entering a negative value).

If the "^" symbol appears between the "%" and the type specification then the corresponding parameter specifies the address of a pointer to the destination object rather than the address of the object itself. This lets you read data into strings and other objects you've allocated on the heap or in a local activation record. The pointer itself must be a static variable (typically in the data segment, though this is not required).

Scanf calls Gets to read strings. Therefore, Scanf can read as many as 255 characters from the user when you specify string input. You must ensure that your string variables have sufficient storage to hold any input.

Given Scanf's nature, it is difficult for Scanf to report an error on a specific input element. Therefore, Scanf does not return with the carry denoting an error state. However, Scanf will raise an appropriate exception if an error occurs. If you enable exceptions you can trap errors that occur within Scanf.

Since Scanff duplicates all the features found in Scanf (in addition to adding floating point support), you should never use both Scanff and Scanf in the same program; doing so would waste memory. MASM will generate a warning message if you call both functions in your program.


13.24.1 Calling Conventions and Assertions


13.24.2 Syntax & Examples

Unlike the CIN stream input operator (see the IOStream documentation), Scanf forces you to specify the type of the object you are reading. The downside of this is that you have to know the types and carefully specify them (CIN handles this for you). Furthermore, you cannot easily extend Scanf to read new types (at least, not without changing its source code). There are two corresponding advantages to Scanf: first, you can read one type of variable using a different input format (e.g., read a hexadecimal value and shove it into an integer); the second advantage is that you can use any variable, not just those you've declared in the VAR..ENDVAR section using the type declaration macros. Other, less important, advantages include the ability to skip certain characters on input.




                print   "Enter an integer, a character, and a string:"
                scanf
                byte    "%d %c %s",0
                dword   IntVar, CharVar, StrVar
                
                printf  
                byte    "You entered int=%d, char=%c, string=%s\n",0
                dword   IntVar, CharVar, StrVar
                

13.24.3 Alternate Syntax

Scanf/Scanff supports an alternate syntax that allows you to include the format string and, optionally, the other parameters as operands to the Scanf/Scanff statement. A typical call to Scanf using this syntax would take the form:




	scanf	"%d %c %s",IntVar,CharVar,StrVar

You may also specify the dword parameters separately, as follows:




	scanf	"%d %c %s"
	dword	IntVar, CharVar, StrVar

13.25 GetTermChar, SetTermChar

Most of the numeric input routines terminate numeric input whenever they encounter a symbol that is not an appropriate digit or other allowable character within a number (e.g., "_"). Legal numeric termination characters include whitespace, a comma, or the end of line. Most other characters, if the function encounters them, will raise a conversion exception or return an error. Occasionally, you may want to allow some other character as the termination value. The standard library numeric input routines provide the ability to use one additional termination character. Normally, this feature is disabled. However, you can activate it using GetTermChar and SetTermChar.

GetTermChar returns in AL the current special termination character. If this value is zero, then this feature is currently disabled. You can use GetTermChar to preserve the current value if you need to change it for a short time period.

SetTermChar sets the special termination character to the value found in the AL register.


13.25.1 Calling Conventions and Assertions


13.25.2 Syntax & Examples




SaveChar        byte    ?
                 .
                 .
                 .
                GetTermChar             ;Save current value
                mov     SaveChar, al
                mov     al, ":"         ;Allow #s to end with
                SetTermChar             ; a ":" character.
                 .
                 .                      ;Numeric input routines
                 .                      ; that allow values to
                 .                      ; end with a ":"
                 .
                mov     al, SaveChar    ;Restore the special
                SetTermChar             ; termination char to
                                        ; its previous value.