From d167c16357297508b4576f5e5af25746a2150110 Mon Sep 17 00:00:00 2001 From: AwesomeAdam54321 Date: Sat, 9 Mar 2024 21:23:53 +0800 Subject: [PATCH] Chapter 6: Nowebify. --- Chapter_6/{Colonies.w => Colonies.nw} | 117 +++++++++--------- .../{Ctags Support.w => Ctags_Support.nw} | 82 ++++++------ Chapter_6/{Git Support.w => Git_Support.nw} | 4 +- Chapter_6/{Makefiles.w => Makefiles.nw} | 82 ++++++------ .../{Readme Writeme.w => Readme_Writeme.nw} | 44 +++---- 5 files changed, 165 insertions(+), 164 deletions(-) rename Chapter_6/{Colonies.w => Colonies.nw} (85%) rename Chapter_6/{Ctags Support.w => Ctags_Support.nw} (74%) rename Chapter_6/{Git Support.w => Git_Support.nw} (98%) rename Chapter_6/{Makefiles.w => Makefiles.nw} (90%) rename Chapter_6/{Readme Writeme.w => Readme_Writeme.nw} (87%) diff --git a/Chapter_6/Colonies.w b/Chapter_6/Colonies.nw similarity index 85% rename from Chapter_6/Colonies.w rename to Chapter_6/Colonies.nw index 1c6e202..64b003e 100644 --- a/Chapter_6/Colonies.w +++ b/Chapter_6/Colonies.nw @@ -2,7 +2,7 @@ Cross-referencing multiple webs gathered together. -@h Colonies of webs. +@ \section{Colonies of webs.} Social spiders are said to form "colonies" when their webs are shared,[1] and in that spirit, a colony to Inweb is a collection of coexisting webs -- which share no code, and in that sense have no connection at run-time, but which @@ -17,49 +17,50 @@ Orb-Weaving Spiders With Communal Webbing in a Man-Made Structural Habitat @ So, then, a colony is really just a membership list: -= +<<*>>= typedef struct colony { - struct linked_list *members; /* of |colony_member| */ + struct linked_list *members; /* of [[colony_member]] */ struct text_stream *home; /* path of home repository */ struct pathname *assets_path; /* where assets shared between weaves live */ struct pathname *patterns_path; /* where additional patterns live */ CLASS_DEFINITION } colony; -@ Each member is represented by an instance of the following. Note the |loaded| +@ Each member is represented by an instance of the following. Note the [[loaded]] field: this holds metadata on the web/module in question. (Recall that a module is really just a web that doesn't tangle to an independent program but to a library of code: for almost all purposes, it's a web.) But for efficiency's sake, we read this metadata only on demand. -Note that the |path| might be either the name of a single-file web, or of a +Note that the [[path]] might be either the name of a single-file web, or of a directory holding a multi-section web. -= +<<*>>= typedef struct colony_member { - int web_rather_than_module; /* |TRUE| for a web, |FALSE| for a module */ - struct text_stream *name; /* the |N| in |N at P in W| */ - struct text_stream *path; /* the |P| in |N at P in W| */ - struct pathname *weave_path; /* the |W| in |N at P in W| */ - struct text_stream *home_leaf; /* usually |index.html|, but not for single-file webs */ + int web_rather_than_module; /* [[TRUE| for a web, |FALSE]] for a module */ + struct text_stream *name; /* the [[N| in |N at P in W]] */ + struct text_stream *path; /* the [[P| in |N at P in W]] */ + struct pathname *weave_path; /* the [[W| in |N at P in W]] */ + struct text_stream *home_leaf; /* usually [[index.html]], but not for single-file webs */ struct text_stream *default_weave_pattern; /* for use when weaving */ struct web_md *loaded; /* metadata on its sections, lazily evaluated */ struct filename *navigation; /* navigation sidebar HTML */ - struct linked_list *breadcrumb_tail; /* of |breadcrumb_request| */ + struct linked_list *breadcrumb_tail; /* of [[breadcrumb_request]] */ CLASS_DEFINITION } colony_member; -@ And the following reads a colony file |F| and produces a suitable |colony| +@ And the following reads a colony file [[F]] and produces a suitable [[colony]] object from it. This, for example, is the colony file for the Inweb repository at GitHub: -= (text from Figures/colony.txt) -= +(text from Figures/colony.txt) + +<<*>>= typedef struct colony_reader_state { struct colony *province; struct filename *nav; - struct linked_list *crumbs; /* of |breadcrumb_request| */ + struct linked_list *crumbs; /* of [[breadcrumb_request]] */ struct text_stream *pattern; } colony_reader_state; @@ -80,14 +81,14 @@ void Colonies::load(filename *F) { @ Lines from the colony file are fed, one by one, into: -= +<<*>>= void Colonies::read_line(text_stream *line, text_file_position *tfp, void *v_crs) { colony_reader_state *crs = (colony_reader_state *) v_crs; colony *C = crs->province; Str::trim_white_space(line); /* ignore trailing space */ if (Str::len(line) == 0) return; /* ignore blank lines */ - if (Str::get_first_char(line) == '#') return; /* lines opening with |#| are comments */ + if (Str::get_first_char(line) == '#') return; /* lines opening with [[#]] are comments */ match_results mr = Regexp::create_mr(); if (Regexp::match(&mr, line, L"(%c*?): \"*(%C+)\" at \"(%c*)\" in \"(%c*)\"")) { @@ -147,7 +148,7 @@ void Colonies::read_line(text_stream *line, text_file_position *tfp, void *v_crs @ "Breadcrumbs" are the chain of links in a horizontal list at the top of the page, and this requests one. -= +<<*>>= void Colonies::add_crumb(linked_list *L, text_stream *spec, text_file_position *tfp) { match_results mr = Regexp::create_mr(); if (Regexp::match(&mr, spec, L"\"(%c*?)\"") == FALSE) { @@ -207,11 +208,11 @@ void Colonies::write_breadcrumb(OUTPUT_STREAM, text_stream *text, text_stream *l } } -@h Searching. -Given a name |T|, we try to find a colony member of that name, returning the +@ \section{Searching.} +Given a name [[T]], we try to find a colony member of that name, returning the first we find. -= +<<*>>= colony_member *Colonies::find(text_stream *T) { colony *C; LOOP_OVER(C, colony) { @@ -229,20 +230,20 @@ already in Inweb's memory (because it is the web being woven, or is a module imported by that web even if not now being woven). If it is, we want to use the data we already have; but if not, we read it in. -= +<<*>>= module *Colonies::as_module(colony_member *CM, source_line *L, web_md *Wm) { - if (CM->loaded == NULL) @; - if (CM->loaded == NULL) @; - if (CM->loaded == NULL) @; - if (CM->loaded == NULL) @; + if (CM->loaded == NULL) <>; + if (CM->loaded == NULL) <>; + if (CM->loaded == NULL) <>; + if (CM->loaded == NULL) <>; return CM->loaded->as_module; } -@ = +<>= if ((Wm) && (Str::eq_insensitive(Wm->as_module->module_name, CM->name))) CM->loaded = Wm; -@ = +<>= if (Wm) { module *M; LOOP_OVER_LINKED_LIST(M, module, Wm->as_module->dependencies) @@ -250,7 +251,7 @@ module *Colonies::as_module(colony_member *CM, source_line *L, web_md *Wm) { CM->loaded = Wm; } -@ = +<>= filename *F = NULL; pathname *P = NULL; if (Str::suffix_eq(CM->path, I".inweb", 6)) @@ -259,14 +260,14 @@ module *Colonies::as_module(colony_member *CM, source_line *L, web_md *Wm) { P = Pathnames::from_text(CM->path); CM->loaded = WebMetadata::get_without_modules(P, F); -@ = +<>= TEMPORARY_TEXT(err) WRITE_TO(err, "unable to load '%S'", CM->name); Main::error_in_web(err, L); @ Finally: -= +<<*>>= text_stream *Colonies::home(void) { colony *C; LOOP_OVER(C, colony) @@ -288,9 +289,9 @@ pathname *Colonies::patterns_path(void) { return NULL; } -@h Cross-references. +@ \section{Cross-references.} The following must decide what references like the following should refer to: -= (text) + Chapter 3 Manual Enumerated Constants @@ -298,15 +299,15 @@ The following must decide what references like the following should refer to: weave_order foundation: Text Streams goldbach -= -The reference text is in |text|; we return |TRUE| if we can make unambiguous -sense of it, or throw an error and return |FALSE| if not. If all is well, we + +The reference text is in [[text]]; we return [[TRUE]] if we can make unambiguous +sense of it, or throw an error and return [[FALSE]] if not. If all is well, we must write a title and URL for the link. -The web metadata |Wm| is for the web currently being woven, and the line |L| +The web metadata [[Wm]] is for the web currently being woven, and the line [[L]] is where the reference is made from. -= +<<*>>= int Colonies::resolve_reference_in_weave(text_stream *url, text_stream *title, filename *for_HTML_file, text_stream *text, web_md *Wm, source_line *L, int *ext) { int r = 0; @@ -331,9 +332,9 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti colony_member *search_CM = NULL; int external = FALSE; - @; - @; - @; + <>; + <>; + <>; module *found_M = NULL; section_md *found_Sm = NULL; @@ -355,8 +356,8 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti if (N == 0) { if ((L) && (external == FALSE)) { - @; - @; + <>; + <>; } TEMPORARY_TEXT(err) WRITE_TO(err, "Can't find the cross-reference '%S'", text); @@ -370,11 +371,11 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti title, search_M, text, TRUE, FALSE); return FALSE; } - @; + <>; return TRUE; } -@ = +<>= match_results mr = Regexp::create_mr(); if (Regexp::match(&mr, text, L"https*://%c*")) { WRITE_TO(url, "%S", text); @@ -385,17 +386,17 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti } Regexp::dispose_of(&mr); -@ = +<>= search_CM = Colonies::find(text); if (search_CM) { module *found_M = Colonies::as_module(search_CM, L, Wm); section_md *found_Sm = FIRST_IN_LINKED_LIST(section_md, found_M->sections_md); int bare_module_name = TRUE; WRITE_TO(title, "%S", search_CM->name); - @; + <>; } -@ = +<>= match_results mr = Regexp::create_mr(); if (Regexp::match(&mr, text, L"(%c*?): (%c*)")) { search_CM = Colonies::find(mr.exp[0]); @@ -411,7 +412,7 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti } Regexp::dispose_of(&mr); -@ = +<>= language_function *fn; LOOP_OVER(fn, language_function) { if (Str::eq_insensitive(fn->function_name, text)) { @@ -422,7 +423,7 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti } } -@ = +<>= language_type *str; LOOP_OVER(str, language_type) { if (Str::eq_insensitive(str->structure_name, text)) { @@ -433,13 +434,13 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti } } -@ = +<>= if (found_M == NULL) internal_error("could not locate M"); - if (search_CM) @ - else @; + if (search_CM) <> + else <>; return TRUE; -@ = +<>= pathname *from = Filenames::up(for_HTML_file); pathname *to = search_CM->weave_path; Pathnames::relative_URL(url, from, to); @@ -452,7 +453,7 @@ int Colonies::resolve_reference_in_weave_inner(text_stream *url, text_stream *ti guess it makes is that modules of the current web will be woven alongside the main one. -@ = +<>= if (found_M == from_M) { Colonies::section_URL(url, found_Sm); } else { @@ -462,9 +463,9 @@ the main one. WRITE_TO(title, " (in %S)", found_M->module_name); } -@h URL management. +@ \section{URL management.} -= +<<*>>= void Colonies::link_URL(OUTPUT_STREAM, text_stream *link_text, filename *F) { match_results mr = Regexp::create_mr(); if (Regexp::match(&mr, link_text, L" *//(%c+)// *")) diff --git a/Chapter_6/Ctags Support.w b/Chapter_6/Ctags_Support.nw similarity index 74% rename from Chapter_6/Ctags Support.w rename to Chapter_6/Ctags_Support.nw index dfb428c..a67e48d 100644 --- a/Chapter_6/Ctags Support.w +++ b/Chapter_6/Ctags_Support.nw @@ -10,15 +10,15 @@ editing the sections in the web. A ctags file is essentially just a list of identifiers called "tagnames", which are usually names of functions or data types, along with details of where they are defined in a program. Ctags files are almost never written by -hand, but are instead generated by a tool such as the eponymous |ctags|. Here, +hand, but are instead generated by a tool such as the eponymous [[ctags]]. Here, though, Inweb is going to do the generation, because it can make sense of the -web structure of source code in a way which the |ctags| parser cannot. +web structure of source code in a way which the [[ctags]] parser cannot. -The original |ctags| dates to 1992, and was devised by Ken Arnold. This was +The original [[ctags]] dates to 1992, and was devised by Ken Arnold. This was much extended as Exuberant Ctags, by Darren Hiebert, which was then forked and re-maintained as Universal Ctags by Reza Jelveh and others. The result is nearly standard now, though as with a lot of early Unix infrastructure (compare -|make|, for example), that standard design feels very antique: white space is +[[make]], for example), that standard design feels very antique: white space is significant, filename extensions are not standard practice, and so on. See //Universal Ctags -> https://ctags.io// for more.[1] @@ -28,10 +28,10 @@ but it omits details of, e.g., exactly what characters must be escaped and how; what characters can legally be part of a tagname; and so on. @ As mentioned above, Ctags go back to an age before filenames necessarily had -extensions, and just as the defaukt make file is |makefile| and not |makefile.mk|, -so the default Ctags file is called |tags| and not |tags.ctag|. +extensions, and just as the defaukt make file is [[makefile]] and not [[makefile.mk]], +so the default Ctags file is called [[tags]] and not [[tags.ctag]]. -= +<<*>>= void Ctags::write(web *W, filename *F) { text_stream ctags_file; pathname *P = NULL; @@ -44,41 +44,41 @@ void Ctags::write(web *W, filename *F) { text_stream *OUT = &ctags_file; if (STREAM_OPEN_TO_FILE(OUT, F, UTF8_ENC) == FALSE) Errors::fatal_with_file("unable to write ctags file", F); - @; - @; - @; - @; + <>; + <>; + <>; + <>; STREAM_CLOSE(OUT); } @ Unless you really want to monkey with identifiers or filenames containing line break characters or tabs, a ctags file has a simple format to read or write: there's one tag on each line, and each line has three or more fields -divided by tab characters. If we write | -> | for a tab, a line looks like: -= (text) +divided by tab characters. If we write [[ -> ]] for a tab, a line looks like: + tagname -> filename -> /find/;" -> more -= + The stranded double-quote there is not a misprint. For example: -= (text) + Frogs::spawn -> pond/Chapter 1/Amphibians.w -> /^void Frogs::spawn(species *S) {$/;" -> f -= -Here the tagname is |Frogs::spawn|. The filename |pond/Chapter 1/Amphibians.w| -is the file defining this function. The |find| field is an EX-format command for -finding the line in question: see below. Finally, the |more| field is actually + +Here the tagname is [[Frogs::spawn]]. The filename [[pond/Chapter 1/Amphibians.w]] +is the file defining this function. The [[find]] field is an EX-format command for +finding the line in question: see below. Finally, the [[more]] field is actually a run of optional extra information, presented in a free-form sort of way, but -we will use it only the simplest of ways. In this example it is just |f|, +we will use it only the simplest of ways. In this example it is just [[f]], meaning "I am a function declaration". The opening lines of the file, however, are usually metadata, i.e., describing the -file itself and where it came from. In those lines, tagnames begin with |!_| and are -called "pseudotags". The |filename| field is instead a value, while the |find| +file itself and where it came from. In those lines, tagnames begin with [[!_]] and are +called "pseudotags". The [[filename]] field is instead a value, while the [[find]] field is instead an optional comment. The first two keys here are essential: the other three seem just to be good practice. -These are the five keys which Universal |ctags| writes by default, so we'll follow +These are the five keys which Universal [[ctags]] writes by default, so we'll follow suit. -@ = +<>= WRITE("!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/\n"); WRITE("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/\n"); WRITE("!_TAG_PROGRAM_AUTHOR\tGraham Nelson\t/graham.nelson@mod-langs.ox.ac.uk/\n"); @@ -88,9 +88,9 @@ suit. @ Having prudently opted to give the tags in an unsorted way, we're free to list them in any order convenient to us, and here goes. -The |more| field |d| says that a tagname is a defined constant: +The [[more]] field [[d]] says that a tagname is a defined constant: -@ = +<>= defined_constant *str; LOOP_OVER(str, defined_constant) if (str->at->owning_section->owning_web == W) { @@ -101,11 +101,11 @@ The |more| field |d| says that a tagname is a defined constant: WRITE("\n"); } -@ The |more| field |t| says that a tagname is a type, and we add a clarifying -detail to say that it results from a |typedef struct|. (Note that |typeref| -here, with an "r", is not a mistake. This is what Universal |ctags| calls it.) +@ The [[more]] field [[t]] says that a tagname is a type, and we add a clarifying +detail to say that it results from a [[typedef struct]]. (Note that [[typeref]] +here, with an "r", is not a mistake. This is what Universal [[ctags]] calls it.) -@ = +<>= language_type *str; LOOP_OVER(str, language_type) if (str->structure_header_at->owning_section->owning_web == W) { @@ -116,9 +116,9 @@ here, with an "r", is not a mistake. This is what Universal |ctags| calls it.) WRITE("\n"); } -@ The |more| field |f| says that a tagname is a function: +@ The [[more]] field [[f]] says that a tagname is a function: -@ = +<>= language_function *fn; LOOP_OVER(fn, language_function) if (fn->function_header_at->owning_section->owning_web == W) { @@ -129,20 +129,20 @@ here, with an "r", is not a mistake. This is what Universal |ctags| calls it.) WRITE("\n"); } -@ So, then, here we write the |filename| and |find| fields for a given -source line |L| in our web. Note that: +@ So, then, here we write the [[filename]] and [[find]] fields for a given +source line [[L]] in our web. Note that: (a) The filename must be given relative to the directory containing the tags file, so for us that will be the home directory of the web. -(b) The |find| field looks like a regular expression but is not one, despite -the suggestive positional markers |^| and |$|. Note in particular that round +(b) The [[find]] field looks like a regular expression but is not one, despite +the suggestive positional markers [[^]] and [[$]]. Note in particular that round brackets and asterisk characters are not escaped, as they would be in a regex. -The Ctags documentation is vague here but does note that |^| and |$| should +The Ctags documentation is vague here but does note that [[^]] and [[$]] should be escaped only where they occur in the first or last positions. Tabs do not need to be escaped. -= +<<*>>= void Ctags::write_line_ref(OUTPUT_STREAM, source_line *L, pathname *P) { TEMPORARY_TEXT(fn) WRITE_TO(fn, "%f", L->owning_section->md->source_file_for_section); @@ -169,16 +169,16 @@ We could laboriously extract that from the hash table of reserved words (see //The Analyser//), but this is one of those times when life is short and memory is cheap. It's easier to keep a duplicate list. -= +<<*>>= typedef struct defined_constant { struct text_stream *name; struct source_line *at; CLASS_DEFINITION } defined_constant; -@ This is called for any |@d| or |@e| constant name, then: +@ This is called for any [[@d]] or [[@e]] constant name, then: -= +<<*>>= void Ctags::note_defined_constant(source_line *L, text_stream *name) { defined_constant *dc = CREATE(defined_constant); dc->name = Str::duplicate(name); diff --git a/Chapter_6/Git Support.w b/Chapter_6/Git_Support.nw similarity index 98% rename from Chapter_6/Git Support.w rename to Chapter_6/Git_Support.nw index d83a1fb..e99888b 100644 --- a/Chapter_6/Git Support.w +++ b/Chapter_6/Git_Support.nw @@ -4,7 +4,7 @@ Constructing a suitable gitignore file for a simple inweb project. @ This is an extremely simple use of //foundation: Preprocessor//. -= +<<*>>= void Git::write_gitignore(web *W, filename *prototype, filename *F) { linked_list *L = NEW_LINKED_LIST(preprocessor_macro); Preprocessor::new_macro(L, I"basics", NULL, Git::basics_expander, NULL); @@ -18,7 +18,7 @@ void Git::write_gitignore(web *W, filename *prototype, filename *F) { @ Our one non-standard macro simply includes a file of standing material which is the same as the default .giscript file anyway: -= +<<*>>= void Git::basics_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { filename *prototype = Filenames::in(path_to_inweb_materials, I"default.giscript"); diff --git a/Chapter_6/Makefiles.w b/Chapter_6/Makefiles.nw similarity index 90% rename from Chapter_6/Makefiles.w rename to Chapter_6/Makefiles.nw index b8b5734..0e3478e 100644 --- a/Chapter_6/Makefiles.w +++ b/Chapter_6/Makefiles.nw @@ -2,13 +2,13 @@ Constructing a suitable makefile for a simple inweb project. -@h Preprocessing. +@ \section{Preprocessing.} We will use //foundation: Preprocessor// with four special macros and one special loop construct. For the syntax being worked through, see //Webs, Tangling and Weaving//. -= +<<*>>= void Makefiles::write(web *W, filename *prototype, filename *F, module_search *I, text_stream *platform) { linked_list *L = NEW_LINKED_LIST(preprocessor_macro); @@ -33,7 +33,7 @@ void Makefiles::write(web *W, filename *prototype, filename *F, module_search *I Makefiles::components_expander, NULL); makefile_specifics *specifics = CREATE(makefile_specifics); - @; + <>; text_stream *header = Str::new(); WRITE_TO(header, "# This makefile was automatically written by inweb -makefile\n"); @@ -47,18 +47,18 @@ void Makefiles::write(web *W, filename *prototype, filename *F, module_search *I @ We will allow a makescript to declare "components" (webs, really), so we need a data structure to store those declarations in: -= +<<*>>= typedef struct makefile_specifics { struct web *for_web; /* if one has been set at the command line */ - struct dictionary *tools_dictionary; /* components with |type: tool| */ - struct dictionary *webs_dictionary; /* components with |type: web| */ - struct dictionary *modules_dictionary; /* components with |type: module| */ + struct dictionary *tools_dictionary; /* components with [[type: tool]] */ + struct dictionary *webs_dictionary; /* components with [[type: web]] */ + struct dictionary *modules_dictionary; /* components with [[type: module]] */ struct module_search *search_path; struct text_stream *which_platform; CLASS_DEFINITION } makefile_specifics; -@ = +<>= specifics->for_web = W; specifics->tools_dictionary = Dictionaries::new(16, FALSE); specifics->webs_dictionary = Dictionaries::new(16, FALSE); @@ -66,9 +66,9 @@ typedef struct makefile_specifics { specifics->search_path = I; specifics->which_platform = platform; -@h The identity-settings expander. +@ \section{The identity-settings expander.} -= +<<*>>= void Makefiles::identity_settings_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { makefile_specifics *specifics = RETRIEVE_POINTER_makefile_specifics(PPS->specifics); @@ -84,13 +84,13 @@ void Makefiles::identity_settings_expander(preprocessor_macro *mm, preprocessor_ } } -@h The platform-settings expander. +@ \section{The platform-settings expander.} We first scan Inweb's platform settings file for a definition line in the shape INWEBPLATFORM = PLATFORM, in order to find out what PLATFORM the make file will be used on. Then we splice in the appropriate file of standard definitions for that platform. -= +<<*>>= void Makefiles::platform_settings_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { makefile_specifics *specifics = RETRIEVE_POINTER_makefile_specifics(PPS->specifics); @@ -123,9 +123,9 @@ void Makefiles::seek_INWEBPLATFORM(text_stream *line, text_file_position *tfp, v Regexp::dispose_of(&mr); } -@h The modify filename expander. +@ \section{The modify filename expander.} -= +<<*>>= void Makefiles::modify_filenames_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { text_stream *OUT = PPS->dest; @@ -142,17 +142,17 @@ void Makefiles::modify_filenames_expander(preprocessor_macro *mm, preprocessor_s if (Characters::is_whitespace(c)) { if ((previous != '\\') && (quoted == FALSE)) boundary = TRUE; } else { - if (boundary) @; + if (boundary) <>; boundary = FALSE; } PUT_TO(captured, c); previous = c; } - @ + <> DISCARD_TEXT(captured) } -@ = +<>= Str::trim_white_space(captured); if (Str::len(captured) > 0) { int in_quotes = FALSE; @@ -179,9 +179,9 @@ void Makefiles::modify_filenames_expander(preprocessor_macro *mm, preprocessor_s Str::clear(captured); } -@h The component expander. +@ \section{The component expander.} -= +<<*>>= void Makefiles::component_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { makefile_specifics *specifics = RETRIEVE_POINTER_makefile_specifics(PPS->specifics); @@ -196,25 +196,25 @@ void Makefiles::component_expander(preprocessor_macro *mm, preprocessor_state *P if (Str::eq(category, I"tool")) { int marker = MAKEFILE_TOOL_MOM; dictionary *D = specifics->tools_dictionary; - @; - @; + <>; + <>; } else if (Str::eq(category, I"web")) { int marker = MAKEFILE_WEB_MOM; dictionary *D = specifics->webs_dictionary; - @; - @; + <>; + <>; } else if (Str::eq(category, I"module")) { int marker = MAKEFILE_MODULE_MOM; dictionary *D = specifics->modules_dictionary; - @; - @; + <>; + <>; } else { Errors::in_text_file("category should be 'tool', 'module' or 'web'", tfp); } PPS->last_line_was_blank = FALSE; } -@ = +<>= web_md *Wm = Reader::load_web_md(Pathnames::from_text(path), NULL, specifics->search_path, TRUE); Wm->as_module->module_name = Str::duplicate(symbol); @@ -223,15 +223,15 @@ void Makefiles::component_expander(preprocessor_macro *mm, preprocessor_state *P Dictionaries::create(D, symbol); Dictionaries::write_value(D, symbol, Wm); -@ = +<>= WRITE("%SLEAF = %S\n", symbol, webname); WRITE("%SWEB = %S\n", symbol, path); WRITE("%SMAKER = $(%SWEB)/%S.mk\n", symbol, symbol, webname); WRITE("%SX = $(%SWEB)/Tangled/%S\n", symbol, symbol, webname); -@h The components loop construct. +@ \section{The components loop construct.} -= +<<*>>= void Makefiles::components_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { Preprocessor::set_loop_var_name(loop, I"SYMBOL"); @@ -240,19 +240,19 @@ void Makefiles::components_expander(preprocessor_macro *mm, preprocessor_state * if (Str::len(set) == 0) set = I"all"; if (Str::eq(category, I"tool")) { int marker = MAKEFILE_TOOL_MOM; - @; + <>; } else if (Str::eq(category, I"web")) { int marker = MAKEFILE_WEB_MOM; - @; + <>; } else if (Str::eq(category, I"module")) { int marker = MAKEFILE_MODULE_MOM; - @; + <>; } else { Errors::in_text_file("category should be 'tool', 'module' or 'web'", tfp); } } -@ = +<>= module *M; LOOP_OVER(M, module) { if ((M->origin_marker == marker) && @@ -262,9 +262,9 @@ void Makefiles::components_expander(preprocessor_macro *mm, preprocessor_state * } } -@h The dependent-files expander. +@ \section{The dependent-files expander.} -= +<<*>>= void Makefiles::dependent_files_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { makefile_specifics *specifics = RETRIEVE_POINTER_makefile_specifics(PPS->specifics); @@ -318,20 +318,20 @@ void Makefiles::dependent_files_expander(preprocessor_macro *mm, preprocessor_st } @ This outputs a makefile pattern matching a bunch of web source code filenames: -say, |inweb/Chapter\ %d/*.w|. +say, [[inweb/Chapter\ %d/*.w]]. -= +<<*>>= void Makefiles::pattern(OUTPUT_STREAM, linked_list *L, filename *F) { dictionary *patterns_done = Dictionaries::new(16, TRUE); - if (F) @; + if (F) <>; section_md *Sm; LOOP_OVER_LINKED_LIST(Sm, section_md, L) { filename *F = Sm->source_file_for_section; - @; + <>; } } -@ = +<>= pathname *P = Filenames::up(F); TEMPORARY_TEXT(leaf_pattern) WRITE_TO(leaf_pattern, "%S", Pathnames::directory_name(P)); @@ -361,7 +361,7 @@ void Makefiles::pattern(OUTPUT_STREAM, linked_list *L, filename *F) { bald statement really doesn't begin to go into how awkward makefiles can be when filenames have spaces in, but there we are.) -= +<<*>>= void Makefiles::pathname_slashed(OUTPUT_STREAM, pathname *P) { TEMPORARY_TEXT(PT) WRITE_TO(PT, "%p", P); diff --git a/Chapter_6/Readme Writeme.w b/Chapter_6/Readme_Writeme.nw similarity index 87% rename from Chapter_6/Readme Writeme.w rename to Chapter_6/Readme_Writeme.nw index 8dad30e..52c2121 100644 --- a/Chapter_6/Readme Writeme.w +++ b/Chapter_6/Readme_Writeme.nw @@ -3,10 +3,10 @@ To construct Readme and similar files. @ This is a simple use of //foundation: Preprocessor//. Note that we use a -non-standard comment syntax (i.e., |/| at start of line, not |#|) to avoid +non-standard comment syntax (i.e., [[/]] at start of line, not [[#]]) to avoid colliding with Markdown's heading syntax. -= +<<*>>= void Readme::write(filename *prototype, filename *F) { linked_list *L = NEW_LINKED_LIST(preprocessor_macro); preprocessor_macro *mm = Preprocessor::new_macro(L, @@ -19,7 +19,7 @@ void Readme::write(filename *prototype, filename *F) { @ And this is the one domain-specific macro: -= +<<*>>= void Readme::bibliographic_expander(preprocessor_macro *mm, preprocessor_state *PPS, text_stream **parameter_values, preprocessor_loop *loop, text_file_position *tfp) { text_stream *datum = parameter_values[0]; @@ -37,7 +37,7 @@ also be a few other rather Inform-specific things; those have a more limited range of bibliographic data, just the version and date (and we will not assume that the version complies with any format). -= +<<*>>= typedef struct writeme_asset { struct text_stream *name; struct web_md *if_web; @@ -56,7 +56,7 @@ void Readme::write_var(text_stream *OUT, text_stream *program, text_stream *datu @ That just leaves the business of inspecting assets to obtain their metadata. -= +<<*>>= writeme_asset *Readme::find_asset(text_stream *program) { writeme_asset *A; LOOP_OVER(A, writeme_asset) if (Str::eq(program, A->name)) return A; @@ -66,48 +66,48 @@ writeme_asset *Readme::find_asset(text_stream *program) { A->date = Str::new(); A->version = Str::new(); A->next_is_version = FALSE; - @; + <>; return A; } -@ = +<>= if (Str::ends_with_wide_string(program, L".i7x")) { - @; + <>; } else { if (WebMetadata::directory_looks_like_a_web(Pathnames::from_text(program))) { A->if_web = WebMetadata::get_without_modules(Pathnames::from_text(program), NULL); } else { filename *I6_vn = Filenames::in( Pathnames::down(Pathnames::from_text(program), I"inform6"), I"header.h"); - if (TextFiles::exists(I6_vn)) @; + if (TextFiles::exists(I6_vn)) <>; filename *template_vn = Filenames::in(Pathnames::from_text(program), I"(manifest).txt"); - if (TextFiles::exists(template_vn)) @; + if (TextFiles::exists(template_vn)) <>; filename *rmt_vn = Filenames::in(Pathnames::from_text(program), I"README.txt"); - if (TextFiles::exists(rmt_vn)) @; + if (TextFiles::exists(rmt_vn)) <>; rmt_vn = Filenames::in(Pathnames::from_text(program), I"README.md"); - if (TextFiles::exists(rmt_vn)) @; + if (TextFiles::exists(rmt_vn)) <>; } } -@ = +<>= TextFiles::read(Filenames::from_text(program), FALSE, "unable to read extension", TRUE, &Readme::extension_harvester, NULL, A); -@ = +<>= TextFiles::read(I6_vn, FALSE, "unable to read header file from I6 source", TRUE, &Readme::header_harvester, NULL, A); -@ = +<>= TextFiles::read(template_vn, FALSE, "unable to read manifest file from website template", TRUE, &Readme::template_harvester, NULL, A); -@ = +<>= TextFiles::read(rmt_vn, FALSE, "unable to read README file from website template", TRUE, &Readme::readme_harvester, NULL, A); @ The format for the contents section of a web is documented in Inweb. -= +<<*>>= void Readme::extension_harvester(text_stream *text, text_file_position *tfp, void *state) { writeme_asset *A = (writeme_asset *) state; match_results mr = Regexp::create_mr(); @@ -117,9 +117,9 @@ void Readme::extension_harvester(text_stream *text, text_file_position *tfp, voi Regexp::dispose_of(&mr); } -@ Explicit code to read from |header.h| in the Inform 6 repository. +@ Explicit code to read from [[header.h]] in the Inform 6 repository. -= +<<*>>= void Readme::header_harvester(text_stream *text, text_file_position *tfp, void *state) { writeme_asset *A = (writeme_asset *) state; match_results mr = Regexp::create_mr(); @@ -133,7 +133,7 @@ void Readme::header_harvester(text_stream *text, text_file_position *tfp, void * @ Explicit code to read from the manifest file of a website template. -= +<<*>>= void Readme::template_harvester(text_stream *text, text_file_position *tfp, void *state) { writeme_asset *A = (writeme_asset *) state; match_results mr = Regexp::create_mr(); @@ -147,9 +147,9 @@ void Readme::template_harvester(text_stream *text, text_file_position *tfp, void Regexp::dispose_of(&mr); } -@ And this is needed for |cheapglk| and |glulxe| in the Inform repository. +@ And this is needed for [[cheapglk]] and [[glulxe]] in the Inform repository. -= +<<*>>= void Readme::readme_harvester(text_stream *text, text_file_position *tfp, void *state) { writeme_asset *A = (writeme_asset *) state; match_results mr = Regexp::create_mr();