Sample Program in Non-Transparent Mode [ SNA IMF Programmer's Reference Manual ] MPE/iX 5.0 Documentation
SNA IMF Programmer's Reference Manual
Sample Program in Non-Transparent Mode
When this program is given aninput parm value of zero, it emulates a
display station (LU Type 2) powering on, logging onto the host, logging
off, and powering off. When it is given a parm value greater than zero,
it starts a Pass Thru session with a spooler file (LU Type 3).
program imf3270 (input, output, parm);
const
SCREENSIZE = 1920;
LINESIZE = 80;
{ constant for OPEN3270 }
TERMINAL = -2;
{ constants for action code of PRINT3270 }
OPEN_FILE = 0;
PRINT_SCREEN = 2;
PRINT_BANNER = 3;
CLOSE_FILE = 4;
{ constants for AID of TRAN3270 }
SYS_REQ_KEY = 48;
ENTER_KEY = 39;
{ constants for ACQUIRE3270 }
LU_T3 = -3;
SPOOLER_FILE = 6;
type
shortint = -32768..32767; { 16 bits = 2 bytes }
string = packed array[1..LINESIZE] of char;
screen = packed array[1..SCREENSIZE] of char;
{ type for OPEN3270: }
{ This type takes up 2 bytes. It can be replaced by the shortint type. }
{ This type is defined for ease of assigning values to each }
{ of the different bit groups }
flags_type = packed record
filler : 0..1023; { ten bits }
dbcs : 0..1; { one bit }
unbind : 0..1; { one bit }
LUT1_LUT3 : 0..1; { one bit }
int_trace : 0..1; { one bit }
trans_mode : 0..1; { one bit }
IO_mode : 0..1; { one bit }
end; { total of 16 bits = 2 bytes }
{ type for ACQUIRE3270: }
{ This type takes up two bytes. It can be replaced by the shortint type. }
{ This type is defined for ease of assigning values to each }
{ of the different bit groups }
{ Note that the readTO field takes up nine bits, but the legal }
{ range of values is 10-255, which only takes up 8 bits. }
{ So, the range is set at 10-256 to take up nine bits, }
{ but a value of 256 or higher is not allowed. }
options_type = packed record
filler : 0..1; { one bit }
int_trace : 0..1; { one bit }
sPriority : 1..13; { four bits }
readTO : 10..256; { nine bits. 256 is illegal value. }
LJ2 : 0..1; { one bit }
end; { total of 16 bits = 2 bytes }
{ Global variables: }
{ These variables are global because they must be used in a number of }
{ procedures. Some of them are used to actually pass parameters }
{ to other procedures. Making them global simplifies the code }
{ and makes intuitive sense. }
var
terminalid : shortint; { terminalid used for intrinsics }
result : shortint; { result code of intrinsic calls }
fileid : shortint; { ID of file printed to }
action : shortint; { action code for PRINT3270 }
priority : shortint; { priority given to spooler file }
cursorrow : shortint; { current cursor row position }
cursorcolumn : shortint; { current cursor column position }
numfields : shortint; { number of fields in the current screen }
error : boolean; { global error flag }
location : string; { location string used by PRINT3270 }
parm : shortint; { parameter specified in command line }
procedure VERS3270; intrinsic;
procedure ERR3270; intrinsic;
procedure ACQUIRE3270; intrinsic;
procedure ATTRLIST; intrinsic;
procedure CLOSE3270; intrinsic;
procedure FIELDATTR; intrinsic;
procedure OPEN3270; intrinsic;
procedure PRINT3270; intrinsic;
procedure READSCREEN; intrinsic;
procedure RECV3270; intrinsic;
procedure SCREENATTR; intrinsic;
procedure TRAN3270; intrinsic;
procedure WRITEFIELD; intrinsic;
procedure READFIELD; intrinsic;
{
* The following procedure takes an errorcode, which is usually a result code
* from another intrinsic call, and prints out the corresponding message.
* The conversion is done by ERR3270. ERR3270 takes an errorcode, fills msgbuf
* with the corresponding message, assigns msglen to the message length,
* and sets result to the result code.
}
procedure print_message (errorcode: shortint);
var
msgbuf : packed array[1..144] of char;
msglen : shortint;
begin
{ Set flag if any fatal errors have occurred. }
{ errorcode=0 (and errorcode=9 on MPE V) are not errors. }
if errorcode <> 0 then
error := TRUE;
msgbuf := ' '
ERR3270 (errorcode, msgbuf, msglen, result);
{ Check whether the ERR3270 intrinsic generated any errors. }
if result = 0 then
writeln (msgbuf:msglen)
else begin
writeln ('INTERNAL ERROR in program: ERR3270 result = ', result:2);
error := TRUE;
end { if - else }
end;
{
* The following procedure calls RECV3270 to receive and print a screen.
* The variables terminalid, fileid, action, location, and priority are
* global. terminalid is set by OPEN3270. fileid is set by the first
* PRINT3270 call, which is the call that opens the print file. The variables
* action, location, and priority are set in procedure initialize.
* Note that the priority variable isn't checked after the first call
* to PRINT3270, which opened the print file.
}
procedure call_recv3270;
begin
write (' RECV3270.........');
RECV3270 (terminalid, result);
print_message (result);
write (' PRINT3270 print to file.....')
PRINT3270 (terminalid, fileid, action, location, priority, result);
print_message (result);
end;
{
* The following procedure prints the internal screen image to the spooler
* file before it calls TRAN3270. The variables terminalid, fileid, action,
* location, priority, cursorrow, and cursorcolumn are global.
* terminalid is set by OPEN3270. fileid is set by the first PRINT3270 call,
* which is the call that opens the print file. The variables
* action, location, and priority are set in procedure initialize.
* Note that priority is not checked after the first call to PRINT3270,
* the call that opened the print file.
* cursorrow and cursorcolumn are set by the previous call to SCREENATTR.
* Usually, call_recv3270 follows shortly after a call to this procedure,
* because RECV3270 is usually the first intrinsic called after TRAN3270.
}
procedure call_tran3270 (aid:shortint);
begin
write (' PRINT3270 print to file.....');
PRINT3270 (terminalid, fileid, action, location, priority, result);
print_message (result);
write (' TRAN3270...................');
TRAN3270 (terminalid, aid, cursorrow, cursorcolumn, result);
print_message (result);
end;
{
* The following procedure writes a string to the specified field
* in the internal screen. The variable terminalid is global and
* is set by OPEN3270.
}
procedure call_writefield (outbuf:string; outbuflen, fieldnum:shortint);
var
offset : shortint;
begin
offset := 0;
write (' WRITEFIELD..............');
WRITEFIELD (terminalid, fieldnum, offset, outbuf, outbuflen, result);
print_message (result);
end;
{
* The following procedure calls READSCREEN to read the internal screen
* image and output it to standard output. The variable terminalid
* is global and is set by OPEN3270.
}
procedure call_readscreen;
var
offset : shortint;
maxinbuflen : shortint;
actinbuflen : shortint;
inbuf : screen;
begin
offset := 0;
maxinbuflen := SCREENSIZE;
inbuf := ' ';
write (' READSCREEN.............');
READSCREEN (terminalid, offset, maxinbuflen, inbuf, actinbuflen, result);
print_message (result);
writeln (' the screen read is shown below:')
writeln (inbuf:actinbuflen);
end;
{
* The following procedure calls ATTRLIST to find all the attribute characters
* in the internal screen and their positions (thereby locating all the fields).
* ATTRLIST sets the variable actlistlen, which then indicates the number of
* fields in the screen. The procedure then calls SCREENATTR to find the
* number of fields, the print format, the current cursor position, and other
* screen information. SCREENATTR returns the number of fields through
* the numfields parameter, which is global and is used outside of
* this procedure after SCREENATTR sets it. SCREENATTR's numfields parameter
* and ATTRLIST's actlistlen parameter should contain the same value,
* since they both represent the number of fields in the screen.
* This procedure also calls FIELDATTR once for each field, to get
* information about each of the fields. Finally, it calls the call_readscreen
* procedure to output the screen image. The variable terminalid
* is global and is set by OPEN3270.
}
procedure check_screen;
var
{ ATTRLIST parameters }
offset : shortint;
subscreensize : shortint;
maxlistlen : shortint;
offsetlist : array[1..20] of shortint;
actlistlen : shortint;
fieldnum : shortint;
{ SCREENATTR parameters }
printformat : shortint;
startprint : shortint;
soundalarm : shortint;
keyboardlock : shortint;
screenstatus : shortint;
{ FIELDATTR parameters }
protectedattr : shortint;
currentfieldlen : shortint;
fieldrow : shortint;
fieldcolumn : shortint;
numericattr : shortint;
displayattr : shortint;
mdt : shortint;
maxfieldlen : shortint;
begin
writeln;
writeln ('Checking screen.....');
offset := 0;
subscreensize := SCREENSIZE;
maxlistlen := 20;
write (' ATTRLIST.............');
ATTRLIST (terminalid, offset, subscreensize, maxlistlen, fieldnum,
offsetlist, actlistlen, result);
print_message (result);
if actlistlen = 0 then
writeln (' no attribute characters');
else
for fieldnum := 1 to actlistlen do
writeln (' attribute character #', fieldnum:1,
' position = ', offsetlist[fieldnum]:2);
write (' SCREENATTR.............');
SCREENATTR (terminalid, printformat, startprint, soundalarm,
keyboardlock, numfields, screenstatus, cursorrow,
cursorcolumn, result);
print_message (result);
writeln (' printformat = ', printformat:2,
' numfields = ', numfields:2);
writeln (' cursorrow = ', cursorrow:2,
' cursorcolumn = ', cursorcolumn:2);
for fieldnum := 1 to numfields do
begin
write (' FIELDATTR ', fieldnum:1, '.............');
FIELDATTR (terminalid, fieldnum, fieldrow, fieldcolumn,
protectedattr, numericattr, displayattr, mdt,
currentfieldlen, maxfieldlen, result);
print_message (result);
writeln (' protectedattr = ', protectedattr:2,
' fieldlen = ', currentfieldlen:2);
end;
call_readscreen;
end;
{
* The following function uses READFIELD to check all the fields of
* the current screen for the string "READY". This function is used
* to tell when the host is finished sending screens. It calls SCREENATTR
* to get the number of fields in the screen. SCREENATTR returns this
* value through the parameter numfields. The variable terminalid is
* global and is set by OPEN3270.
}
function ready : boolean;
var
returnval : boolean;
{ SCREENATTR parameters }
printformat : shortint;
startprint : shortint;
soundalarm : shortint;
keyboardlock : shortint;
screenstatus : shortint;
{ READFIELD parameters }
fieldnum : shortint;
maxinbuflen : shortint;
actinbuflen : shortint;
inbuf : string;
offset : shortint;
begin
returnval := FALSE;
write (' SCREENATTR..............');
SCREENATTR (terminalid, printformat, startprint, soundalarm,
keyboardlock, numfields, screenstatus, cursorrow,
cursorcolumn, result);
print_message (result);
writeln (' printformat = ', printformat:2,
' numfields = ', numfields:2);
writeln (' cursorrow = ', cursorrow:2,
' cursorcolumn = ', cursorcolumn:2);
offset := 0;
maxinbuflen := LINESIZE;
for fieldnum := 1 to numfields do
begin
inbuf := ' ';
write (' READFIELD ', fieldnum:1, '................');
READFIELD (terminalid, fieldnum, offset, maxinbuflen, inbuf,
actinbuflen, result);
print_message (result);
writeln (' inbuf = "', inbuf:actinbuflen, '"');
if inbuf = 'READY' then
returnval := TRUE
end;
ready := returnval;
end;
{
* The following procedure calls OPEN3270, simulating powering on an
* IBM display station. OPEN3270 assigns a value to the global variable
* terminalid. This value is used to reference the device in all subsequent
* SNA IMF intrinsic calls. This procedure also uses PRINT3270 to
* open a spooler file, and it prints the attribute characteristic banner
* to the file. Note that RECV3270 must be called after a call to OPEN3270
* to receive the unowned screen.
}
procedure initialize;
var
{ VERS3270 parameter}
version : string;
{ OPEN3270 parameters }
devicenum : shortint;
snalnkinfo : string;
flags : flags_type;
devtype : shortint;
ffindex : shortint; { not used by SNA IMF. Included }
{ for backwards compatibility. }
screensize : shortint;
timeout : packed array[1..2] of shortint;
begin
writeln (' VERS3270..............');
VERS3270 (version);
writeln (' version = ', version:14);
devicenum := TERMINAL;
snalnkinfo := 'IBMNODE#IMFCLASS '; { non-alphanumeric character }
{ marks end of string }
with flags do
begin
filler := 0;
dbcs := 0; { disable double byte character set option }
unbind := 0; { disable unbind option }
LU1_LU3 := 0; { not applicable to terminal emulation. Set to 0. }
int_trace := 0; { internal tracing off }
trans_mode := 0; { transparent mode off }
IO_mode := 0; { standard I/O mode }
end;
ffindex := 0;
timeout[1] := 30;
timeout[2] := 30;
writeln ('Now opening LU.T2 session.....');
write (' OPEN3270.....................');
OPEN3270 (devicenum, snalnkinfo, flags, terminalid, devtype,
ffindex, screensize, timeout, result);
print_message (result);
action := OPEN_FILE; { set action to open spooler file }
location := ' ';
priority := 6;
write (' PRINT3270 open...............');
PRINT3270 (terminalid, fileid, action, location, priority, result);
print_message (result);
action := PRINT_BANNER; { set action to print attribute character
banner }
write (' PRINT3270 print banner.......');
PRINT3270 (terminalid, fileid, action, location, priority, result);
print_message (result);
action := PRINT_SCREEN; { set action to print internal screen image }
{ for the rest of the PRINT3270s }
writeln;
writeln ('Receiving unowned screen.....');
call_recv3270;
check_screen;
error := FALSE;
end;
{
* The following procedure makes the major procedure calls.
* It does the following:
* 1. Sends a system request to the host and receives the LU-SSCP screen.
* 2. Logs onto the host (starting an LU-LU session). Note that
* after receiving the logon message, the host may send more than one
* screen before it is ready to receive again.
* 3. Logs off the host.
* Note that a call_recv3270 follows shortly after each call_tran3270.
}
procedure process;
var
outbuf : string;
outbuflen : shortint;
fieldnum : shortint;
begin
{ Transmit System Request Key and receive LU-SSCP screen. }
writeln;
writeln ('Transmitting System Request Key and receiving LU-SSCP screen');
call_tran3270 (SYS_REQ_KEY);
call_recv3270;
check_screen;
{ Write logon message to LU-SSCP screen. }
writeln;
writeln ('Writing "logon applid...." to field 0');
outbuf := 'logon applid(tso) data(sales/sales) logmode(imf2k)';
outbuflen := 50;
fieldnum := 0;
call_writefield (outbuf, outbuflen, fieldnum);
call_readscreen;
{ Transmit ENTER key to send logon message to host. }
writeln;
writeln ('Transmitting ENTER key.....');
call_tran3270 (ENTER_KEY);
{ The host may send more than one screen here, so we have to make sure }
{ the host is finished sending before we try to send. Function ready }
{ checks to see if the host is finished by searching for the string "READY" }
{ in the screens received from the host. We could just as easily have }
{ waited for a RECV3270 to time out to tell us when the host was finished }
{ sending and ready to receive, but searching for "READY" is more efficient. }
repeat
writeln;
writeln ('Receiving screen and checking for READY or error.....');
call_recv3270;
until error or ready;
check_screen;
{ Write logoff to unprotected field. }
outbuf := 'logoff';
outbuflen := 6;
fieldnum := numfields - 1; { Write to second-to-last field }
{ because it's the unprotected field. }
if fieldnum < 0 then fieldnum := 0;
writeln;
writeln ('Writing "logoff" to field ', fieldnum:2, '.....');
call_writefield (outbuf, outbuflen, fieldnum);
{ Transmit ENTER key to send logoff message to host. }
writeln;
writeln ('Transmitting ENTER key.....');
call_tran3270 (ENTER_KEY);
call_recv3270;
end;
{
* The following procedure does some cleanup. It closes the spooler file,
* and it calls CLOSE3270, which simulates powering off the device.
}
procedure terminate;
begin
action := CLOSE_FILE;
write (' PRINT3270 close.........');
PRINT3270 (terminalid, fileid, action, location, priority, result);
print_message (result);
write (' CLOSE3270............');
CLOSE3270 (terminalid, result);
print_message (result);
end;
{
* The following procedure calls ACQUIRE3270, starting a Pass Thru session
* on an LU.T3 printer. The printer must be free from MPE control when
* ACQUIRE3270 is called, or an error will occur.
}
procedure call_acquire;
var
snalnkinfo : string;
devicenum : shortint;
ldev : shortint;
enhance : shortint;
priority : shortint;
blanks : shortint;
format : shortint;
flags : shortint;
options : options_type;
pfn : string;
begin
snalnkinfo := 'IBMNODE#IMFCLASS '; { non-alphanumeric character }
{ marks end of string }
devicenum := LU_T3;
ldev := SPOOLER_FILE;
enhance := 0;
priority := 6;
blanks := 0; { convert leading blanks to nulls }
format := 2; { print screen as it appears on terminal }
flags := 2; { continue execution after Pass Thru is activated }
with options do
begin
filler := 0;
int_trace := 1; { internal trace on }
sPriority := 7; { spooler file priority = 7 }
readTO := 15; { terminal timeout, not used in this case }
LJ2 := 1; { LaserJet II option is on }
end;
pfn := 'example '; { non-alphanumeric character marks end of string }
writeln ('Now starting Pass Thru session with spooler file.....');
write (' ACQUIRE3270........');
ACQUIRE3270 (snalnkinfo, devicenum, ldev, enhance, priority,
blanks, format, flags, options, pfn, result);
print_message (result);
end;
begin { main }
if parm > 0 then
call_acquire
else begin
initialize;
process;
terminate;
end;
end.
MPE/iX 5.0 Documentation