GFILI @057173B - complete instruction-level carve (L07, segment 006-S3FS)¶
What GFILI is: the SINTRAN III file-system routine that resolves a file specification (already
tokenised) to an on-disk object entry - directory index + object descriptor + version. It is the
lookup core behind MON 50 OPEN (via OPFIL -> FCON -> FFILE -> GCFIL -> GFILI) and the whole FILSYS
name family. It does NOT create files and does NOT check access rights - those are separate routines
(CROBJ, GFIAC) in the callers.
Source of truth: 006-S3FS.asm (this folder), whole-segment nd100-dis. Addresses octal; every
citation is ADDR (line N). Version L-VSX-500 (L07). Symbols: 006-S3FS.symbols.txt.
Binary: ../../../segments/006-S3FS.bin, load base 26000B; byte offset of A = (A-26000B)*2.
Body span: 057173B (entry) .. 057504B (next symbol DIRUN@057505B). The constant/pointer pool
sits mid-routine at 057353B-057373B (normal NPL literal-pool placement).
Evidence tags: [V] = read from the bytes at the cited addr/line. [I] = inferred from control-flow + symbol names, not fully value-decoded. [OPEN] = not determined.
Runtime convention: reentrant stack. JPL I <p> calls via a pointer cell = SPUSH@003752; result
returned by callee doing MIN ,B4 k times, so SPOP@003776 returns to caller+k (skip-count
multi-return). ,Bn = frame-relative local. SAT c loads an ASCII code (octal): 50=(, 51=),
47=', 56=., 72=:.
1. Routines GFILI calls (all resolved from the pointer pool) [V]¶
Constant/pointer pool 057353B-057373B [V, lines 13345-13361]:
| Cell | Value | Symbol | Role |
|---|---|---|---|
| 057353 | 003752 | SPUSH | push reentrant frame |
| 057354 | 000006 | (const 6) | frame size arg |
| 057355 | 056645 | SEPOB | split spec into subparts; fill empty dir from GDEFD |
| 057356 | 057374 | (landing) | SEPOB-fail landing |
| 057357 | 030062 | GETCH | fetch one spec char |
| 057360-062 | 023/035/033 | (consts) | entry field offsets |
| 057363 | 042622 | SEPFS | split file/type/version fields |
| 057364 | 057376 | (landing) | SEPFS-fail landing / re-scan loop entry |
| 057365 | 056326 | GOBJI | object/file-name scan in one directory |
| 057366 | 057405 | (landing) | GOBJI-fail landing = fallback engine |
| 057367 | 000044 | (const) | |
| 057370 | 057627 | GVERS | parse requested version field -> number |
| 057371 | 057567 | GNEXV | walk the version chain (get next version entry) |
| 057372 | 000046 | (const) | |
| 057373 | 003776 | SPOP | pop frame / return |
Fallback-block pool 057457B-057467B [V, lines 13413-13421]:
| Cell | Value | Symbol | Role |
|---|---|---|---|
| 057460 | 050124 | GDIRT | directory-table accessor (advance to next dir) |
| 057461 | 010506 | (commoncode) | list-end / exit-dispatch helper (below load base) |
| 057462 | 055540 | GSYSI | get user (SYSTEM) index (by name via GMUSI) |
| 057463 | 010500 | (commoncode) | exit-dispatch helper |
| 057466 | 056326 | GOBJI | SECOND object scan (under SYSTEM) |
| 057467 | 057267 | (landing) | SYSTEM-hit -> re-enter version chain |
Not in either pool: GFIAC@057771 is never referenced anywhere in 057173B-057504B. [V - I read
every pointer cell]. GFILI does pure name->entry resolution; the friend/public/ring access check is
run by the CALLER after GFILI returns. (This confirms the earlier [I] as [V].)
2. Stage-by-stage walk [V bytes; per-line]¶
A. Entry + frame (057173-057200)¶
057173 STD I 157 ; save link (SPUSH linkage) (13233)
057176 SAB 51 ; B := 51 (frame base) (13236)
057177 JPL I 154 -> SPUSH ; push reentrant frame (13237)
057200 STT ,B40 ; ,B40 := caller's T (fallback-allow token) (13238)
,B40 is seeded from the caller's T. Callers that permit the SYSTEM fallback pass T = -1
(see the gate in stage F). [V store; [I] that the caller's convention value is -1, but the gate at
057415 compares against -1.]
B. Split spec + detect explicit (USER) (057201-057217)¶
057203 JPL I 152 -> SEPOB ; split spec; SEPOB fills empty dir via GDEFD (13241)
057204 JMP I 152 -> 057374 ; SEPOB fail -> store status, return (13242)
057205 STT ,B43 ; 057206 STA ,B41; ,B43 = directory index, ,B41 = name descriptor(13243-44)
057210 STA ,B42 ; ,B42 = object descriptor copy (13246)
057211 LDX ,B0 ; 057212 (T:=0)
057213 JPL I 144 -> GETCH ; read spec char[0] (13249)
057214 SAT 50 ('(') ; is first char '(' = a (USER) prefix ? (13250)
057215 SKP IF DA EQL ST
057216 JMP 2 -> 057220 ; char != '(' : leave ,B40 (= -1, fallback ON) (13252)
057217 STZ ,B40 ; char == '(' : ,B40 := 0 (fallback OFF) (13253)
'(' (an explicit (USER) prefix), ,B40
is zeroed; otherwise it stays at the caller's -1. Stage F only runs the SYSTEM fallback when
,B40 == -1. This is the byte-level implementation of the Users Guide rule "if a user name is
specified, only that user's directory is searched."
C. Field split + FIRST object scan (057220-057265)¶
057220-057230 init entry fields (const 20 -> +23, 4 -> +33, 5 -> +35) (13254-62)
057242 JPL I 121 -> SEPFS ; split file:type;version (13272)
057243 JMP I 121 -> 057376 ; SEPFS fail -> tail (13273)
057257-057262 load ,B43(dir) + ,B41(name) as scan args
057263 JPL I 102 -> GOBJI ; FIRST file-name scan in directory ,B43 (13289)
057264 JMP I 102 -> 057405 ; GOBJI +0 (fail) -> FALLBACK ENGINE (stage F) (13290)
057265 STD ,B44 ; 057266 STD ,B46; GOBJI success: found entry -> version best (13291-92)
+0 (no unique file) return lands on 057264, which jumps to the
fallback engine at 057405. A unique hit falls through to the version chain.
D. Version chain (057266-057337)¶
057274 JPL I 74 -> GVERS ; parse requested version field to a number (13298)
057276 JAF -> 057314 ; no version requested -> skip explicit-match (13300)
057277-057313 loop: GNEXV (057301) walk chain, keep entry whose version == req (13303)
057314-057336 loop: GNEXV (057326), MIN ,B50 counts, pick highest/!default (13326)
057337 STD ,B44 ; STD ,B46 ; final selected version entry (13332-33)
057567) reads entry version keys from cells +41B/+44B and shifts them
(057600 LDA ,X 41 ; 057602 LDA ,X 44 ; SAD/SHA ZIN SHR 13497-13503) [V]. GVERS (057627) parses
the version subpart chars via GETCH, terminator '(47) (13528) [V]. Full numeric semantics = [I].
E. Success return (057337-057351)¶
057343 LDA ,B42 -> ,B0 ; return object descriptor (13337-38)
057345 LDA ,B43 -> ,B1 ; return directory index (13339-40)
057347 MIN ,B4 ; skip-count = 1 (success) (13341)
057351 JMP I 22 -> SPOP ; pop frame, return to caller+1 (13343)
F. Fallback engine (057376-057504) [V - the current-user -> SYSTEM path]¶
Entered two ways: from GOBJI-fail (057405), or looped back from a re-scan (057376).
057376 STA ,B2 ; (loop-back) save status (13364)
057401 JPL I 57 -> GDIRT ; (loop-back) advance directory (13367)
-- direct GOBJI-fail entry: --
057405 STA ,B2 ; save GOBJI status (13371)
057406 SAT 56 ; 057407 SKP IF DA UEQ ST ; status == 56 "No such file name"? (13372-73)
057410 JMP 4 -> 057414 ; yes -> try fallback (13374)
057411 SAT 57 ; 057412 SKP IF DA EQL ST ; status == 57 "Ambiguous"? (13375-76)
057413 JMP 43 -> 057456 ; neither 56 nor 57 -> return the error (13377)
057414 LDA ,B40 ; 057415 SAT -1 ; 057416 SKP IF DA EQL ST ; ,B40 == -1 ? (13378-80)
057417 JMP 37 -> 057456 ; ,B40 != -1 (user named) -> NO fallback (13381)
-- ,B40 == -1 (unqualified): walk dirs then SYSTEM --
057422 JPL I 36 -> GDIRT ; advance to next directory (13384)
057423 JMP -25 -> 057376 ; GDIRT+0: more dirs -> loop back, re-scan (13385)
057424 JPL I 35 -> 010506 ; GDIRT+1: list-end helper (13386)
057425 JPL I 35 -> GSYSI ; GDIRT+2: get (SYSTEM) user index (13387)
057433 JPL I 25 -> GDIRT ; get SYSTEM's directory (13393)
057443 JPL I 23 -> GOBJI ; SECOND scan, under SYSTEM (13401)
057444 JMP 34 -> 057500 ; SYSTEM GOBJI fail -> final 56 -> return (13402)
057445 STD ,B44 ; STD ,B46 ; SYSTEM hit: save entry (13403-04)
057455 JMP I 12 -> 057267 ; -> re-enter version chain (stage D) with SYSTEM hit(13411)
-- error exits --
057456 JMP -57 -> 057377 ; (error path) (13412)
057470-057504 map GSYSI/GMUSI user errors: 46 no-such-user, 45 ambiguous-user (13422-33)
057500 SAT 56 ... -> 057504 ; SYSTEM also missing -> final "No such file" (56) (13430)
So the observable resolution order for an unqualified spec [V]:
1. caller's default directory (GDEFD inside SEPOB) -> GOBJI (057263).
2. on 56/57, walk further directories via GDIRT, re-scanning GOBJI (057422 -> loop 057376).
3. when the walk is exhausted, GSYSI -> SYSTEM directory -> GOBJI again (057443).
4. SYSTEM miss -> final 56 "No such file name" (057500-057504).
An explicit (USER) prefix zeroes ,B40 (stage B) and short-circuits all of 2-4.
3. Frame local map (as used in the body) [V stores unless marked]¶
| Local | Meaning | Evidence |
|---|---|---|
,B0 / ,B1 |
in: spec ptr; out: object descriptor / dir index | 057211, 057343-057346 |
,B2 |
working status word (from SEPOB/GOBJI) | 057405 STA ,B2 |
,B3 |
out: version/result word | 057342 STA ,B3 |
,B40 |
fallback-allow flag: -1 = allow SYSTEM fallback, 0 = user named -> no fallback |
057200 seed, 057217 zero, 057414-057417 gate |
,B41 |
object-name descriptor (GOBJI arg) | 057206, 057262 |
,B42 |
object descriptor copy (returned in ,B0) | 057210, 057343 |
,B43 |
current directory index (GOBJI/GDIRT arg) | 057205, 057261, 057420 |
,B44 / ,B46 |
version-chain "best entry so far" (double word) | 057265, 057337, 057445 |
,B47 |
version key under compare | 057303-057307 |
,B50 |
version-loop counter | 057316, 057330-057334 |
4. Answers this carve nails down¶
- GFILI is lookup-only. No create path in its pool (create is
CROBJ@063726B, reached fromGCFIL@064670Bon a quoted name). [V - full pool listed in section 1.] - GFIAC (access check) is NOT part of GFILI. Name resolution and permission are separate stages; a file is found by name first, access-checked by the caller second. [V - GFIAC absent from body.]
- The current-user -> (SYSTEM) fallback lives here, inside GFILI, and is gated on the spec having
no
(USER)prefix (,B40). It is SINTRAN-internal, not the linker's. [V] - see companionCARVE-ANSWER-UNQUALIFIED-OPEN-USER-SYSTEM-FALLBACK.md.
5. Still OPEN (honest)¶
- Exact numeric semantics of the version chain (GVERS parse + GNEXV compare) - structure verified, the "which version wins" arithmetic (default vs highest) not fully decoded.
- The
010506/010500commoncode exit-dispatch helpers (below this segment's load base). - The literal string
GSYSIfeedsGMUSIto name user SYSTEM (word055560=010017, not decoded) - so "SYSTEM" rests on the symbol name + the Users Guide, not a decoded ASCII constant. - Which
Tvalue each GFILI caller passes at entry (seeding,B40); the gate compares-1, and the(USER)-prefix zeroing is byte-proven, but the caller-side seed is not traced here.
Companions in this folder: CARVE-ANSWER-UNQUALIFIED-OPEN-USER-SYSTEM-FALLBACK.md (the fallback
question), FLPAR-MDEAB-FILENAME-RESOLVER-CARVE.md (name MATCHING inside a directory).
Status-of-record: SINTRAN/CARVING-HANDOFF.md section 1.8.