1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-01 06:24:58 +03:00

Made pipelines inbuild resources

This commit is contained in:
Graham Nelson 2020-02-10 00:10:58 +00:00
parent f2378d5a07
commit 1338ef1cde
22 changed files with 305 additions and 133 deletions

View file

@ -29,6 +29,7 @@ Setting up the use of this module.
@e inform_template_MT @e inform_template_MT
@e inform_project_MT @e inform_project_MT
@e inform_language_MT @e inform_language_MT
@e inform_pipeline_MT
= =
ALLOCATE_INDIVIDUALLY(inform_kit) ALLOCATE_INDIVIDUALLY(inform_kit)
@ -51,6 +52,7 @@ ALLOCATE_INDIVIDUALLY(extension_census)
ALLOCATE_INDIVIDUALLY(inform_template) ALLOCATE_INDIVIDUALLY(inform_template)
ALLOCATE_INDIVIDUALLY(inform_project) ALLOCATE_INDIVIDUALLY(inform_project)
ALLOCATE_INDIVIDUALLY(inform_language) ALLOCATE_INDIVIDUALLY(inform_language)
ALLOCATE_INDIVIDUALLY(inform_pipeline)
ALLOCATE_IN_ARRAYS(inbuild_work_database_entry, 100) ALLOCATE_IN_ARRAYS(inbuild_work_database_entry, 100)
@ -68,6 +70,7 @@ void InbuildModule::start(void) {
TemplateManager::start(); TemplateManager::start();
LanguageManager::start(); LanguageManager::start();
ProjectManager::start(); ProjectManager::start();
PipelineManager::start();
} }
@ @

View file

