diff --git a/inbuild/Chapter 1/Main.w b/inbuild/Chapter 1/Main.w index 4d16127c8..1a8a17d4b 100644 --- a/inbuild/Chapter 1/Main.w +++ b/inbuild/Chapter 1/Main.w @@ -1,7 +1,7 @@ [Main::] Main. -The top level, which decides what is to be done and then carries -this plan out. +A command-line interface for Inbuild functions which are not part of the +normal operation of the Inform compiler. @h Main routine. @@ -39,6 +39,7 @@ int main(int argc, char **argv) { InbuildModule::start(); targets = NEW_LINKED_LIST(inbuild_copy); @; + @; if (Str::len(unit_test) > 0) dry_run_mode = TRUE; int use = SHELL_METHODOLOGY; @@ -97,7 +98,64 @@ int main(int argc, char **argv) { return 0; } -@ We use Foundation to read the command line: +@ = + if (LinkedLists::len(unsorted_nest_list) == 0) + Inbuild::add_nest( + Pathnames::from_text(I"inform7/Internal"), INTERNAL_NEST_TAG); + + path_to_inbuild = Pathnames::installation_path("INBUILD_PATH", I"inbuild"); + pathname *P = Pathnames::subfolder(path_to_inbuild, I"Tangled"); + filename *S = Filenames::in_folder(P, I"Syntax.preform"); + wording W = Preform::load_from_file(S); + Preform::parse_preform(W, FALSE); + + CommandLine::play_back_log(); + inbuild_copy *proj = NULL, *C; + LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) + if (C->edition->work->genre == project_bundle_genre) { + if (Str::len(project_bundle_request) > 0) + Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title); + else if (proj) Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title); + else proj = C; + } + + proj = Inbuild::optioneering_complete(proj, FALSE); + if (proj) { + int found = FALSE; + LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) + if (C == proj) + found = TRUE; + if (found == FALSE) ADD_TO_LINKED_LIST(proj, inbuild_copy, targets); + } + inbuild_nest_list = Inbuild::nest_list(); + Inbuild::go_operational(); + +@ = +void Main::load_many(pathname *P) { + scan_directory *D = Directories::open(P); + TEMPORARY_TEXT(LEAFNAME); + while (Directories::next(D, LEAFNAME)) { + TEMPORARY_TEXT(FILENAME); + WRITE_TO(FILENAME, "%p%c%S", P, FOLDER_SEPARATOR, LEAFNAME); + Main::load_one(FILENAME, FALSE); + DISCARD_TEXT(FILENAME); + } + DISCARD_TEXT(LEAFNAME); + Directories::close(D); +} + +void Main::load_one(text_stream *arg, int throwing_error) { + inbuild_copy *C = Copies::claim(arg); + if (C == NULL) { + if (throwing_error) Errors::with_text("unable to identify '%S'", arg); + return; + } + ADD_TO_LINKED_LIST(C, inbuild_copy, targets); +} + +@h Command line. +Note the call below to |Inbuild::declare_options|, which adds a whole lot of +other options to the selection defined here. @e BUILD_CLSW @e REBUILD_CLSW @@ -156,38 +214,9 @@ int main(int argc, char **argv) { CommandLine::read(argc, argv, NULL, &Main::option, &Main::bareword); - if (LinkedLists::len(unsorted_nest_list) == 0) - Inbuild::add_nest( - Pathnames::from_text(I"inform7/Internal"), INTERNAL_NEST_TAG); +@ Here we handle those options not handled by the |inbuild| module. - path_to_inbuild = Pathnames::installation_path("INBUILD_PATH", I"inbuild"); - pathname *P = Pathnames::subfolder(path_to_inbuild, I"Tangled"); - filename *S = Filenames::in_folder(P, I"Syntax.preform"); - wording W = Preform::load_from_file(S); - Preform::parse_preform(W, FALSE); - - CommandLine::play_back_log(); - inbuild_copy *proj = NULL, *C; - LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) - if (C->edition->work->genre == project_bundle_genre) { - if (Str::len(project_bundle_request) > 0) - Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title); - else if (proj) Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title); - else proj = C; - } - - proj = Inbuild::optioneering_complete(proj, FALSE); - if (proj) { - int found = FALSE; - LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets) - if (C == proj) - found = TRUE; - if (found == FALSE) ADD_TO_LINKED_LIST(proj, inbuild_copy, targets); - } - inbuild_nest_list = Inbuild::nest_list(); - Inbuild::go_operational(); - -@ = += void Main::option(int id, int val, text_stream *arg, void *state) { switch (id) { case BUILD_CLSW: inbuild_task = BUILD_TTASK; break; @@ -219,46 +248,29 @@ void Main::option(int id, int val, text_stream *arg, void *state) { Inbuild::option(id, val, arg, state); } +@ This is called for a command-line argument which doesn't appear as +subordinate to any switch; we take it as the name of a copy. + += void Main::bareword(int id, text_stream *arg, void *state) { Main::load_one(arg, TRUE); } -void Main::load_many(pathname *P) { - scan_directory *D = Directories::open(P); - TEMPORARY_TEXT(LEAFNAME); - while (Directories::next(D, LEAFNAME)) { - TEMPORARY_TEXT(FILENAME); - WRITE_TO(FILENAME, "%p%c%S", P, FOLDER_SEPARATOR, LEAFNAME); - Main::load_one(FILENAME, FALSE); - DISCARD_TEXT(FILENAME); - } - DISCARD_TEXT(LEAFNAME); - Directories::close(D); -} +@h Interface to Words module. +Since we want to include the |words| module, we have to define the following +structure and initialiser. The type |vocabulary_meaning| is expected to hold +meanings associated with a given word; when |inform7| uses |word| it is rich +and full of significance, but for us it does nothing. We give it a meaningless +integer as its content, since in C it isn't legal to have an empty |struct|. -void Main::load_one(text_stream *arg, int throwing_error) { - inbuild_copy *C = Copies::claim(arg); - if (C == NULL) { - if (throwing_error) Errors::with_text("unable to identify '%S'", arg); - return; - } - ADD_TO_LINKED_LIST(C, inbuild_copy, targets); -} - -@ Since we want to include the words module, we have to define the following -structure and initialiser: - -@d VOCABULARY_MEANING_INITIALISER Main::ignore +@d VOCABULARY_MEANING_INITIALISER Main::create_meaningless_vm = typedef struct vocabulary_meaning { int enigmatic_number; } vocabulary_meaning; -@ - -= -vocabulary_meaning Main::ignore(vocabulary_entry *ve) { +vocabulary_meaning Main::create_meaningless_vm(vocabulary_entry *ve) { vocabulary_meaning vm; vm.enigmatic_number = 90125; return vm; @@ -268,7 +280,7 @@ vocabulary_meaning Main::ignore(vocabulary_entry *ve) { @d PREFORM_LANGUAGE_TYPE void @d PARSE_TREE_TRAVERSE_TYPE void -@d SENTENCE_NODE Main::sentence_level +@d CCCCSENTENCE_NODE Main::sentence_level @d PARSE_TREE_METADATA_SETUP SourceText::node_metadata = diff --git a/inbuild/syntax-module/Chapter 2/Parse Tree.w b/inbuild/syntax-module/Chapter 2/Parse Tree.w index 89c593351..031fbebfb 100644 --- a/inbuild/syntax-module/Chapter 2/Parse Tree.w +++ b/inbuild/syntax-module/Chapter 2/Parse Tree.w @@ -910,7 +910,7 @@ void ParseTree::traverse_from(parse_node *pn, void (*visitor)(parse_node *)) { for (; pn; pn = pn->next) { if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from(pn->down, visitor); if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(pn); } } @@ -923,7 +923,7 @@ void ParseTree::traverse_dfirst_from(parse_node *pn, void (*visitor)(parse_node parse_node *SCS = current_sentence; for (; pn; pn = pn->next) { ParseTree::traverse_dfirst_from(pn->down, visitor); - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(pn); } current_sentence = SCS; @@ -934,7 +934,7 @@ void ParseTree::traverse_wfirst(parse_node_tree *T, void (*visitor)(parse_node * void ParseTree::traverse_wfirst_from(parse_node *pn, void (*visitor)(parse_node *)) { parse_node *SCS = current_sentence; for (; pn; pn = pn->next) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; ParseTree::traverse_wfirst_from(pn->down, visitor); (*visitor)(pn); } @@ -949,7 +949,7 @@ void ParseTree::traverse_from_with_stream(text_stream *OUT, parse_node *pn, void if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_with_stream(OUT, pn->down, visitor); if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(OUT, pn); } } @@ -963,7 +963,7 @@ void ParseTree::traverse_from_int(parse_node *pn, void (*visitor)(parse_node *, for (; pn; pn = pn->next) { if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int(pn->down, visitor, X); if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(pn, X); } } @@ -977,7 +977,7 @@ void ParseTree::traverse_from_int_int(parse_node *pn, void (*visitor)(parse_node for (; pn; pn = pn->next) { if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int_int(pn->down, visitor, X, Y); if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(pn, X, Y); } } @@ -991,7 +991,7 @@ void ParseTree::traverse_from_ppn(parse_node *pn, void (*visitor)(parse_node *, for (; pn; pn = pn->next) { if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_ppn(pn->down, visitor, X); if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(pn, X); } } @@ -1010,7 +1010,7 @@ void ParseTree::traverse_from_ppni(parse_node_tree *T, parse_node *pn, void (*vi ParseTree::traverse_from_ppni(T, pn->down, visitor, H0, N); } if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(T, pn, last_h0, N); } } @@ -1029,7 +1029,7 @@ int ParseTree::traverse_from_up_to_ip(parse_node *end, parse_node *pn, void (*vi } } if (ParseTree::visitable(pn->node_type)) { - if (SENTENCE_NODE(pn->node_type)) current_sentence = pn; + if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn; (*visitor)(pn, X); } } @@ -1055,6 +1055,18 @@ int ParseTree::traverse_from_ppn_nocs(parse_node *pn, int (*visitor)(parse_node return FALSE; } +@ This provides a way for users of the module to indicate what's a sentence: + += +int ParseTree::sentence_node(node_type_t t) { + #ifdef SENTENCE_NODE + return SENTENCE_NODE(t); + #endif + #ifndef SENTENCE_NODE + return FALSE; + #endif +} + @h Verify integrity. The first duty of a tree is to contain no loops, and the following checks that (rejecting even undirected loops). In addition, it checks that each diff --git a/inbuild/syntax-test/Chapter 1/Basics.w b/inbuild/syntax-test/Chapter 1/Basics.w index eb6646e2e..c7b42fb4a 100755 --- a/inbuild/syntax-test/Chapter 1/Basics.w +++ b/inbuild/syntax-test/Chapter 1/Basics.w @@ -150,10 +150,3 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt, @ @d PARSE_TREE_TRAVERSE_TYPE void -@d SENTENCE_NODE Basics::sentence_level - -= -int Basics::sentence_level(node_type_t t) { - return FALSE; -} - diff --git a/inform7/kinds-test/Chapter 1/Basics.w b/inform7/kinds-test/Chapter 1/Basics.w index 5d80c3750..b648737af 100755 --- a/inform7/kinds-test/Chapter 1/Basics.w +++ b/inform7/kinds-test/Chapter 1/Basics.w @@ -155,15 +155,6 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt, @ @d PARSE_TREE_TRAVERSE_TYPE void -@d SENTENCE_NODE Basics::sentence_level - -= -int Basics::sentence_level(node_type_t t) { - return FALSE; -} - -@ - @d ADJECTIVE_MEANING_TYPE void @d VERB_MEANING_EQUALITY vc_be @d VERB_MEANING_POSSESSION vc_have diff --git a/inform7/linguistics-test/Chapter 1/Basics.w b/inform7/linguistics-test/Chapter 1/Basics.w index fd97f1358..8ca29422d 100755 --- a/inform7/linguistics-test/Chapter 1/Basics.w +++ b/inform7/linguistics-test/Chapter 1/Basics.w @@ -156,15 +156,6 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt, @ @d PARSE_TREE_TRAVERSE_TYPE void -@d SENTENCE_NODE Basics::sentence_level - -= -int Basics::sentence_level(node_type_t t) { - return FALSE; -} - -@ - @d ADJECTIVE_MEANING_TYPE void @d VERB_MEANING_EQUALITY vc_be @d VERB_MEANING_POSSESSION vc_have diff --git a/inform7/problems-test/Chapter 1/Basics.w b/inform7/problems-test/Chapter 1/Basics.w index 5c4492e5f..4afe70935 100755 --- a/inform7/problems-test/Chapter 1/Basics.w +++ b/inform7/problems-test/Chapter 1/Basics.w @@ -150,15 +150,4 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt, @ @d PARSE_TREE_TRAVERSE_TYPE void -@d SENTENCE_NODE Basics::sentence_level - -= -int Basics::sentence_level(node_type_t t) { - return FALSE; -} - -@ - @d NO_HEADING_LEVELS 10 - -