241 lines
10 KiB
Rust
241 lines
10 KiB
Rust
//! Laufzeitfehler: Codes und Meldungstexte kompatibel zum Vorbild.
|
||
//!
|
||
//! Die Codes und (englischen) Meldungstexte entsprechen dem Katalog des
|
||
//! Vorbilds (Original-Hilfe, Topic „Run-Time Error Codes"): klassische
|
||
//! Codes 1–76 (QB-Erbe), 80–89 (ISAM), 260–480 (Forms). Programme prüfen
|
||
//! `ERR` gegen diese Nummern, daher sind sie Teil des Kompatibilitäts-
|
||
//! vertrags. Nicht belegte Nummern liefern "Unprintable error" (wie im
|
||
//! Vorbild bei `ERROR n`); Nummer 105 ist im Vorbild intern reserviert.
|
||
|
||
/// Ein Laufzeitfehler des Dialekts, identifiziert durch seinen klassischen Code.
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||
pub struct RuntimeError(pub u16);
|
||
|
||
impl RuntimeError {
|
||
pub const NEXT_WITHOUT_FOR: Self = Self(1);
|
||
pub const SYNTAX_ERROR: Self = Self(2);
|
||
pub const RETURN_WITHOUT_GOSUB: Self = Self(3);
|
||
pub const OUT_OF_DATA: Self = Self(4);
|
||
pub const ILLEGAL_FUNCTION_CALL: Self = Self(5);
|
||
pub const OVERFLOW: Self = Self(6);
|
||
pub const OUT_OF_MEMORY: Self = Self(7);
|
||
pub const LABEL_NOT_DEFINED: Self = Self(8);
|
||
pub const SUBSCRIPT_OUT_OF_RANGE: Self = Self(9);
|
||
pub const DUPLICATE_DEFINITION: Self = Self(10);
|
||
pub const DIVISION_BY_ZERO: Self = Self(11);
|
||
pub const ILLEGAL_IN_DIRECT_MODE: Self = Self(12);
|
||
pub const TYPE_MISMATCH: Self = Self(13);
|
||
pub const OUT_OF_STRING_SPACE: Self = Self(14);
|
||
pub const STRING_TOO_COMPLEX: Self = Self(16);
|
||
pub const CANNOT_CONTINUE: Self = Self(17);
|
||
pub const FUNCTION_NOT_DEFINED: Self = Self(18);
|
||
pub const NO_RESUME: Self = Self(19);
|
||
pub const RESUME_WITHOUT_ERROR: Self = Self(20);
|
||
pub const DEVICE_TIMEOUT: Self = Self(24);
|
||
pub const DEVICE_FAULT: Self = Self(25);
|
||
pub const FOR_WITHOUT_NEXT: Self = Self(26);
|
||
pub const OUT_OF_PAPER: Self = Self(27);
|
||
pub const WHILE_WITHOUT_WEND: Self = Self(29);
|
||
pub const WEND_WITHOUT_WHILE: Self = Self(30);
|
||
pub const DUPLICATE_LABEL: Self = Self(33);
|
||
pub const SUBPROGRAM_NOT_DEFINED: Self = Self(35);
|
||
pub const ARGUMENT_COUNT_MISMATCH: Self = Self(37);
|
||
pub const ARRAY_NOT_DEFINED: Self = Self(38);
|
||
pub const VARIABLE_REQUIRED: Self = Self(40);
|
||
pub const FIELD_OVERFLOW: Self = Self(50);
|
||
pub const INTERNAL_ERROR: Self = Self(51);
|
||
pub const BAD_FILE_NAME_OR_NUMBER: Self = Self(52);
|
||
pub const FILE_NOT_FOUND: Self = Self(53);
|
||
pub const BAD_FILE_MODE: Self = Self(54);
|
||
pub const FILE_ALREADY_OPEN: Self = Self(55);
|
||
pub const FIELD_STATEMENT_ACTIVE: Self = Self(56);
|
||
pub const DEVICE_IO_ERROR: Self = Self(57);
|
||
pub const FILE_ALREADY_EXISTS: Self = Self(58);
|
||
pub const BAD_RECORD_LENGTH: Self = Self(59);
|
||
pub const DISK_FULL: Self = Self(61);
|
||
pub const INPUT_PAST_END_OF_FILE: Self = Self(62);
|
||
pub const BAD_RECORD_NUMBER: Self = Self(63);
|
||
pub const BAD_FILE_NAME: Self = Self(64);
|
||
pub const TOO_MANY_FILES: Self = Self(67);
|
||
pub const DEVICE_UNAVAILABLE: Self = Self(68);
|
||
pub const COMM_BUFFER_OVERFLOW: Self = Self(69);
|
||
pub const PERMISSION_DENIED: Self = Self(70);
|
||
pub const DISK_NOT_READY: Self = Self(71);
|
||
pub const DISK_MEDIA_ERROR: Self = Self(72);
|
||
pub const FEATURE_UNAVAILABLE: Self = Self(73);
|
||
pub const RENAME_ACROSS_DISKS: Self = Self(74);
|
||
pub const PATH_FILE_ACCESS_ERROR: Self = Self(75);
|
||
pub const PATH_NOT_FOUND: Self = Self(76);
|
||
// Forms-Fehler (Auswahl mit benannten Konstanten; vollständige Texte in message()):
|
||
pub const INVALID_SCREEN_MODE: Self = Self(271);
|
||
pub const INVALID_WHEN_FORMS_SHOWING: Self = Self(272);
|
||
pub const INVALID_PROPERTY_VALUE: Self = Self(380);
|
||
pub const DESIGN_TIME_CONTROL: Self = Self(362);
|
||
pub const FORM_ALREADY_DISPLAYED: Self = Self(400);
|
||
pub const NON_MODAL_WHILE_MODAL: Self = Self(401);
|
||
pub const MODAL_NOT_TOPMOST: Self = Self(402);
|
||
pub const MDI_FORM_MODAL: Self = Self(403);
|
||
pub const NO_ACTIVE_CONTROL: Self = Self(430);
|
||
pub const NO_ACTIVE_FORM: Self = Self(431);
|
||
|
||
/// Klassischer Fehlercode für `ERR`.
|
||
pub fn code(self) -> u16 {
|
||
self.0
|
||
}
|
||
|
||
/// Meldungstext des Vorbilds; unbelegte Codes: "Unprintable error".
|
||
pub fn message(self) -> &'static str {
|
||
match self.0 {
|
||
1 => "NEXT without FOR",
|
||
2 => "Syntax error",
|
||
3 => "RETURN without GOSUB",
|
||
4 => "Out of DATA",
|
||
5 => "Illegal function call",
|
||
6 => "Overflow",
|
||
7 => "Out of memory",
|
||
8 => "Label not defined",
|
||
9 => "Subscript out of range",
|
||
10 => "Duplicate definition",
|
||
11 => "Division by zero",
|
||
12 => "Illegal in direct mode",
|
||
13 => "Type mismatch",
|
||
14 => "Out of string space",
|
||
16 => "String formula too complex",
|
||
17 => "Cannot continue",
|
||
18 => "Function not defined",
|
||
19 => "No RESUME",
|
||
20 => "RESUME without error",
|
||
24 => "Device timeout",
|
||
25 => "Device fault",
|
||
26 => "FOR without NEXT",
|
||
27 => "Out of paper",
|
||
29 => "WHILE without WEND",
|
||
30 => "WEND without WHILE",
|
||
33 => "Duplicate label",
|
||
35 => "Subprogram not defined",
|
||
37 => "Argument-count mismatch",
|
||
38 => "Array not defined",
|
||
40 => "Variable required",
|
||
50 => "FIELD overflow",
|
||
51 => "Internal error",
|
||
52 => "Bad file name or number",
|
||
53 => "File not found",
|
||
54 => "Bad file mode",
|
||
55 => "File already open",
|
||
56 => "FIELD statement active",
|
||
57 => "Device I/O error",
|
||
58 => "File already exists",
|
||
59 => "Bad record length",
|
||
61 => "Disk full",
|
||
62 => "Input past end of file",
|
||
63 => "Bad record number",
|
||
64 => "Bad file name",
|
||
67 => "Too many files",
|
||
68 => "Device unavailable",
|
||
69 => "Communication-buffer overflow",
|
||
70 => "Permission denied",
|
||
71 => "Disk not ready",
|
||
72 => "Disk-media error",
|
||
73 => "Feature unavailable",
|
||
74 => "Can't rename with different drive",
|
||
75 => "Path/File access error",
|
||
76 => "Path not found",
|
||
// ISAM (PDS-Erbe) — Terminal Basic implementiert ISAM nicht,
|
||
// die Codes/Texte gehören aber zum Kompatibilitätsvertrag.
|
||
80 => "Feature removed",
|
||
81 => "ISAM - Invalid name",
|
||
82 => "ISAM - Table not found",
|
||
83 => "ISAM - Index not found",
|
||
84 => "ISAM - Invalid column",
|
||
85 => "ISAM - No current record",
|
||
86 => "ISAM - Duplicate value for unique index",
|
||
87 => "ISAM - Invalid operation on NULL index",
|
||
88 => "ISAM - Database inconsistent",
|
||
89 => "ISAM - Insufficient ISAM buffers",
|
||
// Forms-Fehler des Vorbilds
|
||
260 => "No timer available",
|
||
271 => "Invalid screen mode",
|
||
272 => "Invalid when forms are showing",
|
||
340 => "Control array element does not exist",
|
||
341 => "Invalid object array index",
|
||
342 => "Not enough room to allocate control array",
|
||
343 => "Object not an array",
|
||
344 => "Must specify index for object array",
|
||
345 => "Reached limit: cannot create any more controls for this form",
|
||
360 => "Object already loaded",
|
||
361 => "Can't load or unload this object",
|
||
362 => "Can't unload controls created at design time",
|
||
363 => "Custom control not found",
|
||
364 => "Object was unloaded",
|
||
365 => "Unable to unload within this context",
|
||
380 => "Invalid property value",
|
||
381 => "Invalid property array index",
|
||
382 => "Property can't be set at run time",
|
||
383 => "Property is read-only",
|
||
384 => "Property can't be modified when form is minimized or maximized",
|
||
385 => "Must specify index when using property array",
|
||
386 => "Property not available at run time",
|
||
387 => "Property can't be set on this control",
|
||
400 => "Form already displayed; can't show form modally",
|
||
401 => "Can't show non-modal form when a modal form is being displayed",
|
||
402 => "Must close or hide topmost modal form first",
|
||
403 => "MDI form cannot be shown modally",
|
||
410 => "Property can't be modified on MDI form",
|
||
420 => "Invalid object reference",
|
||
421 => "Method not applicable for this object",
|
||
422 => "Property not found",
|
||
423 => "Property or control not found",
|
||
424 => "Object required",
|
||
425 => "Invalid object use",
|
||
430 => "No currently active control",
|
||
431 => "No currently active form",
|
||
480 => "Can't create AutoRedraw image",
|
||
_ => "Unprintable error",
|
||
}
|
||
}
|
||
}
|
||
|
||
impl std::fmt::Display for RuntimeError {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
write!(f, "{}", self.message())
|
||
}
|
||
}
|
||
|
||
impl std::error::Error for RuntimeError {}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn bekannte_codes() {
|
||
assert_eq!(RuntimeError::OVERFLOW.code(), 6);
|
||
assert_eq!(RuntimeError::OVERFLOW.message(), "Overflow");
|
||
assert_eq!(RuntimeError::SUBSCRIPT_OUT_OF_RANGE.code(), 9);
|
||
assert_eq!(RuntimeError::FILE_NOT_FOUND.message(), "File not found");
|
||
assert_eq!(RuntimeError::FEATURE_UNAVAILABLE.code(), 73);
|
||
}
|
||
|
||
#[test]
|
||
fn forms_und_isam_codes() {
|
||
assert_eq!(RuntimeError(80).message(), "Feature removed");
|
||
assert_eq!(
|
||
RuntimeError::INVALID_WHEN_FORMS_SHOWING.message(),
|
||
"Invalid when forms are showing"
|
||
);
|
||
assert_eq!(RuntimeError::NO_ACTIVE_FORM.code(), 431);
|
||
assert_eq!(
|
||
RuntimeError(403).message(),
|
||
"MDI form cannot be shown modally"
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn unbelegte_codes_sind_unprintable() {
|
||
assert_eq!(RuntimeError(15).message(), "Unprintable error");
|
||
assert_eq!(RuntimeError(105).message(), "Unprintable error"); // intern reserviert
|
||
assert_eq!(RuntimeError(200).message(), "Unprintable error");
|
||
assert_eq!(RuntimeError(500).message(), "Unprintable error");
|
||
}
|
||
}
|