A C++ library for scripting and automating IBM TN5250 terminal emulator interactions.
- Full scripting language with lexer, parser, AST, and executor pipeline.
- Screen interaction commands:
-
TYPEtext input andPRESSkey simulation (AID keys and local keys). -
EXPECTconditions to wait for screen content, cursor position, or keyboard state. -
EXTRACTdata from screen text, fields, cursor position, and rows. -
MOVE CURSORwith absolute coordinates, field index, or directional movement.
-
- Variable system with
SET,INC,DEC,ADD, and string interpolation. - Built-in variables:
$TITLE,$CURSOR_ROW,$CURSOR_COL,$KEYBOARD_STATE,$MESSAGE_WAITING,$EXPECT_RESULT. - Control flow:
-
IF/ELSE/ENDIFconditionals with==,!=,<,>,<=,>=,CONTAINS,ISSET. - Compound conditions with
AND,OR,NOT, and parenthesized grouping. -
WHILE/ENDWHILEandREPEAT/ENDREPEATloops. -
LABEL/GOTOfor jump-based flow control.
-
- User-defined functions with
DEF/ENDDEF,CALL,RETURN, and parameter scoping. - Error handling with
ON TIMEOUT GOTOandON ERROR GOTO. - Timing control with
WAIT,GLOBAL DELAY,GLOBAL JITTER, andGLOBAL EXPECT_TIMEOUT. - Utility commands:
LOG,PAUSE,INPUT,ABORT. - Script metadata via comments (
# @script.name,# @script.author,# @menu.path). - Abstract
ScreenInterfacefor integration with any Qt-based host application. - Comprehensive test suite with 160+ test cases.
5250script uses CMake and requires C++20 and Qt6:
cmake -B build -DBUILD_5250SCRIPT_TESTS=ON
cmake --build build
ctest --test-dir build
#include <5250script/script_parser.h>
#include <5250script/script_executor.h>
// 1. Parse the script
ScriptParser parser;
ParseResult result = parser.parse(scriptText);
if (result.hasErrors()) {
for (const auto &err : result.errors) {
qDebug() << "Line" << err.line << ":" << err.message;
}
return;
}
// 2. Create executor with screen implementation
ScriptExecutor executor;
executor.setScreen(screenImpl);
// 3. Set initial variables
QHash<QString, QString> vars;
vars["USERNAME"] = "QSECOFR";
vars["PASSWORD"] = "PASSWORD";
executor.setInitialVariables(vars);
// 4. Connect signals
connect(&executor, &ScriptExecutor::injectAIDKey,
this, &MainWindow::handleAIDKey);
connect(&executor, &ScriptExecutor::executionFinished,
this, &MainWindow::onScriptFinished);
// 5. Execute
executor.execute(result);# @script.name = "Login Script"
# @script.author = "Admin"
# Set credentials
SET $user "QSECOFR"
SET $pass "PASSWORD"
# Wait for login screen
EXPECT TEXT "User" AT ROW 6
MOVE CURSOR AT INPUTFIELD 1
TYPE $user
PRESS TAB
TYPE $pass
PRESS ENTER
# Verify login succeeded
EXPECT TEXT "Main Menu"
LOG "Login successful"
-
Automating a login with retry logic:
DEF login($user, $pass) EXPECT TEXT "User" AT ROW 6 MOVE CURSOR AT INPUTFIELD 1 TYPE $user PRESS TAB TYPE $pass PRESS ENTER ENDDEF ON TIMEOUT GOTO retry GLOBAL EXPECT_TIMEOUT 5000 SET $attempts 0 LABEL retry INC $attempts IF $attempts > 3 ABORT "Login failed after 3 attempts" ENDIF CALL login("QSECOFR", "PASSWORD") EXPECT TEXT "Main Menu" LOG "Logged in after $attempts attempt(s)" -
Extracting screen data with conditions:
EXPECT KEYBOARD UNLOCKED EXTRACT $title FROM 1 1 LENGTH 40 IF $title CONTAINS "Error" LOG "Error screen detected: $title" ABORT "Unexpected error screen" ENDIF SET $row 1 WHILE $row <= 24 EXTRACT $line LINE $row IF $line CONTAINS "MSGW" LOG "Message waiting on row $row" ENDIF INC $row ENDWHILE
Pull requests are welcome. Feel free to open an issue if you want to add other features.
