Build metadata support

This commit is contained in:
Graham Nelson 2020-03-23 15:04:43 +00:00
parent 750eb8a17f
commit c49d4c688b
66 changed files with 2832 additions and 1040 deletions

View file

@ -24,6 +24,7 @@ typedef struct inweb_instructions {
int catalogue_switch; /* |-catalogue|: print catalogue of sections */
int functions_switch; /* |-functions|: print catalogue of functions within sections */
int structures_switch; /* |-structures|: print catalogue of structures within sections */
int advance_switch; /* |-advance-build|: advance build file for web */
int open_pdf_switch; /* |-open-pdf|: open any woven PDF in the OS once it is made */
int scan_switch; /* |-scan|: simply show the syntactic scan of the source */
struct filename *weave_to_setting; /* |-weave-to X|: the pathname X, if supplied */
@ -31,6 +32,7 @@ typedef struct inweb_instructions {
struct filename *tangle_setting; /* |-tangle-to X|: the pathname X, if supplied */
struct filename *makefile_setting; /* |-makefile X|: the filename X, if supplied */
struct filename *gitignore_setting; /* |-gitignore X|: the filename X, if supplied */
struct filename *advance_setting; /* |-advance-build-file X|: advance build file X */
struct filename *prototype_setting; /* |-prototype X|: the pathname X, if supplied */
struct filename *navigation_setting; /* |-navigation X|: the filename X, if supplied */
struct linked_list *breadcrumb_setting; /* of |breadcrumb_request| */
@ -75,6 +77,7 @@ inweb_instructions Configuration::read(int argc, char **argv) {
args.catalogue_switch = FALSE;
args.functions_switch = FALSE;
args.structures_switch = FALSE;
args.advance_switch = FALSE;
args.open_pdf_switch = NOT_APPLICABLE;
args.scan_switch = FALSE;
args.verbose_switch = FALSE;
@ -87,6 +90,7 @@ inweb_instructions Configuration::read(int argc, char **argv) {
args.weave_into_setting = NULL;
args.makefile_setting = NULL;
args.gitignore_setting = NULL;
args.advance_setting = NULL;
args.prototype_setting = NULL;
args.navigation_setting = NULL;
args.breadcrumb_setting = NEW_LINKED_LIST(breadcrumb_request);
@ -106,8 +110,10 @@ provides automatically.
@e CATALOGUE_CLSW
@e FUNCTIONS_CLSW
@e STRUCTURES_CLSW
@e ADVANCE_CLSW
@e GITIGNORE_CLSW
@e MAKEFILE_CLSW
@e ADVANCE_FILE_CLSW
@e PROTOTYPE_CLSW
@e SCAN_CLSW
@ -151,12 +157,16 @@ provides automatically.
L"write a makefile for this web and store it in X");
CommandLine::declare_switch(GITIGNORE_CLSW, L"gitignore", 2,
L"write a .gitignore file for this web and store it in X");
CommandLine::declare_switch(ADVANCE_FILE_CLSW, L"advance-build-file", 2,
L"increment daily build code in file X");
CommandLine::declare_switch(PROTOTYPE_CLSW, L"prototype", 2,
L"translate makefile from prototype X");
CommandLine::declare_switch(FUNCTIONS_CLSW, L"functions", 1,
L"catalogue the functions in the web");
CommandLine::declare_switch(STRUCTURES_CLSW, L"structures", 1,
L"catalogue the structures in the web");
CommandLine::declare_switch(ADVANCE_CLSW, L"advance-build", 1,
L"increment daily build code for the web");
CommandLine::declare_switch(SCAN_CLSW, L"scan", 1,
L"scan the web");
@ -203,6 +213,9 @@ void Configuration::switch(int id, int val, text_stream *arg, void *state) {
case STRUCTURES_CLSW:
args->structures_switch = TRUE;
Configuration::set_fundamental_mode(args, ANALYSE_MODE); break;
case ADVANCE_CLSW:
args->advance_switch = TRUE;
Configuration::set_fundamental_mode(args, ANALYSE_MODE); break;
case MAKEFILE_CLSW:
args->makefile_setting = Filenames::from_text(arg);
if (args->inweb_mode != TRANSLATE_MODE)
@ -213,6 +226,10 @@ void Configuration::switch(int id, int val, text_stream *arg, void *state) {
if (args->inweb_mode != TRANSLATE_MODE)
Configuration::set_fundamental_mode(args, ANALYSE_MODE);
break;
case ADVANCE_FILE_CLSW:
args->advance_setting = Filenames::from_text(arg);
Configuration::set_fundamental_mode(args, TRANSLATE_MODE);
break;
case PROTOTYPE_CLSW:
args->prototype_setting = Filenames::from_text(arg);
Configuration::set_fundamental_mode(args, TRANSLATE_MODE); break;

View file

@ -114,6 +114,8 @@ void Main::follow_instructions(inweb_instructions *ins) {
Makefiles::write(W, ins->prototype_setting, ins->makefile_setting);
else if (ins->gitignore_setting)
Git::write_gitignore(W, ins->prototype_setting, ins->gitignore_setting);
else if (ins->advance_setting)
BuildFiles::advance(ins->advance_setting);
@ But otherwise we do something with the given web:
@ -138,6 +140,8 @@ void Main::follow_instructions(inweb_instructions *ins) {
Analyser::write_makefile(W, ins->makefile_setting);
if (ins->gitignore_setting)
Analyser::write_gitignore(W, ins->gitignore_setting);
if (ins->advance_switch)
BuildFiles::advance_for_web(W);
if (ins->scan_switch)
Analyser::scan_line_categories(W, ins->chosen_range);

View file

@ -61,7 +61,9 @@ void Bibliographic::initialise_data(web *W) {
Bibliographic::set_datum(W, I"Capitalized Title", NULL);
Bibliographic::set_datum(W, I"Build Date", NULL);
Bibliographic::set_datum(W, I"Build Number", NULL);
Bibliographic::set_datum(W, I"Version Number", NULL);
Bibliographic::set_datum(W, I"Prerelease", NULL);
Bibliographic::set_datum(W, I"Semantic Version Number", NULL);
Bibliographic::set_datum(W, I"Version Number", I"1");
Bibliographic::set_datum(W, I"Version Name", NULL);
Bibliographic::set_datum(W, I"Index Template", NULL);
Bibliographic::set_datum(W, I"Preform Language", NULL);
@ -70,6 +72,8 @@ void Bibliographic::initialise_data(web *W) {
bd = Bibliographic::set_datum(W, I"Namespaces", I"Off"); bd->on_or_off = TRUE;
bd = Bibliographic::set_datum(W, I"Strict Usage Rules", I"Off"); bd->on_or_off = TRUE;
bd = Bibliographic::set_datum(W, I"Web Syntax Version", NULL);
BuildFiles::set_bibliographic_data_for(W);
}
@ Once the declarations for a web have been processed, the following is called

View file

@ -34,6 +34,7 @@ typedef struct web {
int analysed; /* has this been scanned for function usage and such? */
struct linked_list *bibliographic_data; /* of |bibliographic_datum|: key-value pairs for title and such */
struct semantic_version_number version_number; /* as deduced from the bibliographic data */
struct programming_language *main_language; /* in which most of the sections are written */
struct linked_list *tangle_targets; /* of |tangle_target| */
@ -66,9 +67,11 @@ web *Reader::load_web(pathname *P, filename *alt_F, module_search *I, int verbos
W->redirect_weaves_to = redirection;
W->as_module = Modules::main_module(W);
W->default_syntax = default_inweb_syntax;
W->version_number = VersionNumbers::null();
Bibliographic::initialise_data(W);
Reader::add_tangle_target(W, Languages::default()); /* the bulk of the web is automatically a target */
Reader::read_contents_page(W, I, verbosely);
BuildFiles::deduce_semver(W);
Parser::parse_web(W, inweb_mode);
if (W->no_sections == 1) {
chapter *C = FIRST_IN_LINKED_LIST(chapter, W->chapters);

View file

@ -245,12 +245,8 @@ void HTMLFormat::paragraph_heading(weave_format *self, text_stream *OUT,
HTML_OPEN_WITH("ul", "class=\"crumbs\"");
HTMLFormat::drop_initial_breadcrumbs(OUT, wv->breadcrumbs, wv->docs_mode);
TEMPORARY_TEXT(titling);
WRITE_TO(titling, "%S", Bibliographic::get_datum(wv->weave_web, I"Title"));
text_stream *v = Bibliographic::get_datum(wv->weave_web, I"Version Number");
if (Str::len(v) > 0) WRITE_TO(titling, " %S", v);
HTMLFormat::breadcrumb(OUT, titling, I"index.html");
DISCARD_TEXT(titling);
HTMLFormat::breadcrumb(OUT,
Bibliographic::get_datum(wv->weave_web, I"Title"), I"index.html");
if (wv->weave_web->chaptered) {
TEMPORARY_TEXT(chapter_link);

198
Chapter 6/Build Files.w Normal file
View file

@ -0,0 +1,198 @@
[BuildFiles::] Build Files.
Manages the build metadata for an inweb project.
@h About build files.
When we read a web, we look for a file in it called |build.txt|. If no such
file exists, we look for the same thing in the current working directory.
=
filename *BuildFiles::build_file_for_web(web *W) {
filename *F = Filenames::in_folder(W->path_to_web, I"build.txt");
if (TextFiles::exists(F)) return F;
F = Filenames::in_folder(NULL, I"build.txt");
if (TextFiles::exists(F)) return F;
return NULL;
}
@ The format of such a file is very simple: up to three text fields:
=
typedef struct build_file_data {
struct text_stream *prerelease_text;
struct text_stream *build_code;
struct text_stream *build_date;
} build_file_data;
@ Here's how to read in a build file:
=
build_file_data BuildFiles::read(filename *F) {
build_file_data bfd;
bfd.prerelease_text = Str::new();
bfd.build_code = Str::new();
bfd.build_date = Str::new();
TextFiles::read(F, FALSE, "unable to read build file", TRUE,
&BuildFiles::build_file_helper, NULL, (void *) &bfd);
return bfd;
}
void BuildFiles::build_file_helper(text_stream *text, text_file_position *tfp, void *state) {
build_file_data *bfd = (build_file_data *) state;
if (Str::len(text) == 0) return;
match_results mr = Regexp::create_mr();
if (Regexp::match(&mr, text, L"Build Date: *(%c*)")) {
bfd->build_date = Str::duplicate(mr.exp[0]);
} else if (Regexp::match(&mr, text, L"Build Number: *(%c*)")) {
bfd->build_code = Str::duplicate(mr.exp[0]);
} else if (Regexp::match(&mr, text, L"Prerelease: *(%c*)")) {
bfd->prerelease_text = Str::duplicate(mr.exp[0]);
} else {
Errors::in_text_file("can't parse build file line", tfp);
}
Regexp::dispose_of(&mr);
}
@ And here is how to write one:
=
void BuildFiles::write(build_file_data bfd, filename *F) {
text_stream vr_stream;
text_stream *OUT = &vr_stream;
if (Streams::open_to_file(OUT, F, UTF8_ENC) == FALSE)
Errors::fatal_with_file("can't write build file", F);
if (Str::len(bfd.prerelease_text) > 0)
WRITE("Prerelease: %S\n", bfd.prerelease_text);
WRITE("Build Date: %S\n", bfd.build_date);
if (Str::len(bfd.build_code) > 0)
WRITE("Build Number: %S\n", bfd.build_code);
Streams::close(OUT);
}
@h Bibliographic implications.
Whenever a web is read in by Inweb, its build file is looked at in order to
set some bibliographic data.
=
void BuildFiles::set_bibliographic_data_for(web *W) {
filename *F = BuildFiles::build_file_for_web(W);
if (F) {
build_file_data bfd = BuildFiles::read(F);
if (Str::len(bfd.prerelease_text) > 0)
Bibliographic::set_datum(W, I"Prerelease", bfd.prerelease_text);
if (Str::len(bfd.build_code) > 0)
Bibliographic::set_datum(W, I"Build Number", bfd.build_code);
if (Str::len(bfd.build_date) > 0)
Bibliographic::set_datum(W, I"Build Date", bfd.build_date);
}
}
@ A little later on, i.e., once the Contents page has been read, we want to
synthesize the semantic version number for the project. Note that this is
called even if no build file had ever been found, so it's quite legal for
the Contents page to specify all of this.
If no error occurs, then the expansion |[[Semantic Version Number]]| is
guaranteed to produce a semver-legal version number.
=
void BuildFiles::deduce_semver(web *W) {
TEMPORARY_TEXT(combined);
text_stream *s = Bibliographic::get_datum(W, I"Semantic Version Number");
if (Str::len(s) > 0) WRITE_TO(combined, "%S", s);
else {
text_stream *v = Bibliographic::get_datum(W, I"Version Number");
if (Str::len(v) > 0) WRITE_TO(combined, "%S", v);
text_stream *p = Bibliographic::get_datum(W, I"Prerelease");
if (Str::len(p) > 0) WRITE_TO(combined, "-%S", p);
text_stream *b = Bibliographic::get_datum(W, I"Build Number");
if (Str::len(b) > 0) WRITE_TO(combined, "+%S", b);
}
if (Str::len(combined) > 0) {
W->version_number = VersionNumbers::from_text(combined);
if (VersionNumbers::is_null(W->version_number)) {
Errors::fatal_with_text(
"Combined version '%S' does not comply with the semver standard",
combined);
} else {
Bibliographic::set_datum(W, I"Semantic Version Number", combined);
}
}
DISCARD_TEXT(combined);
}
@h Advancing.
We update the build date to today and, if supplied, also increment the build
number if we find that the date has changed.
=
void BuildFiles::advance_for_web(web *W) {
filename *F = BuildFiles::build_file_for_web(W);
if (F) BuildFiles::advance(F);
else Errors::fatal("web has no build file");
}
void BuildFiles::advance(filename *F) {
build_file_data bfd = BuildFiles::read(F);
if (BuildFiles::dated_today(bfd.build_date) == FALSE) {
BuildFiles::increment(bfd.build_code);
BuildFiles::write(bfd, F);
}
}
@ The standard date format we use is "26 February 2018". If the contents of
|dateline| match today's date in this format, we return |TRUE|; otherwise we
rewrite |dateline| to today and return |FALSE|.
=
int BuildFiles::dated_today(text_stream *dateline) {
char *monthname[12] = { "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December" };
TEMPORARY_TEXT(today);
WRITE_TO(today, "%d %s %d",
the_present->tm_mday, monthname[the_present->tm_mon], the_present->tm_year+1900);
int rv = TRUE;
if (Str::ne(dateline, today)) {
rv = FALSE;
Str::clear(dateline);
Str::copy(dateline, today);
}
DISCARD_TEXT(today);
return rv;
}
@ Traditional Inform build codes are four-character, e.g., |3Q27|. Here, we
read such a code and increase it by one. The two-digit code at the back is
incremented, but rolls around from |99| to |01|, in which case the letter is
advanced, except that |I| and |O| are skipped, and if the letter passes |Z|
then it rolls back around to |A| and the initial digit is incremented.
This allows for 21384 distinct build codes, enough to use one each day for
some 58 years.
=
void BuildFiles::increment(text_stream *T) {
if (Str::len(T) != 4) Errors::with_text("build code malformed: %S", T);
else {
int N = Str::get_at(T, 0) - '0';
int L = Str::get_at(T, 1);
int M1 = Str::get_at(T, 2) - '0';
int M2 = Str::get_at(T, 3) - '0';
if ((N < 0) || (N > 9) || (L < 'A') || (L > 'Z') ||
(M1 < 0) || (M1 > 9) || (M2 < 0) || (M2 > 9)) {
Errors::with_text("build code malformed: %S", T);
} else {
M2++;
if (M2 == 10) { M2 = 0; M1++; }
if (M1 == 10) { M1 = 0; M2 = 1; L++; }
if ((L == 'I') || (L == 'O')) L++;
if (L > 'Z') { L = 'A'; N++; }
if (N == 10) Errors::with_text("build code overflowed: %S", T);
else {
Str::clear(T);
WRITE_TO(T, "%d%c%d%d", N, L, M1, M2);
PRINT("Build code advanced to %S\n", T);
}
}
}
}

View file

@ -67,3 +67,5 @@ Chapter 6: Extras
"Additional features for turning webs into open-source projects."
Makefiles
Git Support
Build Files

View file

@ -551,3 +551,35 @@ Note that:
substitutes the path |P| for |W/docs/NAME|. But the files created there still
expect that to be able to link to a |../webs.html|, that is, in the directory
above them.
@h Semantic version numbering and build metadata.
When Inweb reads in a web, it also looks for a file called |build.txt| in
the web's directory; if that isn't there, it looks for the same file in the
current working directory; if that's not there either, never mind.
Such a file contains up to three text fields, all optional:
|Prerelease: alpha.1|
|Build Date: 23 March 2020|
|Build Number: 6Q26|
The bibliographic variables |Prerelease| and so on are then set from this
file. (They can equally well be set by the Contents section of the web, and
if so then that takes priority.)
The Prerelease and Build Number, if given, are used in combination with the
Version Number (set in the Contents) to produce the semantic version number,
or semver, for the web. For example, if the Contents included:
|Version Number: 6.2.12|
then the semver would be |6.2.12-alpha.1+6Q26|. This is accessible within
the web as the variable |Semantic Version Number|.
@ A special advancing mechanism exists to update build numbers and dates.
Running Inweb with |-advance-build W| checks the build date for web |W|:
if it differs from today, then it is changed to today, and the build code
is advanced by one.
Running |-advance-build-file B| does this for a stand-alone build file |B|,
without need of a web.

View file

@ -1,7 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>[[Booklet Title]]</title>
<title>[[Title]]</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">

View file

@ -1,6 +1,6 @@
<html>
<head>
<title>[[Title]] [[Version Number]]</title>
<title>[[Title]]</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
@ -11,8 +11,8 @@
[[Navigation]]
</nav>
<main role="main">
<ul class="crumbs">[[Breadcrumbs]]<li><b>[[Title]] [[Version Number]]</b></li></ul>
<p class="purpose">[[Purpose]]</p>
<ul class="crumbs">[[Breadcrumbs]]<li><b>[[Title]]</b></li></ul>
<p class="purpose">[[Purpose]] This is version [[Version Number]].</p>
<hr>
<ul class="chapterlist">
[[Repeat Chapter]]

View file

@ -1,6 +1,6 @@
<html>
<head>
<title>[[Title]] [[Version Number]]</title>
<title>[[Title]]</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
@ -11,8 +11,8 @@
[[Navigation]]
</nav>
<main role="main">
<ul class="crumbs">[[Breadcrumbs]]<li><b>[[Title]] [[Version Number]]</b></li></ul>
<p class="purpose">[[Purpose]]</p>
<ul class="crumbs">[[Breadcrumbs]]<li><b>[[Title]]</b></li></ul>
<p class="purpose">[[Purpose]] This is version [[Version Number]].</p>
<hr>
<ul class="sectionlist">
[[Repeat Section]]

File diff suppressed because it is too large Load diff

3
build.txt Normal file
View file

@ -0,0 +1,3 @@
Prerelease: alpha.1
Build Date: 23 March 2020
Build Number: 1A01

View file

@ -176,6 +176,7 @@ prints a filename by calling <code class="display"><span class="extract">Filenam
<pre class="displaydefn">
<span class="functiontext">Writers::register_writer</span><span class="plain">(</span><span class="character">'f'</span><span class="plain">, &amp;</span><span class="functiontext">Filenames::writer</span><span class="plain">);</span>
<span class="functiontext">Writers::register_writer</span><span class="plain">(</span><span class="character">'p'</span><span class="plain">, &amp;</span><span class="functiontext">Pathnames::writer</span><span class="plain">);</span>
<span class="functiontext">Writers::register_writer</span><span class="plain">(</span><span class="character">'v'</span><span class="plain">, &amp;</span><span class="functiontext">VersionNumbers::writer</span><span class="plain">);</span>
<span class="functiontext">Writers::register_writer</span><span class="plain">(</span><span class="character">'S'</span><span class="plain">, &amp;</span><span class="functiontext">Streams::writer</span><span class="plain">);</span>
</pre>

View file

@ -196,15 +196,15 @@ want speed rather than memory efficiency.
<p class="endnote">The function LinkedLists::len is used in <a href="#SP10">&#167;10</a>, 5/ee (<a href="5-ee.html#SP7_3">&#167;7.3</a>).</p>
<p class="endnote">The function LinkedLists::first is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function LinkedLists::first is used in <a href="#SP7">&#167;7</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
<p class="endnote">The function LinkedLists::entry is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function LinkedLists::last is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function LinkedLists::next is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function LinkedLists::next is used in <a href="#SP7">&#167;7</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
<p class="endnote">The function LinkedLists::content is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function LinkedLists::content is used in <a href="#SP7">&#167;7</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. A macro-ized API. </b>These intentionally hide the implementation. The difference between
<code class="display"><span class="extract">FIRST_IN_LINKED_LIST</span></code> and <code class="display"><span class="extract">FIRST_ITEM_IN_LINKED_LIST</span></code> is that one returns

View file

@ -103,6 +103,8 @@ with the memory system. The ones here are those needed by Foundation.
<span class="definitionkeyword">enum</span> <span class="constant">method_MT</span>
<span class="definitionkeyword">enum</span> <span class="constant">method_set_MT</span>
<span class="definitionkeyword">enum</span> <span class="constant">ebook_mark_MT</span>
<span class="definitionkeyword">enum</span> <span class="constant">semantic_version_number_holder_MT</span>
<span class="definitionkeyword">enum</span> <span class="constant">semver_range_MT</span>
</pre>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>For each type of object to be allocated, a single structure of the
following design is maintained. Types which are allocated individually,
@ -732,6 +734,8 @@ used in the lower levels.
<span class="identifier">ALLOCATE_INDIVIDUALLY</span><span class="plain">(</span><span class="reserved">method</span><span class="plain">)</span>
<span class="identifier">ALLOCATE_INDIVIDUALLY</span><span class="plain">(</span><span class="reserved">method_set</span><span class="plain">)</span>
<span class="identifier">ALLOCATE_INDIVIDUALLY</span><span class="plain">(</span><span class="reserved">ebook_mark</span><span class="plain">)</span>
<span class="identifier">ALLOCATE_INDIVIDUALLY</span><span class="plain">(</span><span class="reserved">semantic_version_number_holder</span><span class="plain">)</span>
<span class="identifier">ALLOCATE_INDIVIDUALLY</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain">)</span>
<span class="identifier">ALLOCATE_IN_ARRAYS</span><span class="plain">(</span><span class="reserved">dict_entry</span><span class="plain">, 100)</span>
<span class="identifier">ALLOCATE_IN_ARRAYS</span><span class="plain">(</span><span class="reserved">HTML_tag</span><span class="plain">, 1000)</span>

View file

@ -511,13 +511,13 @@ all other switches are delegated to the client's callback function <code class="
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">LOG_CLSW</span><span class="plain">: </span>&lt;<span class="cwebmacro">Parse debugging log inclusion</span> <span class="cwebmacronumber">13.1.1</span>&gt;<span class="plain">; </span><span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">VERSION_CLSW</span><span class="plain">: {</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">bn</span><span class="plain"> = </span><span class="string">"[[Build Number]]"</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">vn</span><span class="plain"> = </span><span class="string">"[[Version Number]]"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">vn</span><span class="plain">[0] == 0) </span><span class="identifier">vn</span><span class="plain"> = </span><span class="string">"1"</span><span class="plain">;</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"[[Title]]"</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">svn</span><span class="plain"> = </span><span class="string">"[[Semantic Version Number]]"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">svn</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" version %s"</span><span class="plain">, </span><span class="identifier">svn</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">vname</span><span class="plain"> = </span><span class="string">"[[Version Name]]"</span><span class="plain">;</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"[[Title]] %s"</span><span class="plain">, </span><span class="identifier">vn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">vname</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" '%s'"</span><span class="plain">, </span><span class="identifier">vname</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bn</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" (build %s)"</span><span class="plain">, </span><span class="identifier">bn</span><span class="plain">);</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">d</span><span class="plain"> = </span><span class="string">"[[Build Date]]"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain">[0]) </span><span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" (%s)"</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">innocuous</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>

View file

@ -67,7 +67,7 @@
<p class="endnote">The function Characters::isalpha is used in 2/wal (<a href="2-wal.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Characters::isdigit is used in 2/wal (<a href="2-wal.html#SP5">&#167;5</a>), 3/fln (<a href="3-fln.html#SP9">&#167;9</a>).</p>
<p class="endnote">The function Characters::isdigit is used in 2/wal (<a href="2-wal.html#SP5">&#167;5</a>), 3/fln (<a href="3-fln.html#SP9">&#167;9</a>), 7/vn (<a href="7-vn.html#SP7">&#167;7</a>, <a href="7-vn.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Characters::isupper appears nowhere else.</p>

View file

@ -82,7 +82,7 @@ access.
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::new is used in <a href="#SP3">&#167;3</a>, 2/dl (<a href="2-dl.html#SP4_1">&#167;4.1</a>), 2/dct (<a href="2-dct.html#SP7_3_1">&#167;7.3.1</a>), 3/cla (<a href="3-cla.html#SP6">&#167;6</a>, <a href="3-cla.html#SP11">&#167;11</a>), 5/ee (<a href="5-ee.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Str::new is used in <a href="#SP3">&#167;3</a>, 2/dl (<a href="2-dl.html#SP4_1">&#167;4.1</a>), 2/dct (<a href="2-dct.html#SP7_3_1">&#167;7.3.1</a>), 3/cla (<a href="3-cla.html#SP6">&#167;6</a>, <a href="3-cla.html#SP11">&#167;11</a>), 5/ee (<a href="5-ee.html#SP5">&#167;5</a>), 7/vn (<a href="7-vn.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function Str::new_with_capacity is used in 3/pth (<a href="3-pth.html#SP4">&#167;4</a>), 3/fln (<a href="3-fln.html#SP2">&#167;2</a>).</p>
@ -108,7 +108,7 @@ duplicated as <code class="display"><span class="extract">NULL</span></code>.
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::duplicate is used in 2/dct (<a href="2-dct.html#SP7_3_1">&#167;7.3.1</a>), 3/cla (<a href="3-cla.html#SP5_1">&#167;5.1</a>), 5/ee (<a href="5-ee.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Str::duplicate is used in 2/dct (<a href="2-dct.html#SP7_3_1">&#167;7.3.1</a>), 3/cla (<a href="3-cla.html#SP5_1">&#167;5.1</a>), 5/ee (<a href="5-ee.html#SP5">&#167;5</a>), 7/vn (<a href="7-vn.html#SP7_1">&#167;7.1</a>).</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Converting from C strings. </b>Here we open text streams initially equal to the given C strings, and
with the capacity of the initial block large enough to hold the whole
@ -222,7 +222,7 @@ thing plus a little extra, for efficiency's sake.
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::atoi is used in 3/cla (<a href="3-cla.html#SP12">&#167;12</a>).</p>
<p class="endnote">The function Str::atoi is used in 3/cla (<a href="3-cla.html#SP12">&#167;12</a>), 7/vn (<a href="7-vn.html#SP10">&#167;10</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Length. </b>A puritan would return a <code class="display"><span class="extract">size_t</span></code> here, but I am not a puritan.
</p>
@ -236,7 +236,7 @@ thing plus a little extra, for efficiency's sake.
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::len is used in <a href="#SP3">&#167;3</a>, <a href="#SP7">&#167;7</a>, <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>, <a href="#SP12">&#167;12</a>, <a href="#SP13">&#167;13</a>, <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, <a href="#SP16">&#167;16</a>, <a href="#SP18">&#167;18</a>, <a href="#SP19">&#167;19</a>, <a href="#SP20">&#167;20</a>, <a href="#SP21">&#167;21</a>, <a href="#SP23">&#167;23</a>, <a href="#SP24">&#167;24</a>, <a href="#SP25">&#167;25</a>, 2/dl (<a href="2-dl.html#SP9">&#167;9</a>), 3/cla (<a href="3-cla.html#SP13">&#167;13</a>, <a href="3-cla.html#SP14">&#167;14</a>, <a href="3-cla.html#SP14_1">&#167;14.1</a>), 3/pth (<a href="3-pth.html#SP4">&#167;4</a>, <a href="3-pth.html#SP5">&#167;5</a>, <a href="3-pth.html#SP7">&#167;7</a>), 3/fln (<a href="3-fln.html#SP2">&#167;2</a>, <a href="3-fln.html#SP3">&#167;3</a>, <a href="3-fln.html#SP5">&#167;5</a>, <a href="3-fln.html#SP9">&#167;9</a>), 4/taa (<a href="4-taa.html#SP2_1">&#167;2.1</a>), 4/pm (<a href="4-pm.html#SP3">&#167;3</a>, <a href="4-pm.html#SP4">&#167;4</a>, <a href="4-pm.html#SP11_3">&#167;11.3</a>, <a href="4-pm.html#SP14">&#167;14</a>), 5/htm (<a href="5-htm.html#SP7">&#167;7</a>, <a href="5-htm.html#SP15">&#167;15</a>), 5/ee (<a href="5-ee.html#SP7_1">&#167;7.1</a>, <a href="5-ee.html#SP7_2_3">&#167;7.2.3</a>, <a href="5-ee.html#SP7_2_4">&#167;7.2.4</a>).</p>
<p class="endnote">The function Str::len is used in <a href="#SP3">&#167;3</a>, <a href="#SP7">&#167;7</a>, <a href="#SP10">&#167;10</a>, <a href="#SP11">&#167;11</a>, <a href="#SP12">&#167;12</a>, <a href="#SP13">&#167;13</a>, <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, <a href="#SP16">&#167;16</a>, <a href="#SP18">&#167;18</a>, <a href="#SP19">&#167;19</a>, <a href="#SP20">&#167;20</a>, <a href="#SP21">&#167;21</a>, <a href="#SP23">&#167;23</a>, <a href="#SP24">&#167;24</a>, <a href="#SP25">&#167;25</a>, 2/dl (<a href="2-dl.html#SP9">&#167;9</a>), 3/cla (<a href="3-cla.html#SP13">&#167;13</a>, <a href="3-cla.html#SP14">&#167;14</a>, <a href="3-cla.html#SP14_1">&#167;14.1</a>), 3/pth (<a href="3-pth.html#SP4">&#167;4</a>, <a href="3-pth.html#SP5">&#167;5</a>, <a href="3-pth.html#SP7">&#167;7</a>), 3/fln (<a href="3-fln.html#SP2">&#167;2</a>, <a href="3-fln.html#SP3">&#167;3</a>, <a href="3-fln.html#SP5">&#167;5</a>, <a href="3-fln.html#SP9">&#167;9</a>), 4/taa (<a href="4-taa.html#SP2_1">&#167;2.1</a>), 4/pm (<a href="4-pm.html#SP3">&#167;3</a>, <a href="4-pm.html#SP4">&#167;4</a>, <a href="4-pm.html#SP11_3">&#167;11.3</a>, <a href="4-pm.html#SP14">&#167;14</a>), 5/htm (<a href="5-htm.html#SP7">&#167;7</a>, <a href="5-htm.html#SP15">&#167;15</a>), 5/ee (<a href="5-ee.html#SP7_1">&#167;7.1</a>, <a href="5-ee.html#SP7_2_3">&#167;7.2.3</a>, <a href="5-ee.html#SP7_2_4">&#167;7.2.4</a>), 7/vn (<a href="7-vn.html#SP7">&#167;7</a>, <a href="7-vn.html#SP7_1">&#167;7.1</a>, <a href="7-vn.html#SP10">&#167;10</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Position markers. </b>A position marker is a lightweight way to refer to a particular position
in a given string. Position 0 is before the first character; if, for
@ -370,11 +370,11 @@ at those positions may well not be, of course.)
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::get is used in <a href="#SP7">&#167;7</a>, <a href="#SP16">&#167;16</a>, <a href="#SP19">&#167;19</a>, <a href="#SP21">&#167;21</a>, <a href="#SP22">&#167;22</a>, <a href="#SP23">&#167;23</a>, <a href="#SP24">&#167;24</a>, <a href="#SP25">&#167;25</a>, 2/dct (<a href="2-dct.html#SP4">&#167;4</a>), 3/pth (<a href="3-pth.html#SP4">&#167;4</a>, <a href="3-pth.html#SP5">&#167;5</a>), 3/fln (<a href="3-fln.html#SP2">&#167;2</a>, <a href="3-fln.html#SP3">&#167;3</a>, <a href="3-fln.html#SP7">&#167;7</a>, <a href="3-fln.html#SP8">&#167;8</a>, <a href="3-fln.html#SP9">&#167;9</a>), 3/shl (<a href="3-shl.html#SP1">&#167;1</a>), 4/pm (<a href="4-pm.html#SP5">&#167;5</a>), 5/ee (<a href="5-ee.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function Str::get is used in <a href="#SP7">&#167;7</a>, <a href="#SP16">&#167;16</a>, <a href="#SP19">&#167;19</a>, <a href="#SP21">&#167;21</a>, <a href="#SP22">&#167;22</a>, <a href="#SP23">&#167;23</a>, <a href="#SP24">&#167;24</a>, <a href="#SP25">&#167;25</a>, 2/dct (<a href="2-dct.html#SP4">&#167;4</a>), 3/pth (<a href="3-pth.html#SP4">&#167;4</a>, <a href="3-pth.html#SP5">&#167;5</a>), 3/fln (<a href="3-fln.html#SP2">&#167;2</a>, <a href="3-fln.html#SP3">&#167;3</a>, <a href="3-fln.html#SP7">&#167;7</a>, <a href="3-fln.html#SP8">&#167;8</a>, <a href="3-fln.html#SP9">&#167;9</a>), 3/shl (<a href="3-shl.html#SP1">&#167;1</a>), 4/pm (<a href="4-pm.html#SP5">&#167;5</a>), 5/ee (<a href="5-ee.html#SP5">&#167;5</a>), 7/vn (<a href="7-vn.html#SP7">&#167;7</a>, <a href="7-vn.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Str::get_at is used in <a href="#SP20">&#167;20</a>, <a href="#SP23">&#167;23</a>, <a href="#SP25">&#167;25</a>, 3/pth (<a href="3-pth.html#SP7">&#167;7</a>), 3/fln (<a href="3-fln.html#SP5">&#167;5</a>), 4/taa (<a href="4-taa.html#SP2">&#167;2</a>), 4/pm (<a href="4-pm.html#SP3">&#167;3</a>, <a href="4-pm.html#SP4">&#167;4</a>, <a href="4-pm.html#SP11">&#167;11</a>, <a href="4-pm.html#SP11_4">&#167;11.4</a>, <a href="4-pm.html#SP11_6">&#167;11.6</a>, <a href="4-pm.html#SP14">&#167;14</a>, <a href="4-pm.html#SP14_1">&#167;14.1</a>).</p>
<p class="endnote">The function Str::get_first_char appears nowhere else.</p>
<p class="endnote">The function Str::get_first_char is used in 7/vn (<a href="7-vn.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function Str::get_last_char appears nowhere else.</p>
@ -421,7 +421,7 @@ at those positions may well not be, of course.)
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::clear is used in <a href="#SP16">&#167;16</a>, <a href="#SP17">&#167;17</a>, <a href="#SP24">&#167;24</a>, 3/drc (<a href="3-drc.html#SP2">&#167;2</a>), 4/tf (<a href="4-tf.html#SP6">&#167;6</a>), 4/pm (<a href="4-pm.html#SP11_6">&#167;11.6</a>).</p>
<p class="endnote">The function Str::clear is used in <a href="#SP16">&#167;16</a>, <a href="#SP17">&#167;17</a>, <a href="#SP24">&#167;24</a>, 3/drc (<a href="3-drc.html#SP2">&#167;2</a>), 4/tf (<a href="4-tf.html#SP6">&#167;6</a>), 4/pm (<a href="4-pm.html#SP11_6">&#167;11.6</a>), 7/vn (<a href="7-vn.html#SP7_1">&#167;7.1</a>).</p>
<p class="endnote">The function Str::truncate is used in <a href="#SP23">&#167;23</a>, <a href="#SP24">&#167;24</a>.</p>
@ -517,7 +517,7 @@ at those positions may well not be, of course.)
<p class="endnote">The function Str::eq_insensitive appears nowhere else.</p>
<p class="endnote">The function Str::ne appears nowhere else.</p>
<p class="endnote">The function Str::ne is used in 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
<p class="endnote">The function Str::ne_insensitive appears nowhere else.</p>
@ -550,7 +550,7 @@ alphabetic sorting, like <code class="display"><span class="extract">strlen</spa
<p class="inwebparagraph"></p>
<p class="endnote">The function Str::cmp is used in <a href="#SP18">&#167;18</a>.</p>
<p class="endnote">The function Str::cmp is used in <a href="#SP18">&#167;18</a>, 7/vn (<a href="7-vn.html#SP8">&#167;8</a>).</p>
<p class="endnote">The function Str::cmp_insensitive is used in <a href="#SP18">&#167;18</a>, 3/cla (<a href="3-cla.html#SP15">&#167;15</a>).</p>

View file

@ -0,0 +1,447 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>6/sd</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '7/vn' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#7">Chapter 7: Semantic Versioning</a></li><li><b>Version Numbers</b></li></ul><p class="purpose">Semantic version numbers such as 3.7.1.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Standard adoption</a></li><li><a href="#SP5">&#167;5. Printing and parsing</a></li><li><a href="#SP8">&#167;8. Precendence</a></li><li><a href="#SP11">&#167;11. Trichotomy</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Standard adoption. </b>The Semantic Version Number standard, semver 2.0.0, provides a strict set
of rules for the format and meaning of version numbers: see <code class="display"><span class="extract">https://semver.org</span></code>.
</p>
<p class="inwebparagraph">Prior to the standard most version numbers in computing usage looked like
dot-divided runs of non-negative integers: for example, 4, 7.1, and 0.2.3.
The standard now requires exactly three: major, minor and patch. It's
therefore formally incorrect to have a version 2, or a version 2.3. We will
not be so strict on the textual form, which we will allow to be abbreviated.
Thus:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) The text <code class="display"><span class="extract">6.4.7</span></code> is understood to mean 6.4.7 and printed back as <code class="display"><span class="extract">6.4.7</span></code>
</li><li>(b) The text <code class="display"><span class="extract">6</span></code> is understood to mean 6.0.0 and printed back as <code class="display"><span class="extract">6</span></code>
</li><li>(c) The text <code class="display"><span class="extract">6.1</span></code> is understood to mean 6.1.0 and printed back as <code class="display"><span class="extract">6.1</span></code>
</li><li>(d) The text <code class="display"><span class="extract">6.1.0</span></code> is understood to mean 6.1.0 and printed back as <code class="display"><span class="extract">6.1.0</span></code>
</li></ul>
<p class="inwebparagraph">Similarly, the absence of a version number (called "null" below) will be
understood to mean 0.0.0, but will be distinguished from the explicit choice
to number something as 0.0.0.
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>A complication is that Inform 7 extensions have for many years allowed two
forms of version number: either just <code class="display"><span class="extract">N</span></code>, which fits the scheme above, or
<code class="display"><span class="extract">N/DDDDDD</span></code>, which does not. This is a format which was chosen for sentimental
reasons: IF enthusiasts know it well from the banner text of the Infocom
titles of the 1980s. This story file, for instance, was compiled at the
time of the Reykjavik summit between Presidents Gorbachev and Reagan:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">Moonmist</span>
<span class="plain">Infocom interactive fiction - a mystery story</span>
<span class="plain">Copyright (c) 1986 by Infocom, Inc. All rights reserved.</span>
<span class="plain">Moonmist is a trademark of Infocom, Inc.</span>
<span class="plain">Release number 9 / Serial number 861022</span>
</pre>
<p class="inwebparagraph">Story file collectors customarily abbreviate this in catalogues to <code class="display"><span class="extract">9/861022</span></code>.
</p>
<p class="inwebparagraph">We will therefore allow this notation, and convert it silently each way.
<code class="display"><span class="extract">N/DDDDDD</span></code> is equivalent to <code class="display"><span class="extract">N.DDDDDD</span></code>. Thus, <code class="display"><span class="extract">9/861022</span></code> means 9.861022.0 in
semver precedence order.
</p>
<p class="inwebparagraph">In all non-textual respects, and in particular on precedence rules, we follow
the standard exactly. The only reason we allow these abbreviations is because
we don't want to force Inform extension writers to type "Version 3.4.1 of
Such-and-Such by Me begins here", and so on: it would break all existing
extensions, for one thing, and it looks unfriendly.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>In the array below, unspecified numbers are stored as <code class="display"><span class="extract">-1</span></code>. The three
components are otherwise required to be non-negative integers.
</p>
<p class="inwebparagraph">Semver allows for more elaborate forms: for example <code class="display"><span class="extract">3.1.41-alpha.72.zeta+6Q45</span></code>
would mean 3.1.41 but with prerelease versioning <code class="display"><span class="extract">alpha.72.zeta</span></code> and build
metadata <code class="display"><span class="extract">6Q45</span></code>. The <code class="display"><span class="extract">prerelease_segments</span></code> list for this would be a list of
three texts: <code class="display"><span class="extract">alpha</span></code>, <code class="display"><span class="extract">72</span></code>, <code class="display"><span class="extract">zeta</span></code>.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain"> 3 </span> <span class="comment">major, minor, patch</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_numbers</span><span class="plain">[</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">prerelease_segments</span><span class="plain">; </span> <span class="comment">of <code class="display"><span class="extract">text_stream</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">build_metadata</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">semantic_version_number</span><span class="plain">;</span>
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number_holder</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">version</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">semantic_version_number_holder</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure semantic_version_number is accessed in 7/vnr and here.</p>
<p class="endnote">The structure semantic_version_number_holder is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>All invalid strings of numbers &mdash; i.e., breaking the above rules &mdash; are
called "null" versions, and can never be valid as the version of anything.
Instead they are used to represent the absence of a version number.
(In particular, a string of <code class="display"><span class="extract">-1</span></code>s is null.)
</p>
<pre class="display">
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">pragma</span><span class="plain"> </span><span class="identifier">clang</span><span class="plain"> </span><span class="identifier">diagnostic</span><span class="plain"> </span><span class="identifier">push</span>
<span class="plain">#</span><span class="identifier">pragma</span><span class="plain"> </span><span class="identifier">clang</span><span class="plain"> </span><span class="identifier">diagnostic</span><span class="plain"> </span><span class="identifier">ignored</span><span class="plain"> </span><span class="string">"-Wconditional-uninitialized"</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
<span class="identifier">V</span><span class="element">.prerelease_segments</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">V</span><span class="element">.build_metadata</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">pragma</span><span class="plain"> </span><span class="identifier">clang</span><span class="plain"> </span><span class="identifier">diagnostic</span><span class="plain"> </span><span class="identifier">pop</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0, </span><span class="identifier">allow</span><span class="plain">=</span><span class="constant">TRUE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &lt; -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; </span> <span class="comment">should never happen</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == -1) </span><span class="identifier">allow</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">allow</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; </span> <span class="comment">should never happen</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[0] &lt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::null is used in <a href="#SP7">&#167;7</a>, <a href="#SP7_1">&#167;7.1</a>, 7/vnr (<a href="7-vnr.html#SP3">&#167;3</a>, <a href="7-vnr.html#SP4">&#167;4</a>).</p>
<p class="endnote">The function VersionNumbers::is_null is used in <a href="#SP5">&#167;5</a>, 7/vnr (<a href="7-vnr.html#SP4">&#167;4</a>, <a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Printing and parsing. </b>Printing is simple enough:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VersionNumbers::to_text</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"null"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; (</span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">) &amp;&amp; (</span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &gt;= 0); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">&gt;0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.prerelease_segments</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">V</span><span class="element">.prerelease_segments</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ == 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"-"</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.build_metadata</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"+%S"</span><span class="plain">, </span><span class="identifier">V</span><span class="element">.build_metadata</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::to_text is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>And this provides for the <code class="display"><span class="extract">%v</span></code> escape, though we must be careful when
using this to pass a pointer to the version, not the version itself;
variadic macros are not carefully enough type-checked by <code class="display"><span class="extract">clang</span></code> or <code class="display"><span class="extract">gcc</span></code>
to catch this sort of slip.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VersionNumbers::writer</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">format_string</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vE</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain"> = (</span><span class="reserved">semantic_version_number</span><span class="plain"> *) </span><span class="identifier">vE</span><span class="plain">;</span>
<span class="functiontext">VersionNumbers::to_text</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, *</span><span class="identifier">V</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::writer is used in 1/fnd (<a href="1-fnd.html#SP8_1">&#167;8.1</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Parsing is much more of a slog. The following returns a null version if
the text <code class="display"><span class="extract">T</span></code> is in any respect malformed, i.e., if it deviates from the
above specification in even the most trivial way. We parse the three parts
of a semver version in order: e.g. <code class="display"><span class="extract">3.1.41-alpha.72.zeta+6Q45</span></code> the first
part is up to the hyphen, the second part between the hyphen and the plus
sign, and the third part runs to the end. The second and third parts are
optional, but if both are given, they must be in that order.
</p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">MMP_SEMVERPART</span><span class="definitionkeyword"> from </span><span class="constant">1</span>
<span class="definitionkeyword">enum</span> <span class="constant">PRE_SEMVERPART</span>
<span class="definitionkeyword">enum</span> <span class="constant">BM_SEMVERPART</span>
</pre>
<pre class="display">
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">component</span><span class="plain"> = 0, </span><span class="identifier">val</span><span class="plain"> = -1, </span><span class="identifier">dots_used</span><span class="plain"> = 0, </span><span class="identifier">slashes_used</span><span class="plain"> = 0, </span><span class="identifier">count</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">MMP_SEMVERPART</span><span class="plain">;</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">part</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MMP_SEMVERPART</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) </span><span class="identifier">dots_used</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'/'</span><span class="plain">) </span><span class="identifier">slashes_used</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'/'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'-'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">component</span><span class="plain"> &gt;= </span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">component</span><span class="plain">] = </span><span class="identifier">val</span><span class="plain">;</span>
<span class="identifier">component</span><span class="plain">++; </span><span class="identifier">val</span><span class="plain"> = -1; </span><span class="identifier">count</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'-'</span><span class="plain">) </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">PRE_SEMVERPART</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">) </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">BM_SEMVERPART</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">digit</span><span class="plain"> = </span><span class="identifier">c</span><span class="plain"> - </span><span class="character">'0'</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">val</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">slashes_used</span><span class="plain"> == 0))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> &lt; 0) </span><span class="identifier">val</span><span class="plain"> = </span><span class="identifier">digit</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">val</span><span class="plain"> = 10*</span><span class="identifier">val</span><span class="plain"> + </span><span class="identifier">digit</span><span class="plain">;</span>
<span class="identifier">count</span><span class="plain">++;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PRE_SEMVERPART</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">; </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">BM_SEMVERPART</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">BM_SEMVERPART</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.build_metadata</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">V</span><span class="element">.build_metadata</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">V</span><span class="element">.build_metadata</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">part</span><span class="plain"> == </span><span class="constant">PRE_SEMVERPART</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">) &gt; 0)) </span>&lt;<span class="cwebmacro">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">dots_used</span><span class="plain"> &gt; 0) &amp;&amp; (</span><span class="identifier">slashes_used</span><span class="plain"> &gt; 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">slashes_used</span><span class="plain"> &gt; 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">component</span><span class="plain"> &gt; 1) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count</span><span class="plain"> != 6) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">part</span><span class="plain"> == </span><span class="constant">MMP_SEMVERPART</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">component</span><span class="plain"> &gt;= </span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">component</span><span class="plain">] = </span><span class="identifier">val</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::from_text appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">) == 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="element">.prerelease_segments</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">V</span><span class="element">.prerelease_segments</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">), </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">V</span><span class="element">.prerelease_segments</span><span class="plain">);</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a> (three times).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Precendence. </b>The most important part of the semver standard is the rule on which versions
take precedence over which others, and we follow it exactly. The following
criteria are used in turn: major version; minor version; patch version;
any prerelease elements, which must be compared numerically if consisting
of digits only, and alphabetically otherwise; and finally the number of
prerelease elements. Build metadata is disregarded entirely.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N1</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::floor</span><span class="plain">(</span><span class="identifier">V1</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N2</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::floor</span><span class="plain">(</span><span class="identifier">V2</span><span class="element">.version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &gt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &lt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">I1</span><span class="plain"> = (</span><span class="identifier">V1</span><span class="element">.prerelease_segments</span><span class="plain">)?(</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="identifier">V1</span><span class="element">.prerelease_segments</span><span class="plain">)):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">I2</span><span class="plain"> = (</span><span class="identifier">V2</span><span class="element">.prerelease_segments</span><span class="plain">)?(</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="identifier">V2</span><span class="element">.prerelease_segments</span><span class="plain">)):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">I1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">I2</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T1</span><span class="plain"> = (</span><span class="reserved">text_stream</span><span class="plain"> *) </span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="identifier">I1</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T2</span><span class="plain"> = (</span><span class="reserved">text_stream</span><span class="plain"> *) </span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="identifier">I2</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N1</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::strict_atoi</span><span class="plain">(</span><span class="identifier">T1</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N2</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::strict_atoi</span><span class="plain">(</span><span class="identifier">T2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N1</span><span class="plain"> &gt;= 0) &amp;&amp; (</span><span class="identifier">N2</span><span class="plain"> &gt;= 0)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &lt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &gt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::ne</span><span class="plain">(</span><span class="identifier">T1</span><span class="plain">, </span><span class="identifier">T2</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="identifier">T1</span><span class="plain">, </span><span class="identifier">T2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">I1</span><span class="plain"> = </span><span class="functiontext">LinkedLists::next</span><span class="plain">(</span><span class="identifier">I1</span><span class="plain">);</span>
<span class="identifier">I2</span><span class="plain"> = </span><span class="functiontext">LinkedLists::next</span><span class="plain">(</span><span class="identifier">I2</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">I2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">I2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::le is used in <a href="#SP11">&#167;11</a>, 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>The effect of this is to read unspecified versions of major, minor or patch
as if they were 0:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::floor</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> &lt; 0) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::floor is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>This returns a non-negative integer if <code class="display"><span class="extract">T</span></code> contains only digits, and <code class="display"><span class="extract">-1</span></code>
otherwise. If the value has more than about 10 digits, then the result will
not be meaningful, which I think is a technical violation of the standard.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::strict_atoi</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">) &gt; 1)) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::atoi</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, 0);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::strict_atoi is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Trichotomy. </b>We now use the above function to construct ordering relations on semvers.
These are trichotomous, that is, for each pair <code class="display"><span class="extract">V1, V2</span></code>, exactly one of the
<code class="display"><span class="extract">VersionNumbers::eq(V1, V2)</span></code>, <code class="display"><span class="extract">VersionNumbers::gt(V1, V2)</span></code>, <code class="display"><span class="extract">VersionNumbers::lt(V1, V2)</span></code>
is true.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">, </span><span class="identifier">V1</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::ne</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">))?</span><span class="constant">FALSE</span><span class="plain">:</span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">))?</span><span class="constant">FALSE</span><span class="plain">:</span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::ge</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">, </span><span class="identifier">V1</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::lt</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::ge</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">))?</span><span class="constant">FALSE</span><span class="plain">:</span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::eq is used in <a href="#SP12">&#167;12</a>.</p>
<p class="endnote">The function VersionNumbers::ne appears nowhere else.</p>
<p class="endnote">The function VersionNumbers::gt is used in <a href="#SP12">&#167;12</a>, 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function VersionNumbers::ge is used in 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function VersionNumbers::lt is used in 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>And the following can be used for sorting, following the <code class="display"><span class="extract">strcmp</span></code> convention.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::cmp</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 1;</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::cmp is used in 7/vnr (<a href="7-vnr.html#SP8">&#167;8</a>, <a href="7-vnr.html#SP9">&#167;9</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 7: Semantic Versioning.)</i></li><li><a href="7-vnr.html">Continue with 'Version Number Ranges'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>

View file

@ -0,0 +1,330 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>7/vn</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '7/vnr' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#7">Chapter 7: Semantic Versioning</a></li><li><b>Version Number Ranges</b></li></ul><p class="purpose">Ranges of acceptable version numbers.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Ranges</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Ranges. </b>We often want to check if a semver lies in a given precedence range, which we
store as an "interval" in the mathematical sense. For example, the range <code class="display"><span class="extract">[2,6)</span></code>
means all versions from 2.0.0 (inclusve) up to, but not equal to, 6.0.0. The
lower end is called "closed" because it includes the end-value 2.0.0, and the
upper end "open" because it does not. An infinite end means that there
os no restriction in that direction; an empty end means that, in fact, the
interval is the empty set, that is, that no version number can ever satisfy it.
</p>
<p class="inwebparagraph">The <code class="display"><span class="extract">end_value</span></code> element is meaningful only for <code class="display"><span class="extract">CLOSED_RANGE_END</span></code> and <code class="display"><span class="extract">OPEN_RANGE_END</span></code>
ends. If one end is marked <code class="display"><span class="extract">EMPTY_RANGE_END</span></code>, so must the other be: it makes
no sense for an interval to be empty seen from one end but not the other.
</p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">CLOSED_RANGE_END</span><span class="definitionkeyword"> from </span><span class="constant">1</span>
<span class="definitionkeyword">enum</span> <span class="constant">OPEN_RANGE_END</span>
<span class="definitionkeyword">enum</span> <span class="constant">INFINITE_RANGE_END</span>
<span class="definitionkeyword">enum</span> <span class="constant">EMPTY_RANGE_END</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">range_end</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end_type</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">end_value</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">range_end</span><span class="plain">;</span>
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semver_range</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">lower</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">upper</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">semver_range</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure range_end is private to this section.</p>
<p class="endnote">The structure semver_range is private to this section.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>As hinted above, the notation <code class="display"><span class="extract">[</span></code> and <code class="display"><span class="extract">]</span></code> is used for closed ends, and <code class="display"><span class="extract">(</span></code>
and <code class="display"><span class="extract">)</span></code> for open ones.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no range"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"[%v,"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_value</span><span class="plain">)); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">OPEN_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(%v,"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_value</span><span class="plain">)); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(-infty,"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"empty"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v]"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_value</span><span class="plain">)); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">OPEN_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v)"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_value</span><span class="plain">)); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"infty)"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::write_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The "allow anything" range runs from minus to plus infinity. Every version
number lies in this range.
</p>
<pre class="display">
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> = </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_value</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> = </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_value</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::is_any_range</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::any_range is used in <a href="#SP4">&#167;4</a>, <a href="#SP5">&#167;5</a>.</p>
<p class="endnote">The function VersionNumberRanges::is_any_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The "compatibility" range for a given version lies at the heart of semver:
to be compatible with version <code class="display"><span class="extract">V</span></code>, version <code class="display"><span class="extract">W</span></code> must be of equal or greater
precedence, and must have the same major version number. For example,
for <code class="display"><span class="extract">2.1.7</span></code> the range will be <code class="display"><span class="extract">[2.1.7, 3-A)</span></code>, all versions at least 2.1.7 but
not as high as 3.0.0-A.
</p>
<p class="inwebparagraph">Note that <code class="display"><span class="extract">3.0.0-A</span></code> is the least precendent version allowed by semver with
major version 3. The <code class="display"><span class="extract">-</span></code> gives it lower precedence than all release versions of
3.0.0; the fact that upper case <code class="display"><span class="extract">A</span></code> is alphabetically the earliest non-empty
alphanumeric string gives it lower precendence than all other prerelease
versions.
</p>
<pre class="display">
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::compatibility_range</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">) {</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> = </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_value</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> = </span><span class="constant">OPEN_RANGE_END</span><span class="plain">;</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">W</span><span class="element">.version_numbers</span><span class="plain">[0] = </span><span class="identifier">V</span><span class="element">.version_numbers</span><span class="plain">[0] + 1;</span>
<span class="identifier">W</span><span class="element">.prerelease_segments</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"A"</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">W</span><span class="element">.prerelease_segments</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_value</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::compatibility_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>More straightforwardly, these ranges are for anything from V, or up to V,
inclusive:
</p>
<pre class="display">
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::at_least_range</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">();</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> = </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower.end_value</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::at_most_range</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">();</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> = </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper.end_value</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::at_least_range appears nowhere else.</p>
<p class="endnote">The function VersionNumberRanges::at_most_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Here we test whether V is at least a given end, and then at most:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::version_ge_end</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">, </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">E</span><span class="element">.end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::ge</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="element">.end_value</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">OPEN_RANGE_END</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="element">.end_value</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::version_le_end</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">, </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">E</span><span class="element">.end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="element">.end_value</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">OPEN_RANGE_END</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::lt</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="element">.end_value</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">: </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::version_ge_end is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function VersionNumberRanges::version_le_end is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>This allows a simple way to write:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::in_range</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">, </span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">VersionNumberRanges::version_ge_end</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;lower</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">VersionNumberRanges::version_le_end</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">-</span><span class="element">&gt;upper</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::in_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The following decides which end restriction is stricter: it returns 1
of <code class="display"><span class="extract">E1</span></code> is, -1 if <code class="display"><span class="extract">E2</span></code> is, and 0 if they are equally onerous.
</p>
<p class="inwebparagraph">The empty set is as strict as it gets: nothing qualifies.
</p>
<p class="inwebparagraph">Similarly, infinite ends are as relaxed as can be: everything qualifies.
</p>
<p class="inwebparagraph">And otherwise, we need to know which end we're looking at in order to decide:
a lower end of <code class="display"><span class="extract">[4, ...]</span></code> is stricter than a lower end of <code class="display"><span class="extract">[3, ...]</span></code>, but an
upper end of <code class="display"><span class="extract">[..., 4]</span></code> is not as strict as an upper end of <code class="display"><span class="extract">[..., 3]</span></code>. Where
the boundary value is the same, open ends are stricter than closed ends.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::stricter</span><span class="plain">(</span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">E1</span><span class="plain">, </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">E2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">lower</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">E1</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">E2</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E1</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E2</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">E1</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">E2</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E1</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E2</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 1;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::cmp</span><span class="plain">(</span><span class="identifier">E1</span><span class="element">.end_value</span><span class="plain">, </span><span class="identifier">E2</span><span class="element">.end_value</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> != 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lower</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> -</span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E1</span><span class="element">.end_type</span><span class="plain"> == </span><span class="identifier">E2</span><span class="element">.end_type</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E1</span><span class="element">.end_type</span><span class="plain"> == </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">return</span><span class="plain"> 1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::stricter is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>And so we finally arrive at the following, which intersects two ranges:
that is, it changes <code class="display"><span class="extract">R1</span></code> to the range of versions which lie inside both the
original <code class="display"><span class="extract">R1</span></code> and also <code class="display"><span class="extract">R2</span></code>. (This is used by Inbuild when an extension is
included in two different places in the source text, but with possibly
different version needs.) The return value is true if an actual change took
place, and false otherwise.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::intersect_range</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R1</span><span class="plain">, </span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lc</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::stricter</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">-</span><span class="element">&gt;lower</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">uc</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::stricter</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">-</span><span class="element">&gt;upper</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lc</span><span class="plain"> &gt;= 0) &amp;&amp; (</span><span class="identifier">uc</span><span class="plain"> &gt;= 0)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lc</span><span class="plain"> &lt; 0) </span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower</span><span class="plain"> = </span><span class="identifier">R2</span><span class="plain">-</span><span class="element">&gt;lower</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uc</span><span class="plain"> &lt; 0) </span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper</span><span class="plain"> = </span><span class="identifier">R2</span><span class="plain">-</span><span class="element">&gt;upper</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> != </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> != </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::cmp</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower.end_value</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper.end_value</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> &gt; 0) ||</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> == 0) &amp;&amp; ((</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> == </span><span class="constant">OPEN_RANGE_END</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> == </span><span class="constant">OPEN_RANGE_END</span><span class="plain">)))) {</span>
<span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;lower.end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">; </span><span class="identifier">R1</span><span class="plain">-</span><span class="element">&gt;upper.end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::intersect_range appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="7-vn.html">Back to 'Version Numbers'</a></li><li><i>(This section ends Chapter 7: Semantic Versioning.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>

View file

@ -1,6 +1,6 @@
<html>
<head>
<title>foundation </title>
<title>foundation</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
@ -21,8 +21,8 @@
</nav>
<main role="main">
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><b>foundation </b></li></ul>
<p class="purpose">A library of common code used by all of the Inform tools.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><b>foundation</b></li></ul>
<p class="purpose">A library of common code used by all of the Inform tools. This is version 1.</p>
<hr>
<ul class="chapterlist">
<li>
@ -181,6 +181,20 @@
</li>
</ul>
</li>
<li>
<p><a name="7"></a><spon class="chaptertitle">Chapter 7: Semantic Versioning</span></p>
<p><span class="purpose">For reading, storing and comparing standard semantic version numbers.</span></p>
<ul class="sectionlist">
<li>
<p><a href="7-vn.html"><spon class="sectiontitle">Version Numbers</span></a> -
<span class="purpose">Semantic version numbers such as 3.7.1.</span></p>
</li>
<li>
<p><a href="7-vnr.html"><spon class="sectiontitle">Version Number Ranges</span></a> -
<span class="purpose">Ranges of acceptable version numbers.</span></p>
</li>
</ul>
</li>
</ul>
<hr>
</main>

View file

@ -40,6 +40,7 @@
<span class="definitionkeyword">enum</span> <span class="constant">TEST_REPLACEMENT_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">TEST_LISTS_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">TEST_STACKS_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">TEST_SEMVER_CLSW</span>
</pre>
<pre class="display">
@ -61,6 +62,8 @@
<span class="identifier">L</span><span class="string">"test linked lists (X is ignored)"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">TEST_STACKS_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"test-stacks"</span><span class="plain">, 2,</span>
<span class="identifier">L</span><span class="string">"test LIFO stacks (X is ignored)"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">TEST_SEMVER_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"test-semver"</span><span class="plain">, 2,</span>
<span class="identifier">L</span><span class="string">"test semantic version numbers (X is ignored)"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::read</span><span class="plain">(</span><span class="identifier">argc</span><span class="plain">, </span><span class="identifier">argv</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, &amp;</span><span class="functiontext">Main::respond</span><span class="plain">, &amp;</span><span class="functiontext">Main::ignore</span><span class="plain">);</span>
<span class="functiontext">Foundation::end</span><span class="plain">();</span>
@ -76,6 +79,7 @@
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEST_LITERALS_CLSW</span><span class="plain">: </span><span class="functiontext">Unit::test_literals</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEST_LISTS_CLSW</span><span class="plain">: </span><span class="functiontext">Unit::test_linked_lists</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEST_STACKS_CLSW</span><span class="plain">: </span><span class="functiontext">Unit::test_stacks</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">TEST_SEMVER_CLSW</span><span class="plain">: </span><span class="functiontext">Unit::test_semver</span><span class="plain">(); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>

View file

@ -26,7 +26,7 @@
<!--Weave of 'S/ut' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">foundation-test</a></li><li><b>Unit Tests</b></li></ul><p class="purpose">A selection of tests for, or demonstrations of, foundation features.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Strings</a></li><li><a href="#SP2">&#167;2. Literals</a></li><li><a href="#SP3">&#167;3. Dictionaries</a></li><li><a href="#SP4">&#167;4. Regexp</a></li><li><a href="#SP5">&#167;5. Replacements</a></li><li><a href="#SP6">&#167;6. Linked lists</a></li><li><a href="#SP7">&#167;7. Stacks</a></li></ul><hr class="tocbar">
<ul class="toc"><li><a href="#SP1">&#167;1. Strings</a></li><li><a href="#SP2">&#167;2. Literals</a></li><li><a href="#SP3">&#167;3. Dictionaries</a></li><li><a href="#SP4">&#167;4. Regexp</a></li><li><a href="#SP5">&#167;5. Replacements</a></li><li><a href="#SP6">&#167;6. Linked lists</a></li><li><a href="#SP7">&#167;7. Stacks</a></li><li><a href="#SP8">&#167;8. Semantic versions</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Strings. </b></p>
@ -289,6 +289,126 @@
<p class="endnote">The function Unit::test_stacks is used in S/pc (<a href="S-pc.html#SP1">&#167;1</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Semantic versions. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Unit::test_range</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">);</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::compatibility_range</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Compatibility range of %v = "</span><span class="plain">, &amp;</span><span class="identifier">V</span><span class="plain">);</span>
<span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::at_least_range</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"At-least range of %v = "</span><span class="plain">, &amp;</span><span class="identifier">V</span><span class="plain">);</span>
<span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::at_most_range</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"At-most range of %v = "</span><span class="plain">, &amp;</span><span class="identifier">V</span><span class="plain">);</span>
<span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">r1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">r2</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">text1</span><span class="plain">);</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r1</span><span class="plain"> == 0) </span><span class="identifier">R1</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::compatibility_range</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r1</span><span class="plain"> &gt; 0) </span><span class="identifier">R1</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::at_least_range</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r1</span><span class="plain"> &lt; 0) </span><span class="identifier">R1</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::at_most_range</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">);</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">text2</span><span class="plain">);</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r2</span><span class="plain"> == 0) </span><span class="identifier">R2</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::compatibility_range</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r2</span><span class="plain"> &gt; 0) </span><span class="identifier">R2</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::at_least_range</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">r2</span><span class="plain"> &lt; 0) </span><span class="identifier">R2</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::at_most_range</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">);</span>
<span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" intersect "</span><span class="plain">);</span>
<span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" = "</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">changed</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::intersect_range</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">);</span>
<span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">changed</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain"> (</span><span class="string">" -- changed"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'%S' --&gt; %v\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, &amp;</span><span class="identifier">V</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text1</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text2</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">text1</span><span class="plain">);</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">text2</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">gt</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">eq</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lt</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::lt</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lt</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v &lt; %v"</span><span class="plain">, &amp;</span><span class="identifier">V1</span><span class="plain">, &amp;</span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eq</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v = %v"</span><span class="plain">, &amp;</span><span class="identifier">V1</span><span class="plain">, &amp;</span><span class="identifier">V2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gt</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v &gt; %v"</span><span class="plain">, &amp;</span><span class="identifier">V1</span><span class="plain">, &amp;</span><span class="identifier">V2</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Unit::test_semver</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"71.0.45672"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3.4"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"9/861022"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"9/86102"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"9/8610223"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"9/861022.2"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"9/861022/2"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3-alpha.0.x45.1789"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1+lobster"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2+lobster"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3+lobster"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_read_write</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3-beta.2+shellfish"</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"5"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.0"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.0.0"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.5"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.2.5"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41+arm64"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-pre.0.1"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.72"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.8"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.72a"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.8a"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.72"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-beta.72"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.72"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"3.1.41-alpha.72.zeta"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_precedence</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3+lobster.54"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1.2.3+lobster.100"</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_range</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2-kappa.17"</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2-kappa.17"</span><span class="plain">, 0, </span><span class="identifier">I</span><span class="string">"3.5.5"</span><span class="plain">, 0);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2-kappa.17"</span><span class="plain">, 0, </span><span class="identifier">I</span><span class="string">"6.9.1"</span><span class="plain">, 0);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.9.1"</span><span class="plain">, 0, </span><span class="identifier">I</span><span class="string">"6.4.2-kappa.17"</span><span class="plain">, 0);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2"</span><span class="plain">, 1, </span><span class="identifier">I</span><span class="string">"3.5.5"</span><span class="plain">, 1);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2"</span><span class="plain">, 1, </span><span class="identifier">I</span><span class="string">"3.5.5"</span><span class="plain">, -1);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2"</span><span class="plain">, -1, </span><span class="identifier">I</span><span class="string">"3.5.5"</span><span class="plain">, 1);</span>
<span class="functiontext">Unit::test_intersect</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"6.4.2"</span><span class="plain">, -1, </span><span class="identifier">I</span><span class="string">"3.5.5"</span><span class="plain">, -1);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Unit::test_range appears nowhere else.</p>
<p class="endnote">The function Unit::test_intersect appears nowhere else.</p>
<p class="endnote">The function Unit::test_read_write appears nowhere else.</p>
<p class="endnote">The function Unit::test_precedence appears nowhere else.</p>
<p class="endnote">The function Unit::test_semver is used in S/pc (<a href="S-pc.html#SP1">&#167;1</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="S-pc.html">Back to 'Program Control'</a></li><li><i>(This section ends Sections.)</i></li></ul><hr class="tocbar">
<!--End of weave-->

View file

@ -1,6 +1,6 @@
<html>
<head>
<title>foundation-test </title>
<title>foundation-test</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
@ -21,8 +21,8 @@
</nav>
<main role="main">
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><b>foundation-test </b></li></ul>
<p class="purpose">Unit tests for the foundation module.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><b>foundation-test</b></li></ul>
<p class="purpose">Unit tests for the foundation module. This is version 1.</p>
<hr>
<ul class="sectionlist">
<li>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '1/bsc' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Basics</b></li></ul><p class="purpose">Some fundamental definitions, mostly setting up for the Foundation module to manage memory for us.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Basics</b></li></ul><p class="purpose">Some fundamental definitions, mostly setting up for the Foundation module to manage memory for us.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Build identity</a></li><li><a href="#SP2">&#167;2. Setting up the memory manager</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '1/cnf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Configuration</b></li></ul><p class="purpose">To parse the command line arguments with which inweb was called, and to handle any errors it needs to issue.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Configuration</b></li></ul><p class="purpose">To parse the command line arguments with which inweb was called, and to handle any errors it needs to issue.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Instructions</a></li><li><a href="#SP2">&#167;2. Reading the command line</a></li></ul><hr class="tocbar">
@ -50,6 +50,7 @@ command line: there will only ever be one of these.
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">catalogue_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-catalogue</span></code>: print catalogue of sections</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">functions_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-functions</span></code>: print catalogue of functions within sections</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">structures_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-structures</span></code>: print catalogue of structures within sections</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">advance_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-advance-build</span></code>: advance build file for web</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">open_pdf_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-open-pdf</span></code>: open any woven PDF in the OS once it is made</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">scan_switch</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-scan</span></code>: simply show the syntactic scan of the source</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">weave_to_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-weave-to X</span></code>: the pathname X, if supplied</span>
@ -57,6 +58,7 @@ command line: there will only ever be one of these.
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">tangle_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-tangle-to X</span></code>: the pathname X, if supplied</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">makefile_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-makefile X</span></code>: the filename X, if supplied</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">gitignore_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-gitignore X</span></code>: the filename X, if supplied</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">advance_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-advance-build-file X</span></code>: advance build file X</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">prototype_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-prototype X</span></code>: the pathname X, if supplied</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">navigation_setting</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">-navigation X</span></code>: the filename X, if supplied</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">breadcrumb_setting</span><span class="plain">; </span> <span class="comment">of <code class="display"><span class="extract">breadcrumb_request</span></code></span>
@ -119,6 +121,7 @@ then declare them.
<span class="identifier">args</span><span class="element">.catalogue_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.functions_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.structures_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.advance_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.open_pdf_switch</span><span class="plain"> = </span><span class="constant">NOT_APPLICABLE</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.scan_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.verbose_switch</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
@ -131,6 +134,7 @@ then declare them.
<span class="identifier">args</span><span class="element">.weave_into_setting</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.makefile_setting</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.gitignore_setting</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.advance_setting</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.prototype_setting</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.navigation_setting</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">args</span><span class="element">.breadcrumb_setting</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">breadcrumb_request</span><span class="plain">);</span>
@ -157,8 +161,10 @@ provides automatically.
<span class="definitionkeyword">enum</span> <span class="constant">CATALOGUE_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">FUNCTIONS_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">STRUCTURES_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">ADVANCE_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">GITIGNORE_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">MAKEFILE_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">ADVANCE_FILE_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">PROTOTYPE_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">SCAN_CLSW</span>
<span class="definitionkeyword">enum</span> <span class="constant">WEAVE_CLSW</span>
@ -206,12 +212,16 @@ provides automatically.
<span class="identifier">L</span><span class="string">"write a makefile for this web and store it in X"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">GITIGNORE_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"gitignore"</span><span class="plain">, 2,</span>
<span class="identifier">L</span><span class="string">"write a .gitignore file for this web and store it in X"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">ADVANCE_FILE_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"advance-build-file"</span><span class="plain">, 2,</span>
<span class="identifier">L</span><span class="string">"increment daily build code in file X"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">PROTOTYPE_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"prototype"</span><span class="plain">, 2,</span>
<span class="identifier">L</span><span class="string">"translate makefile from prototype X"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">FUNCTIONS_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"functions"</span><span class="plain">, 1,</span>
<span class="identifier">L</span><span class="string">"catalogue the functions in the web"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">STRUCTURES_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"structures"</span><span class="plain">, 1,</span>
<span class="identifier">L</span><span class="string">"catalogue the structures in the web"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">ADVANCE_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"advance-build"</span><span class="plain">, 1,</span>
<span class="identifier">L</span><span class="string">"increment daily build code for the web"</span><span class="plain">);</span>
<span class="functiontext">CommandLine::declare_switch</span><span class="plain">(</span><span class="constant">SCAN_CLSW</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"scan"</span><span class="plain">, 1,</span>
<span class="identifier">L</span><span class="string">"scan the web"</span><span class="plain">);</span>
@ -265,6 +275,9 @@ provides automatically.
<span class="reserved">case</span><span class="plain"> </span><span class="constant">STRUCTURES_CLSW</span><span class="plain">:</span>
<span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;structures_switch</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="functiontext">Configuration::set_fundamental_mode</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">, </span><span class="constant">ANALYSE_MODE</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ADVANCE_CLSW</span><span class="plain">:</span>
<span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;advance_switch</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="functiontext">Configuration::set_fundamental_mode</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">, </span><span class="constant">ANALYSE_MODE</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">MAKEFILE_CLSW</span><span class="plain">:</span>
<span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;makefile_setting</span><span class="plain"> = </span><span class="functiontext">Filenames::from_text</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;inweb_mode</span><span class="plain"> != </span><span class="constant">TRANSLATE_MODE</span><span class="plain">)</span>
@ -275,6 +288,10 @@ provides automatically.
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;inweb_mode</span><span class="plain"> != </span><span class="constant">TRANSLATE_MODE</span><span class="plain">)</span>
<span class="functiontext">Configuration::set_fundamental_mode</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">, </span><span class="constant">ANALYSE_MODE</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">ADVANCE_FILE_CLSW</span><span class="plain">:</span>
<span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;advance_setting</span><span class="plain"> = </span><span class="functiontext">Filenames::from_text</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
<span class="functiontext">Configuration::set_fundamental_mode</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">, </span><span class="constant">TRANSLATE_MODE</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PROTOTYPE_CLSW</span><span class="plain">:</span>
<span class="identifier">args</span><span class="plain">-</span><span class="element">&gt;prototype_setting</span><span class="plain"> = </span><span class="functiontext">Filenames::from_text</span><span class="plain">(</span><span class="identifier">arg</span><span class="plain">);</span>
<span class="functiontext">Configuration::set_fundamental_mode</span><span class="plain">(</span><span class="identifier">args</span><span class="plain">, </span><span class="constant">TRANSLATE_MODE</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '1/pc' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Program Control</b></li></ul><p class="purpose">The top level, which decides what is to be done and then carries this plan out.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Program Control</b></li></ul><p class="purpose">The top level, which decides what is to be done and then carries this plan out.</p>
<ul class="toc"><li><a href="#SP6">&#167;6. Main routine</a></li><li><a href="#SP7">&#167;7. Following instructions</a></li><li><a href="#SP8">&#167;8. Error messages</a></li></ul><hr class="tocbar">
@ -206,6 +206,8 @@ program: some input, some thinking, a choice of three forms of output.
<span class="functiontext">Makefiles::write</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;prototype_setting</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;makefile_setting</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;gitignore_setting</span><span class="plain">)</span>
<span class="functiontext">Git::write_gitignore</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;prototype_setting</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;gitignore_setting</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;advance_setting</span><span class="plain">)</span>
<span class="functiontext">BuildFiles::advance</span><span class="plain">(</span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;advance_setting</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
@ -254,6 +256,8 @@ program: some input, some thinking, a choice of three forms of output.
<span class="functiontext">Analyser::write_makefile</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;makefile_setting</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;gitignore_setting</span><span class="plain">)</span>
<span class="functiontext">Analyser::write_gitignore</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;gitignore_setting</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;advance_switch</span><span class="plain">)</span>
<span class="functiontext">BuildFiles::advance_for_web</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;scan_switch</span><span class="plain">)</span>
<span class="functiontext">Analyser::scan_line_categories</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ins</span><span class="plain">-</span><span class="element">&gt;chosen_range</span><span class="plain">);</span>
</pre>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '1/ptt' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Patterns</b></li></ul><p class="purpose">Managing weave patterns, which are bundled configuration settings for weaving.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#1">Chapter 1: Top Level</a></li><li><b>Patterns</b></li></ul><p class="purpose">Managing weave patterns, which are bundled configuration settings for weaving.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Reading in</a></li><li><a href="#SP5">&#167;5. Obtaining files</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/bd' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Bibliographic Data</b></li></ul><p class="purpose">To manage key-value pairs of bibliographic data, metadata if you like, associated with a given web.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Bibliographic Data</b></li></ul><p class="purpose">To manage key-value pairs of bibliographic data, metadata if you like, associated with a given web.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Storing data</a></li><li><a href="#SP4">&#167;4. Initialising a web</a></li><li><a href="#SP6">&#167;6. Reading bibliographic data</a></li><li><a href="#SP7">&#167;7. Writing bibliographic data</a></li></ul><hr class="tocbar">
@ -105,7 +105,9 @@ convenient to store them directly here than to use a dictionary.
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Capitalized Title"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Build Date"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Build Number"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Version Number"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Prerelease"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Semantic Version Number"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Version Number"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"1"</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Version Name"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Index Template"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Preform Language"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
@ -114,6 +116,8 @@ convenient to store them directly here than to use a dictionary.
<span class="identifier">bd</span><span class="plain"> = </span><span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Namespaces"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Off"</span><span class="plain">); </span><span class="identifier">bd</span><span class="plain">-</span><span class="element">&gt;on_or_off</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">bd</span><span class="plain"> = </span><span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Strict Usage Rules"</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Off"</span><span class="plain">); </span><span class="identifier">bd</span><span class="plain">-</span><span class="element">&gt;on_or_off</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">bd</span><span class="plain"> = </span><span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Web Syntax Version"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="functiontext">BuildFiles::set_bibliographic_data_for</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
@ -171,7 +175,7 @@ to check that all the mandatory declarations have indeed been made:
<p class="inwebparagraph"></p>
<p class="endnote">The function Bibliographic::get_datum is used in 1/pc (<a href="1-pc.html#SP7_2_2_1">&#167;7.2.2.1</a>, <a href="1-pc.html#SP7_2_3_1">&#167;7.2.3.1</a>), 2/tr (<a href="2-tr.html#SP4">&#167;4</a>, <a href="2-tr.html#SP9_3_1">&#167;9.3.1</a>, <a href="2-tr.html#SP9_3_3_2_1">&#167;9.3.3.2.1</a>, <a href="2-tr.html#SP9_2_2_3_1">&#167;9.2.2.3.1</a>), 3/ti (<a href="3-ti.html#SP2_1_4">&#167;2.1.4</a>, <a href="3-ti.html#SP5_1_8_1">&#167;5.1.8.1</a>), 3/tw (<a href="3-tw.html#SP1_3_3_1_10_4">&#167;1.3.3.1.10.4</a>), 3/tt (<a href="3-tt.html#SP3_2">&#167;3.2</a>), 4/cl (<a href="4-cl.html#SP22">&#167;22</a>), 4/is (<a href="4-is.html#SP13">&#167;13</a>), 5/hf (<a href="5-hf.html#SP9">&#167;9</a>, <a href="5-hf.html#SP27">&#167;27</a>).</p>
<p class="endnote">The function Bibliographic::get_datum is used in 1/pc (<a href="1-pc.html#SP7_2_2_1">&#167;7.2.2.1</a>, <a href="1-pc.html#SP7_2_3_1">&#167;7.2.3.1</a>), 2/tr (<a href="2-tr.html#SP4">&#167;4</a>, <a href="2-tr.html#SP9_3_1">&#167;9.3.1</a>, <a href="2-tr.html#SP9_3_3_2_1">&#167;9.3.3.2.1</a>, <a href="2-tr.html#SP9_2_2_3_1">&#167;9.2.2.3.1</a>), 3/ti (<a href="3-ti.html#SP2_1_4">&#167;2.1.4</a>, <a href="3-ti.html#SP5_1_8_1">&#167;5.1.8.1</a>), 3/tw (<a href="3-tw.html#SP1_3_3_1_10_4">&#167;1.3.3.1.10.4</a>), 3/tt (<a href="3-tt.html#SP3_2">&#167;3.2</a>), 4/cl (<a href="4-cl.html#SP22">&#167;22</a>), 4/is (<a href="4-is.html#SP13">&#167;13</a>), 5/hf (<a href="5-hf.html#SP9">&#167;9</a>, <a href="5-hf.html#SP27">&#167;27</a>), 6/bf2 (<a href="6-bf2.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function Bibliographic::data_exists is used in 1/pc (<a href="1-pc.html#SP7_2_2_1">&#167;7.2.2.1</a>, <a href="1-pc.html#SP7_2_3_1">&#167;7.2.3.1</a>), 1/ptt (<a href="1-ptt.html#SP3_2">&#167;3.2</a>), 3/ts (<a href="3-ts.html#SP3">&#167;3</a>), 3/ti (<a href="3-ti.html#SP2_1">&#167;2.1</a>, <a href="3-ti.html#SP5_1_8">&#167;5.1.8</a>), 3/tw (<a href="3-tw.html#SP1_2">&#167;1.2</a>, <a href="3-tw.html#SP1_4">&#167;1.4</a>), 4/is (<a href="4-is.html#SP13">&#167;13</a>).</p>
@ -194,7 +198,7 @@ so this routine never fails.
<p class="inwebparagraph"></p>
<p class="endnote">The function Bibliographic::set_datum is used in <a href="#SP4">&#167;4</a>, <a href="#SP7_2">&#167;7.2</a>, 1/ptt (<a href="1-ptt.html#SP3_2">&#167;3.2</a>), 2/tr (<a href="2-tr.html#SP9_3_2_1">&#167;9.3.2.1</a>), 3/ts (<a href="3-ts.html#SP3">&#167;3</a>), 3/tw (<a href="3-tw.html#SP1_2">&#167;1.2</a>, <a href="3-tw.html#SP1_4">&#167;1.4</a>), 5/hf (<a href="5-hf.html#SP25">&#167;25</a>).</p>
<p class="endnote">The function Bibliographic::set_datum is used in <a href="#SP4">&#167;4</a>, <a href="#SP7_2">&#167;7.2</a>, 1/ptt (<a href="1-ptt.html#SP3_2">&#167;3.2</a>), 2/tr (<a href="2-tr.html#SP9_3_2_1">&#167;9.3.2.1</a>), 3/ts (<a href="3-ts.html#SP3">&#167;3</a>), 3/tw (<a href="3-tw.html#SP1_2">&#167;1.2</a>, <a href="3-tw.html#SP1_4">&#167;1.4</a>), 5/hf (<a href="5-hf.html#SP25">&#167;25</a>), 6/bf2 (<a href="6-bf2.html#SP5">&#167;5</a>, <a href="6-bf2.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Create a new datum, then</span> <span class="cwebmacronumber">7.1</span>&gt; =

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/ec' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Enumerated Constants</b></li></ul><p class="purpose">To define sequentially numbered values for families of constants.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Enumerated Constants</b></li></ul><p class="purpose">To define sequentially numbered values for families of constants.</p>
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>The idea here is that each enumeration set is a sequence of named constants
with a given postfix: for example, <code class="display"><span class="extract">HARRY_ST</span></code>, <code class="display"><span class="extract">NEVILLE_ST</span></code>, <code class="display"><span class="extract">ANGELINA_ST</span></code>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/lc' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Line Categories</b></li></ul><p class="purpose">To store individual lines from webs, and to categorise them according to their meaning.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Line Categories</b></li></ul><p class="purpose">To store individual lines from webs, and to categorise them according to their meaning.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Line storage</a></li><li><a href="#SP3">&#167;3. Categories</a></li><li><a href="#SP5">&#167;5. Command codes</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/mdl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Modules</b></li></ul><p class="purpose">To search for included modules, and track dependencies between them.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Modules</b></li></ul><p class="purpose">To search for included modules, and track dependencies between them.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP4">&#167;4. Dependencies</a></li><li><a href="#SP5">&#167;5. Searching</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/pm' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Paragraph Macros</b></li></ul><p class="purpose">To manage the set of named paragraph macros in a section.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Paragraph Macros</b></li></ul><p class="purpose">To manage the set of named paragraph macros in a section.</p>
<ul class="toc"><li><a href="#SP3">&#167;3. Paragraph macro search</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/pn' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Paragraph Numbering</b></li></ul><p class="purpose">To work out paragraph numbers within each section.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Paragraph Numbering</b></li></ul><p class="purpose">To work out paragraph numbers within each section.</p>
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>Traditional LP tools have numbered paragraphs in the obvious way, starting
from 1 and working up to what may be an enormous number. (The web for Knuth's

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/tgs' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Tags</b></li></ul><p class="purpose">Thematic tags can be attached to certain paragraphs, some automatically by Inweb, others manually by the author.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>Tags</b></li></ul><p class="purpose">Thematic tags can be attached to certain paragraphs, some automatically by Inweb, others manually by the author.</p>
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>A tag really is just a textual name. Each differently-named tag leads
to one of the following being created:

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/tp' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>The Parser</b></li></ul><p class="purpose">To work through the program read in, assigning each line its category, and noting down other useful information as we go.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>The Parser</b></li></ul><p class="purpose">To work through the program read in, assigning each line its category, and noting down other useful information as we go.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Sequence of parsing</a></li><li><a href="#SP1_1_6">&#167;1.1.6. Categorisatiom</a></li><li><a href="#SP3">&#167;3. Version errors</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '2/tr' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>The Reader</b></li></ul><p class="purpose">To read the Contents section of the web, and through that each of the other sections in turn, and to collate all of this material.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#2">Chapter 2: Parsing a Web</a></li><li><b>The Reader</b></li></ul><p class="purpose">To read the Contents section of the web, and through that each of the other sections in turn, and to collate all of this material.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Web storage</a></li><li><a href="#SP5">&#167;5. Chapters and sections</a></li><li><a href="#SP7">&#167;7. Reading the contents page</a></li><li><a href="#SP10">&#167;10. Reading source files</a></li><li><a href="#SP11">&#167;11. Looking up chapters and sections</a></li><li><a href="#SP13">&#167;13. Ranges and containment</a></li><li><a href="#SP14">&#167;14. Tangle targets</a></li><li><a href="#SP17">&#167;17. Additional header files</a></li></ul><hr class="tocbar">
@ -62,6 +62,7 @@ multi-chapter web.
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">analysed</span><span class="plain">; </span> <span class="comment">has this been scanned for function usage and such?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">bibliographic_data</span><span class="plain">; </span> <span class="comment">of <code class="display"><span class="extract">bibliographic_datum</span></code>: key-value pairs for title and such</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">version_number</span><span class="plain">; </span> <span class="comment">as deduced from the bibliographic data</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">main_language</span><span class="plain">; </span> <span class="comment">in which most of the sections are written</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">tangle_targets</span><span class="plain">; </span> <span class="comment">of <code class="display"><span class="extract">tangle_target</span></code></span>
@ -78,7 +79,7 @@ multi-chapter web.
<p class="inwebparagraph"></p>
<p class="endnote">The structure web is accessed in 1/pc, 1/ptt, 2/bd, 2/mdl, 2/tp, 2/pn, 3/ta, 3/ts, 3/ti, 3/tw, 3/tt, 4/cl, 4/is, 5/hf, 6/mkf and here.</p>
<p class="endnote">The structure web is accessed in 1/pc, 1/ptt, 2/bd, 2/mdl, 2/tp, 2/pn, 3/ta, 3/ts, 3/ti, 3/tw, 3/tt, 4/cl, 4/is, 5/hf, 6/mkf, 6/bf2 and here.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b></p>
@ -102,9 +103,11 @@ multi-chapter web.
<span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;redirect_weaves_to</span><span class="plain"> = </span><span class="identifier">redirection</span><span class="plain">;</span>
<span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;as_module</span><span class="plain"> = </span><span class="functiontext">Modules::main_module</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;default_syntax</span><span class="plain"> = </span><span class="identifier">default_inweb_syntax</span><span class="plain">;</span>
<span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;version_number</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="functiontext">Bibliographic::initialise_data</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Reader::add_tangle_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="functiontext">Languages::default</span><span class="plain">()); </span> <span class="comment">the bulk of the web is automatically a target</span>
<span class="functiontext">Reader::read_contents_page</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">verbosely</span><span class="plain">);</span>
<span class="functiontext">BuildFiles::deduce_semver</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Parser::parse_web</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">inweb_mode</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;no_sections</span><span class="plain"> == 1) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain"> = </span><span class="identifier">FIRST_IN_LINKED_LIST</span><span class="plain">(</span><span class="reserved">chapter</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;chapters</span><span class="plain">);</span>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '3/ta' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Analyser</b></li></ul><p class="purpose">Here we analyse the code in the web, enabling us to see how functions and data structures are used within the program.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Analyser</b></li></ul><p class="purpose">Here we analyse the code in the web, enabling us to see how functions and data structures are used within the program.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Scanning webs</a></li><li><a href="#SP2">&#167;2. The section catalogue</a></li><li><a href="#SP3">&#167;3. Analysing code</a></li><li><a href="#SP5">&#167;5. Identifier searching</a></li><li><a href="#SP6">&#167;6. The identifier hash table</a></li><li><a href="#SP13">&#167;13. Open-source project support</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '3/ti' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Indexer</b></li></ul><p class="purpose">To construct indexes of the material woven, following a template.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Indexer</b></li></ul><p class="purpose">To construct indexes of the material woven, following a template.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Cover sheets</a></li><li><a href="#SP4">&#167;4. Full index pages</a></li><li><a href="#SP5">&#167;5. Running the interpreter</a></li><li><a href="#SP5_2">&#167;5.2. File handling</a></li><li><a href="#SP5_1_1">&#167;5.1.1. The repeat stack and loops</a></li><li><a href="#SP5_1_8">&#167;5.1.8. Variable substitutions</a></li><li><a href="#SP6">&#167;6. Transcribing CSS</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '3/ts' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Swarm</b></li></ul><p class="purpose">To feed multiple output requests to the weaver, and to present weaver results, and update indexes or contents pages.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Swarm</b></li></ul><p class="purpose">To feed multiple output requests to the weaver, and to present weaver results, and update indexes or contents pages.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Swarming</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '3/tt' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Tangler</b></li></ul><p class="purpose">To transcribe a version of the text in the web into a form which can be compiled as a program.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Tangler</b></li></ul><p class="purpose">To transcribe a version of the text in the web into a form which can be compiled as a program.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. The Master Tangler</a></li><li><a href="#SP3">&#167;3. The Code Tangler</a></li><li><a href="#SP4">&#167;4. Prinary target</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '3/tw' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Weaver</b></li></ul><p class="purpose">To weave a portion of the code into instructions for TeX.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#3">Chapter 3: Outputs</a></li><li><b>The Weaver</b></li></ul><p class="purpose">To weave a portion of the code into instructions for TeX.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. The Master Weaver</a></li><li><a href="#SP1_3_1">&#167;1.3.1. The state</a></li><li><a href="#SP1_3_3">&#167;1.3.3. Weaving a section</a></li><li><a href="#SP1_3_3_1_1">&#167;1.3.3.1.1. Reasons to skip things</a></li><li><a href="#SP1_3_3_1_3">&#167;1.3.3.1.3. Headings</a></li><li><a href="#SP1_3_3_1_8">&#167;1.3.3.1.8. Commentary matter</a></li><li><a href="#SP1_3_3_1_9">&#167;1.3.3.1.9. Code-like matter</a></li><li><a href="#SP1_3_3_1_10">&#167;1.3.3.1.10. How paragraphs begin</a></li><li><a href="#SP1_3_3_2">&#167;1.3.3.2. How paragraphs end</a></li><li><a href="#SP2">&#167;2. Endnotes</a></li><li><a href="#SP3">&#167;3. Section tables of contents</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '4/cl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>C-Like Languages</b></li></ul><p class="purpose">To provide special features for the whole C family of languages.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>C-Like Languages</b></li></ul><p class="purpose">To provide special features for the whole C family of languages.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP2">&#167;2. </a></li><li><a href="#SP3">&#167;3. Parsing</a></li><li><a href="#SP3_2">&#167;3.2. Structures</a></li><li><a href="#SP3_3">&#167;3.3. Structure dependency</a></li><li><a href="#SP3_4">&#167;3.4. Functions</a></li><li><a href="#SP5">&#167;5. Subcategorisation</a></li><li><a href="#SP6">&#167;6. Tangling extras</a></li><li><a href="#SP9">&#167;9. Tangling predeclarations</a></li><li><a href="#SP10">&#167;10. Line markers</a></li><li><a href="#SP11">&#167;11. Comments</a></li><li><a href="#SP13">&#167;13. Ifdefs</a></li><li><a href="#SP14">&#167;14. Before and after expansion</a></li><li><a href="#SP15">&#167;15. Begin weave</a></li><li><a href="#SP16">&#167;16. Syntax colouring</a></li><li><a href="#SP19">&#167;19. Overriding regular code weaving</a></li><li><a href="#SP20">&#167;20. Analysis</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '4/is' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>InC Support</b></li></ul><p class="purpose">To support a modest extension of C called InC.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>InC Support</b></li></ul><p class="purpose">To support a modest extension of C called InC.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP3">&#167;3. Parsing methods</a></li><li><a href="#SP3_1">&#167;3.1. Parsing Preform grammar</a></li><li><a href="#SP3_1_1_1">&#167;3.1.1.1. Parsing the body of Preform grammar</a></li><li><a href="#SP3_2">&#167;3.2. Parsing I-literals</a></li><li><a href="#SP4">&#167;4. Tangling methods</a></li><li><a href="#SP14">&#167;14. Weaving</a></li><li><a href="#SP15">&#167;15. Weaving methods</a></li><li><a href="#SP18">&#167;18. Analysis methods</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '4/is2' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>Inform Support</b></li></ul><p class="purpose">To support webs written in Inform 6 or 7.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>Inform Support</b></li></ul><p class="purpose">To support webs written in Inform 6 or 7.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Inform 6</a></li><li><a href="#SP2">&#167;2. Syntax colouring</a></li><li><a href="#SP5">&#167;5. Inform 7</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '4/pl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>Programming Languages</b></li></ul><p class="purpose">To characterise the relevant differences in behaviour between the various programming languages supported.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>Programming Languages</b></li></ul><p class="purpose">To characterise the relevant differences in behaviour between the various programming languages supported.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Languages</a></li><li><a href="#SP3">&#167;3. Creation</a></li><li><a href="#SP4">&#167;4. Parsing methods</a></li><li><a href="#SP7">&#167;7. Tangling methods</a></li><li><a href="#SP22">&#167;22. Weaving methods</a></li><li><a href="#SP28">&#167;28. Analysis methods</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '4/ps' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>Perl Support</b></li></ul><p class="purpose">To support webs written in Perl.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>Perl Support</b></li></ul><p class="purpose">To support webs written in Perl.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP2">&#167;2. Tangling methods</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '5/hf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>HTML Formats</b></li></ul><p class="purpose">To provide for weaving into HTML and into EPUB books.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>HTML Formats</b></li></ul><p class="purpose">To provide for weaving into HTML and into EPUB books.</p>
<ul class="toc"><li><a href="#SP2">&#167;2. Current state</a></li><li><a href="#SP6">&#167;6. Methods</a></li><li><a href="#SP27">&#167;27. EPUB-only methods</a></li></ul><hr class="tocbar">
@ -371,12 +371,8 @@ the page, and this drops one.
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"ul"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">crumbs\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">HTMLFormat::drop_initial_breadcrumbs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">wv</span><span class="plain">-</span><span class="element">&gt;breadcrumbs</span><span class="plain">, </span><span class="identifier">wv</span><span class="plain">-</span><span class="element">&gt;docs_mode</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">titling</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">titling</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">wv</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Title"</span><span class="plain">));</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">v</span><span class="plain"> = </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">wv</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Version Number"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">v</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">titling</span><span class="plain">, </span><span class="string">" %S"</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">);</span>
<span class="functiontext">HTMLFormat::breadcrumb</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">titling</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"index.html"</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">titling</span><span class="plain">);</span>
<span class="functiontext">HTMLFormat::breadcrumb</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">wv</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Title"</span><span class="plain">), </span><span class="identifier">I</span><span class="string">"index.html"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">wv</span><span class="plain">-</span><span class="element">&gt;weave_web</span><span class="plain">-</span><span class="element">&gt;chaptered</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">chapter_link</span><span class="plain">);</span>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '5/ptf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>Plain Text Format</b></li></ul><p class="purpose">To provide for weaving in plain text format, which is not very interesting, but ought to be available.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>Plain Text Format</b></li></ul><p class="purpose">To provide for weaving in plain text format, which is not very interesting, but ought to be available.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP2">&#167;2. Methods</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '5/rtt' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>Running Through TeX</b></li></ul><p class="purpose">To post-process a weave by running it through TeX, or one of its variant typesetting programs.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>Running Through TeX</b></li></ul><p class="purpose">To post-process a weave by running it through TeX, or one of its variant typesetting programs.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Running TeX</a></li><li><a href="#SP4">&#167;4. Reporting</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '5/tf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>TeX Format</b></li></ul><p class="purpose">To provide for weaving in the standard maths and science typesetting software, TeX.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>TeX Format</b></li></ul><p class="purpose">To provide for weaving in the standard maths and science typesetting software, TeX.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Creation</a></li><li><a href="#SP2">&#167;2. Methods</a></li><li><a href="#SP25">&#167;25. Post-processing</a></li><li><a href="#SP28">&#167;28. Removing math mode</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '5/wf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>Weave Formats</b></li></ul><p class="purpose">To characterise the different weaving output formats (text, typeset, web and so on).</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#5">Chapter 5: Formats</a></li><li><b>Weave Formats</b></li></ul><p class="purpose">To characterise the different weaving output formats (text, typeset, web and so on).</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Formats</a></li><li><a href="#SP3">&#167;3. Creation</a></li><li><a href="#SP4">&#167;4. Methods</a></li><li><a href="#SP28">&#167;28. Post-processing</a></li></ul><hr class="tocbar">

