1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-26 04:00:43 +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_project_MT
@e inform_language_MT
@e inform_pipeline_MT
=
ALLOCATE_INDIVIDUALLY(inform_kit)
@ -51,6 +52,7 @@ ALLOCATE_INDIVIDUALLY(extension_census)
ALLOCATE_INDIVIDUALLY(inform_template)
ALLOCATE_INDIVIDUALLY(inform_project)
ALLOCATE_INDIVIDUALLY(inform_language)
ALLOCATE_INDIVIDUALLY(inform_pipeline)
ALLOCATE_IN_ARRAYS(inbuild_work_database_entry, 100)
@ -68,6 +70,7 @@ void InbuildModule::start(void) {
TemplateManager::start();
LanguageManager::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) {
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);
work->genre = genre;
work->raw_author_name = Str::duplicate(an);
work->author_name = Str::duplicate(an);
work->raw_title = Str::duplicate(ti);
work->title = Str::duplicate(ti);
Works::normalise_casing(work->author_name);
Works::normalise_casing(work->title);
if (norm) {
Works::normalise_casing(work->author_name);
Works::normalise_casing(work->title);
}
unsigned int hc = 0;
LOOP_THROUGH_TEXT(pos, work->author_name)
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);
if (C == NULL) {
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);
C = Model::copy_in_directory(edition, P, STORE_POINTER_inform_kit(K));
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
Project Manager
Template Manager
Pipeline Manager
Chapter 4: Services for the Inform Compiler
Kit Services
@ -30,3 +31,4 @@ Chapter 4: Services for the Inform Compiler
Template Services
Project Services
Language Services
Pipeline Services

View file

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

View file

