fix: VarChar handling raw string, VarChar Inz silent drop
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
//! | `rpg_dsply_cstr` | `(ptr: *const c_char)` | Display a null-terminated C string |
|
||||
//! | `rpg_dsply_i64` | `(n: i64)` | Display a signed 64-bit integer |
|
||||
//! | `rpg_dsply_f64` | `(f: f64)` | Display a double-precision float |
|
||||
//! | `rpg_dsply_read` | `(prompt: *const c_char, response: *mut i64)` | Display null-term prompt & read i64 |
|
||||
//! | `rpg_dsply_read_len`| `(ptr: *const u8, len: i64, response: *mut i64)` | Display length-delimited prompt & read i64 |
|
||||
//! | `rpg_halt` | `(code: i32)` | Abnormal program termination |
|
||||
//! | `rpg_char_i64` | `(n: i64) -> *const c_char` | Format integer as null-term C string |
|
||||
//! | `rpg_concat` | `(a: *const c_char, b: *const c_char) -> *const c_char` | Concatenate two C strings |
|
||||
@@ -209,6 +211,59 @@ pub unsafe extern "C" fn rpg_dsply_read(
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// rpg_dsply_read_len — display a length-delimited prompt and read a response
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Three-operand DSPLY where the prompt is a fixed-length (or VarChar) field
|
||||
/// passed as `(ptr, len)` rather than a null-terminated C string.
|
||||
///
|
||||
/// This is called when the prompt operand is a `Char` or `VarChar` variable —
|
||||
/// those are stored as raw byte buffers with no null terminator, so
|
||||
/// `rpg_dsply_read` (which calls `CStr::from_ptr`) cannot be used safely.
|
||||
///
|
||||
/// Trailing ASCII spaces are stripped from the prompt before display, matching
|
||||
/// the behaviour of `rpg_dsply`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must be valid for at least `len` bytes (or be null).
|
||||
/// * `response` must be a valid, writable `i64` pointer.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn rpg_dsply_read_len(
|
||||
ptr: *const u8,
|
||||
len: i64,
|
||||
response: *mut i64,
|
||||
) {
|
||||
use std::io::BufRead;
|
||||
|
||||
// Build the prompt string the same way rpg_dsply does.
|
||||
let bytes = if ptr.is_null() || len <= 0 {
|
||||
b"" as &[u8]
|
||||
} else {
|
||||
unsafe { slice::from_raw_parts(ptr, len as usize) }
|
||||
};
|
||||
let trimmed = rtrim_spaces(bytes);
|
||||
let text = String::from_utf8_lossy(trimmed);
|
||||
|
||||
{
|
||||
let stdout = io::stdout();
|
||||
let mut out = stdout.lock();
|
||||
let _ = writeln!(out, "DSPLY {}", text);
|
||||
let _ = out.flush();
|
||||
}
|
||||
|
||||
// Read one line from stdin and parse it as i64.
|
||||
let stdin = io::stdin();
|
||||
let mut line = String::new();
|
||||
if stdin.lock().read_line(&mut line).is_ok() {
|
||||
let trimmed_line = line.trim();
|
||||
if let Ok(n) = trimmed_line.parse::<i64>() {
|
||||
unsafe { *response = n; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// rpg_halt — abnormal termination
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user