@ -47,15 +47,23 @@ derived from its title and author name.
= =
inbuild_work *Works::new(inbuild_genre *genre, text_stream *ti, text_stream *an) { inbuild_work *Works::new(inbuild_genre *genre, text_stream *ti, text_stream *an) {
return Works::new_inner(genre, ti, an, TRUE);
}
inbuild_work *Works::new_raw(inbuild_genre *genre, text_stream *ti, text_stream *an) {
return Works::new_inner(genre, ti, an, FALSE);
}
inbuild_work *Works::new_inner(inbuild_genre *genre, text_stream *ti, text_stream *an, int norm) {
inbuild_work *work = CREATE(inbuild_work); inbuild_work *work = CREATE(inbuild_work);
work->genre = genre; work->genre = genre;
work->raw_author_name = Str::duplicate(an); work->raw_author_name = Str::duplicate(an);
work->author_name = Str::duplicate(an); work->author_name = Str::duplicate(an);
work->raw_title = Str::duplicate(ti); work->raw_title = Str::duplicate(ti);
work->title = Str::duplicate(ti); work->title = Str::duplicate(ti);
Works::normalise_casing(work->author_name); if (norm) {
Works::normalise_casing(work->title); Works::normalise_casing(work->author_name);
Works::normalise_casing(work->title);
}
unsigned int hc = 0; unsigned int hc = 0;
LOOP_THROUGH_TEXT(pos, work->author_name) LOOP_THROUGH_TEXT(pos, work->author_name)
hc = hc*30011 + (unsigned int) Str::get(pos); hc = hc*30011 + (unsigned int) Str::get(pos);

View file

@ -47,7 +47,7 @@ inbuild_copy *KitManager::new_copy(text_stream *name, pathname *P) {
C = Dictionaries::read_value(kit_copy_cache, key); C = Dictionaries::read_value(kit_copy_cache, key);
if (C == NULL) { if (C == NULL) {
inform_kit *K = Kits::new_ik(name, P); inform_kit *K = Kits::new_ik(name, P);
inbuild_work *work = Works::new(kit_genre, Str::duplicate(name), NULL); inbuild_work *work = Works::new_raw(kit_genre, Str::duplicate(name), NULL);
inbuild_edition *edition = Model::edition(work, K->version); inbuild_edition *edition = Model::edition(work, K->version);
C = Model::copy_in_directory(edition, P, STORE_POINTER_inform_kit(K)); C = Model::copy_in_directory(edition, P, STORE_POINTER_inform_kit(K));
K->as_copy = C; K->as_copy = C;

View file

@ -0,0 +1,157 @@
[PipelineManager::] Pipeline Manager.
An Inform 7 pipeline.
@h Genre definition.
= (early code)
inbuild_genre *pipeline_genre = NULL;
@ =
void PipelineManager::start(void) {
pipeline_genre = Model::genre(I"pipeline");
METHOD_ADD(pipeline_genre, GENRE_WRITE_WORK_MTID, PipelineManager::write_work);
METHOD_ADD(pipeline_genre, GENRE_CLAIM_AS_COPY_MTID, PipelineManager::claim_as_copy);
METHOD_ADD(pipeline_genre, GENRE_SEARCH_NEST_FOR_MTID, PipelineManager::search_nest_for);
METHOD_ADD(pipeline_genre, GENRE_COPY_TO_NEST_MTID, PipelineManager::copy_to_nest);
}
void PipelineManager::write_work(inbuild_genre *gen, OUTPUT_STREAM, inbuild_work *work) {
WRITE("%S", work->title);
}
@ Pipelines live in their namesake subdirectory of a nest:
=
pathname *PipelineManager::path_within_nest(inbuild_nest *N) {
if (N == NULL) internal_error("no nest");
return Pathnames::subfolder(N->location, I"Pipelines");
}
@ Pipeline copies are annotated with a structure called an |inform_pipeline|,
which stores data about pipelines used by the Inform compiler.
=
inform_pipeline *PipelineManager::from_copy(inbuild_copy *C) {
if ((C) && (C->edition->work->genre == pipeline_genre)) {
return RETRIEVE_POINTER_inform_pipeline(C->content);
}
return NULL;
}
inbuild_copy *PipelineManager::new_copy(inbuild_edition *edition, filename *F) {
inform_pipeline *E = Pipelines::new_ip(edition->work->title, F);
inbuild_copy *C = Model::copy_in_file(edition, F, STORE_POINTER_inform_pipeline(E));
E->as_copy = C;
return C;
}
@h Claiming.
Here |arg| is a textual form of a filename or pathname, such as may have been
supplied at the command line; |ext| is a substring of it, and is its extension
(e.g., |jpg| if |arg| is |Geraniums.jpg|), or is empty if there isn't one;
|directory_status| is true if we know for some reason that this is a directory
not a file, false if we know the reverse, and otherwise not applicable.
An pipeline, for us, simply needs to be a file with extension |interpipeline|.
=
void PipelineManager::claim_as_copy(inbuild_genre *gen, inbuild_copy **C,
text_stream *arg, text_stream *ext, int directory_status) {
if (directory_status == TRUE) return;
if (Str::eq_insensitive(ext, I"interpipeline")) {
filename *F = Filenames::from_text(arg);
*C = PipelineManager::claim_file_as_copy(F, NULL, FALSE);
}
}
inbuild_copy *PipelineManager::claim_file_as_copy(filename *F, text_stream *error_text,
int allow_malformed) {
if (TextFiles::exists(F) == FALSE) return NULL;
inbuild_version_number V = VersionNumbers::null();
TEMPORARY_TEXT(unext);
Filenames::write_unextended_leafname(unext, F);
inbuild_copy *C = PipelineManager::new_copy(
Model::edition(Works::new_raw(pipeline_genre, unext, NULL), V), F);
DISCARD_TEXT(unext);
Works::add_to_database(C->edition->work, CLAIMED_WDBC);
PipelineManager::build_graph(C);
return C;
}
@h Searching.
Here we look through a nest to find all pipelines matching the supplied
requirements.
=
void PipelineManager::search_nest_for(inbuild_genre *gen, inbuild_nest *N,
inbuild_requirement *req, linked_list *search_results) {
if ((req->work->genre) && (req->work->genre != pipeline_genre)) return;
pathname *P = PipelineManager::path_within_nest(N);
scan_directory *D = Directories::open(P);
if (D) {
TEMPORARY_TEXT(LEAFNAME);
while (Directories::next(D, LEAFNAME)) {
if (Str::get_last_char(LEAFNAME) != FOLDER_SEPARATOR) {
filename *F = Filenames::in_folder(P, LEAFNAME);
inbuild_copy *C = PipelineManager::claim_file_as_copy(F, NULL,
req->allow_malformed);
if ((C) && (Requirements::meets(C->edition, req))) {
Nests::add_search_result(search_results, N, C);
}
}
}
DISCARD_TEXT(LEAFNAME);
Directories::close(D);
}
}
@h Copying.
Now the task is to copy a pipeline into place in a nest. This is easy,
since a pipeline is a single file; to sync, we just overwrite.
=
filename *PipelineManager::filename_in_nest(inbuild_nest *N, text_stream *title) {
pathname *E = PipelineManager::path_within_nest(N);
TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "%S.interpipeline", title);
filename *F = Filenames::in_folder(E, leaf);
DISCARD_TEXT(leaf);
return F;
}
void PipelineManager::copy_to_nest(inbuild_genre *gen, inbuild_copy *C, inbuild_nest *N,
int syncing, build_methodology *meth) {
filename *F = PipelineManager::filename_in_nest(N, C->edition->work->title);
if (TextFiles::exists(F)) {
if (syncing == FALSE) { Nests::overwrite_error(N, C); return; }
} else {
if (meth->methodology == DRY_RUN_METHODOLOGY) {
TEMPORARY_TEXT(command);
WRITE_TO(command, "mkdir -p ");
Shell::quote_path(command, Filenames::get_path_to(F));
WRITE_TO(STDOUT, "%S\n", command);
DISCARD_TEXT(command);
} else {
Pathnames::create_in_file_system(N->location);
Pathnames::create_in_file_system(Filenames::get_path_to(F));
}
}
TEMPORARY_TEXT(command);
WRITE_TO(command, "cp -f ");
Shell::quote_file(command, C->location_if_file);
Shell::quote_file(command, F);
BuildSteps::shell(command, meth);
DISCARD_TEXT(command);
}
@h Build graph.
The build graph for a pipeline is just a single node: you don't need to
build a pipeline at all.
=
void PipelineManager::build_graph(inbuild_copy *C) {
Graphs::copy_vertex(C);
}

View file

@ -0,0 +1,18 @@
[Pipelines::] Pipeline Services.
A pipeline is a list of steps to be followed by the Inter processor forming
the back end of the Inform compiler.
@ =
typedef struct inform_pipeline {
struct inbuild_copy *as_copy;
struct inbuild_version_number version;
MEMORY_MANAGEMENT
} inform_pipeline;
inform_pipeline *Pipelines::new_ip(text_stream *name, filename *F) {
inform_pipeline *T = CREATE(inform_pipeline);
T->as_copy = NULL;
T->version = VersionNumbers::null();
return T;
}

View file

@ -22,6 +22,7 @@ Chapter 3: Managing Genres of Work
Language Manager Language Manager
Project Manager Project Manager
Template Manager Template Manager
Pipeline Manager
Chapter 4: Services for the Inform Compiler Chapter 4: Services for the Inform Compiler
Kit Services Kit Services
@ -30,3 +31,4 @@ Chapter 4: Services for the Inform Compiler
Template Services Template Services
Project Services Project Services
Language Services Language Services
Pipeline Services

View file

@ -79,7 +79,7 @@
else else
set: $TCACHE = inform7/Internal/I6T/standard_rules/arch-16d.interb set: $TCACHE = inform7/Internal/I6T/standard_rules/arch-16d.interb
endif endif
set: $PIPELINE = inform7/Tests/test.interpipeline set: $PIPELINE = test
! First, problem message cases, where we require ni to fail and with the ! First, problem message cases, where we require ni to fail and with the
! correct output. ! correct output.
@ -199,7 +199,7 @@
else else
set: $TCACHE = inform7/Internal/I6T/standard_rules/arch-16d.interb set: $TCACHE = inform7/Internal/I6T/standard_rules/arch-16d.interb
endif endif
set: $PIPELINE = inform7/Tests/test_basic.interpipeline set: $PIPELINE = test_basic
! First, problem message cases, where we require ni to fail and with the ! First, problem message cases, where we require ni to fail and with the
! correct output. ! correct output.

View file

@ -102,6 +102,7 @@ int CoreMain::main(int argc, char *argv[]) {
Errors::set_internal_handler(&Problems::Issue::internal_error_fn); Errors::set_internal_handler(&Problems::Issue::internal_error_fn);
story_filename_extension = I"ulx"; story_filename_extension = I"ulx";
inter_processing_pipeline = Str::new(); inter_processing_pipeline = Str::new();
inter_processing_file = I"compile";
PRINT("%B build %B has started.\n", FALSE, TRUE); PRINT("%B build %B has started.\n", FALSE, TRUE);
STREAM_FLUSH(STDOUT); STREAM_FLUSH(STDOUT);
@ -436,33 +437,40 @@ with "Output.i6t".
@<Ensure inter pipeline variables dictionary@>; @<Ensure inter pipeline variables dictionary@>;
Str::copy(Dictionaries::create_text(pipeline_vars, I"*in"), I"*memory"); Str::copy(Dictionaries::create_text(pipeline_vars, I"*in"), I"*memory");
Str::copy(Dictionaries::create_text(pipeline_vars, I"*out"), Filenames::get_leafname(filename_of_compiled_i6_code)); Str::copy(Dictionaries::create_text(pipeline_vars, I"*out"), Filenames::get_leafname(filename_of_compiled_i6_code));
pathname *inter_subnests[NO_FS_AREAS] = { NULL, NULL, NULL };
int s = 0; linked_list *inter_paths = NEW_LINKED_LIST(pathname);
inbuild_nest *N; inbuild_nest *N;
LOOP_OVER_LINKED_LIST(N, inbuild_nest, I7_nest_list) { LOOP_OVER_LINKED_LIST(N, inbuild_nest, I7_nest_list)
if (s >= NO_FS_AREAS) break; ADD_TO_LINKED_LIST(KitManager::path_within_nest(N), pathname, inter_paths);
inter_subnests[s++] = KitManager::path_within_nest(N);
}
codegen_pipeline *SS = NULL; codegen_pipeline *SS = NULL;
if (inter_processing_file) if (Str::len(inter_processing_pipeline) > 0) {
SS = CodeGen::Pipeline::parse_from_file(Filenames::from_text(inter_processing_file), pipeline_vars);
else if (Str::len(inter_processing_pipeline) > 0)
SS = CodeGen::Pipeline::parse(inter_processing_pipeline, pipeline_vars); SS = CodeGen::Pipeline::parse(inter_processing_pipeline, pipeline_vars);
else { if (SS == NULL)
for (int area=0; area<NO_FS_AREAS; area++) { Problems::Fatal::issue("The Inter pipeline description contained errors");
pathname *P = inter_subnests[area]; } else {
filename *F = Filenames::in_folder(P, I"default.interpipeline"); inbuild_requirement *req =
if (TextFiles::exists(F)) { Requirements::any_version_of(Works::new(pipeline_genre, inter_processing_file, NULL));
linked_list *L = NEW_LINKED_LIST(inbuild_search_result);
Nests::search_for(req, I7_nest_list, L);
if (LinkedLists::len(L) == 0) {
WRITE_TO(STDERR, "Sought pipeline '%S'\n", inter_processing_file);
Problems::Fatal::issue("The Inter pipeline could not be found");
} else {
inbuild_search_result *R;
LOOP_OVER_LINKED_LIST(R, inbuild_search_result, L) {
inbuild_copy *C = R->copy;
filename *F = C->location_if_file;
SS = CodeGen::Pipeline::parse_from_file(F, pipeline_vars); SS = CodeGen::Pipeline::parse_from_file(F, pipeline_vars);
if (SS == NULL)
Problems::Fatal::filename_related("This Inter pipeline contains errors", F);
break; break;
} }
} }
} }
if (SS == NULL)
Problems::Fatal::issue("The Inter pipeline description contained errors");
CodeGen::Pipeline::set_repository(SS, Emit::tree()); CodeGen::Pipeline::set_repository(SS, Emit::tree());
CodeGen::Pipeline::run(Filenames::get_path_to(filename_of_compiled_i6_code), CodeGen::Pipeline::run(Filenames::get_path_to(filename_of_compiled_i6_code),
SS, NO_FS_AREAS, inter_subnests, Kits::list_of_inter_libraries()); SS, inter_paths, Kits::list_of_inter_libraries());
} }
LOG("Back end elapsed time: %dcs\n", ((int) (clock() - front_end)) / (CLOCKS_PER_SEC/100)); LOG("Back end elapsed time: %dcs\n", ((int) (clock() - front_end)) / (CLOCKS_PER_SEC/100));
} }

View file

@ -8,22 +8,14 @@ To configure the many locations used in the host filing system.
of where everything lives in the filing system. Very early in Inform's run, of where everything lives in the filing system. Very early in Inform's run,
it works out the filenames of everything it will ever need to refer to, and it works out the filenames of everything it will ever need to refer to, and
these are stored in the following globals. Explanations are given below, these are stored in the following globals. Explanations are given below,
not here. First, some "areas": not here.
@d NO_FS_AREAS 3
@d MATERIALS_FS_AREA 0 /* must match |ORIGIN_WAS_*| constants minus 1 */
@d EXTERNAL_FS_AREA 1
@d INTERNAL_FS_AREA 2
=
char *AREA_NAME[3] = { "from .materials", "installed", "built in" };
@ Now for the folders:
= (early code) = (early code)
linked_list *I7_nest_list = NULL; linked_list *I7_nest_list = NULL;
pathname *pathname_of_area[NO_FS_AREAS] = { NULL, NULL, NULL };
pathname *pathname_of_website_templates[NO_FS_AREAS] = { NULL, NULL, NULL }; pathname *pathname_of_materials = NULL;
pathname *pathname_of_external_folder = NULL;
pathname *pathname_of_internal_folder = NULL;
pathname *pathname_of_extension_docs = NULL; pathname *pathname_of_extension_docs = NULL;
pathname *pathname_of_extension_docs_inner = NULL; pathname *pathname_of_extension_docs_inner = NULL;
@ -83,16 +75,16 @@ void Locations::set_project(text_stream *loc) {
} }
void Locations::set_internal(text_stream *loc) { void Locations::set_internal(text_stream *loc) {
pathname_of_area[INTERNAL_FS_AREA] = Pathnames::from_text(loc); pathname_of_internal_folder = Pathnames::from_text(loc);
} }
void Locations::set_default_internal(pathname *P) { void Locations::set_default_internal(pathname *P) {
if (pathname_of_area[INTERNAL_FS_AREA] == NULL) if (pathname_of_internal_folder == NULL)
pathname_of_area[INTERNAL_FS_AREA] = P; pathname_of_internal_folder = P;
} }
void Locations::set_external(text_stream *loc) { void Locations::set_external(text_stream *loc) {
pathname_of_area[EXTERNAL_FS_AREA] = Pathnames::from_text(loc); pathname_of_external_folder = Pathnames::from_text(loc);
} }
void Locations::set_transient(text_stream *loc) { void Locations::set_transient(text_stream *loc) {
@ -132,18 +124,18 @@ int Locations::set_defaults(int census_mode) {
if ((census_mode) && (filename_of_i7_source)) if ((census_mode) && (filename_of_i7_source))
Problems::Fatal::issue("In census mode, no source text may be supplied"); Problems::Fatal::issue("In census mode, no source text may be supplied");
I7_nest_list = NEW_LINKED_LIST(inbuild_nest); I7_nest_list = NEW_LINKED_LIST(inbuild_nest);
if (pathname_of_area[MATERIALS_FS_AREA]) { if (pathname_of_materials) {
inbuild_nest *nest = Nests::new(pathname_of_area[MATERIALS_FS_AREA]); inbuild_nest *nest = Nests::new(pathname_of_materials);
Nests::set_tag(nest, ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA); Nests::set_tag(nest, ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA);
ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list); ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list);
} }
if (pathname_of_area[EXTERNAL_FS_AREA]) { if (pathname_of_external_folder) {
inbuild_nest *nest = Nests::new(pathname_of_area[EXTERNAL_FS_AREA]); inbuild_nest *nest = Nests::new(pathname_of_external_folder);
Nests::set_tag(nest, ORIGIN_WAS_USER_EXTENSIONS_AREA); Nests::set_tag(nest, ORIGIN_WAS_USER_EXTENSIONS_AREA);
ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list); ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list);
} }
if (pathname_of_area[INTERNAL_FS_AREA]) { if (pathname_of_internal_folder) {
inbuild_nest *nest = Nests::new(pathname_of_area[INTERNAL_FS_AREA]); inbuild_nest *nest = Nests::new(pathname_of_internal_folder);
Nests::set_tag(nest, ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA); Nests::set_tag(nest, ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA);
ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list); ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list);
} }
@ -169,13 +161,11 @@ language definitions, and website templates. The Standard Rules, for
example, live inside the Extensions part of this. example, live inside the Extensions part of this.
@<Internal resources@> = @<Internal resources@> =
if (pathname_of_area[INTERNAL_FS_AREA] == NULL) if (pathname_of_internal_folder == NULL)
Problems::Fatal::issue("Did not set -internal when calling"); Problems::Fatal::issue("Did not set -internal when calling");
Locations::EILT_at(INTERNAL_FS_AREA, pathname_of_area[INTERNAL_FS_AREA]);
pathname *inter_resources = pathname *inter_resources =
Pathnames::subfolder(pathname_of_area[INTERNAL_FS_AREA], I"Inter"); Pathnames::subfolder(pathname_of_internal_folder, I"Inter");
filename_of_default_inter_pipeline = filename_of_default_inter_pipeline =
Filenames::in_folder(inter_resources, I"default.interpipeline"); Filenames::in_folder(inter_resources, I"default.interpipeline");
@ -191,14 +181,14 @@ brief specifications of phrases, extracted from the manual "Writing with
Inform". This is used to generate the Phrasebook index. Inform". This is used to generate the Phrasebook index.
@<Miscellaneous other stuff@> = @<Miscellaneous other stuff@> =
pathname *misc = Pathnames::subfolder(pathname_of_area[INTERNAL_FS_AREA], I"Miscellany"); pathname *misc = Pathnames::subfolder(pathname_of_internal_folder, I"Miscellany");
filename_of_large_default_cover_art = Filenames::in_folder(misc, I"Cover.jpg"); filename_of_large_default_cover_art = Filenames::in_folder(misc, I"Cover.jpg");
filename_of_small_default_cover_art = Filenames::in_folder(misc, I"Small Cover.jpg"); filename_of_small_default_cover_art = Filenames::in_folder(misc, I"Small Cover.jpg");
filename_of_intro_postcard = Filenames::in_folder(misc, I"Postcard.pdf"); filename_of_intro_postcard = Filenames::in_folder(misc, I"Postcard.pdf");
filename_of_intro_booklet = Filenames::in_folder(misc, I"IntroductionToIF.pdf"); filename_of_intro_booklet = Filenames::in_folder(misc, I"IntroductionToIF.pdf");
pathname_of_HTML_models = Pathnames::subfolder(pathname_of_area[INTERNAL_FS_AREA], I"HTML"); pathname_of_HTML_models = Pathnames::subfolder(pathname_of_internal_folder, I"HTML");
filename_of_cblorb_report_model = Filenames::in_folder(pathname_of_HTML_models, I"CblorbModel.html"); filename_of_cblorb_report_model = Filenames::in_folder(pathname_of_HTML_models, I"CblorbModel.html");
filename_of_xrefs = Filenames::in_folder(pathname_of_HTML_models, I"xrefs.txt"); filename_of_xrefs = Filenames::in_folder(pathname_of_HTML_models, I"xrefs.txt");
@ -226,24 +216,24 @@ If |-transient| is not specified, it's the same folder, i.e., Inform does
not distinguish between permanent and transient external resources. not distinguish between permanent and transient external resources.
@<External resources@> = @<External resources@> =
if (pathname_of_area[EXTERNAL_FS_AREA] == NULL) { if (pathname_of_external_folder == NULL) {
pathname_of_area[EXTERNAL_FS_AREA] = home_path; pathname_of_external_folder = home_path;
char *subfolder_within = INFORM_FOLDER_RELATIVE_TO_HOME; char *subfolder_within = INFORM_FOLDER_RELATIVE_TO_HOME;
if (subfolder_within[0]) { if (subfolder_within[0]) {
TEMPORARY_TEXT(SF); TEMPORARY_TEXT(SF);
WRITE_TO(SF, "%s", subfolder_within); WRITE_TO(SF, "%s", subfolder_within);
pathname_of_area[EXTERNAL_FS_AREA] = Pathnames::subfolder(home_path, SF); pathname_of_external_folder = Pathnames::subfolder(home_path, SF);
DISCARD_TEXT(SF); DISCARD_TEXT(SF);
} }
pathname_of_area[EXTERNAL_FS_AREA] = pathname_of_external_folder =
Pathnames::subfolder(pathname_of_area[EXTERNAL_FS_AREA], I"Inform"); Pathnames::subfolder(pathname_of_external_folder, I"Inform");
} }
if (Pathnames::create_in_file_system(pathname_of_area[EXTERNAL_FS_AREA]) == 0) return FALSE; if (Pathnames::create_in_file_system(pathname_of_external_folder) == 0) return FALSE;
@<Permanent external resources@>; @<Permanent external resources@>;
if (pathname_of_transient_external_resources == NULL) if (pathname_of_transient_external_resources == NULL)
pathname_of_transient_external_resources = pathname_of_transient_external_resources =
pathname_of_area[EXTERNAL_FS_AREA]; pathname_of_external_folder;
if (Pathnames::create_in_file_system(pathname_of_transient_external_resources) == 0) return FALSE; if (Pathnames::create_in_file_system(pathname_of_transient_external_resources) == 0) return FALSE;
@<Transient external resources@>; @<Transient external resources@>;
@ -256,9 +246,8 @@ a useful little file to add source text to everything Inform compiles,
generally to set use options. generally to set use options.
@<Permanent external resources@> = @<Permanent external resources@> =
Locations::EILT_at(EXTERNAL_FS_AREA, pathname_of_area[EXTERNAL_FS_AREA]);
filename_of_options = filename_of_options =
Filenames::in_folder(pathname_of_area[EXTERNAL_FS_AREA], I"Options.txt"); Filenames::in_folder(pathname_of_external_folder, I"Options.txt");
@ The transient resources are all written by us. @ The transient resources are all written by us.
@ -418,16 +407,14 @@ For the third and final time, there are EILT resources.
Str::truncate(mf, i); Str::truncate(mf, i);
WRITE_TO(mf, ".materials"); WRITE_TO(mf, ".materials");
} }
pathname_of_area[MATERIALS_FS_AREA] = pathname_of_materials =
Pathnames::subfolder(pathname_of_project->pathname_of_parent, mf); Pathnames::subfolder(pathname_of_project->pathname_of_parent, mf);
DISCARD_TEXT(mf); DISCARD_TEXT(mf);
if (Pathnames::create_in_file_system(pathname_of_area[MATERIALS_FS_AREA]) == 0) return FALSE; if (Pathnames::create_in_file_system(pathname_of_materials) == 0) return FALSE;
} else { } else {
pathname_of_area[MATERIALS_FS_AREA] = Pathnames::from_text(I"inform.materials"); pathname_of_materials = Pathnames::from_text(I"inform.materials");
} }
Locations::EILT_at(MATERIALS_FS_AREA, pathname_of_area[MATERIALS_FS_AREA]);
@<Figures and sounds@>; @<Figures and sounds@>;
@<The Release folder@>; @<The Release folder@>;
@<Existing story file@>; @<Existing story file@>;
@ -442,15 +429,15 @@ This is also where the originals (not the released copies) of the Figures
and Sounds, if any, live: in their own subfolders. and Sounds, if any, live: in their own subfolders.
@<Figures and sounds@> = @<Figures and sounds@> =
pathname_of_materials_figures = Pathnames::subfolder(pathname_of_area[MATERIALS_FS_AREA], I"Figures"); pathname_of_materials_figures = Pathnames::subfolder(pathname_of_materials, I"Figures");
pathname_of_materials_sounds = Pathnames::subfolder(pathname_of_area[MATERIALS_FS_AREA], I"Sounds"); pathname_of_materials_sounds = Pathnames::subfolder(pathname_of_materials, I"Sounds");
filename_of_large_cover_art_jpeg = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], I"Cover.jpg"); filename_of_large_cover_art_jpeg = Filenames::in_folder(pathname_of_materials, I"Cover.jpg");
filename_of_large_cover_art_png = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], I"Cover.png"); filename_of_large_cover_art_png = Filenames::in_folder(pathname_of_materials, I"Cover.png");
filename_of_small_cover_art_jpeg = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], I"Small Cover.jpg"); filename_of_small_cover_art_jpeg = Filenames::in_folder(pathname_of_materials, I"Small Cover.jpg");
filename_of_small_cover_art_png = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], I"Small Cover.png"); filename_of_small_cover_art_png = Filenames::in_folder(pathname_of_materials, I"Small Cover.png");
filename_of_epsfile = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], I"Inform Map.eps"); filename_of_epsfile = Filenames::in_folder(pathname_of_materials, I"Inform Map.eps");
@ On a release run, Inblorb will populate the Release subfolder of Materials; @ On a release run, Inblorb will populate the Release subfolder of Materials;
figures and sounds will be copied into the relevant subfolders. The principle figures and sounds will be copied into the relevant subfolders. The principle
@ -458,7 +445,7 @@ is that everything in Release can always be thrown away without loss, because
it can all be generated again. it can all be generated again.
@<The Release folder@> = @<The Release folder@> =
pathname_of_materials_release = Pathnames::subfolder(pathname_of_area[MATERIALS_FS_AREA], I"Release"); pathname_of_materials_release = Pathnames::subfolder(pathname_of_materials, I"Release");
pathname_of_released_interpreter = Pathnames::subfolder(pathname_of_materials_release, I"interpreter"); pathname_of_released_interpreter = Pathnames::subfolder(pathname_of_materials_release, I"interpreter");
pathname_of_released_figures = Pathnames::subfolder(pathname_of_materials_release, I"Figures"); pathname_of_released_figures = Pathnames::subfolder(pathname_of_materials_release, I"Figures");
pathname_of_released_sounds = Pathnames::subfolder(pathname_of_materials_release, I"Sounds"); pathname_of_released_sounds = Pathnames::subfolder(pathname_of_materials_release, I"Sounds");
@ -472,19 +459,9 @@ have by default, if so.
TEMPORARY_TEXT(leaf); TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "story.%S", story_filename_extension); WRITE_TO(leaf, "story.%S", story_filename_extension);
filename_of_existing_story_file = filename_of_existing_story_file =
Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], leaf); Filenames::in_folder(pathname_of_materials, leaf);
DISCARD_TEXT(leaf); DISCARD_TEXT(leaf);
@h EILTs.
Each of the materials folder, the internal and external areas has a suite
of subfolders to hold I7 extensions (in an author tree: see below), I6
template files, language definitions and website templates.
=
void Locations::EILT_at(int area, pathname *P) {
pathname_of_website_templates[area] = Pathnames::subfolder(P, I"Templates");
}
@h Location of extensions. @h Location of extensions.
When Inform needs one of the EILT resources, it now has three places to look: When Inform needs one of the EILT resources, it now has three places to look:
the internal resources folder, the external one, and the materials folder. the internal resources folder, the external one, and the materials folder.