@ -102,6 +102,7 @@ int CoreMain::main(int argc, char *argv[]) {
Errors::set_internal_handler(&Problems::Issue::internal_error_fn);
story_filename_extension = I"ulx";
inter_processing_pipeline = Str::new();
inter_processing_file = I"compile";
PRINT("%B build %B has started.\n", FALSE, TRUE);
STREAM_FLUSH(STDOUT);
@ -436,33 +437,40 @@ with "Output.i6t".
@<Ensure inter pipeline variables dictionary@>;
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));
pathname *inter_subnests[NO_FS_AREAS] = { NULL, NULL, NULL };
int s = 0;
linked_list *inter_paths = NEW_LINKED_LIST(pathname);
inbuild_nest *N;
LOOP_OVER_LINKED_LIST(N, inbuild_nest, I7_nest_list) {
if (s >= NO_FS_AREAS) break;
inter_subnests[s++] = KitManager::path_within_nest(N);
}
LOOP_OVER_LINKED_LIST(N, inbuild_nest, I7_nest_list)
ADD_TO_LINKED_LIST(KitManager::path_within_nest(N), pathname, inter_paths);
codegen_pipeline *SS = NULL;
if (inter_processing_file)
SS = CodeGen::Pipeline::parse_from_file(Filenames::from_text(inter_processing_file), pipeline_vars);
else if (Str::len(inter_processing_pipeline) > 0)
if (Str::len(inter_processing_pipeline) > 0) {
SS = CodeGen::Pipeline::parse(inter_processing_pipeline, pipeline_vars);
else {
for (int area=0; area<NO_FS_AREAS; area++) {
pathname *P = inter_subnests[area];
filename *F = Filenames::in_folder(P, I"default.interpipeline");
if (TextFiles::exists(F)) {
if (SS == NULL)
Problems::Fatal::issue("The Inter pipeline description contained errors");
} else {
inbuild_requirement *req =
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);
if (SS == NULL)
Problems::Fatal::filename_related("This Inter pipeline contains errors", F);
break;
}
}
}
if (SS == NULL)
Problems::Fatal::issue("The Inter pipeline description contained errors");
CodeGen::Pipeline::set_repository(SS, Emit::tree());
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));
}

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,
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,
not here. First, some "areas":
@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:
not here.
= (early code)
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_inner = NULL;
@ -83,16 +75,16 @@ void Locations::set_project(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) {
if (pathname_of_area[INTERNAL_FS_AREA] == NULL)
pathname_of_area[INTERNAL_FS_AREA] = P;
if (pathname_of_internal_folder == NULL)
pathname_of_internal_folder = P;
}
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) {
@ -132,18 +124,18 @@ int Locations::set_defaults(int census_mode) {
if ((census_mode) && (filename_of_i7_source))
Problems::Fatal::issue("In census mode, no source text may be supplied");
I7_nest_list = NEW_LINKED_LIST(inbuild_nest);
if (pathname_of_area[MATERIALS_FS_AREA]) {
inbuild_nest *nest = Nests::new(pathname_of_area[MATERIALS_FS_AREA]);
if (pathname_of_materials) {
inbuild_nest *nest = Nests::new(pathname_of_materials);
Nests::set_tag(nest, ORIGIN_WAS_MATERIALS_EXTENSIONS_AREA);
ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list);
}
if (pathname_of_area[EXTERNAL_FS_AREA]) {
inbuild_nest *nest = Nests::new(pathname_of_area[EXTERNAL_FS_AREA]);
if (pathname_of_external_folder) {
inbuild_nest *nest = Nests::new(pathname_of_external_folder);
Nests::set_tag(nest, ORIGIN_WAS_USER_EXTENSIONS_AREA);
ADD_TO_LINKED_LIST(nest, inbuild_nest, I7_nest_list);
}
if (pathname_of_area[INTERNAL_FS_AREA]) {
inbuild_nest *nest = Nests::new(pathname_of_area[INTERNAL_FS_AREA]);
if (pathname_of_internal_folder) {
inbuild_nest *nest = Nests::new(pathname_of_internal_folder);
Nests::set_tag(nest, ORIGIN_WAS_BUILT_IN_EXTENSIONS_AREA);
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.
@<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");
Locations::EILT_at(INTERNAL_FS_AREA, pathname_of_area[INTERNAL_FS_AREA]);
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 =
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.
@<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_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_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_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.
@<External resources@> =
if (pathname_of_area[EXTERNAL_FS_AREA] == NULL) {
pathname_of_area[EXTERNAL_FS_AREA] = home_path;
if (pathname_of_external_folder == NULL) {
pathname_of_external_folder = home_path;
char *subfolder_within = INFORM_FOLDER_RELATIVE_TO_HOME;
if (subfolder_within[0]) {
TEMPORARY_TEXT(SF);
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);
}
pathname_of_area[EXTERNAL_FS_AREA] =
Pathnames::subfolder(pathname_of_area[EXTERNAL_FS_AREA], I"Inform");
pathname_of_external_folder =
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@>;
if (pathname_of_transient_external_resources == NULL)
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;
@<Transient external resources@>;
@ -256,9 +246,8 @@ a useful little file to add source text to everything Inform compiles,
generally to set use options.
@<Permanent external resources@> =
Locations::EILT_at(EXTERNAL_FS_AREA, pathname_of_area[EXTERNAL_FS_AREA]);
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.
@ -418,16 +407,14 @@ For the third and final time, there are EILT resources.
Str::truncate(mf, i);
WRITE_TO(mf, ".materials");
}
pathname_of_area[MATERIALS_FS_AREA] =
pathname_of_materials =
Pathnames::subfolder(pathname_of_project->pathname_of_parent, 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 {
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@>;
@<The Release folder@>;
@<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.
@<Figures and sounds@> =
pathname_of_materials_figures = Pathnames::subfolder(pathname_of_area[MATERIALS_FS_AREA], I"Figures");
pathname_of_materials_sounds = Pathnames::subfolder(pathname_of_area[MATERIALS_FS_AREA], I"Sounds");
pathname_of_materials_figures = Pathnames::subfolder(pathname_of_materials, I"Figures");
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_png = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], 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_png = Filenames::in_folder(pathname_of_area[MATERIALS_FS_AREA], I"Small Cover.png");
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_materials, I"Cover.png");
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_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;
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.
@<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_figures = Pathnames::subfolder(pathname_of_materials_release, I"Figures");
pathname_of_released_sounds = Pathnames::subfolder(pathname_of_materials_release, I"Sounds");
@ -472,19 +459,9 @@ have by default, if so.
TEMPORARY_TEXT(leaf);
WRITE_TO(leaf, "story.%S", story_filename_extension);
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);
@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.
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.

View file

@ -27,7 +27,7 @@ void NaturalLanguages::scan(void) {
}
@h Language of play.
The following is the language read and typed by the player:
The followin
=
inform_language *language_of_play = NULL;
@ -36,8 +36,10 @@ inform_language *language_of_index = NULL;
@ =
void NaturalLanguages::default_to_English(void) {
language_of_syntax = NaturalLanguages::English();
language_of_index = language_of_syntax;
inform_language *E = NaturalLanguages::English();
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) {
@ -45,12 +47,19 @@ void NaturalLanguages::set_language_of_play(inform_language *L) {
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) {
NaturalLanguages::scan();
inform_language *L = Languages::from_name(I"english");
if (L == NULL) internal_error("unable to find English language bundle");
L->kit_required = TRUE;
English_language = 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.)
@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_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);
WRITE_TO(leaf, "%N", Wordings::first_wn(SW));
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);
}
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));
TEMPORARY_TEXT(leaf);
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);
PL::Bibliographic::Release::create_aux_file(A,
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));
TEMPORARY_TEXT(leaf);
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);
PL::Bibliographic::Release::create_aux_file(A,
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));
TEMPORARY_TEXT(leaf);
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);
TEMPORARY_TEXT(folder);
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@> =
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),
"In order to release the story file along with other "
"resources, I tried to create a folder alongside this "
"Inform project, but was unable to do so. The folder "
"was to have been called",
pathname_of_area[MATERIALS_FS_AREA]);
pathname_of_materials);
return;
}
@ -614,7 +614,7 @@ void PL::Bibliographic::Release::write_ifiction_record(OUTPUT_STREAM, zbyte *hea
WRITE("<auxiliary>\n"); INDENT;
WRITE("<leafname>");
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);
DISCARD_TEXT(rel);
WRITE("</leafname>\n");
@ -1001,14 +1001,14 @@ file online.
LOOP_OVER(af, auxiliary_file)
if (af->from_payload == JAVASCRIPT_PAYLOAD) {
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);
DISCARD_TEXT(rel);
}
LOOP_OVER(af, auxiliary_file)
if (af->from_payload == CSS_PAYLOAD) {
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);
DISCARD_TEXT(rel);
}
@ -1029,8 +1029,9 @@ file online.
with the earliest quoted searched first.
@<Tell Inblorb where to find the website templates@> =
for (int area=0; area<NO_FS_AREAS; area++)
WRITE("template path \"%p\"\n", pathname_of_website_templates[area]);
inbuild_nest *N;
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.
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) {
WRITE("<key>%d</key>\n", bf->figure_number);
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);
DISCARD_TEXT(rel);
}
@ -335,7 +335,7 @@ void PL::Figures::index_all(OUTPUT_STREAM) {
Index::link(OUT, Wordings::first_wn(bf->name));
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");
WRITE("%SFilename: \"%S\" - resource number %d", line2, rel, bf->figure_number);
DISCARD_TEXT(rel);

View file

@ -175,7 +175,7 @@ void PL::Sounds::write_sounds_manifest(OUTPUT_STREAM) {
LOOP_OVER(bs, blorb_sound) {
WRITE("<key>%d</key>\n", bs->sound_number);
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);
DISCARD_TEXT(rel);
}
@ -331,7 +331,7 @@ void PL::Sounds::index_all(OUTPUT_STREAM) {
WRITE("%+W", bs->name);
Index::link(OUT, Wordings::first_wn(bs->name));
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");
WRITE("%SFilename: \"%S\" - resource number %d", line2, rel, bs->sound_number);
DISCARD_TEXT(rel);

View file

@ -152,13 +152,12 @@ void Main::act(void) {
if ((pipeline_as_file) || (pipeline_as_text)) {
if (NUMBER_CREATED(inter_file) > 0)
Errors::fatal("-pipeline and -pipeline-file cannot be combined with inter file parameters");
int no_subnests = 0;
pathname *subnests[1];
if (template_path) { no_subnests = 1; subnests[0] = template_path; }
linked_list *inter_paths = NEW_LINKED_LIST(pathname);
ADD_TO_LINKED_LIST(template_path, pathname, inter_paths);
codegen_pipeline *SS;
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);
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 if (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 text_stream *package_argument;
struct filename *parsed_filename;
struct pathname **the_PP;
int the_N;
struct linked_list *the_PP; /* of |pathname| */
int to_debugging_log;
int from_memory;
int repository_argument;
@ -43,7 +42,6 @@ pipeline_step *CodeGen::Pipeline::new_step(void) {
void CodeGen::Pipeline::clean_step(pipeline_step *step) {
step->parsed_filename = NULL;
step->text_out_file = NULL;
step->the_N = -1;
step->to_debugging_log = FALSE;
step->from_memory = FALSE;
step->the_PP = NULL;
@ -237,7 +235,7 @@ void CodeGen::Pipeline::set_repository(codegen_pipeline *S, inter_tree *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) {
if (S == NULL) return;
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::clean_step(step);
step->the_N = N;
step->the_PP = PP;
step->repository = I;
step->pipeline = S;

View file

@ -14,11 +14,11 @@ int CodeGen::MergeTemplate::run_pipeline_stage(pipeline_step *step) {
inter_bookmark IBM;
if (main_package) IBM = Inter::Bookmarks::at_end_of_this_package(main_package);
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;
}
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");
inter_tree *I = Inter::Bookmarks::tree(IBM);
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);
I6T_kit kit = TemplateReader::kit_out(&link_bookmark, &(CodeGen::MergeTemplate::receive_raw), &(CodeGen::MergeTemplate::receive_command), NULL);
kit.no_i6t_file_areas = N;
for (int i=0; i<N; i++) kit.i6t_files[i] = Pathnames::subfolder(PP[i], I"Sections");
kit.no_i6t_file_areas = LinkedLists::len(PP);
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;
if (Str::eq(template_file, I"none")) stage = CATCH_ALL_LINK_STAGE;
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.
[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}
^^{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.
[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}
^^{>VERSION}

View file

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