256B FullFileName¶
Validated MON 256B (174 decimal) · Mnemonic DEABF · Group: File Operations (manual section 2.4)
Available from: All programs (manual compatibility box)
Emulation source: src/handlers/mon_256B_FullFileName.c
Description¶
Returns a complete file name from an abbreviated one. The directory, the user, the file name, the file type, and the version are returned.
Notes¶
- You must have read access to the file.
- The abbreviation must be unambiguous.
- SINTRAN III, version K, allows remote file names. If the abbreviated file name contains a remote specification, the name of the remote system cannot be abbreviated.
Parameters¶
| Name | Type | Direction | Description |
|---|---|---|---|
AbbrevFileName |
STRING | In | Abbreviated file name string (64 chars). May include a file type. |
FileName |
STRING | Out | Buffer to receive complete file name, terminated by apostrophe (64 chars). |
FileType |
STRING | In | Default file type string (4 chars). Used on ND-100 only, ignored by ND-500. |
Direction: In = the program supplies the value, Out = the call returns it, In/Out = both.
See also¶
Compatibility¶
| Machines | Users | Programs |
|---|---|---|
| ND-100 and ND-500 | All users | All programs |
The manual's compatibility box for this call, word for word.
Yes/no fields from the YAML extraction (not in the manual's words):
| ND-100 | ND-500 | User programs | RT programs | System programs |
|---|---|---|---|---|
| Yes | Yes | Yes | Yes | No |
Examples¶
From the manual (OCR text, not corrected).
BYTES : AbbrevFileName(0:63), FileName(0:63), FileType(0:3)
...
ON ROUTINEERROR DO
IF ErrCode > 0 THEN ...
ENDON
Monitor_Call('FullFileName', AbbrevFileName, FileName, FileType)
CHARACTER AbbrevFileName*64, FileName*64, FileType*4
...
Monitor_Call('FullFileName', AbbrevFileName(1:64), FileName(1:64),
C FileType(1:4))
IF (ErrCode .NE. 0) THEN ...
AbbrevFileName, FileName : PACKED ARRAY [0..63] OF CHAR;
FileType : PACKED ARRAY [0..3] OF CHAR;
...
FullFileName(AbbrevFileName, FileName, FileType);
IF ErrCode <> 0 THEN ...
01 AbbrevFileName PIC X(64).
01 FileName PIC X(64).
01 FileType PIC X(4).
01 ErrCode COMP.
...
MONITOR-CALL "FullFileName" USING AbbrevFileName, FileName, FileType.
CALL "CbError" USING ErrCode.
IF ErrCode NOT = 0 GO ...
AbbrevFileName : STRINGDATA 'EX'''
FileName : STRING 64
FileType : STRINGDATA 'SYMB''' %Default file type.
ErrCode : W BLOCK 1
FullFileName : EQU 37B9 + 256B
...
CALLG FullFileName, 3, AbbrevFileName, FileName, FileType
IF K GO ERROR
...
ERROR : W1 := ErrCode %ErrorCode in W1 register.
LDX (ABBR) %Address of abbreviated file name string.
LDA (FILE) %Address of string to receive full file name.
LDT (TYPE) %Address of default file type string.
MON 256 %Monitor call FullFileName.
JMP ERROR %Error return from monitor call.
... %Normal return.
ERROR, ... %Error number in register A.
...
ABBR, 'EX' %Find full file name of EX.
FILE, 0 %Empty string. (A and X may be identical.)
*+76/ %Make space to receive full file name.
TYPE, 'SYMB' %Default file type SYMB.
ndmonlib implementation¶
Validated Registered MON_STATUS_VALIDATED in src/core/mon_registry.c: implemented, tested and working.
| Handler | mon_256B_FullFileName |
| Code lines | 102 (non-blank, non-comment lines in the file) |
Notes from the handler source¶
src/handlers/mon_256B_FullFileName.c line 32
ND-500 form takes 2 args (AbrevName, FullName). The default-file-type
(arg 3) is ND-100-only and ignored here; require only 2 args so NC's real
2-arg CALLG is not rejected.
src/handlers/mon_256B_FullFileName.c line 42
Read the abbreviated name. On ND-500 a STR argument is a [length:4][ptr:4]
descriptor, which is how the ND linker passes it: for `OPEN-DOMAIN "A-TEST"`
arg 0 is {len=64, ptr-> "A-TEST:DOM'"}. Reading it INLINE (mon_read_sintran_
string) read the descriptor's own first byte - the high byte of the length,
0x00 - as a terminator and yielded an EMPTY name, so DEABF returned "no such
file" and the linker aborted OPEN-DOMAIN with error 41B. Read the descriptor
form first; fall back to inline only if the descriptor is not valid, so a
caller that passes an inline string still works.
src/handlers/mon_256B_FullFileName.c line 66
Split the abbreviated name into user/name/type so we can resolve it to a
host file and check existence. If the name carries no type, fall back to
the (ND-100) default file type when one was supplied.
src/handlers/mon_256B_FullFileName.c line 69
+1 for the null terminator (matching mon_path.c). Without it a full-length
16-char SINTRAN name like "LINKER-AUTO-FORT" is truncated to 15 chars
("LINKER-AUTO-FOR"), so DEABF then reports NO SUCH FILE NAME and the ND
LINKER's CLOSE auto-job (which resolves LINKER-AUTO-<lang>:JOB through
DEABF) fails - breaking every link.
src/handlers/mon_256B_FullFileName.c line 86
Resolve to a host path and check whether the file exists. Rebuild the
(USER)NAME form for the translator so its user handling applies.
src/handlers/mon_256B_FullFileName.c line 96
Resolve for lookup: own directory first, then the SINTRAN (SYSTEM)
fallback for an unqualified name (verified GFILI behaviour, carve
006-S3FS). mon_translate_path_lookup leaves host_path on the own-directory
path when the file is found in neither, so the not-found (create) path is
unchanged.
src/handlers/mon_256B_FullFileName.c line 113
Found: build the canonical expanded name (DIR:USER)NAME:TYPE;VERSION.
DEABF returns "the directory, the user, the file name, the file type, AND the
VERSION" (Monitor Calls ND-860228, 256B FULLFILENAME). The version is NOT
cosmetic: on a name with no explicit ;version, SINTRAN's GFILI resolver walks
the file's on-disk version chain and selects the default (highest) version, and
the canonical name it hands back carries that ;VERSION field. Byte-verified in
the S3FS carve: FLPAR/MDEAB resolver + GFILI @057173 version chain
(057276 "no version requested -> pick default", framing NAME:TYPE;VERSION) --
/mnt/e/Dev/Ronny/NDInsight/tools/sintran-segment-carver/versions/L-VSX-500/re/
segments-ref/006-S3FS/{CARVE-ANSWER-FLPAR-MDEAB-FOR-IMPLEMENTER,
GFILI-COMPLETE-CARVE}.md
The ND Linker relies on this: `LOAD B:NRF` resolved to version-less "B:NRF" was
rejected with (-677:52) BEFORE any object open; with the ;VERSION it OPENs .NRF.
Our host files carry no SINTRAN version chain, so each maps to a single on-disk
version whose default is version 1 -- exactly what GFILI's default-version walk
yields. So append ";1" UNLESS the resolved name already carries an explicit
version (defensive; the linker never sends one). Only FOUND files get a version;
a not-yet-created name still returns not-found so NC's create path is unchanged.
src/handlers/mon_256B_FullFileName.c line 133
The canonical name is ALWAYS fully qualified "(DIR:USER)NAME:TYPE" -
DEABF "returns the directory, the user, ..." even when the caller gave
an unqualified abbreviation. CONVERT-DOM-A03 asserts on this: it scans
the expanded name for the "(DIR:USER)" prefix (check at 0x080025B6..D1,
EASSERT at 0x080025D3) to learn where the old domain's files live, and
an unqualified reply is a hard EASSERT VIOLATION. Report the USER the
lookup actually resolved to (own dir or the SYSTEM fallback), derived
from the host path "<root>/<USER>/<NAME>.<TYPE>"; the directory level
does not exist in the host mapping, so use the fixed main-directory
name PACK-ONE (the name ND's own manuals use in examples).
src/handlers/mon_256B_FullFileName.c line 178
Write the full name to the OUTPUT argument. On ND-500 arg 1 is also a
[length:4][ptr:4] descriptor, so the bytes go to the descriptor's POINTER,
not to the descriptor address itself. Writing to the descriptor address
corrupted the descriptor; the linker then read its "full name" through a
garbage pointer and took a page fault. Terminate with 0x27 (apostrophe).
Fall back to writing inline at the arg address if arg 1 is not a valid
descriptor (an inline caller).
src/handlers/mon_256B_FullFileName.c line 197
K=CLEAR on success. An earlier revision set K=1 here, justified by reading
`callg ...; if k go <target>` at B004DA08/B004DA13 as a jump-if-success.
That reading was wrong on two counts, both byte-verified in
/mnt/d/ND/500/nd-linker/linker-b01.dom.asm:
1. B004D9E6-B004DA5B is the linker's GENERIC indirect MON trampoline
(one `callg b.0x40,$N,...` per arity 1..6). It is not DEABF-specific,
so it says nothing about this call's private convention.
2. In that trampoline the if-k target is the ERROR arm:
B004DBF1: w move b.0x44,b.0xC <- returned W1 into the error slot
while the fall-through (K clear) arm is the SUCCESS one:
B004DBED: w stz b.0xC <- error slot zeroed
The wrapper at B004D8DE treats a NONZERO b.0xC as an error code.
The OPEN-DOMAIN call site agrees and tests K directly with no masking:
B0000A6D: call $0xFFFFFFFFF80000AE,$0x3 ; MON 256B DEABF
B0000A76: if k go $0x3 ; -> B0000A79 ... retk (error)
B0000A78: ret ; K clear = success
With K=1 the linker took the error arm out of OPEN-DOMAIN and reported
"SINTRAN (0000:00)" even though every MON call had succeeded. The old K=1
was invisible at the LOAD site only because the companion I1=0 below makes
the error arm copy 0 into b.0xC, which the wrapper reads as "no error".
So: K clear on success, which is what mon_set_success already does.
src/handlers/mon_256B_FullFileName.c line 222
Success return value: W1/i1 = 0. The linker's generic MON trampoline
(callg at B004DA08; B004DA11 `w1 =: b.0x44`) copies our returned I1 into
the caller's result slot b.0xC, and the wrapper at B004D8DE treats a
NONZERO b.0xC as an error code (b.0xC!=0 -> retk with w1=b.0xC). Neither
mon_set_success nor the executor writes I1 on success, so without this I1
kept the trampoline's leftover call-target value 0xF80000AE
(0xF8000000 + 0xAE; 0xAE = 256B octal = DEABF's own routine number). The
linker then read 0xF80000AE as an error code from LOAD's name-resolve and
re-prompted the object-file field forever instead of opening the file.
The DEABF contract is that the caller distinguishes success by W1/i1 == 0
(see 256B_FULLFILENAME.yaml return_contract), so set it here.
Emulation research¶
Source
This section comes from the emulation: block of the call's YAML file in the NDInsight repo. It records what was learned while implementing the call in nd500x; its status is nd500x's, not ndmonlib's.
| Status (nd500x) | implemented |
| nd500x handler | nd500x/src/libmon/handlers/mon_256B_FullFileName.c |
| Last updated | 2026-07-17 |
Parameter notes¶
1. FileType
| Field | Value |
|---|---|
| Note | The ND-500 form of this call takes TWO arguments (AbbrevFileName, FileName). The default-file-type parameter is ND-100-only and is IGNORED on the ND-500 - which the manual field in this YAML already says. REQUIRING three arguments rejects the real 2-arg CALLG that NC and the linker issue, so the handler requires only 2 and reads arg 2 if present. |
| Verified | Yes |
2. FileName
| Field | Value |
|---|---|
| Note | The output name is written to the caller's buffer and terminated with 047 octal (0x27, apostrophe) - not a NUL. |
| Verified | Yes |
Return contract¶
- Success: The expanded name is written to FileName, apostrophe-terminated. K FLAG: the ND-500 form (as the B01 linker calls it) returns with K SET on success, NOT cleared - the caller distinguishes success from error by W1/i1 (0 = success, error code otherwise), not by the K flag alone. This corrects the earlier 'K flag cleared' reading, which came from the generic MAC-style 'IF K GO ERROR' example and was never byte-verified for the ND-500 body. Live-linker evidence 2026-07-18: see updates_2026_07_18.
-
Errors
Code Octal Meaning 46 056B No such file name (unresolved abbreviation, or an unparseable name). This exact code is what NC tests to decide whether to CREATE the file. 111 157B Missing parameter (fewer than 2 args)
Verified¶
1. On an unresolved name this call must set K and return 46 (056B). A pass-through echo that always succeeds silently breaks NC's create-if-missing path.
| Field | Value |
|---|---|
| Evidence | Verified against the carve (006-S3FS DEABF) and the NC-oracle tier3 contract. Recorded in nd500x/docs/MON_CSHARP_SYNC_HANDOFF.md section "256B DEABF (FullFileName)" and MON_COMPLETENESS_MATRIX.md row 256B. |
2. The 2-argument ND-500 form is the real one.
| Field | Value |
|---|---|
| Evidence | NC and the linker issue a 2-arg CALLG; requiring 3 rejected it. Same source as above. |
Unverified¶
- The ND-500 DEABF body does NOT cleanly decode in the carve, so the FIELD ASSEMBLY of the returned name (directory, user, file name, file type, version - the five things the manual promises) follows the MANUAL, not a byte-proven layout. nd500x currently returns only (USER)NAME:TYPE - it does NOT return the directory or the version. Treat the exact returned form as INFERRED.
- nd500x resolves by checking host-file EXISTENCE via the path translator. It does NOT run the carved COMPS/GOBJI abbreviation matcher that 50B OPEN uses (mon_file_table.c). So a name that 50B OPEN would resolve by abbreviation may be reported as "no such file name" here. This is a known INCONSISTENCY between the two calls and has not been reconciled.
- There is no AMBIGUOUS return path. The manual says "The abbreviation must be unambiguous"; the carved scanner (GOBJI @056326) returns 057 for an ambiguous name. nd500x never returns 057 from this call.
- "You must have read access to the file" is not modelled.
- Remote file names (SINTRAN III version K) are not modelled.
- Two 256B unit tests in nd500x/test/test_mon_calls.c fail as a KNOWN, INTENTIONAL consequence of the err-46-on-unresolved change: they were written against the old always-succeed echo. The failures are expected, not a regression.
Sources¶
| Doc | Note | Carve |
|---|---|---|
| SINTRAN III Monitor Calls (ND-860228.2 EN) | The manual page this YAML was extracted from. | |
| L-VSX-500 segment 006-S3FS, DEABF (body does not cleanly decode - routing/contract only) | ||
| nd500x/docs/MON_CSHARP_SYNC_HANDOFF.md | Section "256B DEABF (FullFileName) - matters for NC create-if-missing". | |
| nd500x/docs/MON_COMPLETENESS_MATRIX.md | Row 256B - FIXED. |
Updates 2026 07 17¶
1. STR args are [len][ptr] descriptors on ND-500, not inline
| Field | Value |
|---|---|
| Status | verified |
| Detail | DEABF arg 0 (abbreviated name, IN) and arg 1 (full name, OUT) are ND-500 string DESCRIPTORS: [length:4][pointer:4]. The name bytes live at the pointer, not at the argument address. Reading arg 0 inline gets the descriptor's own first byte (the length's high byte, 0x00) as a terminator and yields an EMPTY name. Observed: the ND linker's OPEN-DOMAIN "A-TEST" passes arg 0 = {len=64, ptr-> "A-TEST:DOM'"}. arg 3 (default file type) is a dummy on ND-500. |
| Effect | With inline reads DEABF returned "no such file" for a valid name, and the linker aborted OPEN-DOMAIN with error 41B; it also wrote its output to the descriptor address, corrupting it (later page fault). Fixed to read/write via the descriptor pointer, with inline fallback. Same [len][ptr] class as 12B SETCM / NC UECOM. |
| Nd500x commit | 975707b |
Updates 2026 07 18¶
1. ND-500 DEABF returns K SET on success (corrects return_contract.success)
| Field | Value |
|---|---|
| Status | verified-against-live-linker |
| Detail | The B01 linker resolves file names with callg <seg31:256B DEABF> at B004DA08, then if k go at B004DA13. The DEABF K flag propagates through the linker's scanner/resolve chain (B004D4F4 -> B004D8DE) and finally gates B0040D75 if -k go: with K SET the linker calls B0040C44 and continues the LOAD; with K CLEAR it falls through to error 52 ("(-677:52)", blank message) and LOAD aborts BEFORE opening the object file. So the ND-500 linker requires DEABF success to end with K SET. |
| Evidence | CALLTRACE differential (nd500x test/diag_linkdrive) of OPEN-DOMAIN A-TEST;;LOAD B:NRF;;EXIT. PRE-FIX (DEABF success -> K cleared, the old convention): B004DA16->B004DBD0->B004DBED (b.0xC=0), helper B004D8DE returns K CLEAR, B0040D75 falls to error 52. POST-FIX (DEABF success -> K set): B004DA13->B004DBF1, helper returns K SET, B0040D75 calls B0040C44, LOAD proceeds. Cross-check: LOAD NOPE (nonexistent) still returns error 46 and the linker correctly prints "*** ERROR - NOPE ... No such file name", so K-set-on-success does NOT break the error path - the caller distinguishes success (i1=0) from error (i1=46) by W1/i1, not by K. |
| Caveat | The carve's earlier 'success = K cleared' was inherited from the generic MAC/ND-100 IF K GO ERROR example and the YAML's own unverified note already flagged the ND-500 DEABF body as not-cleanly-decoded. This update supersedes that line for the ND-500 form. The ERROR case (set K, return 46) remains carve-verified and unchanged: on the ND-500 the caller keys on i1/W1, and both success (i1=0) and error (i1!=0) end with K set. |
| Nd500x handler | nd500x/src/libmon/handlers/mon_256B_FullFileName.c |
| Nd500x change | On the resolve/success path, after mon_set_success (which sets K=0), explicitly ctx->set_k_flag(cpu, 1). Error path (mon_set_error) already set K=1, so no change there. Not yet committed as of 2026-07-18. |
Updates 2026 07 18b¶
1. DEABF success MUST also set W1/i1 = 0 (this is what actually unblocks LOAD)
| Field | Value |
|---|---|
| Status | verified-against-live-linker |
| Detail | The K=1-on-success change alone did NOT make LOAD work - it only traded one failure for another. The linker resolves the LOAD object name through its universal MON dispatcher B004D4F4 (called at B0040D5C with routine 0xAE = 256B), whose generic trampoline copies the callee's returned I1 into the caller result slot (B004DA11 w1 =: b.0x44 -> b.0xC) and treats a NONZERO value as an error code (wrapper B004D8DE: b.0xC != 0 -> retk). Our DEABF success path called mon_set_success (which does NOT write I1) and the executor writes I1 only on error, so on success I1 kept the trampoline's leftover call-target 0xF80000AE (0xF8000000 + 0xAE; 0xAE is 256B's own routine number). The linker read that as error 0xF80000AE and RE-PROMPTED the LOAD object-file field forever (each fed line concatenated into the un-cleared VTM field, e.g. EXIT after LOAD B:NRF -> DEABF lookup of 'EXITB:NRF'). |
| Fix | In mon_256B_FullFileName.c, on the success path set ctx->set_i1(cpu, 0) (in addition to the existing set_k_flag(cpu,1)). This matches the documented contract (caller distinguishes success by W1/i1 == 0). |
| Evidence | BREAK at B004DA13 during LOAD: pre-fix I1 = 0xF80000AE (the leftover target), K set. Post-fix I1 = 0, and the re-prompt loop is gone: LOAD proceeds past name-resolution and EXIT exits cleanly (MON 0B LEAVE), OPEN-DOMAIN "A-TEST" still creates+reads the domain (no regression on the other DEABF caller at B0000A6D). |
| Still blocked | LOAD does NOT yet open/read the object B.NRF. After DEABF success the linker's LOAD-object routine (B0040CB0..B0040D84) still raises error 52 ("(-677:52)", blank message) at B0040D75: there K is CLEAR (the dispatcher B004D4F4 returns via ret) and the status byte b.0x49 == 1 (the success path at B0040CC1 sets b.0x49 = 4). This is a multi-step routine (calls B0040250, B0040C44, then DEABF) and the error-52 root cause is NOT yet found - it is the same error 52 the prior session flagged as unresolved, now isolated to this routine and this status byte. Run the linker from build/link_sandbox (NOT nc_sandbox). |
| Nd500x handler | nd500x/src/libmon/handlers/mon_256B_FullFileName.c |
Source¶
SINTRAN III Monitor Calls (ND-860228.2 EN).