Are code offset and strings offset available in Inform 6?

The source code of the veneer routine Z__Region (part of the compiler) uses the constants #code_offset and #strings_offset.

In an attempt to write my own Z__Region routine of sorts, I tried to use these constants in an Inform 6 program, but they weren’t recognized. Are they available but under different names, or am I just out of luck here?

This code (based on the Borogove I6 template) compiles and runs for me:

Constant Story "My Story";
Constant Headline "^An Interactive Fiction^";

Include "Parser";
Include "VerbLib";

Object ExampleRoom "Example Room"
    with description
        "This is the starting location.",
has light;

[ Initialise;
    location = ExampleRoom;
    print #strings_offset, " ", #code_offset;
];

Include "Grammar";

Result:

11014 1320

My Story
An Interactive Fiction
Release 1 / Serial number 260408 / Inform v6.36 Library v6.12.6 SD
Example Room
This is the starting location.

Thanks for trying it out!

As it turns out, I can use these constants, but not in assembly. Odd. I was trying to do:

	@jl p_value #strings_offset ?rfalse;

and in that context, the constant isn’t recognized.

However, I can declare my own constant, and use that instead in assembly:

Constant _StringsOffset = #strings_offset;

Huh! Honestly, that strikes me as a bug worth reporting. As far as I know, the # sign in front of a constant is supposed to be an implementation detail (it flags values that aren’t known until the end of compilation), not something authors should ever have to care about.

1 Like

If the Constant _StringsOffset = #strings_offset; thing works reliably (and it seems to), then yes, this can be filed. It gets the same assembly_operand into the routine being assembled, so it’s just a matter of parsing the #const form.

(However, if you’re writing assembly code, you are going to need to know about low-level details. Just saying. :)

1 Like

Thanks. Since it seems like incorrect behaviour, I’ll file it.

@zarf : As someone who is reasonably well aquainted with the compiler, do you know if there’s any scenario where #code_offset > 32767, i.e. it’s a negative number when considered as a signed 16-bit int?

There’s a word in the header that points to the absolute address where execution begins. If this is always in the routine area, it means the routine area must begin no later than 65535 ($FFFF), which would mean #code_offset <= 65535 / 2, i.e. 32767, right?.

Input values may be packed routine or string addresses anywhere in memory, so I would assume >32767 is possible. (Historically Z__Region used Unsigned__Compare to avoid precisely this issue.)

Isn’t #code_offset the same as the value stored in the header at 0x0006? If so, then it’s not a packed value and can be greater than 0x7FFF.

#code_offset and #strings_offset are both in packed form.

In Z__Region, the value that is sent into the routine is compared to both #code_offset and #strings_offset, like this:

		if (Unsigned__Compare(addr, #strings_offset)>=0) return 3;
		if (Unsigned__Compare(addr, #code_offset)>=0) return 2;

Yeah, found the code that emits it in expressp.c.

        case strings_offset_SC:
            return strings_offset/scale_factor;
        case code_offset_SC:
            return code_offset/scale_factor;
1 Like

Annoyingly, this works fine:

	@jl #strings_offset p_value ?rfalse;
2 Likes

Absolutely fascinated by the fact that Inform’s lexer (or some other component?) treats the first operand of an assembly instruction different from the second. Treating the store or jump target differently, I’d understand, but the two arguments of a @jl?

Well yes and no… My program wouldn’t do what I want it to do then :wink:

But yeah, that’s weird!

After some digging, I think that this is a lexer bug. The fix is not entirely obvious, as Inform’s lexer is not very tidy.

However, you can work around the bug by putting the system constant in parens.

	@jl p_value (#strings_offset) ?rfalse;
4 Likes

Thanks for looking into it! A simple workaround is a good start.