This is so fiddly I’m not sure I can even summarize it concisely so I’ll just wade in:
Here’s a minimalist “game” source file, sample.t
:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
versionInfo: GameID;
gameMain: GameMainDef newGame() {};
Here’s a separate source file containing a couple grammatical productions, yzzyxProd.t
:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
class YzzyxProd: CommandProd;
grammar yzzyxPhrase(foozle)
: yzzyxPredicate->cmd_
: YzzyxProd
;
grammar yzzyxPredicate(yzzyx)
: 'yzzyx'
: HelloAction
execAction() {}
;
Here’s the makefile.t3m
:
-D LANGUAGE=en_us
-D MESSAGESTYLE=neu
-Fy obj -Fo obj
-o game.t3
-lib system
-lib adv3/adv3
-source sample
-source yzzyxProd
If you try to compile this using the current rev of FrobTADS, on OpenBSD:
> t3make -a -f makefile.t3m
TADS Compiler 3.1.3 Copyright 1999, 2012 Michael J. Roberts
Files to build: 90
symbol_export /usr/local/share/frobtads/tads3/lib/_main.t -> obj/_main.t3s
symbol_export /usr/local/share/frobtads/tads3/lib/file.t -> obj/file.t3s
symbol_export /usr/local/share/frobtads/tads3/lib/tok.t -> obj/tok.t3s
[...]
symbol_export sample.t -> obj/sample.t3s
symbol_export yzzyxProd.t -> obj/yzzyxProd.t3s
Segmentation fault (core dumped)
…it segfaults.
The same code compiles fine under linux (tested with the current rev of Ubuntu). And the compiler doesn’t have problems in general on OpenBSD.
Reversing the order of the grammar declarations fixes the problem, which suggests the problem is with the production referencing a predicate that hasn’t been declared yet. So this version of yzzyxProd.t
compiles without error:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
class YzzyxProd: CommandProd;
grammar yzzyxPredicate(yzzyx)
: 'yzzyx'
: HelloAction
execAction() {}
;
grammar yzzyxPhrase(foozle)
: yzzyxPredicate->cmd_
: YzzyxProd
;
But it isn’t the fact that the production references a predicate before it’s declared. Because if you move the same code to sample.t
, it works fine. That is, with sample.t
:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
versionInfo: GameID;
gameMain: GameMainDef newGame() {};
class YzzyxProd: CommandProd;
grammar yzzyxPhrase(foozle)
: yzzyxPredicate->cmd_
: YzzyxProd
;
grammar yzzyxPredicate(yzzyx)
: 'yzzyx'
: HelloAction
execAction() {}
;
…and the edited yzzyxProd.t
:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
/*
class YzzyxProd: CommandProd;
grammar yzzyxPhrase(foozle)
: yzzyxPredicate->cmd_
: YzzyxProd
;
grammar yzzyxPredicate(yzzyx)
: 'yzzyx'
: HelloAction
execAction() {}
;
*/
Thus:
> t3make -a -f makefile.t3m
TADS Compiler 3.1.3 Copyright 1999, 2012 Michael J. Roberts
Files to build: 90
symbol_export /usr/local/share/frobtads/tads3/lib/_main.t -> obj/_main.t3s
symbol_export /usr/local/share/frobtads/tads3/lib/file.t -> obj/file.t3s
symbol_export /usr/local/share/frobtads/tads3/lib/tok.t -> obj/tok.t3s
[...]
compile sample.t -> obj/sample.t3o
compile yzzyxProd.t -> obj/yzzyxProd.t3o
link -> game.t3p
preinit -> game.t3
…and in fact this works if only the yzzyxPhrase
production declaration is moved to sample.t
(and so the compiler will reach it before it has seen the predicate declaration).
I can’t upload a tarball of the code here, so here’s a github repo of the whole “project” that illustrates the problem.
The platform I observed the problem was OpenBSD 7.6 on amd64, and it does not happen on Ubuntu 24.04 on amd64.