View file

@ -27,7 +27,7 @@ void NaturalLanguages::scan(void) {
} }
@h Language of play. @h Language of play.
The following is the language read and typed by the player: The followin
= =
inform_language *language_of_play = NULL; inform_language *language_of_play = NULL;
@ -36,8 +36,10 @@ inform_language *language_of_index = NULL;
@ = @ =
void NaturalLanguages::default_to_English(void) { void NaturalLanguages::default_to_English(void) {
language_of_syntax = NaturalLanguages::English(); inform_language *E = NaturalLanguages::English();
language_of_index = language_of_syntax; NaturalLanguages::set_language_of_syntax(E);
NaturalLanguages::set_language_of_index(E);
NaturalLanguages::set_language_of_play(E);
} }
void NaturalLanguages::set_language_of_play(inform_language *L) { void NaturalLanguages::set_language_of_play(inform_language *L) {
@ -45,12 +47,19 @@ void NaturalLanguages::set_language_of_play(inform_language *L) {
if (L) L->kit_required = TRUE; if (L) L->kit_required = TRUE;
} }
void NaturalLanguages::set_language_of_index(inform_language *L) {
language_of_index = L;
}
void NaturalLanguages::set_language_of_syntax(inform_language *L) {
language_of_syntax = L;
English_language = L;
}
inform_language *NaturalLanguages::English(void) { inform_language *NaturalLanguages::English(void) {
NaturalLanguages::scan(); NaturalLanguages::scan();
inform_language *L = Languages::from_name(I"english"); inform_language *L = Languages::from_name(I"english");
if (L == NULL) internal_error("unable to find English language bundle"); if (L == NULL) internal_error("unable to find English language bundle");
L->kit_required = TRUE;
English_language = L;
return L; return L;
} }

View file

@ -71,7 +71,7 @@ but in that event the Extensions.w routines do indeed want to know this.
source code is classified.) source code is classified.)
@d ORIGIN_WAS_PRIMARY_SOURCE 0 @d ORIGIN_WAS_PRIMARY_SOURCE 0
@d ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA 1 /* must match |*_FS_AREA| numbers plus 1 */ @d ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA 1
@d ORIGIN_WAS_USER_EXTENSIONS_AREA 2 @d ORIGIN_WAS_USER_EXTENSIONS_AREA 2
@d ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA 3 @d ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA 3

