I'm sick of repeatedly adding and removing local changes to Recipe

when testing a new game, so here's a new architecture for the Recipe
file. mkfiles.pl now supports several new features:

 - an `!include' directive, which accepts wildcards
 - += to append to an existing object group definition
 - the ability to divert output to an arbitrary file.

So now each puzzle has a `.R' file containing a fragment of Recipe
code describing that puzzle, and the central Recipe does `!include
*.R' to construct the Makefiles. That way, I can keep as many
experimental half-finished puzzles lying around my working directory
as I like, and I won't have to keep reverting Recipe when I check in
any other changes.

As part of this change, list.c is no longer a version-controlled
file; it's now constructed by mkfiles.pl, so that it too can take
advantage of this mechanism.

[originally from svn r6781]
This commit is contained in:
Simon Tatham
2006-08-05 17:20:29 +00:00
parent f05c25347d
commit cf880225ed
30 changed files with 512 additions and 195 deletions

View File

@ -17,16 +17,19 @@
# - special-define objects (foo.o[PREPROCSYMBOL]) are not
# supported in the mac or vcproj makefiles.
use FileHandle;
use IO::Handle;
use Cwd;
open IN, "Recipe" or do {
@filestack = ();
$in = new IO::Handle;
open $in, "Recipe" or do {
# We want to deal correctly with being run from one of the
# subdirs in the source tree. So if we can't find Recipe here,
# try one level up.
chdir "..";
open IN, "Recipe" or die "unable to open Recipe file\n";
open $in, "Recipe" or die "unable to open Recipe file\n";
};
push @filestack, $in;
# HACK: One of the source files in `charset' is auto-generated by
# sbcsgen.pl. We need to generate that _now_, before attempting
@ -45,13 +48,20 @@ $project_name = "project"; # this is a good enough default
@allobjs = (); # all object file names
while (<IN>) {
readinput: while (1) {
while (not defined ($_ = <$in>)) {
close $in;
last readinput if 0 == scalar @filestack;
$in = pop @filestack;
}
chomp;
split;
# Skip comments (unless the comments belong, for example because
# they're part of a diversion).
next if /^\s*#/ and !defined $divert;
chomp;
split;
if ($_[0] eq "!begin" and $_[1] eq "help") { $divert = \$help; next; }
if ($_[0] eq "!end") { $divert = undef; next; }
if ($_[0] eq "!name") { $project_name = $_[1]; next; }
@ -59,13 +69,27 @@ while (<IN>) {
if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;}
if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
if ($_[0] eq "!begin") {
if (&mfval($_[1])) {
if ($_[1] =~ /^>(.*)/) {
$divert = \$auxfiles{$1};
} elsif (&mfval($_[1])) {
$divert = \$makefile_extra{$_[1]};
} else {
$divert = \$dummy;
}
next;
}
if ($_[0] eq "!include") {
@newfiles = ();
for ($i = 1; $i <= $#_; $i++) {
push @newfiles, (sort glob $_[$i]);
}
for ($i = $#newfiles; $i >= 0; $i--) {
$file = $newfiles[$i];
$f = new IO::Handle;
open $f, "<$file" or die "unable to open include file '$file'\n";
push @filestack, $f;
}
$in = $filestack[$#filestack];
next;
}
# If we're gathering help text, keep doing so.
if (defined $divert) { ${$divert} .= "$_\n"; next; }
# Ignore blank lines.
@ -80,6 +104,11 @@ while (<IN>) {
$prog = undef;
die "$.: unexpected + line\n" if !defined $lastlistref;
} elsif ($_[1] eq "=") {
$groups{$_[0]} = [];
$listref = $groups{$_[0]};
$prog = undef;
shift @objs; # eat the group name
} elsif ($_[1] eq "+=") {
$groups{$_[0]} = [] if !defined $groups{$_[0]};
$listref = $groups{$_[0]};
$prog = undef;
@ -89,7 +118,7 @@ while (<IN>) {
$prog = $_[0];
shift @objs; # eat the program name
} else {
die "$.: unrecognised line type\n";
die "$.: unrecognised line type: '$_'\n";
}
shift @objs; # eat the +, the = or the :
@ -113,7 +142,11 @@ while (<IN>) {
$lastlistref = $listref;
}
close IN;
foreach $aux (sort keys %auxfiles) {
open AUX, ">$aux";
print AUX $auxfiles{$aux};
close AUX;
}
# Find object file names with predefines (in square brackets after
# the module name), and decide on actual object names for them.