diff --git a/docs/core-module/1-htc.html b/docs/core-module/1-htc.html
index 5a9d7ed42..25cdb670a 100644
--- a/docs/core-module/1-htc.html
+++ b/docs/core-module/1-htc.html
@@ -325,7 +325,7 @@ so on. Those absolute basics are made here.
BENCH(Phrases::Manager::rulebooks_array)BENCH_IF(scenes_plugin, PL::Scenes::DetectSceneChange_routine)BENCH_IF(scenes_plugin, PL::Scenes::ShowSceneStatus_routine)
-BENCH(ExternalFiles::arrays)
+BENCH(RTExternalFiles::arrays)BENCH(Rulebooks::rulebook_var_creators)BENCH(Activities::activity_var_creators)BENCH(RTRelations::IterateRelations)
diff --git a/docs/index-module/2-ifs.html b/docs/index-module/2-ifs.html
index a33f3bf84..77bc34a1c 100644
--- a/docs/index-module/2-ifs.html
+++ b/docs/index-module/2-ifs.html
@@ -758,7 +758,7 @@ to show, hide and colour things:
#ifdefMULTIMEDIA_MODULEIXFigures::index_all(OUT);IXSounds::index_all(OUT);
-ExternalFiles::index_all(OUT);
+IXExternalFiles::index_all(OUT); #endifreturn; }
@@ -943,7 +943,7 @@ the source text in the application.
diff --git a/docs/multimedia-module/1-mm.html b/docs/multimedia-module/1-mm.html
index 21ab1c4e7..6e8e1f36a 100644
--- a/docs/multimedia-module/1-mm.html
+++ b/docs/multimedia-module/1-mm.html
@@ -71,42 +71,35 @@ which use this module:
defineMULTIMEDIA_MODULETRUE
-
§2. This module defines the following classes:
+
§2. Like all modules, this one must define a start and end function:
§1. The test group :files exercises the features below.
+
§1. The test group :files exercises the features in this plugin.
-
§2. Each file can be text or binary, has a name, and can be owned by a this
-project, by an unspecified other project, or by a project named by IFID.
-
-typedefstructexternal_file {
-structwordingname; text of name
-intunextended_filename; word number of text like "bones"
-structtext_stream *exf_I6_identifier; an I6 identifier
-intfile_is_binary; true or false
-intfile_ownership; one of the above
-structtext_stream *IFID_of_owner; an I6 identifier
-structinter_name *exf_iname;
-structinter_name *IFID_array_iname;
-CLASS_DEFINITION
-} external_file;
-
-
The structure external_file is accessed in 2/fgr, 2/se and here.
-
§3. A --> array to a run-time data structure associated
-with an external file, read or written by the story file during play.
+
§3. And this is the Preform grammar needed for the subject phrase:
@@ -180,10 +138,10 @@ with an external file, read or written by the story file during play.
<external-file-owner>::=anotherproject|==> { FALSE, - }project{<quoted-text-without-subs>}|==> { TRUE, - }
-...==>Issue PM_BadFileOwner problem7.1
+...==>Issue PM_BadFileOwner problem3.1
§4. The object phrase is simply quoted text. Although the Preform grammar doesn't
go into this level of detail, it's actually required to have 3 to 23 English
letters or digits, with the first being a letter.
@@ -209,23 +167,8 @@ letters or digits, with the first being a letter.
-StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_FilenameNotTextual),
-"a file can only be called with a single quoted piece of text",
-"as in: 'The File of Wisdom is called \"wisdom\".'");
- ==> { -1, - };
-
§9. This handles the special meaning "File... is the file...".
-
-
-
<new-file-sentence-object>::=<indefinite-article><new-file-sentence-object-unarticled>|==> { pass 2 }<new-file-sentence-object-unarticled>==> { pass 1 }
@@ -237,38 +180,46 @@ letters or digits, with the first being a letter.
<external-file-sentence-subject>==> { 0, Diagrams::new_UNPARSED_NOUN(W) }
§5.1. The restrictions here are really very conservative.
+
+
+
Vet the filename5.1 =
+
+
+
+intbad_filename = FALSE;if (Wide::len(p) < 5) bad_filename = TRUE;if (Characters::isalpha(p[1]) == FALSE) bad_filename = TRUE;for (inti=0; p[i]; i++) {
@@ -291,13 +242,24 @@ letters or digits, with the first being a letter.
"automatically: this is invisible to Inform.)");return; }
+
§5.2. Each file can be text or binary, has a name, and can be owned by this project,
+by an unspecified other project, or by a project identified by its IFID.
+
+if (<external-file-sentence-subject>(W) == FALSE) internal_error("bad ef grammar");
+binary = <<r>>;
+W = GET_RW(<external-file-name>, 1);
+Make sure W can be the name of a new file anyway5.2.1;if (<<ownership>> == TRUE) {wordingOW = GET_RW(<external-file-owner>, 1);intj, invalid = FALSE;
@@ -310,152 +272,106 @@ letters or digits, with the first being a letter.
invalid = TRUE;LOG("Objected to character %c\n", p[j]); }
-if ((invalid) || (j==47)) {
+if ((invalid) || (j==47))StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_BadFileIFID),"the owner of the file should be specified ""using a valid double-quoted IFID","as in: 'The File of Wisdom (owned by project ""\"4122DDA8-A153-46BC-8F57-42220F9D8795\") ""is called \"wisdom\".'");
- } else
+elseownership = OWNED_BY_SPECIFIC_PROJECT; }
-if (<<ownership>> == FALSE) {
-ownership = OWNED_BY_ANOTHER_PROJECT;
- }
+if (<<ownership>> == FALSE) ownership = OWNED_BY_ANOTHER_PROJECT;
+
+Assertions::Creator::vet_name_for_noun(W);
+if ((<s-value>(W)) && (Rvalues::is_CONSTANT_of_kind(<<rp>>, K_external_file))) {StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_FilenameDuplicate),"this is already the name of a file","so there must be some duplication somewhere.");return; }
+
§11. I6 arrays of file structures. External files are written in I6 as their array names:
+
§8. Significant new instances. This structure of additional data is attached to each figure instance.
-voidExternalFiles::arrays(void) {
-if (PluginManager::active(files_plugin) == FALSE) return;
-
-inter_name *iname = Hierarchy::find(NO_EXTERNAL_FILES_HL);
-Emit::named_numeric_constant(iname, (inter_ti) (NUMBER_CREATED(external_file)));
-Hierarchy::make_available(Emit::tree(), iname);
-
-external_file *exf;
-LOOP_OVER(exf, external_file) {
-if (exf->file_ownership == OWNED_BY_SPECIFIC_PROJECT) {
-packaging_statesave = Emit::named_string_array_begin(exf->IFID_array_iname, K_value);
-TEMPORARY_TEXT(II)
-WRITE_TO(II, "//%S", exf->IFID_of_owner);
- Emit::array_text_entry(II);
- DISCARD_TEXT(II)
- Emit::array_end(save);
- }
- }
-
- LOOP_OVER(exf, external_file) {
- packaging_state save = Emit::named_array_begin(exf->exf_iname, K_value);
- Emit::array_iname_entry(Hierarchy::find(AUXF_MAGIC_VALUE_HL));
- Emit::array_iname_entry(Hierarchy::find(AUXF_STATUS_IS_CLOSED_HL));
- if (exf->file_is_binary) Emit::array_numeric_entry(1);
- else Emit::array_numeric_entry(0);
- Emit::array_numeric_entry(0);
- TEMPORARY_TEXT(WW)
- WRITE_TO(WW, "%w", Lexer::word_raw_text(exf->unextended_filename));
- Str::delete_first_character(WW);
- Str::delete_last_character(WW);
- Emit::array_text_entry(WW);
- DISCARD_TEXT(WW)
- switch (exf->file_ownership) {
- case OWNED_BY_THIS_PROJECT: Emit::array_iname_entry(PL::Bibliographic::IFID::UUID()); break;
- case OWNED_BY_ANOTHER_PROJECT: Emit::array_null_entry(); break;
- case OWNED_BY_SPECIFIC_PROJECT: Emit::array_iname_entry(exf->IFID_array_iname); break;
- }
- Emit::array_end(save);
- }
-
- iname = Hierarchy::find(TABLEOFEXTERNALFILES_HL);
- packaging_state save = Emit::named_array_begin(iname, K_value);
- Emit::array_numeric_entry(0);
- LOOP_OVER(exf, external_file) Emit::array_iname_entry(exf->exf_iname);
- Emit::array_numeric_entry(0);
- Emit::array_end(save);
- Hierarchy::make_available(Emit::tree(), iname);
-}
+typedefstructfiles_data {
+structwordingname; text of name
+intunextended_filename; word number of text like "bones"
+structtext_stream *exf_identifier; an Inter identifier
+intfile_is_binary; true or false
+intfile_ownership; one of the OWNED_BY_* values above
+structtext_stream *IFID_of_owner; if we know that
+structexternal_file_compilation_datacompilation_data;
+CLASS_DEFINITION
+} files_data;
-
§12. External Files Index. More or less perfunctory, but still of some use, if only as a list.
+
The structure files_data is accessed in 2/fgr, 2/se and here.
+
§9. We allow instances of "external file" to be created only through the above
+code calling Figures::figures_create. If any other proposition somehow
+manages to make a figure, a problem message is thrown.
§1. Prerequisites. The knowledge module is a part of the Inform compiler toolset. It is
+presented as a literate program or "web". Before diving in:
+
+
+
(a) It helps to have some experience of reading webs: see inweb for more.
+
(b) The module is written in C, in fact ANSI C99, but this is disguised by the
+fact that it uses some extension syntaxes provided by the inweb literate
+programming tool, making it a dialect of C called InC. See inweb for
+full details, but essentially: it's C without predeclarations or header files,
+and where functions have names like Tags::add_by_name rather than just add_by_name.
+
Three plugins enabling Inform-written works of IF to make use of multimedia features of the Glulx virtual machine.
diff --git a/docs/runtime-module/2-emt.html b/docs/runtime-module/2-emt.html
index 2cdf8e93c..75fab6ed2 100644
--- a/docs/runtime-module/2-emt.html
+++ b/docs/runtime-module/2-emt.html
@@ -84,7 +84,7 @@ function togglePopup(material_id) {
inter_tree *I7_generation_tree = NULL;
-inter_tree *Emit::tree(void) {
+inter_tree *Emit::tree(void) {returnI7_generation_tree;}
@@ -349,7 +349,7 @@ insert them into the Inter stream close to the top.
Packaging::exit(Emit::tree(), save);}
-inter_name *Emit::named_numeric_constant(inter_name *name, inter_tival) {
+inter_name *Emit::named_numeric_constant(inter_name *name, inter_tival) {packaging_statesave = Packaging::enter_home_of(name);inter_symbol *con_name = Produce::define_symbol(name);Produce::guard(Inter::Constant::new_numerical(Packaging::at(Emit::tree()), Inter::SymbolsTables::id_from_IRS_and_symbol(Packaging::at(Emit::tree()), con_name), Inter::SymbolsTables::id_from_IRS_and_symbol(Packaging::at(Emit::tree()), int_interk), LITERAL_IVAL, val, Produce::baseline(Packaging::at(Emit::tree())), NULL));
@@ -405,7 +405,7 @@ insert them into the Inter stream close to the top.
returnsave;}
-packaging_stateEmit::named_string_array_begin(inter_name *name, kind *K) {
+packaging_stateEmit::named_string_array_begin(inter_name *name, kind *K) {packaging_statesave = Emit::named_array_begin(name, K);Produce::annotate_iname_i(name, STRINGARRAY_IANN, 1);returnsave;
@@ -496,13 +496,13 @@ insert them into the Inter stream close to the top.
current_A->no_entries++;}
-packaging_stateEmit::sum_constant_begin(inter_name *name, kind *K) {
+packaging_stateEmit::sum_constant_begin(inter_name *name, kind *K) {packaging_statesave = Emit::named_array_begin(name, K);current_A->array_form = CONSTANT_SUM_LIST;returnsave;}
-packaging_stateEmit::named_array_begin(inter_name *N, kind *K) {
+packaging_stateEmit::named_array_begin(inter_name *N, kind *K) {packaging_statesave = Packaging::enter_home_of(N);inter_symbol *symb = Produce::define_symbol(N);Emit::push_array();
@@ -512,7 +512,7 @@ insert them into the Inter stream close to the top.
returnsave;}
-voidEmit::array_iname_entry(inter_name *iname) {
+voidEmit::array_iname_entry(inter_name *iname) {if (current_A == NULL) internal_error("entry outside of inter array");inter_symbol *alias;if (iname == NULL) alias = Site::veneer_symbol(Emit::tree(), NOTHING_VSYMB);
@@ -523,15 +523,15 @@ insert them into the Inter stream close to the top.
Emit::add_entry(val1, val2);}
-voidEmit::array_null_entry(void) {
+voidEmit::array_null_entry(void) {Emit::array_iname_entry(Hierarchy::find(NULL_HL));}
-voidEmit::array_MPN_entry(void) {
+voidEmit::array_MPN_entry(void) {Emit::array_iname_entry(Hierarchy::find(MAX_POSITIVE_NUMBER_HL));}
-voidEmit::array_generic_entry(inter_tival1, inter_tival2) {
+voidEmit::array_generic_entry(inter_tival1, inter_tival2) {if (current_A == NULL) internal_error("entry outside of inter array");Emit::add_entry(val1, val2);}
@@ -547,7 +547,7 @@ insert them into the Inter stream close to the top.
}#endif
-voidEmit::array_text_entry(text_stream *content) {
+voidEmit::array_text_entry(text_stream *content) {if (current_A == NULL) internal_error("entry outside of inter array");inter_tiv1 = 0, v2 = 0;Produce::text_value(Emit::tree(), &v1, &v2, content);
@@ -568,7 +568,7 @@ insert them into the Inter stream close to the top.
Emit::add_entry(v1, v2);}
-voidEmit::array_numeric_entry(inter_tiN) {
+voidEmit::array_numeric_entry(inter_tiN) {if (current_A == NULL) internal_error("entry outside of inter array");Emit::add_entry(LITERAL_IVAL, N);}
@@ -586,7 +586,7 @@ insert them into the Inter stream close to the top.
returnIBM;}
-voidEmit::array_end(packaging_statesave) {
+voidEmit::array_end(packaging_statesave) {if (current_A == NULL) internal_error("inter array not opened");inter_symbol *con_name = current_A->array_name_symbol;inter_bookmark *IBM = Packaging::at(Emit::tree());
@@ -617,7 +617,7 @@ insert them into the Inter stream close to the top.
Packaging::exit(Emit::tree(), save);}
-inter_name *Emit::named_iname_constant(inter_name *name, kind *K, inter_name *iname) {
+inter_name *Emit::named_iname_constant(inter_name *name, kind *K, inter_name *iname) {packaging_statesave = Packaging::enter_home_of(name);inter_symbol *con_name = Produce::define_symbol(name);inter_symbol *val_kind = Produce::kind_to_symbol(K);
@@ -633,7 +633,7 @@ insert them into the Inter stream close to the top.
returnname;}
-inter_name *Emit::named_numeric_constant_hex(inter_name *name, inter_tival) {
+inter_name *Emit::named_numeric_constant_hex(inter_name *name, inter_tival) {packaging_statesave = Packaging::enter_home_of(name);inter_symbol *con_name = Produce::define_symbol(name);Produce::annotate_symbol_i(con_name, HEX_IANN, 0);
@@ -642,7 +642,7 @@ insert them into the Inter stream close to the top.
returnname;}
-inter_name *Emit::named_unchecked_constant_hex(inter_name *name, inter_tival) {
+inter_name *Emit::named_unchecked_constant_hex(inter_name *name, inter_tival) {packaging_statesave = Packaging::enter_home_of(name);inter_symbol *con_name = Produce::define_symbol(name);Produce::annotate_symbol_i(con_name, HEX_IANN, 0);
@@ -651,7 +651,7 @@ insert them into the Inter stream close to the top.
returnname;}
-inter_name *Emit::named_numeric_constant_signed(inter_name *name, intval) {
+inter_name *Emit::named_numeric_constant_signed(inter_name *name, intval) {packaging_statesave = Packaging::enter_home_of(name);inter_symbol *con_name = Produce::define_symbol(name);Produce::annotate_symbol_i(con_name, SIGNED_IANN, 0);
@@ -667,7 +667,7 @@ insert them into the Inter stream close to the top.
*/}
-voidEmit::code_comment(text_stream *text) {
+voidEmit::code_comment(text_stream *text) { inter_ti ID = Inter::Warehouse::create_text(Inter::Tree::warehouse(Emit::tree()), Inter::Bookmarks::package(Packaging::at(Emit::tree())));Str::copy(Inter::Warehouse::get_text(Inter::Tree::warehouse(Emit::tree()), ID), text);Produce::guard(Inter::Comment::new(Produce::at(Emit::tree()), (inter_ti) Produce::level(Emit::tree()), NULL, ID));
@@ -675,7 +675,7 @@ insert them into the Inter stream close to the top.
}
-voidEmit::routine(inter_name *rname, kind *rkind, inter_package *block) {
+voidEmit::routine(inter_name *rname, kind *rkind, inter_package *block) {if (Packaging::at(Emit::tree()) == NULL) internal_error("no inter repository");inter_symbol *AB_symbol = Produce::kind_to_symbol(rkind);inter_symbol *rsymb = Produce::define_symbol(rname);
@@ -686,7 +686,7 @@ insert them into the Inter stream close to the top.
Produce::baseline(Packaging::at(Emit::tree())), NULL));}
-inter_symbol *Emit::local(kind *K, text_stream *lname, inter_tiannot, text_stream *comm) {
+inter_symbol *Emit::local(kind *K, text_stream *lname, inter_tiannot, text_stream *comm) {if (Site::get_cir(Emit::tree()) == NULL) internal_error("not in an inter routine");if (K == NULL) K = K_number;inter_symbol *loc_name = Produce::new_local_symbol(Site::get_cir(Emit::tree()), lname);
@@ -702,13 +702,13 @@ insert them into the Inter stream close to the top.
returnloc_name;}
-voidEmit::cast(kind *F, kind *T) {
+voidEmit::cast(kind *F, kind *T) {inter_symbol *from_kind = Produce::kind_to_symbol(F);inter_symbol *to_kind = Produce::kind_to_symbol(T);Produce::guard(Inter::Cast::new(Produce::at(Emit::tree()), from_kind, to_kind, (inter_ti) Produce::level(Emit::tree()), NULL));}
-voidEmit::intervention(intstage, text_stream *segment, text_stream *part, text_stream *i6, text_stream *seg) {
+voidEmit::intervention(intstage, text_stream *segment, text_stream *part, text_stream *i6, text_stream *seg) {inter_warehouse *warehouse = Inter::Tree::warehouse(Emit::tree());inter_tiID1 = Inter::Warehouse::create_text(warehouse, Inter::Bookmarks::package(Packaging::at(Emit::tree())));Str::copy(Inter::Warehouse::get_text(Inter::Tree::warehouse(Emit::tree()), ID1), segment);
@@ -736,12 +736,12 @@ insert them into the Inter stream close to the top.