From 575100e844f6463f497ba523ed20b8cdc099579e Mon Sep 17 00:00:00 2001
From: Graham Nelson
-void Copies::attach_error(inbuild_copy *C, copy_error *CE) { +void Copies::attach_error(inbuild_copy *C, copy_error *CE) { if (C == NULL) internal_error("no copy to attach to"); CopyErrors::supply_attached_copy(CE, C); ADD_TO_LINKED_LIST(CE, copy_error, C->errors_reading_source_text); diff --git a/docs/supervisor-module/2-nst.html b/docs/supervisor-module/2-nst.html index 5d0846e69..c88fdb80f 100644 --- a/docs/supervisor-module/2-nst.html +++ b/docs/supervisor-module/2-nst.html @@ -73,7 +73,7 @@ positions in the file system hierarchy which may or may not exist. int tag_value; used to indicate whether internal, external, and such CLASS_DEFINITION } inbuild_nest; -inbuild_nest *Nests::new(pathname *P) { +inbuild_nest *Nests::new(pathname *P) { inbuild_nest *N = CREATE(inbuild_nest); N->location = P; N->read_only = FALSE; @@ -81,7 +81,7 @@ positions in the file system hierarchy which may or may not exist. return N; }-
§2. Nests used by the Inform and Inbuild tools are tagged with the following
constants. (There used to be quite a good joke here, but refactoring of the
code removed its premise. Literate programming is like that sometimes.)
@@ -103,7 +103,7 @@ see below for why. Lower-tag-numbered origins are better than later ones.
return N->tag_value;
}
-void Nests::set_tag(inbuild_nest *N, int t) {
+void Nests::set_tag(inbuild_nest *N, int t) {
if (N == NULL) internal_error("no nest");
N->tag_value = t;
}
diff --git a/docs/supervisor-module/3-is2.html b/docs/supervisor-module/3-is2.html
index a7f8e77c8..927ace8a3 100644
--- a/docs/supervisor-module/3-is2.html
+++ b/docs/supervisor-module/3-is2.html
@@ -89,6 +89,7 @@ if we are running inside info
LOOP_OVER_LINKED_LIST(N, inbuild_nest, L) {
switch (Nests::get_tag(N)) {
case MATERIALS_NEST_TAG: continue;
+ case EXTENSION_NEST_TAG: continue;
case EXTERNAL_NEST_TAG: WRITE_TO(command, "-external "); break;
case GENERIC_NEST_TAG: WRITE_TO(command, "-nest "); break;
case INTERNAL_NEST_TAG: WRITE_TO(command, "-internal "); break;
diff --git a/docs/supervisor-module/5-es.html b/docs/supervisor-module/5-es.html
index 19cacc267..52c4fd76b 100644
--- a/docs/supervisor-module/5-es.html
+++ b/docs/supervisor-module/5-es.html
@@ -94,6 +94,7 @@ length to one character less than the following constants:
struct linked_list *activations; of element_activation
struct linked_list *extensions; of inbuild_requirement
struct linked_list *kits; of inbuild_requirement
+ struct inbuild_nest *materials_nest;
CLASS_DEFINITION
} inform_extension;
@@ -152,6 +153,7 @@ compatibility notes given (such as "for Glulx only").
E->activations = NEW_LINKED_LIST(element_activation);
E->extensions = NEW_LINKED_LIST(inbuild_requirement);
E->kits = NEW_LINKED_LIST(inbuild_requirement);
+ E->materials_nest = NULL;
§2.2. The following scans a potential extension file. If it seems malformed, a
@@ -531,7 +533,7 @@ are immutable, and need to be for the extensions dictionary to work.
§5. Cached metadata. The following data hides between runs in the Dictionary.
§8. Since there are two ways projects can be stored:
-inform_extension *Extensions::from_copy(inbuild_copy *C) {
+inform_extension *Extensions::from_copy(inbuild_copy *C) {
inform_extension *ext = ExtensionBundleManager::from_copy(C);
if (ext == NULL) ext = ExtensionManager::from_copy(C);
return ext;
@@ -551,11 +553,20 @@ are immutable, and need to be for the extensions dictionary to work.
return F;
}
-pathname *Extensions::materials_path(inform_extension *E) {
+pathname *Extensions::materials_path(inform_extension *E) {
pathname *P = E->as_copy->location_if_path;
if (P) P = Pathnames::down(P, I"Materials");
return P;
}
+
+inbuild_nest *Extensions::materials_nest(inform_extension *E) {
+ pathname *P = Extensions::materials_path(E);
+ if ((E->materials_nest == NULL) && (P)) {
+ E->materials_nest = Nests::new(P);
+ Nests::set_tag(E->materials_nest, EXTENSION_NEST_TAG);
+ }
+ return E->materials_nest;
+}
inform_language *Languages::find_for(text_stream *name, linked_list *search) {
+ text_stream *author = NULL;
+ match_results mr = Regexp::create_mr();
+ if (Regexp::match(&mr, name, L"(%c+) [Ll]anguage by (%c+)")) {
+ name = mr.exp[0]; author = mr.exp[1];
+ } else if (Regexp::match(&mr, name, L"(%c+) by (%c+)")) {
+ name = mr.exp[0]; author = mr.exp[1];
+ } else if (Regexp::match(&mr, name, L"(%c+) [Ll]anguage")) {
+ name = mr.exp[0];
+ }
+ TEMPORARY_TEXT(title)
+ WRITE_TO(title, "%S Language", name);
+ inbuild_requirement *extension_req =
+ Requirements::any_version_of(Works::new(extension_bundle_genre, title, author));
+ inbuild_search_result *extension_R = Nests::search_for_best(extension_req, search);
+ DISCARD_TEXT(title)
+ if (extension_R) {
+ inform_extension *E = Extensions::from_copy(extension_R->copy);
+ inbuild_nest *N = Extensions::materials_nest(E);
+ if (N) {
+ linked_list *longer = NEW_LINKED_LIST(inbuild_nest);
+ ADD_TO_LINKED_LIST(N, inbuild_nest, longer);
+ inbuild_requirement *req =
+ Requirements::any_version_of(Works::new(language_genre, name, I""));
+ inbuild_search_result *R = Nests::search_for_best(req, longer);
+ if (R) {
+ inform_language *L = LanguageManager::from_copy(R->copy);
+ L->belongs_to = E;
+ Regexp::dispose_of(&mr);
+ return L;
+ }
+ }
+ }
inbuild_requirement *req =
Requirements::any_version_of(Works::new(language_genre, name, I""));
inbuild_search_result *R = Nests::search_for_best(req, search);
+ Regexp::dispose_of(&mr);
if (R) return LanguageManager::from_copy(R->copy);
return NULL;
}
diff --git a/docs/supervisor-module/5-ps2.html b/docs/supervisor-module/5-ps2.html
index 6f8c12648..8ad878e92 100644
--- a/docs/supervisor-module/5-ps2.html
+++ b/docs/supervisor-module/5-ps2.html
@@ -315,12 +315,20 @@ reasons, this list is created on demand.
}
return proj->search_list;
}
+
+void Projects::add_language_extension_nest(inform_project *proj) {
+ if ((proj->language_of_play) && (proj->language_of_play->belongs_to)) {
+ inform_extension *E = proj->language_of_play->belongs_to;
+ inbuild_nest *N = Extensions::materials_nest(E);
+ if (N) ADD_TO_LINKED_LIST(N, inbuild_nest, proj->search_list);
+ }
+}
-inform_project *Projects::from_copy(inbuild_copy *C) {
+inform_project *Projects::from_copy(inbuild_copy *C) {
inform_project *project = ProjectBundleManager::from_copy(C);
if (project == NULL) project = ProjectFileManager::from_copy(C);
return project;
@@ -331,7 +339,7 @@ has a single, "primary", one.
-void Projects::set_primary_source(inform_project *proj, filename *F) { +void Projects::set_primary_source(inform_project *proj, filename *F) { proj->primary_source = F; } @@ -347,7 +355,7 @@ the outcome.-linked_list *Projects::source(inform_project *proj) { +linked_list *Projects::source(inform_project *proj) { if (proj == NULL) return NULL; if (LinkedLists::len(proj->source_vertices) == 0) Try the source file set at the command line, if any was10.1; @@ -394,7 +402,7 @@ that dependency graph.)-void Projects::add_heading_source(inform_project *proj, text_stream *path) { +void Projects::add_heading_source(inform_project *proj, text_stream *path) { pathname *P = NULL; if (proj->as_copy->location_if_path) P = Pathnames::down(Projects::materials_path(proj), I"Source"); @@ -475,7 +483,7 @@ are set only once, and can't be changed after that.-void Projects::set_languages(inform_project *proj) { +void Projects::set_languages(inform_project *proj) { if (proj == NULL) internal_error("no project"); text_stream *S_name = I"English"; text_stream *S_clue = proj->clue_for_language_of_syntax; @@ -500,6 +508,7 @@ are set only once, and can't be changed after that. inform_language *L = Languages::find_for(name, Projects::nest_list(proj)); if (L) { proj->language_of_play = L; + Projects::add_language_extension_nest(proj); } else { build_vertex *RV = Graphs::req_vertex( Requirements::any_version_of(Works::new(language_genre, name, I""))); @@ -520,14 +529,14 @@ and that means it's not beneath our notice.)-void Projects::set_compilation_options(inform_project *proj, int r, int co, int rng) { +void Projects::set_compilation_options(inform_project *proj, int r, int co, int rng) { proj->compile_for_release = r; proj->compile_only = co; proj->fix_rng = rng; Projects::set_languages(proj); } -int Projects::currently_releasing(inform_project *proj) { +int Projects::currently_releasing(inform_project *proj) { if (proj == NULL) return FALSE; return proj->compile_for_release; } @@ -549,7 +558,7 @@ at least one kit, and probably several.-int Projects::add_kit_dependency(inform_project *project, text_stream *kit_name, +int Projects::add_kit_dependency(inform_project *project, text_stream *kit_name, inform_language *because_of_language, inform_kit *because_of_kit, inbuild_requirement *req, linked_list *nests) { if (Projects::uses_kit(project, kit_name)) return TRUE; @@ -575,7 +584,7 @@ at least one kit, and probably several.-int Projects::uses_kit(inform_project *project, text_stream *name) { +int Projects::uses_kit(inform_project *project, text_stream *name) { kit_dependency *kd; LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include) if (Str::eq(kd->kit->as_copy->edition->work->title, name)) @@ -589,11 +598,11 @@ at least one kit, and probably several.int forcible_basic_mode = FALSE; -void Projects::enter_forcible_basic_mode(void) { +void Projects::enter_forcible_basic_mode(void) { forcible_basic_mode = TRUE; } -void Projects::finalise_kit_dependencies(inform_project *project) { +void Projects::finalise_kit_dependencies(inform_project *project) { Add dependencies for the standard kits22.1; int parity = TRUE; Perform if-this-then-that22.2; parity = FALSE; Perform if-this-then-that22.2; @@ -628,8 +637,13 @@ on WorldModelKit, thr if (LinkedLists::len(project->kits_to_include) > 0) no_word_from_JSON = FALSE; Projects::add_kit_dependency(project, I"BasicInformKit", NULL, NULL, NULL, NULL); inform_language *L = project->language_of_play; - if (L) Languages::add_kit_dependencies_to_project(L, project); - else internal_error("no language of play"); + if (L) { + Languages::add_kit_dependencies_to_project(L, project); + } else { + Copies::attach_error(project->as_copy, + CopyErrors::new_T(LANGUAGE_UNAVAILABLE_CE, -1, + project->name_of_language_of_play)); + } if ((no_word_from_JSON) && (forcible_basic_mode == FALSE)) Projects::add_kit_dependency(project, I"CommandParserKit", NULL, NULL, NULL, NULL);@@ -720,7 +734,7 @@ reads them in for every kit which is included in the project.-void Projects::activate_elements(inform_project *project) { +void Projects::activate_elements(inform_project *project) { Features::activate_bare_minimum(); element_activation *EA; LOOP_OVER_LINKED_LIST(EA, element_activation, project->activations) { @@ -748,7 +762,7 @@ reads them in for every kit which is included in the project. LOG("\n"); } -void Projects::activate_extension_elements(inform_project *project) { +void Projects::activate_extension_elements(inform_project *project) { inform_extension *ext; LOOP_OVER_LINKED_LIST(ext, inform_extension, project->extensions_included) Extensions::activate_elements(ext, project); @@ -797,7 +811,7 @@ may be multiple sentences, which we need to count up.-void Projects::early_source_text(OUTPUT_STREAM, inform_project *project) { +void Projects::early_source_text(OUTPUT_STREAM, inform_project *project) { kit_dependency *kd; LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include) Kits::early_source_text(OUT, kd->kit); @@ -811,7 +825,7 @@ details instead.#ifdef PIPELINE_MODULE -linked_list *Projects::list_of_attachment_instructions(inform_project *project) { +linked_list *Projects::list_of_attachment_instructions(inform_project *project) { linked_list *requirements_list = NEW_LINKED_LIST(attachment_instruction); kit_dependency *kd; LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include) { @@ -827,11 +841,11 @@ details instead.-void Projects::set_primary_output(inform_project *proj, filename *F) { +void Projects::set_primary_output(inform_project *proj, filename *F) { proj->primary_output = F; } -filename *Projects::get_primary_output(inform_project *proj) { +filename *Projects::get_primary_output(inform_project *proj) { if (proj->primary_output) return proj->primary_output; if (proj->stand_alone) { return Filenames::set_extension(proj->primary_source, @@ -855,7 +869,7 @@ done by having the syntaxinform_project *project_being_scanned = NULL; -void Projects::dialogue_present(void) { +void Projects::dialogue_present(void) { if (project_being_scanned) { Projects::add_kit_dependency(project_being_scanned, I"DialogueKit", NULL, NULL, NULL, NULL); Projects::activate_elements(project_being_scanned); @@ -867,7 +881,7 @@ rather like a family tree for a minor European royal family.-void Projects::construct_graph(inform_project *proj) { +void Projects::construct_graph(inform_project *proj) { if (proj == NULL) return; if (proj->chosen_build_target == NULL) { Projects::finalise_kit_dependencies(proj); @@ -1038,7 +1052,7 @@ want the dependencies A ->-void Projects::graph_dependent_kit(inform_project *proj, +void Projects::graph_dependent_kit(inform_project *proj, build_vertex *V, kit_dependency *kd, int use) { build_vertex *KV = kd->kit->as_copy->vertex; if (use) Graphs::need_this_to_use(V, KV); @@ -1052,7 +1066,7 @@ want the dependencies A -> Projects::graph_dependent_kit(proj, KV, kd2, TRUE); } -void Projects::graph_dependent_language(inform_project *proj, +void Projects::graph_dependent_language(inform_project *proj, build_vertex *V, inform_language *L, int use) { build_vertex *LV = L->as_copy->vertex; if (use) Graphs::need_this_to_use(V, LV); @@ -1071,7 +1085,7 @@ each extension against the intersection of all requirements put on it:-void Projects::check_extension_versions(inform_project *proj) { +void Projects::check_extension_versions(inform_project *proj) { Projects::check_extension_versions_d(proj, proj->as_copy->vertex); } @@ -1121,7 +1135,7 @@ for the extensions they refer to, in a post-processing phase.-void Projects::read_source_text_for(inform_project *proj) { +void Projects::read_source_text_for(inform_project *proj) { inform_language *E = Languages::find_for(I"English", Projects::nest_list(proj)); if (E == NULL) return; Languages::read_Preform_definition(E, proj->search_list); @@ -1267,7 +1281,7 @@ source file of the project.enum BadTitleSentence_SYNERROR-void Projects::scan_bibliographic_data(inform_project *proj) { +void Projects::scan_bibliographic_data(inform_project *proj) { linked_list *L = Projects::source(proj); build_vertex *N; LOOP_OVER_LINKED_LIST(N, build_vertex, L) { diff --git a/inbuild/supervisor-module/Chapter 2/Copy Errors.w b/inbuild/supervisor-module/Chapter 2/Copy Errors.w index 2bf899e8c..8e9950478 100644 --- a/inbuild/supervisor-module/Chapter 2/Copy Errors.w +++ b/inbuild/supervisor-module/Chapter 2/Copy Errors.w @@ -18,6 +18,7 @@ fields are blank. @e EXT_BAD_DIRNAME_CE @e EXT_TITLE_TOO_LONG_CE @e EXT_AUTHOR_TOO_LONG_CE +@e LANGUAGE_UNAVAILABLE_CE @e LEXER_CE /* an error generated by the |words| module */ @e SYNTAX_CE /* an error generated by the |syntax| module, or by our reading of the tree */ @@ -135,6 +136,8 @@ void CopyErrors::write(OUTPUT_STREAM, copy_error *CE) { CE->details_N, MAX_EXTENSION_TITLE_LENGTH); break; case EXT_AUTHOR_TOO_LONG_CE: WRITE("author name too long: %d characters (max is %d)", CE->details_N, MAX_EXTENSION_AUTHOR_LENGTH); break; + case LANGUAGE_UNAVAILABLE_CE: WRITE("%S refers to an unavailable language: %S", + CE->copy->edition->work->genre->genre_name, CE->details); break; case LEXER_CE: @; break; case SYNTAX_CE: @ ; break; default: internal_error("an unknown error occurred"); diff --git a/inbuild/supervisor-module/Chapter 3/Inform7 Skill.w b/inbuild/supervisor-module/Chapter 3/Inform7 Skill.w index 0b71b5435..4d58ebdb7 100644 --- a/inbuild/supervisor-module/Chapter 3/Inform7 Skill.w +++ b/inbuild/supervisor-module/Chapter 3/Inform7 Skill.w @@ -31,6 +31,7 @@ int Inform7Skill::inform7_via_shell(build_skill *skill, build_step *S, LOOP_OVER_LINKED_LIST(N, inbuild_nest, L) { switch (Nests::get_tag(N)) { case MATERIALS_NEST_TAG: continue; + case EXTENSION_NEST_TAG: continue; case EXTERNAL_NEST_TAG: WRITE_TO(command, "-external "); break; case GENERIC_NEST_TAG: WRITE_TO(command, "-nest "); break; case INTERNAL_NEST_TAG: WRITE_TO(command, "-internal "); break; diff --git a/inbuild/supervisor-module/Chapter 5/Extension Services.w b/inbuild/supervisor-module/Chapter 5/Extension Services.w index c916d6052..71ddae546 100644 --- a/inbuild/supervisor-module/Chapter 5/Extension Services.w +++ b/inbuild/supervisor-module/Chapter 5/Extension Services.w @@ -34,6 +34,7 @@ typedef struct inform_extension { struct linked_list *activations; /* of |element_activation| */ struct linked_list *extensions; /* of |inbuild_requirement| */ struct linked_list *kits; /* of |inbuild_requirement| */ + struct inbuild_nest *materials_nest; CLASS_DEFINITION } inform_extension; @@ -87,6 +88,7 @@ void Extensions::scan(inbuild_copy *C) { E->activations = NEW_LINKED_LIST(element_activation); E->extensions = NEW_LINKED_LIST(inbuild_requirement); E->kits = NEW_LINKED_LIST(inbuild_requirement); + E->materials_nest = NULL; @ The following scans a potential extension file. If it seems malformed, a suitable error is written to the stream |error_text|. If not, this is left @@ -403,6 +405,15 @@ pathname *Extensions::materials_path(inform_extension *E) { return P; } +inbuild_nest *Extensions::materials_nest(inform_extension *E) { + pathname *P = Extensions::materials_path(E); + if ((E->materials_nest == NULL) && (P)) { + E->materials_nest = Nests::new(P); + Nests::set_tag(E->materials_nest, EXTENSION_NEST_TAG); + } + return E->materials_nest; +} + @h Cached metadata. The following data hides between runs in the //Dictionary//. @@ -533,8 +544,7 @@ void Extensions::activate_elements(inform_extension *E, inform_project *proj) { } } linked_list *L = NEW_LINKED_LIST(inbuild_nest); - inbuild_nest *N = Nests::new(Extensions::materials_path(E)); - N->tag_value = EXTENSION_NEST_TAG; + inbuild_nest *N = Extensions::materials_nest(E); ADD_TO_LINKED_LIST(N, inbuild_nest, L); inbuild_requirement *req; LOOP_OVER_LINKED_LIST(req, inbuild_requirement, E->kits) { diff --git a/inbuild/supervisor-module/Chapter 5/Language Services.w b/inbuild/supervisor-module/Chapter 5/Language Services.w index ee10548f2..a55b7ec9a 100644 --- a/inbuild/supervisor-module/Chapter 5/Language Services.w +++ b/inbuild/supervisor-module/Chapter 5/Language Services.w @@ -16,6 +16,7 @@ typedef struct inform_language { struct text_stream *iso_code; /* e.g., "fr" or "de" */ struct text_stream *translated_name; /* e.g., "Français" or "Deutsch" */ struct text_stream *native_cue; /* e.g., "en français" or "in deutscher Sprache" */ + struct inform_extension *belongs_to; /* if it does belong to an extension */ int adaptive_person; /* which person text substitutions are written from */ int Preform_loaded; /* has a Preform syntax definition been read for this? */ CLASS_DEFINITION @@ -41,6 +42,7 @@ void Languages::scan(inbuild_copy *C) { L->translated_name = I"English"; /* but not this one */ L->native_cue = NULL; + L->belongs_to = NULL; filename *about_file = Filenames::in(Languages::path_to_bundle(L), I"about.txt"); if (TextFiles::exists(about_file)) { @@ -170,6 +172,7 @@ void Languages::add_kit_dependencies_to_project(inform_language *L, inform_proje if (md == NULL) return; /* should never happen, but fail safe */ JSON_value *needs = JSON::look_up_object(md, I"needs"); if (needs == NULL) return; /* should never happen, but fail safe */ +WRITE_TO(STDERR, "add_kit_dependencies_to_project on %S\n", L->as_copy->edition->work->title); JSON_value *E; LOOP_OVER_LINKED_LIST(E, JSON_value, needs->if_list) { JSON_value *need_clause = JSON::look_up_object(E, I"need"); @@ -179,6 +182,7 @@ void Languages::add_kit_dependencies_to_project(inform_language *L, inform_proje JSON_value *need_version = JSON::look_up_object(need_clause, I"version"); if (Str::eq(need_type->if_string, I"kit")) { inbuild_work *work = Works::new_raw(kit_genre, need_title->if_string, I""); +WRITE_TO(STDERR, "and it needs %X\n", work); inbuild_requirement *req; if (need_version) req = Requirements::new(work, VersionNumberRanges::compatibility_range(VersionNumbers::from_text(need_version->if_string))); @@ -221,9 +225,42 @@ inform_language *Languages::Preform_find(text_stream *name) { = inform_language *Languages::find_for(text_stream *name, linked_list *search) { + text_stream *author = NULL; + match_results mr = Regexp::create_mr(); + if (Regexp::match(&mr, name, L"(%c+) [Ll]anguage by (%c+)")) { + name = mr.exp[0]; author = mr.exp[1]; + } else if (Regexp::match(&mr, name, L"(%c+) by (%c+)")) { + name = mr.exp[0]; author = mr.exp[1]; + } else if (Regexp::match(&mr, name, L"(%c+) [Ll]anguage")) { + name = mr.exp[0]; + } + TEMPORARY_TEXT(title) + WRITE_TO(title, "%S Language", name); + inbuild_requirement *extension_req = + Requirements::any_version_of(Works::new(extension_bundle_genre, title, author)); + inbuild_search_result *extension_R = Nests::search_for_best(extension_req, search); + DISCARD_TEXT(title) + if (extension_R) { + inform_extension *E = Extensions::from_copy(extension_R->copy); + inbuild_nest *N = Extensions::materials_nest(E); + if (N) { + linked_list *longer = NEW_LINKED_LIST(inbuild_nest); + ADD_TO_LINKED_LIST(N, inbuild_nest, longer); + inbuild_requirement *req = + Requirements::any_version_of(Works::new(language_genre, name, I"")); + inbuild_search_result *R = Nests::search_for_best(req, longer); + if (R) { + inform_language *L = LanguageManager::from_copy(R->copy); + L->belongs_to = E; + Regexp::dispose_of(&mr); + return L; + } + } + } inbuild_requirement *req = Requirements::any_version_of(Works::new(language_genre, name, I"")); inbuild_search_result *R = Nests::search_for_best(req, search); + Regexp::dispose_of(&mr); if (R) return LanguageManager::from_copy(R->copy); return NULL; } diff --git a/inbuild/supervisor-module/Chapter 5/Project Services.w b/inbuild/supervisor-module/Chapter 5/Project Services.w index 87a00c9e7..76ba745da 100644 --- a/inbuild/supervisor-module/Chapter 5/Project Services.w +++ b/inbuild/supervisor-module/Chapter 5/Project Services.w @@ -238,6 +238,14 @@ linked_list *Projects::nest_list(inform_project *proj) { return proj->search_list; } +void Projects::add_language_extension_nest(inform_project *proj) { + if ((proj->language_of_play) && (proj->language_of_play->belongs_to)) { + inform_extension *E = proj->language_of_play->belongs_to; + inbuild_nest *N = Extensions::materials_nest(E); + if (N) ADD_TO_LINKED_LIST(N, inbuild_nest, proj->search_list); + } +} + @ Since there are two ways projects can be stored: = @@ -405,6 +413,7 @@ void Projects::set_languages(inform_project *proj) { inform_language *L = Languages::find_for(name, Projects::nest_list(proj)); if (L) { proj->language_of_play = L; + Projects::add_language_extension_nest(proj); } else { build_vertex *RV = Graphs::req_vertex( Requirements::any_version_of(Works::new(language_genre, name, I""))); @@ -523,8 +532,13 @@ on //WorldModelKit//, through the if-this-then-that mechanism. if (LinkedLists::len(project->kits_to_include) > 0) no_word_from_JSON = FALSE; Projects::add_kit_dependency(project, I"BasicInformKit", NULL, NULL, NULL, NULL); inform_language *L = project->language_of_play; - if (L) Languages::add_kit_dependencies_to_project(L, project); - else internal_error("no language of play"); + if (L) { + Languages::add_kit_dependencies_to_project(L, project); + } else { + Copies::attach_error(project->as_copy, + CopyErrors::new_T(LANGUAGE_UNAVAILABLE_CE, -1, + project->name_of_language_of_play)); + } if ((no_word_from_JSON) && (forcible_basic_mode == FALSE)) Projects::add_kit_dependency(project, I"CommandParserKit", NULL, NULL, NULL, NULL); @@ -1183,7 +1197,7 @@ But not always: Regexp::dispose_of(&mr); } -@ = +@ = text_stream *language_name = mr.exp[0]; proj->name_of_language_of_play = Str::duplicate(language_name); diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt index a89325f11..cf6f4e986 100644 --- a/inform7/Figures/memory-diagnostics.txt +++ b/inform7/Figures/memory-diagnostics.txt @@ -1,19 +1,19 @@ -Total memory consumption was 121434K = 119 MB +Total memory consumption was 121647K = 119 MB - ---- was used for 2058109 objects, in 366643 frames in 0 x 800K = 0K = 0 MB: + ---- was used for 2061120 objects, in 368367 frames in 0 x 800K = 0K = 0 MB: - 33.6% inter_tree_node_array 58 x 8192 = 475136 objects, 41813824 bytes - 21.0% text_stream_array 4649 x 100 = 464900 objects, 26183168 bytes - 19.8% linked_list 44171 objects, 24735760 bytes + 33.5% inter_tree_node_array 58 x 8192 = 475136 objects, 41813824 bytes + 21.0% text_stream_array 4662 x 100 = 466200 objects, 26256384 bytes + 20.0% linked_list 44493 objects, 24916080 bytes 11.3% inter_symbol_array 133 x 1024 = 136192 objects, 14168224 bytes 10.7% inter_error_stash_array 102 x 1024 = 104448 objects, 13372608 bytes - 8.3% parse_node 130355 objects, 10428400 bytes + 8.3% parse_node 130371 objects, 10429680 bytes 6.1% verb_conjugation 164 objects, 7610912 bytes 4.4% parse_node_annotation_array 348 x 500 = 174000 objects, 5579136 bytes + 3.5% scan_directory 1076 objects, 4441728 bytes 2.7% pcalc_prop_array 25 x 1000 = 25000 objects, 3400800 bytes 2.5% inter_name_array 67 x 1000 = 67000 objects, 3218144 bytes 2.1% kind_array 67 x 1000 = 67000 objects, 2682144 bytes - 1.8% scan_directory 548 objects, 2262144 bytes 1.6% inter_name_generator_array 51 x 1000 = 51000 objects, 2041632 bytes 1.6% inter_schema_token 14043 objects, 2022192 bytes 1.4% package_request 21191 objects, 1864808 bytes @@ -36,7 +36,7 @@ Total memory consumption was 121434K = 119 MB 0.3% local_variable_array 47 x 100 = 4700 objects, 452704 bytes 0.3% verb_usage 1148 objects, 394912 bytes 0.2% rule 470 objects, 368480 bytes - 0.2% dictionary 7661 objects, 367728 bytes + 0.2% dictionary 7662 objects, 367776 bytes 0.2% verb_form 388 objects, 350752 bytes 0.2% noun 2389 objects, 286680 bytes 0.2% compilation_subtask 3367 objects, 269360 bytes @@ -66,8 +66,8 @@ Total memory consumption was 121434K = 119 MB ---- linked_list_item_array 4 x 1000 = 4000 objects, 64128 bytes ---- kind_macro_definition 9 objects, 62280 bytes ---- booking 861 objects, 61992 bytes - ---- scenes_rcd_data 1894 objects, 60608 bytes ---- actions_rcd_data 1894 objects, 60608 bytes + ---- scenes_rcd_data 1894 objects, 60608 bytes ---- kind_constructor 78 objects, 59280 bytes ---- command_grammar 130 objects, 58240 bytes ---- table 7 objects, 56672 bytes @@ -86,12 +86,15 @@ Total memory consumption was 121434K = 119 MB ---- shared_variable_access_list_array 12 x 100 = 1200 objects, 38784 bytes ---- parsing_data 677 objects, 37912 bytes ---- production_list 630 objects, 35280 bytes + ---- filename 881 objects, 35240 bytes ---- regions_data 677 objects, 32496 bytes ---- counting_data 677 objects, 32496 bytes ---- property_permission 96 objects, 31488 bytes ---- verb_sense 407 objects, 29304 bytes ---- stack_frame_box 305 objects, 29280 bytes + ---- parse_node_tree 33 objects, 28776 bytes ---- action_pattern_array 7 x 100 = 700 objects, 28224 bytes + ---- pathname 627 objects, 25080 bytes ---- shared_variable_set_array 6 x 100 = 600 objects, 24192 bytes ---- property 146 objects, 22192 bytes ---- backdrops_data 677 objects, 21664 bytes @@ -99,60 +102,57 @@ Total memory consumption was 121434K = 119 MB ---- nonlocal_variable 94 objects, 20304 bytes ---- pipeline_step 15 objects, 20280 bytes ---- action_name 90 objects, 20160 bytes - ---- filename 489 objects, 19560 bytes ---- timed_rules_rfd_data 401 objects, 19248 bytes ---- method 390 objects, 18720 bytes + ---- build_vertex 154 objects, 18480 bytes ---- pcalc_prop_deferral 86 objects, 17888 bytes ---- instance 167 objects, 17368 bytes ---- JSON_value 195 objects, 17160 bytes ---- to_phrase_request 62 objects, 16864 bytes - ---- build_vertex 138 objects, 16560 bytes - ---- pathname 403 objects, 16120 bytes ---- understanding_reference_array 2 x 100 = 200 objects, 16064 bytes ---- action_name_list_array 1 x 1000 objects, 16032 bytes ---- match_avinue_array 1 x 1000 objects, 16032 bytes ---- adjective 137 objects, 15344 bytes - ---- parse_node_tree 17 objects, 14824 bytes ---- booking_list 407 objects, 13024 bytes ---- adjective_iname_holder 320 objects, 12800 bytes ---- web_bibliographic_datum 174 objects, 11136 bytes ---- uniqueness_count 453 objects, 10872 bytes ---- inter_construct 30 objects, 10320 bytes + ---- heading_tree 33 objects, 10296 bytes ---- stopwatch_timer 120 objects, 9600 bytes + ---- inbuild_work 138 objects, 8832 bytes + ---- inbuild_copy 69 objects, 8280 bytes ---- equation_node 68 objects, 7616 bytes ---- understanding_item_array 3 x 100 = 300 objects, 7296 bytes + ---- inbuild_edition 101 objects, 7272 bytes ---- shared_variable_array 1 x 100 objects, 7232 bytes ---- determiner 22 objects, 7216 bytes ---- verb 109 objects, 6976 bytes ---- hierarchy_attachment_point 78 objects, 6864 bytes + ---- inform_extension 32 objects, 6656 bytes ---- text_literal_holder 163 objects, 6520 bytes - ---- inbuild_copy 53 objects, 6360 bytes - ---- inbuild_work 98 objects, 6272 bytes - ---- heading_tree 17 objects, 5304 bytes - ---- inbuild_edition 69 objects, 4968 bytes + ---- compatibility_specification 114 objects, 5472 bytes + ---- build_script 154 objects, 4928 bytes ---- explicit_action_array 1 x 100 objects, 4832 bytes ---- section_md 50 objects, 4800 bytes ---- activity 35 objects, 4760 bytes ---- value_property_data 84 objects, 4704 bytes ---- parsing_pp_data 96 objects, 4608 bytes - ---- build_script 138 objects, 4416 bytes ---- command_line_switch 51 objects, 4080 bytes - ---- compatibility_specification 80 objects, 3840 bytes + ---- semver_range 39 objects, 4056 bytes ---- parse_node_annotation_type 119 objects, 3808 bytes ---- submodule_request 85 objects, 3400 bytes ---- method_set 106 objects, 3392 bytes ---- property_setting_bp_data 84 objects, 3360 bytes ---- kind_constructor_comparison_schema_array 1 x 100 objects, 3232 bytes - ---- semver_range 31 objects, 3224 bytes - ---- inform_extension 16 objects, 3200 bytes ---- definition 44 objects, 3168 bytes ---- either_or_property_data 62 objects, 2976 bytes ---- target_vm 20 objects, 2880 bytes ---- use_option 29 objects, 2552 bytes ---- part_of_inference_data 79 objects, 2528 bytes ---- parentage_inference_data 79 objects, 2528 bytes - ---- kind_constructor_casting_rule_array 1 x 100 objects, 2432 bytes ---- kind_constructor_instance_array 1 x 100 objects, 2432 bytes + ---- kind_constructor_casting_rule_array 1 x 100 objects, 2432 bytes ---- equation_symbol 30 objects, 2400 bytes ---- scene 1 object, 2352 bytes ---- JSON_type 31 objects, 2232 bytes @@ -164,44 +164,45 @@ Total memory consumption was 121434K = 119 MB ---- inform_pipeline 24 objects, 1536 bytes ---- noun_filter_token 22 objects, 1408 bytes ---- inter_node_array 35 objects, 1400 bytes + ---- inbuild_requirement 35 objects, 1400 bytes ---- special_meaning_holder 35 objects, 1400 bytes ---- constant_phrase 20 objects, 1280 bytes ---- table_column 16 objects, 1280 bytes ---- invocation_options_array 1 x 100 objects, 1224 bytes ---- direction_inference_data 30 objects, 1200 bytes ---- JSON_requirement 36 objects, 1152 bytes + ---- inbuild_search_result 28 objects, 1120 bytes ---- tree_inventory_item 28 objects, 1120 bytes - ---- inbuild_requirement 27 objects, 1080 bytes ---- submodule_identity 33 objects, 1056 bytes ---- runtime_kind_structure 13 objects, 1040 bytes ---- quantifier 16 objects, 1024 bytes - ---- named_rulebook_outcome 15 objects, 960 bytes ---- pipeline_stage 20 objects, 960 bytes + ---- named_rulebook_outcome 15 objects, 960 bytes ---- control_structure_phrase 12 objects, 864 bytes ---- web_md 6 objects, 864 bytes ---- cached_understanding 21 objects, 840 bytes ---- JSON_pair_requirement 26 objects, 832 bytes ---- phrase_option_array 1 x 100 objects, 824 bytes - ---- inbuild_search_result 20 objects, 800 bytes ---- internal_test 15 objects, 720 bytes + ---- copy_error 6 objects, 672 bytes ---- relation_guard 5 objects, 640 bytes ---- inform_kit 6 objects, 624 bytes ---- implication 13 objects, 624 bytes ---- code_generation 1 object, 576 bytes - ---- generated_segment 14 objects, 560 bytes ---- inter_warehouse_room 10 objects, 560 bytes ---- inter_annotation_form 14 objects, 560 bytes + ---- generated_segment 14 objects, 560 bytes ---- rulebook_outcome 17 objects, 544 bytes - ---- chapter_md 6 objects, 528 bytes ---- small_word_set 11 objects, 528 bytes - ---- inform_language 6 objects, 480 bytes + ---- inform_language 6 objects, 528 bytes + ---- chapter_md 6 objects, 528 bytes ---- equation 4 objects, 480 bytes ---- module 6 objects, 480 bytes ---- i6_memory_setting 14 objects, 448 bytes ---- bp_family 14 objects, 448 bytes ---- inference_family 11 objects, 440 bytes - ---- article_usage 8 objects, 384 bytes ---- inbuild_genre 8 objects, 384 bytes + ---- article_usage 8 objects, 384 bytes ---- source_file 5 objects, 360 bytes ---- tree_inventory 1 object, 320 bytes ---- grammatical_category 8 objects, 320 bytes @@ -211,45 +212,45 @@ Total memory consumption was 121434K = 119 MB ---- module_request 8 objects, 320 bytes ---- inter_pipeline 1 object, 312 bytes ---- up_family 9 objects, 288 bytes - ---- compilation_unit 5 objects, 280 bytes - ---- explicit_bp_data 5 objects, 280 bytes - ---- contents_entry 7 objects, 280 bytes ---- door_to_notice 5 objects, 280 bytes - ---- inbuild_nest 7 objects, 280 bytes + ---- compilation_unit 5 objects, 280 bytes + ---- contents_entry 7 objects, 280 bytes + ---- explicit_bp_data 5 objects, 280 bytes ---- verb_usage_tier 5 objects, 240 bytes ---- adjective_meaning_family 7 objects, 224 bytes ---- inform_project 1 object, 224 bytes ---- test_scenario 1 object, 216 bytes ---- release_instructions 1 object, 208 bytes - ---- build_skill 5 objects, 200 bytes ---- code_generator 5 objects, 200 bytes - ---- plural_dictionary_entry 4 objects, 192 bytes - ---- kit_dependency 4 objects, 192 bytes + ---- build_skill 5 objects, 200 bytes ---- element_activation 6 objects, 192 bytes - ---- imperative_defn_family 4 objects, 160 bytes - ---- inter_architecture 4 objects, 160 bytes + ---- kit_dependency 4 objects, 192 bytes + ---- plural_dictionary_entry 4 objects, 192 bytes ---- attachment_instruction 4 objects, 160 bytes ---- inference_subject_family 5 objects, 160 bytes + ---- imperative_defn_family 4 objects, 160 bytes + ---- inter_architecture 4 objects, 160 bytes + ---- inbuild_nest 3 objects, 120 bytes ---- local_block_value 2 objects, 112 bytes ---- inform_kit_ittt 2 objects, 96 bytes - ---- article 2 objects, 80 bytes ---- compile_task_data 1 object, 80 bytes + ---- article 2 objects, 80 bytes ---- group_together_function 2 objects, 80 bytes - ---- figures_data 1 object, 56 bytes - ---- inter_warehouse 1 object, 56 bytes ---- build_methodology 1 object, 56 bytes + ---- inter_warehouse 1 object, 56 bytes + ---- figures_data 1 object, 56 bytes ---- star_invention 1 object, 48 bytes ---- HTML_file_state 1 object, 48 bytes - ---- kind_template_definition 1 object, 40 bytes + ---- loop_over_scope 1 object, 40 bytes ---- by_function_bp_data 1 object, 40 bytes ---- I6_generation_data 1 object, 40 bytes - ---- loop_over_scope 1 object, 40 bytes + ---- kind_template_definition 1 object, 40 bytes 100.0% was used for memory not allocated for objects: - 56.9% text stream storage 70764524 bytes in 482127 claims - 4.2% dictionary storage 5335040 bytes in 7661 claims - ---- sorting 1696 bytes in 183 claims + 56.9% text stream storage 70981100 bytes in 483534 claims + 4.2% dictionary storage 5335552 bytes in 7662 claims + ---- sorting 2720 bytes in 351 claims 5.7% source text 7200000 bytes in 3 claims 8.6% source text details 10800000 bytes in 2 claims 0.2% documentation fragments 262144 bytes in 1 claim @@ -257,7 +258,7 @@ Total memory consumption was 121434K = 119 MB ---- small word set array 105600 bytes in 22 claims 3.6% inter symbols storage 4562240 bytes in 28004 claims 13.4% inter bytecode storage 16767540 bytes in 14 claims - 5.0% inter links storage 6222976 bytes in 11 claims + 4.9% inter links storage 6222976 bytes in 11 claims 0.1% inter tree location list storage 191232 bytes in 32 claims 1.3% instance-of-kind counting 1731856 bytes in 1 claim ---- compilation workspace for objects 22136 bytes in 25 claims @@ -265,5 +266,5 @@ Total memory consumption was 121434K = 119 MB ---- code generation workspace for objects 3480 bytes in 19 claims 0.2% emitter array storage 280544 bytes in 2001 claims --150.-4% was overhead - -187098264 bytes = -182713K = -178 MB +-152.-2% was overhead - -189592632 bytes = -185149K = -180 MB diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index b1ac6a998..1b76a283c 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,25 +1,26 @@ 100.0% in inform7 run - 70.9% in compilation to Inter - 50.3% in //Sequence::undertake_queued_tasks// - 4.9% in //MajorNodes::pre_pass// + 69.9% in compilation to Inter + 49.5% in //Sequence::undertake_queued_tasks// + 4.7% in //MajorNodes::pre_pass// 3.3% in //MajorNodes::pass_1// 1.7% in //ImperativeDefinitions::assess_all// + 1.5% in //RTPhrasebook::compile_entries// 1.3% in //RTKindConstructors::compile// - 1.3% in //RTPhrasebook::compile_entries// - 1.1% in //Sequence::lint_inter// + 0.9% in //Sequence::lint_inter// + 0.5% in //ImperativeDefinitions::compile_first_block// 0.5% in //MajorNodes::pass_2// 0.5% in //Sequence::undertake_queued_tasks// 0.5% in //Sequence::undertake_queued_tasks// 0.5% in //World::stage_V// - 0.3% in //ImperativeDefinitions::compile_first_block// 0.1% in //CompletionModule::compile// 0.1% in //InferenceSubjects::emit_all// 0.1% in //RTKindConstructors::compile_permissions// 0.1% in //Task::make_built_in_kind_constructors// - 2.8% not specifically accounted for - 25.8% in running Inter pipeline - 10.1% in step 14/15: generate inform6 -> auto.inf - 5.7% in step 5/15: load-binary-kits + 0.1% in //World::stages_II_and_III// + 2.6% not specifically accounted for + 26.4% in running Inter pipeline + 10.3% in step 14/15: generate inform6 -> auto.inf + 5.9% in step 5/15: load-binary-kits 5.3% in step 6/15: make-synoptic-module 1.7% in step 9/15: make-identifiers-unique 0.3% in step 12/15: eliminate-redundant-operations @@ -27,6 +28,6 @@ 0.3% in step 7/15: shorten-wiring 0.3% in step 8/15: detect-indirect-calls 0.1% in step 11/15: eliminate-redundant-labels - 0.9% not specifically accounted for - 2.5% in supervisor - 0.6% not specifically accounted for + 1.2% not specifically accounted for + 3.1% in supervisor + 0.4% not specifically accounted for diff --git a/inform7/Internal/Inter/BasicInformExtrasKit/kit_metadata.json b/inform7/Internal/Inter/BasicInformExtrasKit/kit_metadata.json index 739372b65..461e4faed 100644 --- a/inform7/Internal/Inter/BasicInformExtrasKit/kit_metadata.json +++ b/inform7/Internal/Inter/BasicInformExtrasKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "BasicInformExtrasKit", - "version": "10.2.0-beta+6W19" + "version": "10.2.0-beta+6W20" }, "kit-details": { "has-priority": 1 diff --git a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json index 0471bb72b..84d4024fb 100644 --- a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json +++ b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "BasicInformKit", - "version": "10.2.0-beta+6W19" + "version": "10.2.0-beta+6W20" }, "needs": [ { "unless": { diff --git a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json index eaa6cc726..784729a88 100644 --- a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json +++ b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "CommandParserKit", - "version": "10.2.0-beta+6W19" + "version": "10.2.0-beta+6W20" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json index 5f5b85a37..7c7628f12 100644 --- a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json +++ b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "EnglishLanguageKit", - "version": "10.2.0-beta+6W19" + "version": "10.2.0-beta+6W20" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json index 5478b7722..8c14974c2 100644 --- a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json +++ b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "WorldModelKit", - "version": "10.2.0-beta+6W19" + "version": "10.2.0-beta+6W20" }, "needs": [ { "need": { diff --git a/inform7/core-module/Chapter 2/Problems With Source Text.w b/inform7/core-module/Chapter 2/Problems With Source Text.w index 774861055..0f0c79e18 100644 --- a/inform7/core-module/Chapter 2/Problems With Source Text.w +++ b/inform7/core-module/Chapter 2/Problems With Source Text.w @@ -47,7 +47,7 @@ void SourceProblems::issue_problems_arising(inbuild_copy *C) { if (CE->copy->found_by) { Problems::quote_work(1, CE->copy->found_by->work); Problems::quote_stream(2, CE->details); - Problems::quote_stream(3, CE->copy->edition->work->genre->genre_name); + SourceProblems::quote_genre(3, CE); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(Untestable)); Problems::issue_problem_segment( "The %3 %1, which your source text makes use of, seems to have " @@ -56,13 +56,23 @@ void SourceProblems::issue_problems_arising(inbuild_copy *C) { } else { Problems::quote_work(1, CE->copy->edition->work); Problems::quote_stream(2, CE->details); - Problems::quote_stream(3, CE->copy->edition->work->genre->genre_name); + SourceProblems::quote_genre(3, CE); StandardProblems::handmade_problem(Task::syntax_tree(), _p_(Untestable)); Problems::issue_problem_segment( "The %3 %1 seems to have metadata problems. Specifically: %2."); Problems::issue_problem_end(); } break; + case LANGUAGE_UNAVAILABLE_CE: + Problems::quote_work(1, CE->copy->edition->work); + Problems::quote_stream(2, CE->details); + SourceProblems::quote_genre(3, CE); + StandardProblems::handmade_problem(Task::syntax_tree(), _p_(Untestable)); + Problems::issue_problem_segment( + "The %3 %1 seems to need me to know about a non-English language, '%2'. " + "I can't find any definition for this language."); + Problems::issue_problem_end(); + break; case EXT_TITLE_TOO_LONG_CE: { int max = MAX_EXTENSION_TITLE_LENGTH; int overage = CE->details_N - MAX_EXTENSION_TITLE_LENGTH; @@ -547,3 +557,11 @@ void SourceProblems::issue_problems_arising(inbuild_copy *C) { } } } + +void SourceProblems::quote_genre(int N, copy_error *CE) { + text_stream *name = CE->copy->edition->work->genre->genre_name; + if (Str::eq(name, I"projectbundle")) name = I"project"; + if (Str::eq(name, I"projectfile")) name = I"project"; + if (Str::eq(name, I"extensionbundle")) name = I"extension"; + Problems::quote_stream(N, name); +} diff --git a/inform7/if-module/Chapter 2/The Blurb File.w b/inform7/if-module/Chapter 2/The Blurb File.w index c424a06f7..872a95594 100644 --- a/inform7/if-module/Chapter 2/The Blurb File.w +++ b/inform7/if-module/Chapter 2/The Blurb File.w @@ -242,13 +242,25 @@ file online. WRITE("website \"%w\"\n", rel->website_template_leafname); @ The order here is significant, since Inblorb searches the folders in order, -with the earliest quoted searched first. +with the earliest quoted searched first. We want first the materials folder for +a project, then the |Templates| directory in the materials for extensions +included by the project, and then the external area, and finally the internal. @ = inbuild_nest *N; linked_list *L = Projects::nest_list(Task::project()); - LOOP_OVER_LINKED_LIST(N, inbuild_nest, L) + LOOP_OVER_LINKED_LIST(N, inbuild_nest, L) { WRITE("template path \"%p\"\n", TemplateManager::path_within_nest(N)); + if (Nests::get_tag(N) == MATERIALS_NEST_TAG) { + inform_extension *E; + LOOP_OVER_LINKED_LIST(E, inform_extension, Task::project()->extensions_included) { + pathname *P = Extensions::materials_path(E); + if (P) { + WRITE("template path \"%p\"\n", TemplateManager::path_within_nest(Nests::new(P))); + } + } + } + } @ 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 diff --git a/inform7/multimedia-module/Chapter 2/Resource Finder.w b/inform7/multimedia-module/Chapter 2/Resource Finder.w index a2f7e67dc..2f0e274d2 100644 --- a/inform7/multimedia-module/Chapter 2/Resource Finder.w +++ b/inform7/multimedia-module/Chapter 2/Resource Finder.w @@ -6,12 +6,13 @@ To find resources such as sound and image files. This simple function is shared by the code for figures, sound effects and internal data files. When Inform reads a sentence such as: = (text as Inform 7) - Sound of Organ is the file "Passacaglia.mid". + Sound of Organ is the file "Passacaglia.aiff". = -it looks for the file first in the |Sounds| folder of the materials for the -project, and then, if it isn't there, in the |Sounds| folder of the materials -for the extension in which the sentence occurs (if it occurs in an extension). -Here |"Sounds"| is what we will call the department name for sound effects. +it needs to find this file, which will either be in the materials for the +project, or in materials for the extension in which this sentence occurs +(if it occurs in an extension). In either case, it'll be in the |Sounds| +subdirectory. Here |"Sounds"| is what we will call the department name for +sound effects. This code was introduced as part of the implementation of IE-0001, and for the first time throws problem messages is named resources do not exist. @@ -28,29 +29,10 @@ filename *ResourceFinder::find_resource(text_stream *department, text_stream *le if (Wordings::nonempty(W)) E = Extensions::corresponding_to(Lexer::file_of_origin(Wordings::first_wn(W))); - pathname *P1 = Pathnames::down(Task::resources_path(), department); - pathname *P2 = E?(Pathnames::down(Extensions::materials_path(E), department)):NULL; - if (P1) { - filename *F = Filenames::in(P1, leaf); - FILE *HANDLE = Filenames::fopen(F, "rb"); - if (HANDLE) { - fclose(HANDLE); - return F; - } - } - if (P2) { - filename *F = Filenames::in(P2, leaf); - FILE *HANDLE = Filenames::fopen(F, "rb"); - if (HANDLE) { - fclose(HANDLE); - return F; - } - } - - if (check_resources_are_present == FALSE) return Filenames::in(P1, leaf); - - LOG("Tried in %p\n", P1); - if (P2) LOG("And also in %p\n", P2); + pathname *materials_dept = Pathnames::down(Task::resources_path(), department); + pathname *extension_dept = E?(Pathnames::down(Extensions::materials_path(E), department)):NULL; + if (extension_dept) @ ; + if (materials_dept) @ ; Problems::quote_source(1, current_sentence); Problems::quote_wording(2, W); @@ -59,7 +41,7 @@ filename *ResourceFinder::find_resource(text_stream *department, text_stream *le Problems::issue_problem_segment( "You wrote %1, which means I am looking for a file called %2, but I'm " "unable to find it. "); - if (P2) + if (extension_dept) Problems::issue_problem_segment( "The file should either be in the '%3' subfolder of the materials folder, " "or in the 'Materials/%3' subfolder of this extension."); @@ -69,3 +51,43 @@ filename *ResourceFinder::find_resource(text_stream *department, text_stream *le Problems::issue_problem_end(); return NULL; } + +@ So here we're reading the line from an extension, say |Leipzig Organ Recitals|. +We first look for an audio file called something like +|Leipzig Organ Recitals-v1/Materials/Sounds/Passacaglia.aiff|. If that exists, then we +know this is a resource which the extension provides; but we still give the +project a chance to override that with a file +|Project.materials/Sounds/Leipzig Organ Recitals/Passacaglia.aiff|, +which would be used in preference. + +@ = + filename *F = ResourceFinder::if_present(Filenames::in(extension_dept, leaf)); + if (F) { + pathname *materials_override = + Pathnames::down(materials_dept, E->as_copy->edition->work->title); + filename *OF = ResourceFinder::if_present(Filenames::in(materials_override, leaf)); + if (OF) return OF; + return F; + } + +@ Otherwise the resource is not provided by the extension in which the sentence +occurs, or else, the sentence does not occur in an extension. (Of course, this is +by far the most likely thing.) Here we just look in the project's materials folder, +so for example |Project.materials/Sounds/Passacaglia.aiff|. + +@ = + filename *F = Filenames::in(materials_dept, leaf); + if (check_resources_are_present == FALSE) return F; + F = ResourceFinder::if_present(F); + if (F) return F; + +@ This checks the existence of such a file on disc. We're not going to fret +over the possibility of accidentally opening a directory here. + += +filename *ResourceFinder::if_present(filename *F) { + FILE *handle = Filenames::fopen(F, "rb"); + if (handle == NULL) return NULL; + fclose(handle); + return F; +}