View file

@ -209,7 +209,7 @@ void PL::Bibliographic::Release::handle_release_declaration_inner(parse_node *p)
TEMPORARY_TEXT(leaf); TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "%N", Wordings::first_wn(SW)); WRITE_TO(leaf, "%N", Wordings::first_wn(SW));
filename_of_existing_story_file = filename_of_existing_story_file =
Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], leaf); Filenames::in_folder(pathname_of_materials, leaf);
DISCARD_TEXT(leaf); DISCARD_TEXT(leaf);
} }
existing_story_file = TRUE; existing_story_file = TRUE;
@ -221,7 +221,7 @@ void PL::Bibliographic::Release::handle_release_declaration_inner(parse_node *p)
Word::dequote(Wordings::first_wn(DW)); Word::dequote(Wordings::first_wn(DW));
TEMPORARY_TEXT(leaf); TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "%N", Wordings::first_wn(LW)); WRITE_TO(leaf, "%N", Wordings::first_wn(LW));
filename *A = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], leaf); filename *A = Filenames::in_folder(pathname_of_materials, leaf);
DISCARD_TEXT(leaf); DISCARD_TEXT(leaf);
PL::Bibliographic::Release::create_aux_file(A, PL::Bibliographic::Release::create_aux_file(A,
pathname_of_materials_release, pathname_of_materials_release,
@ -234,7 +234,7 @@ void PL::Bibliographic::Release::handle_release_declaration_inner(parse_node *p)
Word::dequote(Wordings::first_wn(LW)); Word::dequote(Wordings::first_wn(LW));
TEMPORARY_TEXT(leaf); TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "%N", Wordings::first_wn(LW)); WRITE_TO(leaf, "%N", Wordings::first_wn(LW));
filename *A = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], leaf); filename *A = Filenames::in_folder(pathname_of_materials, leaf);
DISCARD_TEXT(leaf); DISCARD_TEXT(leaf);
PL::Bibliographic::Release::create_aux_file(A, PL::Bibliographic::Release::create_aux_file(A,
pathname_of_materials_release, pathname_of_materials_release,
@ -249,7 +249,7 @@ void PL::Bibliographic::Release::handle_release_declaration_inner(parse_node *p)
Word::dequote(Wordings::first_wn(FW)); Word::dequote(Wordings::first_wn(FW));
TEMPORARY_TEXT(leaf); TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "%N", Wordings::first_wn(LW)); WRITE_TO(leaf, "%N", Wordings::first_wn(LW));
filename *A = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], leaf); filename *A = Filenames::in_folder(pathname_of_materials, leaf);
DISCARD_TEXT(leaf); DISCARD_TEXT(leaf);
TEMPORARY_TEXT(folder); TEMPORARY_TEXT(folder);
WRITE_TO(folder, "%N", Wordings::first_wn(FW)); WRITE_TO(folder, "%N", Wordings::first_wn(FW));
@ -352,13 +352,13 @@ application sandboxing in Mac OS X in 2012 may force us to revisit this.
} }
@<Create the Materials folder if not already present@> = @<Create the Materials folder if not already present@> =
if (Pathnames::create_in_file_system(pathname_of_area[MATERIALS_FS_AREA]) == FALSE) { if (Pathnames::create_in_file_system(pathname_of_materials) == FALSE) {
Problems::Issue::release_problem_path(_p_(Untestable), Problems::Issue::release_problem_path(_p_(Untestable),
"In order to release the story file along with other " "In order to release the story file along with other "
"resources, I tried to create a folder alongside this " "resources, I tried to create a folder alongside this "
"Inform project, but was unable to do so. The folder " "Inform project, but was unable to do so. The folder "
"was to have been called", "was to have been called",
pathname_of_area[MATERIALS_FS_AREA]); pathname_of_materials);
return; return;
} }
@ -614,7 +614,7 @@ void PL::Bibliographic::Release::write_ifiction_record(OUTPUT_STREAM, zbyte *hea
WRITE("<auxiliary>\n"); INDENT; WRITE("<auxiliary>\n"); INDENT;
WRITE("<leafname>"); WRITE("<leafname>");
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, af->name_of_original_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, af->name_of_original_file, pathname_of_materials);
HTMLFiles::write_xml_safe_text(OUT, rel); HTMLFiles::write_xml_safe_text(OUT, rel);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);
WRITE("</leafname>\n"); WRITE("</leafname>\n");
@ -1001,14 +1001,14 @@ file online.
LOOP_OVER(af, auxiliary_file) LOOP_OVER(af, auxiliary_file)
if (af->from_payload == JAVASCRIPT_PAYLOAD) { if (af->from_payload == JAVASCRIPT_PAYLOAD) {
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, af->name_of_original_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, af->name_of_original_file, pathname_of_materials);
WRITE("<script src='%S'></script>", rel); WRITE("<script src='%S'></script>", rel);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);
} }
LOOP_OVER(af, auxiliary_file) LOOP_OVER(af, auxiliary_file)
if (af->from_payload == CSS_PAYLOAD) { if (af->from_payload == CSS_PAYLOAD) {
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, af->name_of_original_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, af->name_of_original_file, pathname_of_materials);
WRITE("<link rel='stylesheet' href='%S' type='text/css' media='all'></link>", rel); WRITE("<link rel='stylesheet' href='%S' type='text/css' media='all'></link>", rel);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);
} }
@ -1029,8 +1029,9 @@ file online.
with the earliest quoted searched first. with the earliest quoted searched first.
@<Tell Inblorb where to find the website templates@> = @<Tell Inblorb where to find the website templates@> =
for (int area=0; area<NO_FS_AREAS; area++) inbuild_nest *N;
WRITE("template path \"%p\"\n", pathname_of_website_templates[area]); LOOP_OVER_LINKED_LIST(N, inbuild_nest, I7_nest_list)
WRITE("template path \"%p\"\n", TemplateManager::path_within_nest(N));
@ Inblorb reports its progress, or lack of it, with an HTML page, just as we do. @ Inblorb reports its progress, or lack of it, with an HTML page, just as we do.
This page however includes some hints on what the user might have chosen This page however includes some hints on what the user might have chosen

