CARVE ANSWER - MON 50B OPEN quoted-vs-unquoted file-name semantics¶
Answers CARVE-REQUEST-OPEN-QUOTED-FILENAME.md. Source: SINTRAN III L07, L-VSX-500 carve. All addresses are virtual addresses in the named segment's own space (006-S3FS loads at 26000B; 012-S3SFS is the byte-identical save copy at the same VAs; 044-S3IDPIT loads at 4000B). Tags: [V] = byte-verified (word read from the .bin), [I] = inferred with stated basis.
TL;DR¶
- The quote is handled by ONE routine: GCFIL @064670B (006-S3FS). First character '"' (042B) selects the CREATE dispatch (CROBJ @063726B); no quote selects the LOOKUP-ONLY dispatch (GFILI @057173B). The quotes are stripped by the copy loop; there is no "create flag" - quoted and unquoted names take different routines. [V]
- Quoted + file already exists = error 076B "File already exists". Not opened, not truncated, not versioned. Create happens ONLY if the lookup returns 056B no-such / 057B ambiguous (or the found-but-empty sub-case below). [V]
- Unquoted + missing = error 056B "No such file name" (46 decimal), for every access code. GFILI contains no create call at all - byte-listed pointer pool. SINTRAN III has NO write-open-creates. Your auto-create is non-standard, confirmed. [V]
- Version-in-quotes is the same lexical layer:
NAME;"n"routes to CRNEW @064410B inside the same GCFIL scan; GVERS also accepts a quoted version. [V]
0. Dispatch chain (how MON 50B reaches this code)¶
[V] MCTAB[50B] = 103034B (044-S3IDPIT, MCTAB@005620B; table validated by
MCTAB[5B]=102021B RDISK and MCTAB[144B]=026354B MAGTP; note: this build's slot 200B
is 0). 103034B = OPFIL (FILSYS-SYMBOLS exact hit). OPFIL is a 4-entry cluster
(DOPEN=103026B, SCROP=103031B, OPFIL=103034B, +103037B) encoding an open-mode
variant via SSM/SSK flags (103046B-103063B).
[V] The name/create machinery: FCON @067002B (file connect) calls FFILE @065144B (pointer cell 067340B = 065144B, call at 067240B); FFILE calls GCFIL @064670B (pointer cell 065273B = 064670B). [I] The OPFIL -> FCON hop is inferred from role and family placement; everything from GCFIL down is byte-walked.
1. Q1: where the '"' is detected and what happens to it¶
GCFIL @064670B ("get/create file"), 006-S3FS:
064676 JPL I -> GETCH(030062B) ; fetch char[0] of the name
064677 171042 SAT 42 ; '"' ?
064700 140065 SKP IF DA EQL ST
064701 124101 JMP -> 065002 ; NOT quoted -> unquoted scan
064702 000675/STZ ,B 14 ; QUOTED: output index := 0
Quoted path 064703B-064762B [V]: fetches char[i+1] (one ahead of the opening quote), validates it (alphanumerics 060-072B / 0101-0132B and the specials ( ) , - " ; anything else -> error 021B "Illegal character in parameter" at 064746B), and copies it down one position via PUTCH (064757B-064761B) - i.e. THE QUOTES ARE STRIPPED BY THE COPY. The closing '"' (064754B test) ends the copy; char after it must be the ' terminator (047B) or error 021B (064766B-064771B). Then:
064775 044402 LDA ,B 2
064776 135134 JPL I 134 ; -> ptr 065132B = 063726B = CROBJ (CREATE)
Unquoted path 065002B-065015B [V]: scans to ';' or ' terminator, then:
065062 044402 LDA ,B 2
065063 050401 LDT ,B 1
065064 135050 JPL I 50 ; -> ptr 065134B = 057173B = GFILI (LOOKUP ONLY)
So the "create if quoted" convention is implemented as a ROUTINE DISPATCH, not a flag. Related quote sites [V]:
- SEPUS @043100B (user-prefix parser) skips exactly ONE leading '"' before '(' (043120B-043125B) - this is why a quote can wrap the whole spec including the (USER) prefix. A quote anywhere else inside the parens = error 021B (043144B).
- SEPFS @042622B (spec splitter, runs on the already-stripped name) treats '"' in any part as error 021B (042642B-042644B etc.) - quotes never survive to the part level.
2. Q2: quoted-name create semantics¶
CROBJ @063726B [V]:
- Directory-access pre-checks: missing directory-access bits -> error 070B "Not directory access" (063745B-063750B, 063753B-063756B).
- GVERS parses the version; result defaulted to 1 if none (064007B-064011B).
- GOBJI lookup (call 064034B via ptr 064136B = 056326B). Branches:
064035 JMP -> 064042 ; lookup ERROR return:
064042 SAT 56 ... ==056B -> create ; no such file name
064045 SAT 57 ... ==057B -> create ; ambiguous file name
else -> abort with that error
064036 SKP IF DT UEQ 0 ; lookup SUCCESS return:
064037 JMP -> 064051 (create) ; T == 0 -> proceed to create
064040 170476 SAA 76 ; T != 0 -> ERROR 076B "File already exists"
- Create = COBJE @061502B (create object entry, call 064055B via ptr 064137B) then CNEWV @063313B in a loop (064057B-064071B) for quoted version counts > 1.
ANSWER: a quoted name creates ONLY if absent. If the quoted file already exists, OPEN fails with 076B "File already exists" (manual error table, ND-60.050.06 line 10378) - it is NOT truncated, NOT overwritten, NOT re-versioned, NOT opened as-is. [V]
The linker manual's "an existing (unquoted) domain is overwritten" is therefore the LINKER's doing: it opens the existing file (unquoted, access W/RW) and writes over its contents. OPEN itself never truncates. [I - linker side not carved; the OPEN side is V]
Sub-case not fully pinned [I]: lookup success with T == 0 also proceeds to create (064037B). Most plausibly "object entry exists but holds no version"; the exact meaning of T from GOBJI's success return was not chased.
3. Q3: unquoted name, file does not exist¶
GFILI @057173B [V] is lookup-only. Its complete pointer pool (057353B-057371B): SPUSH, SEPOB 056645B, GETCH 030062B, SEPFS 042622B, GOBJI 056326B, GVERS 057627B, GNEXV 057567B, plus three local labels. No COBJE, no CNEWV, no CROBJ - there is no create path. The no-match error from GOBJI is 056B (= 46 decimal, "No such file name"; GOBJI's 056/057 codes byte-verified at 056576B-056607B in the earlier FLPAR carve; manual table line 10351). Your assumption 056B/46 is CONFIRMED.
Access codes never enter this decision: name resolution (GCFIL/GFILI/CROBJ) runs before and independent of access-code processing in OPFIL. There is no access code 0..9 for which an unquoted missing file is created. [V structurally: the only create sites reachable from OPEN's resolution are CROBJ/CNEWV, both behind the quote dispatch]
4. Q4: access-code interaction¶
Uniform. [V] The quote decision is purely lexical, taken in GCFIL on the name string alone; A/T at the dispatch carry buffer/directory arguments, not the access code. Access 0 (sequential write) of a missing unquoted file returns 056B exactly like access 3. Write-access does NOT imply create. (The separate SCROP entry at 103031B is the scratch-open variant and does not create named files either; scratch files are pre-existing. [I on the scratch detail])
5. Q5: the NC compiler case¶
Honest limit: NC's binary is not in this repo, so its exact OPEN sequence is not carved. But the SINTRAN side is now byte-certain and it settles the design:
- Real SINTRAN III NEVER creates on an unquoted open, for any access code. [V]
- Therefore, on real hardware NC's output files (A:NRF, A:LIST) can only have come from: (a) quoted names passed through to MON 50B, (b) a pre-create via MON 221B (CRALF @105562B = MCTAB[221B] [V]), or (c) files that already existed. There is no fourth mechanism.
- So enforcing unquoted-missing -> 056B in nd500x is CORRECT and cannot "break NC vs real hardware": if NC then fails in the emulator, it was depending on the emulator's non-standard auto-create, and the same invocation would fail on a real machine. Fix the invocation (quote the output names, or pre-create), not the semantics. Recommendation: trace NC's actual MON 50B/221B arguments once under the corrected semantics; that will show which of (a)/(b) it uses. [I on NC's choice; V on the constraint set]
6. Q6: version-in-quotes¶
Same lexical layer, two sites [V]:
- Inside GCFIL:
NAME;"n"- after the ';' a '"' routes to the quoted-version parser (065016B-065056B) which dispatches CRNEW @064410B ("create new version") at 065055B-065056B via ptr 065133B. - GVERS @057627B (the general version parser used by both GFILI and CROBJ) itself accepts a quoted version number (SAT 42 at 057644B, quoted-digits branch 057647B+).
For a plain quoted-name create this does not matter: CROBJ defaults the version to 1 (064007B-064011B) and creates it via COBJE/CNEWV.
Error codes referenced (ND-60.050.06 error table)¶
| Code | Meaning | Where returned |
|---|---|---|
| 021B | Illegal character in parameter | GCFIL bad char / bad quote nesting (064746B, 064711B, 064771B); SEPFS/SEPUS quote misuse |
| 056B | No such file name | GOBJI no-match -> GFILI -> unquoted OPEN of missing file |
| 057B | Ambiguous file name | GOBJI multi-match (CROBJ treats it like absent and creates) |
| 070B | Not directory access | CROBJ pre-check (create requires directory access) |
| 076B | File already exists | CROBJ when the quoted file exists (064040B) |
Evidence register (words re-read from the .bin files)¶
006-S3FS.bin (base 26000B): 064677B=171042B (SAT 42, first-char test); 064701B=124101B (unquoted branch); 064775B/064776B=044402B/135134B with ptr 065132B=063726B (CROBJ); 065062B-065064B with ptr 065134B=057173B (GFILI); 065055B-065056B with ptr 065133B=064410B (CRNEW); 064035B-064050B (056B/057B -> create, T!=0 -> SAA 76); 064040B=170476B; 063747B/063755B=170470B (SAA 70); 057173B pointer pool 057353B-057371B (no create targets); 043120B-043125B (SEPUS leading-quote skip); 042642B-042644B (SEPFS quote -> 021B); 057644B=171042B (GVERS quoted version); ptr 067340B=065144B (FFILE), call at 067240B; ptr 065273B=064670B (GCFIL from FFILE).
044-S3IDPIT.bin (base 4000B): MCTAB[50B]=103034B OPFIL, MCTAB[43B]=103355B CLOFI, MCTAB[221B]=105562B CRALF, MCTAB[54B]=106063B MDLFI; validation slots MCTAB[5B]=102021B, MCTAB[144B]=026354B.
Symbols: FILSYS-SYMBOLS L07 exact hits: OPFIL=103034, GCFIL=064670, CROBJ=063726, CRNEW=064410, GFILI=057173, COBJE=061502, CNEWV=063313, GOBJI=056326, GVERS=057627, GNEXV=057567, SEPFS=042622, SEPUS=043100, SEPOB=056645, GETCH=030062, PUTCH=030100, FFILE=065144, FCON=067002, CRALF=105562.