298
docs/inweb/6-bf2.html Normal file
View file

@ -0,0 +1,298 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>6/gs</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '6/bf2' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#6">Chapter 6: Extras</a></li><li><b>Build Files</b></li></ul><p class="purpose">Manages the build metadata for an inweb project.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. About build files</a></li><li><a href="#SP5">&#167;5. Bibliographic implications</a></li><li><a href="#SP7">&#167;7. Advancing</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. About build files. </b>When we read a web, we look for a file in it called <code class="display"><span class="extract">build.txt</span></code>. If no such
file exists, we look for the same thing in the current working directory.
</p>
<pre class="display">
<span class="reserved">filename</span><span class="plain"> *</span><span class="functiontext">BuildFiles::build_file_for_web</span><span class="plain">(</span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;path_to_web</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"build.txt"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">TextFiles::exists</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">F</span><span class="plain">;</span>
<span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"build.txt"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">TextFiles::exists</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">F</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::build_file_for_web is used in <a href="#SP5">&#167;5</a>, <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>The format of such a file is very simple: up to three text fields:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">build_file_data</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">prerelease_text</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">build_code</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">build_date</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">build_file_data</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure build_file_data is private to this section.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Here's how to read in a build file:
</p>
<pre class="display">
<span class="reserved">build_file_data</span><span class="plain"> </span><span class="functiontext">BuildFiles::read</span><span class="plain">(</span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="reserved">build_file_data</span><span class="plain"> </span><span class="identifier">bfd</span><span class="plain">;</span>
<span class="identifier">bfd</span><span class="element">.prerelease_text</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">bfd</span><span class="element">.build_code</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">bfd</span><span class="element">.build_date</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">, </span><span class="string">"unable to read build file"</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">,</span>
<span class="plain">&amp;</span><span class="functiontext">BuildFiles::build_file_helper</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, (</span><span class="reserved">void</span><span class="plain"> *) &amp;</span><span class="identifier">bfd</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">bfd</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::build_file_helper</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">, </span><span class="reserved">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">) {</span>
<span class="reserved">build_file_data</span><span class="plain"> *</span><span class="identifier">bfd</span><span class="plain"> = (</span><span class="reserved">build_file_data</span><span class="plain"> *) </span><span class="identifier">state</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">) == 0) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Build Date: *(%c*)"</span><span class="plain">)) {</span>
<span class="identifier">bfd</span><span class="plain">-</span><span class="element">&gt;build_date</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Build Number: *(%c*)"</span><span class="plain">)) {</span>
<span class="identifier">bfd</span><span class="plain">-</span><span class="element">&gt;build_code</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Prerelease: *(%c*)"</span><span class="plain">)) {</span>
<span class="identifier">bfd</span><span class="plain">-</span><span class="element">&gt;prerelease_text</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">mr</span><span class="element">.exp</span><span class="plain">[0]);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Errors::in_text_file</span><span class="plain">(</span><span class="string">"can't parse build file line"</span><span class="plain">, </span><span class="identifier">tfp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::read is used in <a href="#SP5">&#167;5</a>, <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function BuildFiles::build_file_helper appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>And here is how to write one:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::write</span><span class="plain">(</span><span class="reserved">build_file_data</span><span class="plain"> </span><span class="identifier">bfd</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="reserved">text_stream</span><span class="plain"> </span><span class="identifier">vr_stream</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain"> = &amp;</span><span class="identifier">vr_stream</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Streams::open_to_file</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">, </span><span class="constant">UTF8_ENC</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="functiontext">Errors::fatal_with_file</span><span class="plain">(</span><span class="string">"can't write build file"</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.prerelease_text</span><span class="plain">) &gt; 0)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Prerelease: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">bfd</span><span class="element">.prerelease_text</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Build Date: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">bfd</span><span class="element">.build_date</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.build_code</span><span class="plain">) &gt; 0)</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Build Number: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">bfd</span><span class="element">.build_code</span><span class="plain">);</span>
<span class="functiontext">Streams::close</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::write is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Bibliographic implications. </b>Whenever a web is read in by Inweb, its build file is looked at in order to
set some bibliographic data.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::set_bibliographic_data_for</span><span class="plain">(</span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">BuildFiles::build_file_for_web</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="reserved">build_file_data</span><span class="plain"> </span><span class="identifier">bfd</span><span class="plain"> = </span><span class="functiontext">BuildFiles::read</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.prerelease_text</span><span class="plain">) &gt; 0)</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Prerelease"</span><span class="plain">, </span><span class="identifier">bfd</span><span class="element">.prerelease_text</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.build_code</span><span class="plain">) &gt; 0)</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Build Number"</span><span class="plain">, </span><span class="identifier">bfd</span><span class="element">.build_code</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.build_date</span><span class="plain">) &gt; 0)</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Build Date"</span><span class="plain">, </span><span class="identifier">bfd</span><span class="element">.build_date</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::set_bibliographic_data_for is used in 2/bd (<a href="2-bd.html#SP4">&#167;4</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>A little later on, i.e., once the Contents page has been read, we want to
synthesize the semantic version number for the project. Note that this is
called even if no build file had ever been found, so it's quite legal for
the Contents page to specify all of this.
</p>
<p class="inwebparagraph">If no error occurs, then the expansion <code class="display"><span class="extract">[[Semantic Version Number]]</span></code> is
guaranteed to produce a semver-legal version number.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::deduce_semver</span><span class="plain">(</span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">s</span><span class="plain"> = </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Semantic Version Number"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">s</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">s</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">v</span><span class="plain"> = </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Version Number"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">v</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">v</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Prerelease"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">, </span><span class="string">"-%S"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">b</span><span class="plain"> = </span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Build Number"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">b</span><span class="plain">) &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">, </span><span class="string">"+%S"</span><span class="plain">, </span><span class="identifier">b</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">) &gt; 0) {</span>
<span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;version_number</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-</span><span class="element">&gt;version_number</span><span class="plain">)) {</span>
<span class="functiontext">Errors::fatal_with_text</span><span class="plain">(</span>
<span class="string">"Combined version '%S' does not comply with the semver standard"</span><span class="plain">,</span>
<span class="identifier">combined</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Bibliographic::set_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Semantic Version Number"</span><span class="plain">, </span><span class="identifier">combined</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">combined</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::deduce_semver is used in 2/tr (<a href="2-tr.html#SP2">&#167;2</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Advancing. </b>We update the build date to today and, if supplied, also increment the build
number if we find that the date has changed.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::advance_for_web</span><span class="plain">(</span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">BuildFiles::build_file_for_web</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">F</span><span class="plain">) </span><span class="functiontext">BuildFiles::advance</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Errors::fatal</span><span class="plain">(</span><span class="string">"web has no build file"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::advance</span><span class="plain">(</span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="reserved">build_file_data</span><span class="plain"> </span><span class="identifier">bfd</span><span class="plain"> = </span><span class="functiontext">BuildFiles::read</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">BuildFiles::dated_today</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.build_date</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">) {</span>
<span class="functiontext">BuildFiles::increment</span><span class="plain">(</span><span class="identifier">bfd</span><span class="element">.build_code</span><span class="plain">);</span>
<span class="functiontext">BuildFiles::write</span><span class="plain">(</span><span class="identifier">bfd</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::advance_for_web is used in 1/pc (<a href="1-pc.html#SP7_2_1">&#167;7.2.1</a>).</p>
<p class="endnote">The function BuildFiles::advance is used in 1/pc (<a href="1-pc.html#SP7_1">&#167;7.1</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The standard date format we use is "26 February 2018". If the contents of
<code class="display"><span class="extract">dateline</span></code> match today's date in this format, we return <code class="display"><span class="extract">TRUE</span></code>; otherwise we
rewrite <code class="display"><span class="extract">dateline</span></code> to today and return <code class="display"><span class="extract">FALSE</span></code>.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">BuildFiles::dated_today</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">dateline</span><span class="plain">) {</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">monthname</span><span class="plain">[12] = { </span><span class="string">"January"</span><span class="plain">, </span><span class="string">"February"</span><span class="plain">, </span><span class="string">"March"</span><span class="plain">, </span><span class="string">"April"</span><span class="plain">, </span><span class="string">"May"</span><span class="plain">, </span><span class="string">"June"</span><span class="plain">,</span>
<span class="string">"July"</span><span class="plain">, </span><span class="string">"August"</span><span class="plain">, </span><span class="string">"September"</span><span class="plain">, </span><span class="string">"October"</span><span class="plain">, </span><span class="string">"November"</span><span class="plain">, </span><span class="string">"December"</span><span class="plain"> };</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">today</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">today</span><span class="plain">, </span><span class="string">"%d %s %d"</span><span class="plain">,</span>
<span class="identifier">the_present</span><span class="plain">-&gt;</span><span class="identifier">tm_mday</span><span class="plain">, </span><span class="identifier">monthname</span><span class="plain">[</span><span class="identifier">the_present</span><span class="plain">-&gt;</span><span class="identifier">tm_mon</span><span class="plain">], </span><span class="identifier">the_present</span><span class="plain">-&gt;</span><span class="identifier">tm_year</span><span class="plain">+1900);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::ne</span><span class="plain">(</span><span class="identifier">dateline</span><span class="plain">, </span><span class="identifier">today</span><span class="plain">)) {</span>
<span class="identifier">rv</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">dateline</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">dateline</span><span class="plain">, </span><span class="identifier">today</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">today</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::dated_today is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Traditional Inform build codes are four-character, e.g., <code class="display"><span class="extract">3Q27</span></code>. Here, we
read such a code and increase it by one. The two-digit code at the back is
incremented, but rolls around from <code class="display"><span class="extract">99</span></code> to <code class="display"><span class="extract">01</span></code>, in which case the letter is
advanced, except that <code class="display"><span class="extract">I</span></code> and <code class="display"><span class="extract">O</span></code> are skipped, and if the letter passes <code class="display"><span class="extract">Z</span></code>
then it rolls back around to <code class="display"><span class="extract">A</span></code> and the initial digit is incremented.
</p>
<p class="inwebparagraph">This allows for 21384 distinct build codes, enough to use one each day for
some 58 years.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">BuildFiles::increment</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">) != 4) </span><span class="functiontext">Errors::with_text</span><span class="plain">(</span><span class="string">"build code malformed: %S"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, 0) - </span><span class="character">'0'</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, 1);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">M1</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, 2) - </span><span class="character">'0'</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">M2</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, 3) - </span><span class="character">'0'</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N</span><span class="plain"> &lt; 0) || (</span><span class="identifier">N</span><span class="plain"> &gt; 9) || (</span><span class="identifier">L</span><span class="plain"> &lt; </span><span class="character">'A'</span><span class="plain">) || (</span><span class="identifier">L</span><span class="plain"> &gt; </span><span class="character">'Z'</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">M1</span><span class="plain"> &lt; 0) || (</span><span class="identifier">M1</span><span class="plain"> &gt; 9) || (</span><span class="identifier">M2</span><span class="plain"> &lt; 0) || (</span><span class="identifier">M2</span><span class="plain"> &gt; 9)) {</span>
<span class="functiontext">Errors::with_text</span><span class="plain">(</span><span class="string">"build code malformed: %S"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">M2</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">M2</span><span class="plain"> == 10) { </span><span class="identifier">M2</span><span class="plain"> = 0; </span><span class="identifier">M1</span><span class="plain">++; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">M1</span><span class="plain"> == 10) { </span><span class="identifier">M1</span><span class="plain"> = 0; </span><span class="identifier">M2</span><span class="plain"> = 1; </span><span class="identifier">L</span><span class="plain">++; }</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L</span><span class="plain"> == </span><span class="character">'I'</span><span class="plain">) || (</span><span class="identifier">L</span><span class="plain"> == </span><span class="character">'O'</span><span class="plain">)) </span><span class="identifier">L</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> &gt; </span><span class="character">'Z'</span><span class="plain">) { </span><span class="identifier">L</span><span class="plain"> = </span><span class="character">'A'</span><span class="plain">; </span><span class="identifier">N</span><span class="plain">++; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == 10) </span><span class="functiontext">Errors::with_text</span><span class="plain">(</span><span class="string">"build code overflowed: %S"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"%d%c%d%d"</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">M1</span><span class="plain">, </span><span class="identifier">M2</span><span class="plain">);</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"Build code advanced to %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function BuildFiles::increment is used in <a href="#SP7">&#167;7</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="6-gs.html">Back to 'Git Support'</a></li><li><i>(This section ends Chapter 6: Extras.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '6/gs' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#6">Chapter 6: Extras</a></li><li><b>Git Support</b></li></ul><p class="purpose">Constructing a suitable gitignore file for a simple inweb project.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#6">Chapter 6: Extras</a></li><li><b>Git Support</b></li></ul><p class="purpose">Constructing a suitable gitignore file for a simple inweb project.</p>
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>This section offers just one function, which constructs a <code class="display"><span class="extract">.gitignore</span></code>
file by following a "prototype".
@ -119,7 +119,7 @@ file by following a "prototype".
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="6-mkf.html">Back to 'Makefiles'</a></li><li><i>(This section ends Chapter 6: Extras.)</i></li></ul><hr class="tocbar">
<ul class="toc"><li><a href="6-mkf.html">Back to 'Makefiles'</a></li><li><a href="6-bf2.html">Continue with 'Build Files'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of '6/mkf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#6">Chapter 6: Extras</a></li><li><b>Makefiles</b></li></ul><p class="purpose">Constructing a suitable makefile for a simple inweb project.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#6">Chapter 6: Extras</a></li><li><b>Makefiles</b></li></ul><p class="purpose">Constructing a suitable makefile for a simple inweb project.</p>
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>This section offers just one function, which constructs a makefile by
following a "prototype".

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of 'M/awwp' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#M">Manual</a></li><li><b>Advanced Weaving with Patterns</b></li></ul><p class="purpose">Customise the booklets woven from a web.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#M">Manual</a></li><li><b>Advanced Weaving with Patterns</b></li></ul><p class="purpose">Customise the booklets woven from a web.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Weave patterns</a></li><li><a href="#SP4">&#167;4. Cover sheets</a></li><li><a href="#SP5">&#167;5. Indexing</a></li><li><a href="#SP7">&#167;7. Navigation and breadcrumbs</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of 'M/htwaw' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#M">Manual</a></li><li><b>How to Write a Web</b></li></ul><p class="purpose">How to mark up code for literate programming.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#M">Manual</a></li><li><b>How to Write a Web</b></li></ul><p class="purpose">How to mark up code for literate programming.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. The title of a section</a></li><li><a href="#SP2">&#167;2. Paragraphing</a></li><li><a href="#SP6">&#167;6. Conditional compilation</a></li><li><a href="#SP7">&#167;7. Commentary</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of 'M/iti' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#M">Manual</a></li><li><b>Introduction to Inweb</b></li></ul><p class="purpose">What Inweb is, and why it is not CWEB.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#M">Manual</a></li><li><b>Introduction to Inweb</b></li></ul><p class="purpose">What Inweb is, and why it is not CWEB.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Introduction</a></li><li><a href="#SP2">&#167;2. Installation</a></li><li><a href="#SP4">&#167;4. Historical note</a></li></ul><hr class="tocbar">

View file

@ -24,7 +24,7 @@
<main role="main">
<!--Weave of 'M/tid' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#M">Manual</a></li><li><b>The InC Dialect</b></li></ul><p class="purpose">A modest extension of C used by the Inform project.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#M">Manual</a></li><li><b>The InC Dialect</b></li></ul><p class="purpose">A modest extension of C used by the Inform project.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. The InC language</a></li></ul><hr class="tocbar">

View file

@ -24,9 +24,9 @@
<main role="main">
<!--Weave of 'M/wtaw' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb 7</a></li><li><a href="index.html#M">Manual</a></li><li><b>Webs, Tangling and Weaving</b></li></ul><p class="purpose">How to use Inweb to weave or tangle a web already written.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#M">Manual</a></li><li><b>Webs, Tangling and Weaving</b></li></ul><p class="purpose">How to use Inweb to weave or tangle a web already written.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. All-in-one webs</a></li><li><a href="#SP4">&#167;4. Multi-section webs</a></li><li><a href="#SP7">&#167;7. Tangling</a></li><li><a href="#SP10">&#167;10. Weaving</a></li><li><a href="#SP13">&#167;13. Weave tags</a></li><li><a href="#SP14">&#167;14. Modules</a></li><li><a href="#SP17">&#167;17. The section catalogue</a></li><li><a href="#SP18">&#167;18. Makefile</a></li><li><a href="#SP19">&#167;19. Gitignore</a></li><li><a href="#SP20">&#167;20. GitHub Pages support</a></li></ul><hr class="tocbar">
<ul class="toc"><li><a href="#SP1">&#167;1. All-in-one webs</a></li><li><a href="#SP4">&#167;4. Multi-section webs</a></li><li><a href="#SP7">&#167;7. Tangling</a></li><li><a href="#SP10">&#167;10. Weaving</a></li><li><a href="#SP13">&#167;13. Weave tags</a></li><li><a href="#SP14">&#167;14. Modules</a></li><li><a href="#SP17">&#167;17. The section catalogue</a></li><li><a href="#SP18">&#167;18. Makefile</a></li><li><a href="#SP19">&#167;19. Gitignore</a></li><li><a href="#SP20">&#167;20. GitHub Pages support</a></li><li><a href="#SP21">&#167;21. Semantic version numbering and build metadata</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. All-in-one webs. </b>A program written for use with Inweb is called a "web". Inweb was primarily
designed for large, multisection webs, but it can also be used in a much
@ -874,6 +874,54 @@ expect that to be able to link to a <code class="display"><span class="extract">
above them.
</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Semantic version numbering and build metadata. </b>When Inweb reads in a web, it also looks for a file called <code class="display"><span class="extract">build.txt</span></code> in
the web's directory; if that isn't there, it looks for the same file in the
current working directory; if that's not there either, never mind.
</p>
<p class="inwebparagraph">Such a file contains up to three text fields, all optional:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">Prerelease: alpha.1</span>
<span class="plain">Build Date: 23 March 2020</span>
<span class="plain">Build Number: 6Q26</span>
</pre>
<p class="inwebparagraph">The bibliographic variables <code class="display"><span class="extract">Prerelease</span></code> and so on are then set from this
file. (They can equally well be set by the Contents section of the web, and
if so then that takes priority.)
</p>
<p class="inwebparagraph">The Prerelease and Build Number, if given, are used in combination with the
Version Number (set in the Contents) to produce the semantic version number,
or semver, for the web. For example, if the Contents included:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">Version Number: 6.2.12</span>
</pre>
<p class="inwebparagraph">then the semver would be <code class="display"><span class="extract">6.2.12-alpha.1+6Q26</span></code>. This is accessible within
the web as the variable <code class="display"><span class="extract">Semantic Version Number</span></code>.
</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. </b>A special advancing mechanism exists to update build numbers and dates.
Running Inweb with <code class="display"><span class="extract">-advance-build W</span></code> checks the build date for web <code class="display"><span class="extract">W</span></code>:
if it differs from today, then it is changed to today, and the build code
is advanced by one.
</p>
<p class="inwebparagraph">Running <code class="display"><span class="extract">-advance-build-file B</span></code> does this for a stand-alone build file <code class="display"><span class="extract">B</span></code>,
without need of a web.
</p>
<hr class="tocbar">
<ul class="toc"><li><a href="M-iti.html">Back to 'Introduction to Inweb'</a></li><li><a href="M-htwaw.html">Continue with 'How to Write a Web'</a></li></ul><hr class="tocbar">
<!--End of weave-->

View file

@ -1,6 +1,6 @@
<html>
<head>
<title>inweb 7</title>
<title>inweb</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
@ -21,8 +21,8 @@
</nav>
<main role="main">
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><b>inweb 7</b></li></ul>
<p class="purpose">A modern system for literate programming.</p>
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><b>inweb</b></li></ul>
<p class="purpose">A modern system for literate programming. This is version 7.</p>
<hr>
<ul class="chapterlist">
<li>
@ -205,6 +205,10 @@
<p><a href="6-gs.html"><spon class="sectiontitle">Git Support</span></a> -
<span class="purpose">Constructing a suitable gitignore file for a simple inweb project.</span></p>
</li>
<li>
<p><a href="6-bf2.html"><spon class="sectiontitle">Build Files</span></a> -
<span class="purpose">Manages the build metadata for an inweb project.</span></p>
</li>
</ul>
</li>
</ul>

View file

@ -1,7 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Booklet Title</title>
<title>Overview</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">

View file

@ -358,13 +358,13 @@ all other switches are delegated to the client's callback function |f|.
break;
case LOG_CLSW: @<Parse debugging log inclusion@>; innocuous = TRUE; break;
case VERSION_CLSW: {
char *bn = "[[Build Number]]";
char *vn = "[[Version Number]]";
if (vn[0] == 0) vn = "1";
PRINT("[[Title]]");
char *svn = "[[Semantic Version Number]]";
if (svn[0]) PRINT(" version %s", svn);
char *vname = "[[Version Name]]";
PRINT("[[Title]] %s", vn);
if (vname[0]) PRINT(" '%s'", vname);
if (bn[0]) PRINT(" (build %s)", bn);
char *d = "[[Build Date]]";
if (d[0]) PRINT(" (%s)", d);
PRINT("\n");
innocuous = TRUE; break;
}

View file

@ -74,6 +74,11 @@ endef
test:
$(INTEST) -from $(ME) all
.PHONY: commit
commit:
$(INWEB) -advance-build-file $(ME)/build.txt
cd $(ME); git commit -a
.PHONY: pages
pages:
mkdir -p $(ME)/docs

View file

@ -92,6 +92,14 @@ endef
test:
$(INTEST) -from $(ME) all
# "make commit" should be used only by the Benevolent Overlord of Inweb.
# It updates the build code and commits to the repository.
.PHONY: commit
commit:
$(INWEB) -advance-build-file $(ME)/build.txt
cd $(ME); git commit -a
# Weaving the web for GitHub Pages:
.PHONY: pages