View file

@ -211,7 +211,7 @@ void PL::Figures::write_picture_manifest(OUTPUT_STREAM, int include_cover,
if (bf->figure_number > 1) { if (bf->figure_number > 1) {
WRITE("<key>%d</key>\n", bf->figure_number); WRITE("<key>%d</key>\n", bf->figure_number);
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, bf->filename_of_image_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, bf->filename_of_image_file, pathname_of_materials);
WRITE("<string>%S</string>\n", rel); WRITE("<string>%S</string>\n", rel);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);
} }
@ -335,7 +335,7 @@ void PL::Figures::index_all(OUTPUT_STREAM) {
Index::link(OUT, Wordings::first_wn(bf->name)); Index::link(OUT, Wordings::first_wn(bf->name));
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, bf->filename_of_image_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, bf->filename_of_image_file, pathname_of_materials);
HTML_TAG("br"); HTML_TAG("br");
WRITE("%SFilename: \"%S\" - resource number %d", line2, rel, bf->figure_number); WRITE("%SFilename: \"%S\" - resource number %d", line2, rel, bf->figure_number);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);

View file

@ -175,7 +175,7 @@ void PL::Sounds::write_sounds_manifest(OUTPUT_STREAM) {
LOOP_OVER(bs, blorb_sound) { LOOP_OVER(bs, blorb_sound) {
WRITE("<key>%d</key>\n", bs->sound_number); WRITE("<key>%d</key>\n", bs->sound_number);
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, bs->filename_of_sound_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, bs->filename_of_sound_file, pathname_of_materials);
WRITE("<string>%S</string>\n", rel); WRITE("<string>%S</string>\n", rel);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);
} }
@ -331,7 +331,7 @@ void PL::Sounds::index_all(OUTPUT_STREAM) {
WRITE("%+W", bs->name); WRITE("%+W", bs->name);
Index::link(OUT, Wordings::first_wn(bs->name)); Index::link(OUT, Wordings::first_wn(bs->name));
TEMPORARY_TEXT(rel); TEMPORARY_TEXT(rel);
Filenames::to_text_relative(rel, bs->filename_of_sound_file, pathname_of_area[MATERIALS_FS_AREA]); Filenames::to_text_relative(rel, bs->filename_of_sound_file, pathname_of_materials);
HTML_TAG("br"); HTML_TAG("br");
WRITE("%SFilename: \"%S\" - resource number %d", line2, rel, bs->sound_number); WRITE("%SFilename: \"%S\" - resource number %d", line2, rel, bs->sound_number);
DISCARD_TEXT(rel); DISCARD_TEXT(rel);

View file

@ -152,13 +152,12 @@ void Main::act(void) {
if ((pipeline_as_file) || (pipeline_as_text)) { if ((pipeline_as_file) || (pipeline_as_text)) {
if (NUMBER_CREATED(inter_file) > 0) if (NUMBER_CREATED(inter_file) > 0)
Errors::fatal("-pipeline and -pipeline-file cannot be combined with inter file parameters"); Errors::fatal("-pipeline and -pipeline-file cannot be combined with inter file parameters");
int no_subnests = 0; linked_list *inter_paths = NEW_LINKED_LIST(pathname);
pathname *subnests[1]; ADD_TO_LINKED_LIST(template_path, pathname, inter_paths);
if (template_path) { no_subnests = 1; subnests[0] = template_path; }
codegen_pipeline *SS; codegen_pipeline *SS;
if (pipeline_as_file) SS = CodeGen::Pipeline::parse_from_file(pipeline_as_file, pipeline_vars); if (pipeline_as_file) SS = CodeGen::Pipeline::parse_from_file(pipeline_as_file, pipeline_vars);
else SS = CodeGen::Pipeline::parse(pipeline_as_text, pipeline_vars); else SS = CodeGen::Pipeline::parse(pipeline_as_text, pipeline_vars);
if (SS) CodeGen::Pipeline::run(domain_path, SS, no_subnests, subnests, requirements_list); if (SS) CodeGen::Pipeline::run(domain_path, SS, inter_paths, requirements_list);
else Errors::fatal("pipeline could not be parsed"); else Errors::fatal("pipeline could not be parsed");
} else if (unit_test_file) { } else if (unit_test_file) {
UnitTests::run(unit_test_file); UnitTests::run(unit_test_file);

View file

@ -15,8 +15,7 @@ typedef struct pipeline_step {
struct code_generation_target *target_argument; struct code_generation_target *target_argument;
struct text_stream *package_argument; struct text_stream *package_argument;
struct filename *parsed_filename; struct filename *parsed_filename;
struct pathname **the_PP; struct linked_list *the_PP; /* of |pathname| */
int the_N;
int to_debugging_log; int to_debugging_log;
int from_memory; int from_memory;
int repository_argument; int repository_argument;
@ -43,7 +42,6 @@ pipeline_step *CodeGen::Pipeline::new_step(void) {
void CodeGen::Pipeline::clean_step(pipeline_step *step) { void CodeGen::Pipeline::clean_step(pipeline_step *step) {
step->parsed_filename = NULL; step->parsed_filename = NULL;
step->text_out_file = NULL; step->text_out_file = NULL;
step->the_N = -1;
step->to_debugging_log = FALSE; step->to_debugging_log = FALSE;
step->from_memory = FALSE; step->from_memory = FALSE;
step->the_PP = NULL; step->the_PP = NULL;
@ -237,7 +235,7 @@ void CodeGen::Pipeline::set_repository(codegen_pipeline *S, inter_tree *I) {
S->memory_repository = I; S->memory_repository = I;
} }
void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, int N, pathname **PP, void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, linked_list *PP,
linked_list *requirements_list) { linked_list *requirements_list) {
if (S == NULL) return; if (S == NULL) return;
clock_t start = clock(); clock_t start = clock();
@ -257,7 +255,6 @@ void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, int N, pathname **
CodeGen::Pipeline::lint(I); CodeGen::Pipeline::lint(I);
CodeGen::Pipeline::clean_step(step); CodeGen::Pipeline::clean_step(step);
step->the_N = N;
step->the_PP = PP; step->the_PP = PP;
step->repository = I; step->repository = I;
step->pipeline = S; step->pipeline = S;

View file

@ -14,11 +14,11 @@ int CodeGen::MergeTemplate::run_pipeline_stage(pipeline_step *step) {
inter_bookmark IBM; inter_bookmark IBM;
if (main_package) IBM = Inter::Bookmarks::at_end_of_this_package(main_package); if (main_package) IBM = Inter::Bookmarks::at_end_of_this_package(main_package);
else IBM = Inter::Bookmarks::at_start_of_this_repository(step->repository); else IBM = Inter::Bookmarks::at_start_of_this_repository(step->repository);
CodeGen::MergeTemplate::link(&IBM, step->step_argument, step->the_N, step->the_PP, NULL); CodeGen::MergeTemplate::link(&IBM, step->step_argument, step->the_PP, NULL);
return TRUE; return TRUE;
} }
void CodeGen::MergeTemplate::link(inter_bookmark *IBM, text_stream *template_file, int N, pathname **PP, inter_package *owner) { void CodeGen::MergeTemplate::link(inter_bookmark *IBM, text_stream *template_file, linked_list *PP, inter_package *owner) {
if (IBM == NULL) internal_error("no inter to link with"); if (IBM == NULL) internal_error("no inter to link with");
inter_tree *I = Inter::Bookmarks::tree(IBM); inter_tree *I = Inter::Bookmarks::tree(IBM);
if (Str::eq(template_file, I"none")) if (Str::eq(template_file, I"none"))
@ -32,8 +32,11 @@ void CodeGen::MergeTemplate::link(inter_bookmark *IBM, text_stream *template_fil
Inter::Bookmarks::at_end_of_this_package(template_package); Inter::Bookmarks::at_end_of_this_package(template_package);
I6T_kit kit = TemplateReader::kit_out(&link_bookmark, &(CodeGen::MergeTemplate::receive_raw), &(CodeGen::MergeTemplate::receive_command), NULL); I6T_kit kit = TemplateReader::kit_out(&link_bookmark, &(CodeGen::MergeTemplate::receive_raw), &(CodeGen::MergeTemplate::receive_command), NULL);
kit.no_i6t_file_areas = N; kit.no_i6t_file_areas = LinkedLists::len(PP);
for (int i=0; i<N; i++) kit.i6t_files[i] = Pathnames::subfolder(PP[i], I"Sections"); pathname *P;
int i=0;
LOOP_OVER_LINKED_LIST(P, pathname, PP)
kit.i6t_files[i] = Pathnames::subfolder(P, I"Sections");
int stage = EARLY_LINK_STAGE; int stage = EARLY_LINK_STAGE;
if (Str::eq(template_file, I"none")) stage = CATCH_ALL_LINK_STAGE; if (Str::eq(template_file, I"none")) stage = CATCH_ALL_LINK_STAGE;
TEMPORARY_TEXT(T); TEMPORARY_TEXT(T);

View file

@ -582,7 +582,7 @@ To provide an example, ^{@Emily Short}'s useful extension "Locksmith" is one of
Each time that Inform translates any source text, it performs a quick check of the extensions available, and updates its own internal records. A directory of the extensions currently installed can be found by clicking on "Installed Extensions" from the Extensions panel. This is also worth visiting in order to browse the Public Library, a selection of extensions contributed by Inform users. Each time that Inform translates any source text, it performs a quick check of the extensions available, and updates its own internal records. A directory of the extensions currently installed can be found by clicking on "Installed Extensions" from the Extensions panel. This is also worth visiting in order to browse the Public Library, a selection of extensions contributed by Inform users.
[x] Including extensions {PM_IncludeExtQuoted} {PM_ExtVersionMalformed} {PM_ExtMiswordedBeginsHere} {PM_ExtMisidentified} {PM_ExtMalformedVM} {PM_ExtInadequateVM} {PM_ExtMisidentifiedEnds} [x] Including extensions {PM_IncludeExtQuoted} {PM_ExtVersionMalformed} {PM_ExtMiswordedBeginsHere} {PM_ExtMalformedVM} {PM_ExtInadequateVM} {PM_ExtMisidentifiedEnds}
^^{extensions: using} ^^{extensions: using}
^^{include (extension) by (extension author)+assert+} ^^{include (extension) by (extension author)+assert+}
@ -17442,7 +17442,7 @@ Sometimes authorship is complicated. What if Mary Brown finds some Inform 6 code
But Mary and John deserve their credits too: see the next section for how to give them. But Mary and John deserve their credits too: see the next section for how to give them.
[x] A simple example extension {PM_ExtMultipleBeginsHere} {PM_ExtBeginsAfterEndsHere} {PM_ExtEndsWithoutBegins} {PM_ExtMultipleEndsHere} {PM_ExtNoBeginsHere} {PM_ExtNoEndsHere} [x] A simple example extension {PM_ExtMultipleBeginsHere} {PM_ExtBeginsAfterEndsHere} {PM_ExtMultipleEndsHere} {PM_ExtNoBeginsHere} {PM_ExtNoEndsHere}
^^{extensions: writing: example} ^^{extensions: writing: example}
^^{>VERSION} ^^{>VERSION}

View file

@ -490,7 +490,6 @@ integration: \
$(SRULESINPLACE) \ $(SRULESINPLACE) \
$(BINFORMINPLACE) \ $(BINFORMINPLACE) \
kitsintegration \ kitsintegration \
$(INTERNAL)/Inter/default.interpipeline \
$(DOCEXEMPLUM) \ $(DOCEXEMPLUM) \
$(INTERNALEXEMPLUM) \ $(INTERNALEXEMPLUM) \
$(IMAGESEXEMPLUM) \ $(IMAGESEXEMPLUM) \
@ -506,7 +505,6 @@ forceintegration:
$(call transfer-preform) $(call transfer-preform)
$(call transfer-standard-rules) $(call transfer-standard-rules)
$(call transfer-kits) $(call transfer-kits)
$(call transfer-inter-resources)
$(call transfer-internal-tree) $(call transfer-internal-tree)
$(call transfer-images) $(call transfer-images)
$(call make-inapp-documentation) $(call make-inapp-documentation)
@ -590,19 +588,11 @@ define transfer-xefs
cp -f inform7/Internal/HTML/xrefs.txt "$(INTERNAL)/HTML" cp -f inform7/Internal/HTML/xrefs.txt "$(INTERNAL)/HTML"
endef endef
# (d) Copying the I6 template into the app # (d) Copying kits and pipelines into the app
define transfer-kits define transfer-kits
$(INBUILDX) -sync-to $(INTERNAL) -contents-of inform7/Internal/Inter $(INBUILDX) -sync-to $(INTERNAL) -contents-of inform7/Internal/Inter
endef $(INBUILDX) -sync-to $(INTERNAL) -contents-of inform7/Internal/Pipelines
$(INTERNAL)/Inter/default.interpipeline: inform7/Internal/Inter/*.interpipeline
$(call transfer-inter-resources)
define transfer-inter-resources
mkdir -p "$(INTERNAL)/Inter"
rm -f $(INTERNAL)/Inter/*.interpipeline
cp -R -f inform7/Internal/Inter/*.interpipeline $(INTERNAL)/Inter
endef endef
# (e) Copying internal resources into the app # (e) Copying internal resources into the app